From 71ebeaa55985a4033c86793f6c91fc0fe65cf8b0 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Fri, 7 Aug 2026 21:43:34 +0800 Subject: [PATCH] fix(client-runtime): localize remote namespace dependency --- docs/api-gateway.i18n.yaml | 4 ++-- docs/api-gateway.md | 4 +++- docs/api-gateway.zh.md | 4 +++- packages/client/runtime/src/client/index.ts | 4 ++-- packages/client/runtime/tests/client-apply.spec.ts | 1 - packages/client/runtime/tests/wire-events.spec.ts | 1 - 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/api-gateway.i18n.yaml b/docs/api-gateway.i18n.yaml index 2a6ae0807b..074644ff3e 100644 --- a/docs/api-gateway.i18n.yaml +++ b/docs/api-gateway.i18n.yaml @@ -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 docs/api-gateway.md -api-gateway.md: ba95d429dd0c9f9f354baf0063197cea6e3ecbf8 -api-gateway.zh.md: 4e42ebea7a5db19c7df23079050b9488679a3a23 +api-gateway.md: 33dfb30c9da25e46b660a3fa54ef37f587cbda08 +api-gateway.zh.md: 633eb10c0f2f065ecf27545813cc17d79f391865 diff --git a/docs/api-gateway.md b/docs/api-gateway.md index ba95d429dd..33dfb30c9d 100644 --- a/docs/api-gateway.md +++ b/docs/api-gateway.md @@ -55,7 +55,7 @@ export class GoalService extends GatewayService { Remote methods may return a value synchronously or return a Promise. For cooperative cancellation, the final parameter in the Host signature must be `signal: AbortSignal` using the global type; it is recorded in the descriptor instead of entering `args`, while the generated Client method accepts an optional final `AbortSignal`. -The Client uses concrete functions on ordinary objects, not a JavaScript Proxy. Direct and scoped calls appear under `ctx.remote.` and `agentCtx.remote.`. Each namespace is a traced Cordis child Service registered as `remote.`; the Client assembly mounts contributions through `ctx.remote.$mount()`, consumers inject both `remote` and the namespace Service they call, and the namespace unloads after its last method is withdrawn. When an `@Remote` method has exactly one lookup parameter and a same-named `TypeRTContextMap` uses the same wire identity, the generated scoped signature omits that identity parameter. `@RemoteScope` generates only the scoped invocation interface. +The Client uses concrete functions on ordinary objects, not a JavaScript Proxy. Direct and scoped calls appear under `ctx.remote.` and `agentCtx.remote.`. Each namespace is a traced Cordis child Service registered as `remote.`; the Client assembly mounts contributions through `ctx.remote.$mount()`, and the namespace unloads after its last method is withdrawn. Dependency declarations belong to the actual caller: only a business package that reads `ctx.remote.` or `agentCtx.remote.` declares both `remote` and `remote.` in its own `inject`; assemblies that only mount contributions and higher-level runtimes that do not call that namespace do not declare the namespace dependency on the business package's behalf. When an `@Remote` method has exactly one lookup parameter and a same-named `TypeRTContextMap` uses the same wire identity, the generated scoped signature omits that identity parameter. `@RemoteScope` generates only the scoped invocation interface. ```ts import type { SessionId } from '@deepseek-ai/dsh-session/types' @@ -63,6 +63,8 @@ import type { AgentContext } from '@deepseek-ai/dsh-client-runtime/client' import type { Context } from 'cordis' import type {} from '@deepseek-ai/dsh-api-remotes/client' +export const inject = ['remote', 'remote.goals'] + declare const ctx: Context declare const agentCtx: AgentContext declare const agentId: SessionId diff --git a/docs/api-gateway.zh.md b/docs/api-gateway.zh.md index 4e42ebea7a..633eb10c0f 100644 --- a/docs/api-gateway.zh.md +++ b/docs/api-gateway.zh.md @@ -55,7 +55,7 @@ export class GoalService extends GatewayService { Remote 方法可以同步返回或返回 Promise。若需要协作式取消,Host 签名的最后一个参数必须是全局类型的 `signal: AbortSignal`;它记录在描述符中而不是进入 `args`,Client 生成的方法则接受最后一个可选的 `AbortSignal`。 -Client 使用普通对象上的具体函数,不使用 JavaScript Proxy。直接调用与作用域调用分别出现在 `ctx.remote.` 和 `agentCtx.remote.`。每个 namespace 都是注册为 `remote.` 的可追踪 Cordis 子 Service;Client assembly 通过 `ctx.remote.$mount()` 挂载贡献,消费方同时注入 `remote` 与所调用的 namespace Service,最后一个方法撤回后该 namespace 随即卸载。当一个 `@Remote` 方法恰好有一个 lookup 参数、且同名 `TypeRTContextMap` 使用相同 wire identity 时,生成的作用域签名会省略该 identity 参数。`@RemoteScope` 只生成作用域调用界面。 +Client 使用普通对象上的具体函数,不使用 JavaScript Proxy。直接调用与作用域调用分别出现在 `ctx.remote.` 和 `agentCtx.remote.`。每个 namespace 都是注册为 `remote.` 的可追踪 Cordis 子 Service;Client assembly 通过 `ctx.remote.$mount()` 挂载贡献,最后一个方法撤回后该 namespace 随即卸载。依赖声明归实际调用方所有:只有读取 `ctx.remote.` 或 `agentCtx.remote.` 的业务包才在自己的 `inject` 中同时声明 `remote` 与 `remote.`;只负责挂载 contribution 的 assembly,以及不调用该 namespace 的上层 runtime,不代业务包声明 namespace 依赖。当一个 `@Remote` 方法恰好有一个 lookup 参数、且同名 `TypeRTContextMap` 使用相同 wire identity 时,生成的作用域签名会省略该 identity 参数。`@RemoteScope` 只生成作用域调用界面。 ```ts import type { SessionId } from '@deepseek-ai/dsh-session/types' @@ -63,6 +63,8 @@ import type { AgentContext } from '@deepseek-ai/dsh-client-runtime/client' import type { Context } from 'cordis' import type {} from '@deepseek-ai/dsh-api-remotes/client' +export const inject = ['remote', 'remote.goals'] + declare const ctx: Context declare const agentCtx: AgentContext declare const agentId: SessionId diff --git a/packages/client/runtime/src/client/index.ts b/packages/client/runtime/src/client/index.ts index b772e315a3..5a1677df96 100644 --- a/packages/client/runtime/src/client/index.ts +++ b/packages/client/runtime/src/client/index.ts @@ -179,8 +179,8 @@ declare module 'cordis' { } } -/** Required services: the Remote root and Goal namespace, wire handle, and Client TypeRT registry. */ -export const inject = ['remote', 'remote.goals', 'connection', 'typert'] +/** Required services: the Remote root, wire handle, and Client TypeRT registry. */ +export const inject = ['remote', 'connection', 'typert'] /** Mounts the browser runtime services and connection stream. * @param ctx - Client Cordis context. diff --git a/packages/client/runtime/tests/client-apply.spec.ts b/packages/client/runtime/tests/client-apply.spec.ts index e9b387fb00..b700c4c066 100644 --- a/packages/client/runtime/tests/client-apply.spec.ts +++ b/packages/client/runtime/tests/client-apply.spec.ts @@ -39,7 +39,6 @@ async function mount(): Promise { } ctx.reflect.provide('connection', handle) ctx.reflect.provide('remote', {}) - ctx.reflect.provide('remote.goals', {}) await ctx.plugin(RuntimeClient).await() return bench } diff --git a/packages/client/runtime/tests/wire-events.spec.ts b/packages/client/runtime/tests/wire-events.spec.ts index 703c5b1728..dfafcd07aa 100644 --- a/packages/client/runtime/tests/wire-events.spec.ts +++ b/packages/client/runtime/tests/wire-events.spec.ts @@ -33,7 +33,6 @@ async function mount(): Promise { } ctx.reflect.provide('connection', handle) ctx.reflect.provide('remote', {}) - ctx.reflect.provide('remote.goals', {}) await ctx.plugin(RuntimeClient).await() return bench }