diff --git a/docs/subsystems/tools.md b/docs/subsystems/tools.md index 98c0faca51..bff827d584 100644 --- a/docs/subsystems/tools.md +++ b/docs/subsystems/tools.md @@ -676,11 +676,11 @@ Source: [`packages/core/tools/src/index.ts`](../../packages/core/tools/src/index #### `tools/change` — emit -A tool or executor was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent's next assembly. +A tool was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent's next assembly. ```ts cordis-catalog /** - * A tool or executor was registered or unregistered, or a scoped restriction changed. + * A tool was registered or unregistered, or a scoped restriction changed. * Unfiltered registry notification: scoped listeners receive changes from every * scope because a global contribution can affect every agent's next assembly. * @mode emit diff --git a/docs/subsystems/tools.zh.md b/docs/subsystems/tools.zh.md index daaabb8988..53dbd43fb7 100644 --- a/docs/subsystems/tools.zh.md +++ b/docs/subsystems/tools.zh.md @@ -676,11 +676,11 @@ Source: [`packages/core/tools/src/index.ts`](../../packages/core/tools/src/index #### `tools/change` — emit -A tool or executor was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent's next assembly. +A tool was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent's next assembly. ```ts cordis-catalog /** - * A tool or executor was registered or unregistered, or a scoped restriction changed. + * A tool was registered or unregistered, or a scoped restriction changed. * Unfiltered registry notification: scoped listeners receive changes from every * scope because a global contribution can affect every agent's next assembly. * @mode emit diff --git a/packages/core/agent-loop/tests/tool-executors.spec.ts b/packages/core/agent-loop/tests/tool-executors.spec.ts index 900eba6031..eaf3a4726d 100644 --- a/packages/core/agent-loop/tests/tool-executors.spec.ts +++ b/packages/core/agent-loop/tests/tool-executors.spec.ts @@ -191,14 +191,20 @@ it('rejects new batches after unload while an accepted batch settles on its orig expect(trace).toEqual(['old_eval:execute', 'replacement_eval:execute']) }) -it('refreshes the selected projection when the same assembly context is reused', async () => { +it('refreshes executor projections without emitting tool registry changes', async () => { const ctx = await setup() + let registryChanges = 0 + ctx.on('tools/change', () => { registryChanges++ }) const key = { preset: 'refresh' } const scope = await scoped(ctx, key) const context: AssembleContext = { scope: key } expect((await ctx.systemPrompt.assemble(context)).tools.map(tool => tool.name)).toEqual(['echo']) - scope.ctx.tools.setExecutor(independent(scope.ctx, 'new_eval', [])) + const dispose = scope.ctx.tools.setExecutor(independent(scope.ctx, 'new_eval', [])) expect((await ctx.systemPrompt.assemble(context)).tools.map(tool => tool.name)).toEqual(['new_eval']) + expect(registryChanges).toBe(0) + dispose() + await expect(ctx.systemPrompt.assemble(context)).rejects.toThrow('selected tool executor is unavailable') + expect(registryChanges).toBe(0) }) it.each([ diff --git a/packages/core/tools/README.i18n.yaml b/packages/core/tools/README.i18n.yaml index 687c39c221..1f9c8098ed 100644 --- a/packages/core/tools/README.i18n.yaml +++ b/packages/core/tools/README.i18n.yaml @@ -21,8 +21,8 @@ en: 9d2e6caa39c53d62 zh: 096a777f828c7565 /deepseek-ai-dsh-tools/use-this-package/select-an-executor: - en: 1ddfa584f9280cb7 - zh: b0899fcb8163569e + en: bdf27b6f339ea866 + zh: b89205eedea1db0a /deepseek-ai-dsh-tools/use-this-package/restrict-tools-per-agent: en: c6f98b2283cc2e47 zh: c2cdce5d13473f15 diff --git a/packages/core/tools/README.md b/packages/core/tools/README.md index cee98fd3f7..3f0db3fcf6 100644 --- a/packages/core/tools/README.md +++ b/packages/core/tools/README.md @@ -65,7 +65,7 @@ The unified schema DSL supports `string`, `number`, `integer`, `boolean`, `null` ### Select an executor -Mount one executor in the deployment, preset, or Agent scope. The nearest scope selects the provider; duplicate providers in one scope fail. Native exposes visible capabilities directly; PTC exposes `run_code` and a generated SDK. +Mount one executor in the deployment, preset, or Agent scope. The nearest scope selects the provider; duplicate providers in one scope fail. Native exposes visible capabilities directly; PTC exposes `run_code` and a generated SDK. Executor registration and disposal do not emit `tools/change`; prompt assemblies and batches resolve the current executor when they run. ```yaml - name: '@deepseek-ai/dsh-tools' diff --git a/packages/core/tools/README.zh.md b/packages/core/tools/README.zh.md index fe97c14c4a..012ff9798a 100644 --- a/packages/core/tools/README.zh.md +++ b/packages/core/tools/README.zh.md @@ -65,7 +65,7 @@ ctx.tools.register(defineTool({ ### 选择执行器 -在部署、预设或 Agent 作用域中挂载一个执行器。最近的作用域决定提供者,同一作用域的重复提供者会报错。原生执行器直接公开可见能力;PTC 执行器公开 `run_code` 和生成的 SDK。 +在部署、预设或 Agent 作用域中挂载一个执行器。最近的作用域决定提供者,同一作用域的重复提供者会报错。原生执行器直接公开可见能力;PTC 执行器公开 `run_code` 和生成的 SDK。执行器注册和卸载不触发 `tools/change`;提示词组装和批次执行在运行时解析当前执行器。 ```yaml - name: '@deepseek-ai/dsh-tools' diff --git a/packages/core/tools/src/events.ts b/packages/core/tools/src/events.ts index cb890d2df7..f736de8908 100644 --- a/packages/core/tools/src/events.ts +++ b/packages/core/tools/src/events.ts @@ -48,7 +48,7 @@ declare module '@deepseek-ai/cordis' { */ 'tools/result'(this: Scoped, exec: Readonly, result: Readonly): undefined /** - * A tool or executor was registered or unregistered, or a scoped restriction changed. + * A tool was registered or unregistered, or a scoped restriction changed. * Unfiltered registry notification: scoped listeners receive changes from every * scope because a global contribution can affect every agent's next assembly. * @mode emit diff --git a/packages/core/tools/src/index.ts b/packages/core/tools/src/index.ts index 92f0ca612a..3bbf45ad6a 100644 --- a/packages/core/tools/src/index.ts +++ b/packages/core/tools/src/index.ts @@ -260,11 +260,9 @@ export class ToolsService extends Service { } if (scope === undefined) this.root = record else this.scoped.set(scope, record) - this.ctx.emit('tools/change') yield () => { // Keep an unavailable selection so a program cannot fall through to a different executor. record.executor = undefined - this.ctx.emit('tools/change') } }.bind(this), 'tools.setExecutor()') } diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index 11338a3f37..75f0e3ffe1 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -4691,8 +4691,8 @@ export const EVENT_API: readonly EventApiEntry[] = [ name: 'tools/change', mode: 'emit', signature: '\'tools/change\'(): void', - summary: 'A tool or executor was registered or unregistered, or a scoped restriction changed.', - description: 'A tool or executor was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent\'s next assembly.', + summary: 'A tool was registered or unregistered, or a scoped restriction changed.', + description: 'A tool was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent\'s next assembly.', parameters: [], }, {