refactor(typert): rename RemoteContext to RemoteScope

This commit is contained in:
imccyu
2026-08-07 18:35:50 +08:00
parent d6ffd87c5f
commit d362cdb54f
27 changed files with 127 additions and 127 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/api/gateway/README.md
README.md: e37359db71c1388667e9e61f538354711e90c0c1
README.zh.md: 2054febb9a5423297c32b029b40a035062250aab
README.md: 0e1a03d2016b8cfbe165dbf1b0a9802290b29502
README.zh.md: 6b5ccff2340405cc0045147239c5bd4f3eead7da

View File

@@ -6,9 +6,9 @@ Two-sided TypeRT RPC endpoint for Host and Client Cordis environments. The Host
## Host service: `TypertGatewayService` (ctx key: `typertGateway`)
`ctx.typertGateway.invoke()` resolves the current descriptor and Cordis Service for each call, validates exact named arguments, resolves registered object or Context identities, invokes the public business method, and validates its result. Business Services extend `GatewayService` and mark methods with `@Remote` or `@RemoteContext` from [`dsh-type-meta`](../../typert/type-meta/README.md); `bindTypeRTGateway()` remains available when another base class owns inheritance.
`ctx.typertGateway.invoke()` resolves the current descriptor and Cordis Service for each call, validates exact named arguments, resolves registered object or Context identities, invokes the public business method, and validates its result. Business Services extend `GatewayService` and mark methods with `@Remote` or `@RemoteScope` from [`dsh-type-meta`](../../typert/type-meta/README.md); `bindTypeRTGateway()` remains available when another base class owns inheritance.
Strict mode reads generated invocation descriptors from `ctx.typert.local`. Lookup parameters use the currently active resolver in `ctx.typert.lookups`: the business package registers the stable declaration and default policy, while Host composition can override resolution behavior with effect-scoped `configure()`; `@RemoteContext` resolves its receiver through a registered Host Context provider. SRC mode is a development fallback for endpoints that have never had a strict definition; it parses simple parameter names and accepts only JSON-safe values for non-lookup parameters. Withdrawing an observed strict definition fails instead of weakening validation.
Strict mode reads generated invocation descriptors from `ctx.typert.local`. Lookup parameters use the currently active resolver in `ctx.typert.lookups`: the business package registers the stable declaration and default policy, while Host composition can override resolution behavior with effect-scoped `configure()`; `@RemoteScope` resolves its receiver through a registered Host Context provider. SRC mode is a development fallback for endpoints that have never had a strict definition; it parses simple parameter names and accepts only JSON-safe values for non-lookup parameters. Withdrawing an observed strict definition fails instead of weakening validation.
The Host entry registers a trusted-host interceptor on Connection's shared `/api` FetchHandler. Connection passes this composite handler through its HTTP bridge; the handler dispatches claimed endpoints to Gateway and unclaimed endpoints to API Proxy. Direct `invoke()` calls preserve business errors; `TypertGatewayError` distinguishes failures owned by dispatch, binding, providers, lookup, Context, arguments, and codecs. A resolver may use `TypeRTLookupFailure` to carry an existing RPC error, preserving its original error code for policy rejections such as cold-resume failures or ownership fences.

View File

@@ -6,9 +6,9 @@
## Host 服务:`TypertGatewayService`ctx key`typertGateway`
每次调用时,`ctx.typertGateway.invoke()` 都会解析当前的描述符和 Cordis 服务,校验具名参数是否完全匹配,解析已注册的对象或 Context 身份标识,调用公开的业务方法,并校验其结果。业务服务继承 [`dsh-type-meta`](../../typert/type-meta/README.md) 的 `GatewayService`,并用 `@Remote``@RemoteContext` 标记方法;已有其他基类时仍可改用 `bindTypeRTGateway()`
每次调用时,`ctx.typertGateway.invoke()` 都会解析当前的描述符和 Cordis 服务,校验具名参数是否完全匹配,解析已注册的对象或 Context 身份标识,调用公开的业务方法,并校验其结果。业务服务继承 [`dsh-type-meta`](../../typert/type-meta/README.md) 的 `GatewayService`,并用 `@Remote``@RemoteScope` 标记方法;已有其他基类时仍可改用 `bindTypeRTGateway()`
严格模式从 `ctx.typert.local` 读取生成的调用描述符。查找参数使用 `ctx.typert.lookups` 中当前有效的 resolver业务包注册稳定声明与默认策略Host 组合可用 effect-scoped `configure()` 覆盖解析行为;`@RemoteContext` 则通过已注册的 Host Context 提供方解析其接收者。SRC 模式是开发阶段的回退路径,适用于从未具备严格定义的端点;它解析简单参数名,并且只允许非查找参数使用可安全表示为 JSON 的值。已观测到的严格定义一旦撤回,系统会直接报错,而不会降低校验强度。
严格模式从 `ctx.typert.local` 读取生成的调用描述符。查找参数使用 `ctx.typert.lookups` 中当前有效的 resolver业务包注册稳定声明与默认策略Host 组合可用 effect-scoped `configure()` 覆盖解析行为;`@RemoteScope` 则通过已注册的 Host Context 提供方解析其接收者。SRC 模式是开发阶段的回退路径,适用于从未具备严格定义的端点;它解析简单参数名,并且只允许非查找参数使用可安全表示为 JSON 的值。已观测到的严格定义一旦撤回,系统会直接报错,而不会降低校验强度。
Connection 可用时Host 入口会在 Connection 共享的 `/api` FetchHandler 上注册 trusted-host interceptor。Connection 把这个复合 handler 交给 HTTP bridgehandler 将已认领 endpoint 分发给 Gateway未认领 endpoint 则交给 API Proxy。直接调用 `invoke()` 会保留业务错误;`TypertGatewayError` 可区分分发、绑定、提供方、查找、Context、参数和编解码器各自负责的故障。resolver 可以用 `TypeRTLookupFailure` 携带既有 RPC error使冷恢复失败或 ownership fence 等策略拒绝保持原错误码。

View File

@@ -5,7 +5,7 @@ import type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client
import type {
InvocationDescriptor,
TypeRTContext,
TypeRTRemoteContextApi,
TypeRTRemoteScopeApi,
TypeRTRemoteNamespace,
} from '@deepseek-ai/dsh-type-meta'
import TypertRegistry from '@deepseek-ai/dsh-typert-registry'
@@ -24,7 +24,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
) => Promise<{ readonly ref: string }>
}
interface TypeRTRemoteContextMap {
interface TypeRTRemoteScopeMap {
'fixture:goals/create': (
request: { readonly objective: string },
signal?: AbortSignal,
@@ -38,7 +38,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
}
type FixtureContext = Omit<Context, 'remote'> & { readonly remote: TypeRTRemoteContextApi<'fixture'> }
type FixtureContext = Omit<Context, 'remote'> & { readonly remote: TypeRTRemoteScopeApi<'fixture'> }
const idSchema = z.string().min(1)
const requestSchema = z.object({ objective: z.string().min(1) })

View File

@@ -8,7 +8,7 @@ import type { HttpServerService, WebRoute } from '@deepseek-ai/dsh-host-webserve
import {
bindTypeRTGateway,
Remote,
RemoteContext,
RemoteScope,
TypeRTLookupFailure,
type InvocationDescriptor,
type TypeRTContext,
@@ -65,7 +65,7 @@ class GoalService extends Service {
}
}
@RemoteContext('gatewayFixture')
@RemoteScope('gatewayFixture')
rename(request: { readonly title: string }): unknown {
this.calls.push('rename')
return { title: request.title, scope: (this.ctx as MarkedContext).fixtureScope ?? 'root' }
@@ -299,7 +299,7 @@ class ContextWireService extends Service {
super(ctx, 'contextWire')
}
@RemoteContext('gatewayFixture')
@RemoteScope('gatewayFixture')
run(agentId: string): string {
return agentId
}
@@ -389,7 +389,7 @@ describe('TypertGatewayService', () => {
expect(service.lastSignal?.aborted).toBe(false)
})
it('resolves strict Remote Context identity without adding a business argument', async () => {
it('resolves strict Remote Scope identity without adding a business argument', async () => {
const { ctx, service } = await setup()
const scoped = ctx.extend({ fixtureScope: 'agent-scope' })
ctx.typert.contexts.registerHost('gatewayFixture', contextProvider(scoped))
@@ -432,7 +432,7 @@ describe('TypertGatewayService', () => {
expect(service.calls).toEqual([])
})
it('derives SRC Remote Context identity and preserves the scoped Proxy receiver', async () => {
it('derives SRC Remote Scope identity and preserves the scoped Proxy receiver', async () => {
const { ctx } = await setup()
const scoped = ctx.extend({ fixtureScope: 'agent-src' })
ctx.typert.contexts.registerHost('gatewayFixture', contextProvider(scoped))

View File

@@ -18,11 +18,11 @@
import { Context as CordisContext } from 'cordis'
import type { Context, Fiber } from 'cordis'
import type { SessionId } from '@deepseek-ai/dsh-client-connection/client'
import type { TypeRTClientRemote, TypeRTRemoteContextApi } from '@deepseek-ai/dsh-type-meta'
import type { TypeRTClientRemote, TypeRTRemoteScopeApi } from '@deepseek-ai/dsh-type-meta'
/** Client Cordis Context carrying one Agent identity and its scoped Remote namespaces. */
export type AgentContext = Omit<Context, 'remote'> & {
readonly remote: TypeRTClientRemote & TypeRTRemoteContextApi<'agent'>
readonly remote: TypeRTClientRemote & TypeRTRemoteScopeApi<'agent'>
}
/** Context tag written by {@link createScope}. */

View File

@@ -1032,10 +1032,10 @@ class FaceAnalyzer {
if (invocation.kind === 'context') {
const context = this.contextDeclarations().get(invocation.context)
if (context === undefined) {
this.fail(method, `Remote Context ${invocation.context} has no TypeRTContextMap entry`)
this.fail(method, `Remote Scope ${invocation.context} has no TypeRTContextMap entry`)
}
const wire = `${invocation.context}Id`
if (wires.has(wire)) this.fail(method, `Remote Context wire field ${wire} conflicts with a method parameter`)
if (wires.has(wire)) this.fail(method, `Remote Scope wire field ${wire} conflicts with a method parameter`)
receiver = {
kind: 'context',
context: invocation.context,
@@ -1200,18 +1200,18 @@ class FaceAnalyzer {
}
marker = { kind: 'direct', exportName }
} else if (ts.isCallExpression(expression)
&& this.isTypeMetaSymbol(expression.expression, 'RemoteContext')) {
&& this.isTypeMetaSymbol(expression.expression, 'RemoteScope')) {
if (expression.arguments.length < 1 || expression.arguments.length > 2) {
this.fail(expression, 'RemoteContext() requires a Context key and optional exported method name')
this.fail(expression, 'RemoteScope() requires a Context key and optional exported method name')
}
const context = stringLiteralValue(expression.arguments[0])
if (context === undefined || !isRemoteSegment(context)) {
this.fail(expression.arguments[0] ?? expression, 'RemoteContext() key must be a string literal containing only RPC endpoint segment characters')
this.fail(expression.arguments[0] ?? expression, 'RemoteScope() key must be a string literal containing only RPC endpoint segment characters')
}
const exportArgument = expression.arguments[1]
const exportName = exportArgument === undefined ? undefined : stringLiteralValue(exportArgument)
if (exportArgument !== undefined && (exportName === undefined || !isRemoteSegment(exportName))) {
this.fail(exportArgument, 'RemoteContext() name must be a string literal containing only RPC endpoint segment characters')
this.fail(exportArgument, 'RemoteScope() name must be a string literal containing only RPC endpoint segment characters')
}
marker = { kind: 'context', context, ...exportName === undefined ? {} : { exportName } }
} else {
@@ -2529,7 +2529,7 @@ function sourceFileHasSurface(sourceFile: ts.SourceFile): boolean {
? decorator.expression.expression
: decorator.expression
const name = expressionName(expression)
if (name === 'Remote' || name === 'RemoteContext') return true
if (name === 'Remote' || name === 'RemoteScope') return true
}
}
}

View File

@@ -376,7 +376,7 @@ export class FaceModelEmitter {
lines.push(' }')
}
if (scoped.length > 0) {
lines.push(' interface TypeRTRemoteContextMap {')
lines.push(' interface TypeRTRemoteScopeMap {')
for (const invocation of scoped) {
this.pushRemoteSignature(lines, sourceMap, packageModel, invocation, referenceNames, true)
}

View File

@@ -1,4 +1,4 @@
import { GatewayService, Remote, RemoteContext } from '@deepseek-ai/dsh-type-meta'
import { GatewayService, Remote, RemoteScope } from '@deepseek-ai/dsh-type-meta'
import type { Agent } from '@fixture/domain'
import type {
CreateGoalRequest,
@@ -19,7 +19,7 @@ export class GoalService extends GatewayService {
return { ref: `${agent.id}:${request.title}` }
}
@RemoteContext('agent')
@RemoteScope('agent')
rename(request: RenameGoalRequest): RenameGoalResult {
return { renamed: request.title.length > 0 }
}

View File

@@ -11,7 +11,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
export interface TypeRTLookupMap {}
export interface TypeRTContextMap {}
export interface TypeRTRemoteMap {}
export interface TypeRTRemoteContextMap {}
export interface TypeRTRemoteScopeMap {}
export type TypeRTRemoteNamespace<Namespace extends string> = {
[Endpoint in keyof TypeRTRemoteMap as Endpoint extends `${Namespace}/${infer Method}`
@@ -56,7 +56,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Result>,
) => void
export function RemoteContext(key: Extract<keyof TypeRTContextMap, string>, exportName?: string):
export function RemoteScope(key: Extract<keyof TypeRTContextMap, string>, exportName?: string):
<This extends object, Args extends unknown[], Result>(
method: (this: This, ...args: Args) => Result,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Result>,

View File

@@ -288,7 +288,7 @@ export interface BoxPayload {
const root = copyFixture()
editFile(root, 'packages/remote/src/index.ts', source => source
.replace(' @Remote\n', '')
.replace(" @RemoteContext('agent')\n", ''))
.replace(" @RemoteScope('agent')\n", ''))
editFile(root, 'packages/remote/src/types.ts', source => `${source}
/** @typert schema */
@@ -377,8 +377,8 @@ export interface ClientMarker {
name: 'duplicate GatewayService field binding',
edit: (source: string) => source
.replace(
'import { GatewayService, Remote, RemoteContext }',
'import { GatewayService, Remote, RemoteContext, bindTypeRTGateway }',
'import { GatewayService, Remote, RemoteScope }',
'import { GatewayService, Remote, RemoteScope, bindTypeRTGateway }',
)
.replace(
'export class GoalService extends GatewayService {',
@@ -495,11 +495,11 @@ export interface ClientMarker {
expect(() => analyzeRemote(root)).not.toThrow()
})
it('rejects a Remote Context without a static Context declaration', () => {
it('rejects a Remote Scope without a static Context declaration', () => {
const root = copyFixture()
editFile(root, 'packages/remote/src/index.ts', source => source.replace("@RemoteContext('agent')", "@RemoteContext('missing')"))
editFile(root, 'packages/remote/src/index.ts', source => source.replace("@RemoteScope('agent')", "@RemoteScope('missing')"))
expect(() => analyzeRemote(root, false)).toThrow(/Remote Context missing has no TypeRTContextMap entry/)
expect(() => analyzeRemote(root, false)).toThrow(/Remote Scope missing has no TypeRTContextMap entry/)
})
it('rejects a direct scoped projection whose Context and lookup wire symbols differ', () => {
@@ -579,7 +579,7 @@ function assertRemoteConsumerTypechecks(
import remote from '@fixture/remote/remote'
import type {
TypeRTRemoteContribution,
TypeRTRemoteContextMap,
TypeRTRemoteScopeMap,
TypeRTRemoteMap,
TypeRTRemoteNamespaceMap,
} from '@deepseek-ai/dsh-type-meta'
@@ -587,8 +587,8 @@ import type { CreateGoalResult, RenameGoalResult } from '@fixture/remote/types'
const contribution: TypeRTRemoteContribution = remote
declare const create: TypeRTRemoteMap['goals/create']
declare const createScoped: TypeRTRemoteContextMap['agent:goals/create']
declare const rename: TypeRTRemoteContextMap['agent:goals/rename']
declare const createScoped: TypeRTRemoteScopeMap['agent:goals/create']
declare const rename: TypeRTRemoteScopeMap['agent:goals/rename']
const created: Promise<CreateGoalResult> = create('agent-1', { title: 'ship' })
const cancellable: Promise<CreateGoalResult> = create('agent-1', { title: 'ship' }, new AbortController().signal)
const createdScoped: Promise<CreateGoalResult> = createScoped({ title: 'ship' })

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/typert/type-meta/README.md
README.md: a76169742cb78d0d19814bcd0f978c71036a5a1c
README.zh.md: 6f2d2fd6e241441fae8102c0639608e9b27b9bec
README.md: 9bd475f8973ec54756fe0e63d5b7fa485381697d
README.zh.md: 10a6309bc47001d572abb3dd3f794ebfcf6252e8

View File

@@ -7,7 +7,7 @@ Compiler-independent declarations shared by business packages, generated TypeRT
## Remote declarations
- `@Remote` marks a public instance method for direct invocation on its registered Cordis Service.
- `@RemoteContext(key)` marks a method whose receiver is selected from a merge-declared scoped Context kind.
- `@RemoteScope(key)` marks a method whose receiver is selected from a merge-declared scoped Context kind.
- `GatewayService` binds the Cordis key passed to `super(ctx, serviceKey, options?)` to the same default wire namespace.
- `bindTypeRTGateway(this, serviceKey, options?)` provides the same visible, frozen binding for a Service that cannot inherit from `GatewayService`.
- `remoteMethods(service)` returns a detached declaration-order snapshot used by the Gateway's SRC fallback.
@@ -18,7 +18,7 @@ Decorator initializers retain markers in a module-private `WeakMap` keyed by the
## TypeRT protocol
Business packages extend `TypeRTLookupMap` and `TypeRTContextMap` to associate Host objects or scoped Contexts with their wire identities. Generated artifacts extend `TypeRTRemoteMap`, `TypeRTRemoteContextMap`, and `TypeRTRemoteNamespaceMap` so Client imports expose only selected Remote methods. `InvocationDescriptor` is the shared runtime form consumed by the registry, Gateway, and Client API.
Business packages extend `TypeRTLookupMap` and `TypeRTContextMap` to associate Host objects or scoped Contexts with their wire identities. Generated artifacts extend `TypeRTRemoteMap`, `TypeRTRemoteScopeMap`, and `TypeRTRemoteNamespaceMap` so Client imports expose only selected Remote methods. `InvocationDescriptor` is the shared runtime form consumed by the registry, Gateway, and Client Remote.
Lookup and Context packages own both sides of their contract: declaration merging supplies the static association, while runtime providers register identity resolution with `ctx.typert`. A lookup or Host Context provider supplies the stable declaration and default resolver, while Host composition may separately configure a synchronous or asynchronous resolver; policy rejections may use `TypeRTLookupFailure` to carry a failure value owned by the boundary adapter. Strict codecs carry generated schemas; `src-json` codecs identify the weaker source-launch path.

View File

@@ -7,7 +7,7 @@
## Remote 声明
- `@Remote` 将公开实例方法标记为可在其注册的 Cordis 服务上直接调用。
- `@RemoteContext(key)` 标记接收者选自合并声明的作用域 Context 类型的方法。
- `@RemoteScope(key)` 标记接收者选自合并声明的作用域 Context 类型的方法。
- `GatewayService``super(ctx, serviceKey, options?)` 接收的 Cordis key 同时绑定为默认 wire namespace。
- `bindTypeRTGateway(this, serviceKey, options?)` 为无法继承 `GatewayService` 的 Service 提供同样可见且冻结的绑定。
- `remoteMethods(service)` 返回按声明顺序排列、与内部状态分离的快照,供 Gateway 的 SRC 回退路径使用。
@@ -18,7 +18,7 @@ Host 方法通过将 `signal: AbortSignal` 声明为最后一个参数来启用
## TypeRT 协议
业务包扩展 `TypeRTLookupMap``TypeRTContextMap`,以关联 Host 对象或作用域 Context 与其协议身份。生成的产物扩展 `TypeRTRemoteMap``TypeRTRemoteContextMap``TypeRTRemoteNamespaceMap`,使 Client 导入后仅暴露选定的 Remote 方法。`InvocationDescriptor` 是供注册表、Gateway 和 Client API 使用的共享运行时形式。
业务包扩展 `TypeRTLookupMap``TypeRTContextMap`,以关联 Host 对象或作用域 Context 与其协议身份。生成的产物扩展 `TypeRTRemoteMap``TypeRTRemoteScopeMap``TypeRTRemoteNamespaceMap`,使 Client 导入后仅暴露选定的 Remote 方法。`InvocationDescriptor` 是供注册表、Gateway 和 Client Remote 使用的共享运行时形式。
查找包与 Context 包同时负责其契约的两侧:声明合并提供静态关联,运行时提供方则向 `ctx.typert` 注册身份解析。lookup 或 Host Context provider 提供稳定声明与默认 resolverHost 组合可以另行配置同步或异步 resolver策略拒绝可用 `TypeRTLookupFailure` 携带由边界适配器拥有的失败值。严格编解码器携带生成的 schema`src-json` 编解码器标识约束更弱的源码启动路径。

View File

@@ -60,9 +60,9 @@ export type {
TypeRTLookupResolver,
TypeRTLookupRegistry,
TypeRTLookupWire,
TypeRTRemoteContextApi,
TypeRTRemoteContextMap,
TypeRTRemoteContextNamespace,
TypeRTRemoteScopeApi,
TypeRTRemoteScopeMap,
TypeRTRemoteScopeNamespace,
TypeRTRemoteContribution,
TypeRTRemoteMap,
TypeRTRemoteNamespace,
@@ -191,16 +191,16 @@ export function Remote<This extends object, Args extends unknown[], Result>(
}
/**
* Create a decorator for a method resolved from one scoped Remote Context.
* @param key - merge-declared Context key.
* Create a decorator for a method resolved from one Remote Scope.
* @param key - scope key declared through the Context map.
* @param exportName - optional Remote export name; defaults to the method name.
* @returns a standard method decorator that records only private module state.
*/
export function RemoteContext(
export function RemoteScope(
key: Extract<keyof TypeRTContextMap, string>,
exportName?: string,
): RemoteMethodDecorator {
validateName('Context key', key)
validateName('Scope key', key)
if (exportName !== undefined) validateName('Remote export name', exportName)
return function <This extends object, Args extends unknown[], Result>(
_method: (this: This, ...args: Args) => Result,

View File

@@ -40,7 +40,7 @@ export interface TypeRTContextMap {}
export interface TypeRTRemoteMap {}
/** Merge-extensible scoped Remote method signatures generated for consumers. */
export interface TypeRTRemoteContextMap {}
export interface TypeRTRemoteScopeMap {}
/**
* Resolve one direct Remote namespace from the generated flat endpoint map.
@@ -57,24 +57,24 @@ export type TypeRTRemoteNamespace<Namespace extends string> = {
* The calling Cordis Context supplies the concrete identity at runtime.
* @template Namespace - wire namespace between the Context prefix and method.
*/
export type TypeRTRemoteContextNamespace<
export type TypeRTRemoteScopeNamespace<
Namespace extends string,
ContextKey extends string = string,
> = {
[Endpoint in keyof TypeRTRemoteContextMap as Endpoint extends `${ContextKey}:${Namespace}/${infer Method}`
[Endpoint in keyof TypeRTRemoteScopeMap as Endpoint extends `${ContextKey}:${Namespace}/${infer Method}`
? Method
: never]: TypeRTRemoteContextMap[Endpoint]
: never]: TypeRTRemoteScopeMap[Endpoint]
}
type TypeRTRemoteContextNamespaceKey<
type TypeRTRemoteScopeNamespaceKey<
ContextKey extends string,
Endpoint = keyof TypeRTRemoteContextMap,
Endpoint = keyof TypeRTRemoteScopeMap,
> = Endpoint extends `${ContextKey}:${infer Namespace}/${string}` ? Namespace : never
/** Generated scoped Remote namespaces available to one Context kind. */
export type TypeRTRemoteContextApi<ContextKey extends string> = {
[Namespace in TypeRTRemoteContextNamespaceKey<ContextKey>]:
TypeRTRemoteContextNamespace<Namespace, ContextKey>
export type TypeRTRemoteScopeApi<ContextKey extends string> = {
[Namespace in TypeRTRemoteScopeNamespaceKey<ContextKey>]:
TypeRTRemoteScopeNamespace<Namespace, ContextKey>
}
/** Merge-extensible direct namespace surface generated for Client Remote services. */
@@ -227,7 +227,7 @@ export interface TypeRTLookupDefinition {
readonly wireTypeSymbol: string
}
/** Host resolver for one scoped Remote Context kind. */
/** Host resolver for one scoped Remote kind. */
export interface TypeRTHostContextProvider<Wire = unknown> {
/** Wire field carrying the Context identity. */
readonly wire: string

View File

@@ -2,7 +2,7 @@ import { Context } from 'cordis'
import {
GatewayService,
Remote,
RemoteContext,
RemoteScope,
remoteMethods,
} from '@deepseek-ai/dsh-type-meta'
@@ -16,7 +16,7 @@ class Goals extends GatewayService {
return value
}
@RemoteContext('agent')
@RemoteScope('agent')
scoped(value: string): string {
return value
}

View File

@@ -6,7 +6,7 @@ import {
bindTypeRTGateway,
GatewayService,
Remote,
RemoteContext,
RemoteScope,
remoteMethods,
type TypeRTContext,
} from '@deepseek-ai/dsh-type-meta'
@@ -29,7 +29,7 @@ describe('type-meta Remote declarations', () => {
return value
}
@RemoteContext('metaFixture')
@RemoteScope('metaFixture')
scoped(value: string): string {
return value
}
@@ -84,7 +84,7 @@ describe('type-meta Remote declarations', () => {
Reflect.get(Goals.prototype, 'create') as (this: Goals, ...args: unknown[]) => unknown,
methodContext('create', initializers),
)
RemoteContext('metaFixture')(
RemoteScope('metaFixture')(
Reflect.get(Goals.prototype, 'scoped') as (this: Goals, ...args: unknown[]) => unknown,
methodContext('scoped', initializers),
)
@@ -141,7 +141,7 @@ describe('type-meta Remote declarations', () => {
Reflect.get(Service.prototype, 'run') as (this: Service, ...args: unknown[]) => unknown,
methodContext('run', initializers),
)
RemoteContext('metaFixture', 'inspect')(
RemoteScope('metaFixture', 'inspect')(
Reflect.get(Service.prototype, 'scoped') as (this: Service, ...args: unknown[]) => unknown,
methodContext('scoped', initializers),
)
@@ -166,8 +166,8 @@ describe('type-meta Remote declarations', () => {
expect(() => Remote('bad name')).toThrow('export name')
expect(() => Remote('.')).toThrow('export name')
expect(() => Remote('..')).toThrow('export name')
expect(() => RemoteContext('' as 'metaFixture')).toThrow('Context key')
expect(() => RemoteContext('metaFixture', 'bad/name')).toThrow('export name')
expect(() => RemoteScope('' as 'metaFixture')).toThrow('Scope key')
expect(() => RemoteScope('metaFixture', 'bad/name')).toThrow('export name')
for (const context of [
{ ...methodContext('run', []), private: true },
@@ -195,7 +195,7 @@ describe('type-meta Remote declarations', () => {
Reflect.get(Service.prototype, 'run'),
methodContext('run', conflicting),
)
RemoteContext('metaFixture')(
RemoteScope('metaFixture')(
Reflect.get(Service.prototype, 'run'),
methodContext('run', conflicting),
)