Download packages/agent-core-v2/test/agent/toolActivation/toolActivationService.test.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 21.7 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/agent-core-v2/test/agent/toolActivation/toolActivationService.test.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/packages/agent-core-v2/test/agent/toolActivation/toolActivationService.test.ts
-
curl -L -o toolActivationService.test.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/agent-core-v2/test/agent/toolActivation/toolActivationService.test.ts
21.7 kB
| import { afterEach, beforeEach, describe, expect, it } from 'vitest'; | |
| import { DisposableStore, toDisposable } from '#/_base/di/lifecycle'; | |
| import { type CollectionView } from '#/_base/di/collection'; | |
| import { SyncDescriptor } from '#/_base/di/descriptors'; | |
| import { createDecorator } from '#/_base/di/instantiation'; | |
| import { Service } from '#/_base/di/service'; | |
| import { LifecycleScope } from '#/app/scopes'; | |
| import { | |
| ScopeActivation, | |
| _clearScopedRegistryForTests, | |
| createAppScope, | |
| registerScopedService, | |
| type ScopeSeed, | |
| } from '#/_base/di/scope'; | |
| import { createServices } from '#/_base/di/test'; | |
| import { IEventBus } from '#/app/event/eventBus'; | |
| import { Emitter, Event } from '#/_base/event'; | |
| import { IAgentProfileService, type ProfileData } from '#/agent/profile/profile'; | |
| import { IAgentRuntimeService } from '#/agent/runtimeBinding/agentRuntime'; | |
| import { IAgentToolActivationService } from '#/agent/toolActivation/toolActivation'; | |
| import { AgentToolActivationService } from '#/agent/toolActivation/toolActivationService'; | |
| import { | |
| BuiltinToolAssemblyService, | |
| IBuiltinToolAssemblyService, | |
| } from '#/agent/toolRegistry/builtinToolAssemblyService'; | |
| import { | |
| _clearAgentToolContributionsForTests, | |
| AgentToolContribution, | |
| getAgentToolContributions, | |
| registerAgentToolService, | |
| } from '#/agent/toolRegistry/toolContribution'; | |
| import { IAgentToolRegistryService } from '#/agent/toolRegistry/toolRegistry'; | |
| import { AgentToolRegistryService } from '#/agent/toolRegistry/toolRegistryService'; | |
| import { | |
| IAgentToolSelectService, | |
| SELECT_TOOLS_TOOL_NAME, | |
| } from '#/agent/toolSelect/toolSelect'; | |
| import { ISessionToolPolicyGate } from '#/session/sessionToolPolicyGate/sessionToolPolicyGate'; | |
| import type { RuntimeCapability } from '#/runtime/runtime'; | |
| import type { AgentTool, ToolExecution } from '#/tool/toolContract'; | |
| import '#/agent/tools/agent/agentTool'; | |
| import '#/agent/tools/ask-user-question/askUserQuestionTool'; | |
| import '#/agent/tools/edit/editTool'; | |
| import '#/agent/tools/fetch-url/fetchUrlTool'; | |
| import '#/agent/tools/os/bash/bashTool'; | |
| import '#/agent/tools/os/glob/globTool'; | |
| import '#/agent/tools/os/grep/grepTool'; | |
| import '#/agent/tools/os/read/readTool'; | |
| import '#/agent/tools/os/write/writeTool'; | |
| import '#/agent/tools/select-tools/selectToolsTool'; | |
| import '#/features/skill/tools/skillTool'; | |
| import '#/agent/tools/task/task-list/taskListTool'; | |
| import '#/agent/tools/task/task-output/taskOutputTool'; | |
| import '#/agent/tools/task/task-stop/taskStopTool'; | |
| import '#/features/todo/tools/todo-list/todoListTool'; | |
| import '#/agent/tools/web-search/webSearchTool'; | |
| class StubTool implements AgentTool { | |
| declare readonly _serviceBrand: undefined; | |
| readonly description = 'stub'; | |
| readonly parameters: Record<string, unknown> = {}; | |
| constructor(readonly name: string) {} | |
| resolveExecution(): ToolExecution { | |
| return { isError: true, output: 'stub' }; | |
| } | |
| } | |
| const IAlphaTool = createDecorator<AgentTool>('activationTestAlphaTool'); | |
| const IBetaTool = createDecorator<AgentTool>('activationTestBetaTool'); | |
| const IGammaTool = createDecorator<AgentTool>('activationTestGammaTool'); | |
| const IAgentStubTool = createDecorator<AgentTool>('activationTestAgentTool'); | |
| const ISelectToolsStub = createDecorator<AgentTool>('activationTestSelectToolsStub'); | |
| let alphaConstructions = 0; | |
| let betaConstructions = 0; | |
| let gammaConstructions = 0; | |
| class AlphaTool extends StubTool { | |
| constructor() { | |
| super('Alpha'); | |
| alphaConstructions += 1; | |
| } | |
| } | |
| class BetaTool extends StubTool { | |
| constructor() { | |
| super('Beta'); | |
| betaConstructions += 1; | |
| } | |
| } | |
| class GammaTool extends StubTool { | |
| constructor() { | |
| super('Gamma'); | |
| gammaConstructions += 1; | |
| } | |
| } | |
| class AgentStubTool extends StubTool { | |
| constructor() { | |
| super('Agent'); | |
| } | |
| } | |
| class SelectToolsStub extends StubTool { | |
| constructor() { | |
| super(SELECT_TOOLS_TOOL_NAME); | |
| } | |
| } | |
| class TestContributionAssembly extends Service { | |
| constructor() { | |
| super(); | |
| for (const record of getAgentToolContributions()) { | |
| this.provide(AgentToolContribution, record); | |
| } | |
| } | |
| } | |
| const IDynamicToolProvider = createDecorator<DynamicToolProvider>( | |
| 'activationTestDynamicToolProvider', | |
| ); | |
| class DynamicToolProvider extends Service { | |
| declare readonly _serviceBrand: undefined; | |
| constructor() { | |
| super(); | |
| this.provide(AgentToolContribution, { | |
| id: IGammaTool, | |
| ctor: GammaTool, | |
| options: { name: 'Gamma' }, | |
| }); | |
| } | |
| } | |
| const ICollectionProbe = createDecorator<CollectionProbe>('activationTestCollectionProbe'); | |
| class CollectionProbe extends Service { | |
| declare readonly _serviceBrand: undefined; | |
| constructor( | |
| readonly view: CollectionView<AgentToolContribution>, | |
| ) { | |
| super(); | |
| } | |
| } | |
| describe('AgentToolActivationService', () => { | |
| let savedContributions: readonly AgentToolContribution[]; | |
| let disposables: DisposableStore; | |
| const profileData: { | |
| activeToolNames?: readonly string[]; | |
| disallowedTools?: readonly string[]; | |
| } = {}; | |
| const gateData: { disabledTools: readonly string[] } = { disabledTools: [] }; | |
| const runtimeChangeEmitter = new Emitter<void>(); | |
| const runtimeData = { | |
| available: true, | |
| capabilities: new Set<RuntimeCapability>(['fs', 'process']), | |
| }; | |
| function createActivationHost() { | |
| disposables = new DisposableStore(); | |
| const ix = createServices(disposables, { | |
| strict: true, | |
| additionalServices: (reg) => { | |
| reg.definePartialInstance(IAgentProfileService, { | |
| data: () => profileData as ProfileData, | |
| }); | |
| reg.definePartialInstance(IEventBus, { | |
| subscribe: () => toDisposable(() => {}), | |
| }); | |
| reg.definePartialInstance(IAgentRuntimeService, { | |
| onDidChange: runtimeChangeEmitter.event, | |
| isAvailable: (required = []) => | |
| runtimeData.available && required.every((capability) => runtimeData.capabilities.has(capability)), | |
| }); | |
| reg.defineInstance(ISessionToolPolicyGate, { | |
| _serviceBrand: undefined, | |
| get disabledTools() { | |
| return gateData.disabledTools; | |
| }, | |
| onDidChange: Event.None as Event<void>, | |
| } satisfies ISessionToolPolicyGate); | |
| reg.define(IAgentToolRegistryService, AgentToolRegistryService); | |
| reg.define(IAgentToolActivationService, AgentToolActivationService); | |
| reg.define(IAlphaTool, AlphaTool); | |
| reg.define(IBetaTool, BetaTool); | |
| reg.define(IGammaTool, GammaTool); | |
| reg.define(IAgentStubTool, AgentStubTool); | |
| reg.define(ISelectToolsStub, SelectToolsStub); | |
| }, | |
| }); | |
| disposables.add(ix.createInstance(TestContributionAssembly)); | |
| return ix; | |
| } | |
| beforeEach(() => { | |
| savedContributions = [...getAgentToolContributions()]; | |
| disposables = new DisposableStore(); | |
| alphaConstructions = 0; | |
| betaConstructions = 0; | |
| gammaConstructions = 0; | |
| runtimeData.available = true; | |
| runtimeData.capabilities.clear(); | |
| runtimeData.capabilities.add('fs'); | |
| runtimeData.capabilities.add('process'); | |
| _clearScopedRegistryForTests(); | |
| _clearAgentToolContributionsForTests(); | |
| delete profileData.activeToolNames; | |
| delete profileData.disallowedTools; | |
| gateData.disabledTools = []; | |
| }); | |
| afterEach(() => { | |
| disposables.dispose(); | |
| _clearScopedRegistryForTests(); | |
| _clearAgentToolContributionsForTests(); | |
| for (const contribution of savedContributions) { | |
| registerAgentToolService(contribution.id, contribution.ctor, contribution.options); | |
| } | |
| }); | |
| it('keeps an AgentTool unconstructed during scope creation and resolves a real instance', () => { | |
| _clearScopedRegistryForTests(); | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| const app = createAppScope(); | |
| const session = app.createChild(LifecycleScope.Session, 'session'); | |
| const agent = session.createChild(LifecycleScope.Agent, 'agent'); | |
| expect(alphaConstructions).toBe(0); | |
| const tool = agent.accessor.get(IAlphaTool); | |
| expect(tool).toBeInstanceOf(AlphaTool); | |
| expect(alphaConstructions).toBe(1); | |
| app.dispose(); | |
| }); | |
| it('activates every contribution when the profile has no allowlist', async () => { | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeInstanceOf(BetaTool); | |
| }); | |
| it('declares the runtime requirements used by every static runtime-bound tool', () => { | |
| const requirements = Object.fromEntries( | |
| savedContributions.map((contribution) => [ | |
| contribution.options.name, | |
| contribution.options.requiredRuntimeCapabilities, | |
| ]), | |
| ); | |
| expect(requirements).toMatchObject({ | |
| Agent: ['process'], | |
| Read: undefined, | |
| Write: ['fs'], | |
| Edit: ['fs'], | |
| Bash: ['process'], | |
| Grep: ['fs', 'process'], | |
| Glob: ['fs', 'process'], | |
| }); | |
| }); | |
| it('keeps Agent and runtime-independent tools on a process-only runtime', async () => { | |
| runtimeData.capabilities.delete('fs'); | |
| const agentOptions = savedContributions.find((record) => record.options.name === 'Agent')!.options; | |
| registerAgentToolService(IAlphaTool, AlphaTool, { | |
| name: 'Alpha', | |
| requiredRuntimeCapabilities: ['fs'], | |
| }); | |
| registerAgentToolService(IAgentStubTool, AgentStubTool, agentOptions); | |
| registerAgentToolService(IGammaTool, GammaTool, { name: 'Gamma' }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeUndefined(); | |
| expect(registry.resolve('Agent')).toBeInstanceOf(AgentStubTool); | |
| expect(registry.resolve('Gamma')).toBeInstanceOf(GammaTool); | |
| expect(alphaConstructions).toBe(0); | |
| }); | |
| it('withdraws Agent when process becomes unavailable and restores it later', async () => { | |
| const agentOptions = savedContributions.find((record) => record.options.name === 'Agent')!.options; | |
| registerAgentToolService(IAgentStubTool, AgentStubTool, agentOptions); | |
| const ix = createActivationHost(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| expect(registry.resolve('Agent')).toBeInstanceOf(AgentStubTool); | |
| runtimeData.capabilities.delete('process'); | |
| runtimeChangeEmitter.fire(); | |
| expect(registry.resolve('Agent')).toBeUndefined(); | |
| runtimeData.capabilities.add('process'); | |
| runtimeChangeEmitter.fire(); | |
| expect(registry.resolve('Agent')).toBeInstanceOf(AgentStubTool); | |
| }); | |
| it('withdraws and restores only runtime-bound tools on capability and status changes', async () => { | |
| registerAgentToolService(IAlphaTool, AlphaTool, { | |
| name: 'Alpha', | |
| requiredRuntimeCapabilities: ['fs'], | |
| }); | |
| registerAgentToolService(IBetaTool, BetaTool, { | |
| name: 'Beta', | |
| requiredRuntimeCapabilities: ['process'], | |
| }); | |
| registerAgentToolService(IGammaTool, GammaTool, { name: 'Gamma' }); | |
| const ix = createActivationHost(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| runtimeData.capabilities.delete('fs'); | |
| runtimeChangeEmitter.fire(); | |
| expect(registry.resolve('Alpha')).toBeUndefined(); | |
| expect(registry.resolve('Beta')).toBeInstanceOf(BetaTool); | |
| expect(registry.resolve('Gamma')).toBeInstanceOf(GammaTool); | |
| runtimeData.capabilities.add('fs'); | |
| runtimeChangeEmitter.fire(); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| runtimeData.available = false; | |
| runtimeChangeEmitter.fire(); | |
| expect(registry.resolve('Alpha')).toBeUndefined(); | |
| expect(registry.resolve('Beta')).toBeUndefined(); | |
| expect(registry.resolve('Gamma')).toBeInstanceOf(GammaTool); | |
| runtimeData.available = true; | |
| runtimeChangeEmitter.fire(); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeInstanceOf(BetaTool); | |
| }); | |
| it('activates only the tools allowed by the profile allowlist', async () => { | |
| profileData.activeToolNames = ['Alpha']; | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| registerAgentToolService(ISelectToolsStub, SelectToolsStub, { name: SELECT_TOOLS_TOOL_NAME }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeUndefined(); | |
| expect(registry.resolve(SELECT_TOOLS_TOOL_NAME)).toBeInstanceOf(SelectToolsStub); | |
| expect(betaConstructions).toBe(0); | |
| }); | |
| it('honors the profile disallowedTools', async () => { | |
| profileData.disallowedTools = ['Beta', SELECT_TOOLS_TOOL_NAME]; | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| registerAgentToolService(ISelectToolsStub, SelectToolsStub, { name: SELECT_TOOLS_TOOL_NAME }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeUndefined(); | |
| expect(registry.resolve(SELECT_TOOLS_TOOL_NAME)).toBeUndefined(); | |
| expect(betaConstructions).toBe(0); | |
| }); | |
| it('skips contributions whose when predicate fails', async () => { | |
| registerAgentToolService(IGammaTool, GammaTool, { name: 'Gamma', when: () => false }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| expect(ix.get(IAgentToolRegistryService).resolve('Gamma')).toBeUndefined(); | |
| expect(gammaConstructions).toBe(0); | |
| }); | |
| it('honors the workspace tool-policy veto before the profile', async () => { | |
| gateData.disabledTools = ['Beta']; | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeUndefined(); | |
| expect(registry.list().map((t) => t.name)).not.toContain('Beta'); | |
| expect(betaConstructions).toBe(0); | |
| }); | |
| it('lets the workspace veto win over a profile allowlist', async () => { | |
| profileData.activeToolNames = ['Alpha', 'Beta']; | |
| gateData.disabledTools = ['Beta']; | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| const ix = createActivationHost(); | |
| await ix.get(IAgentToolActivationService).activate(); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeUndefined(); | |
| }); | |
| it('is idempotent and picks up newly allowed tools on re-activation', async () => { | |
| profileData.activeToolNames = ['Alpha']; | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| const ix = createActivationHost(); | |
| const activation = ix.get(IAgentToolActivationService); | |
| const registry = ix.get(IAgentToolRegistryService); | |
| await activation.activate(); | |
| const alpha = registry.resolve('Alpha'); | |
| expect(alpha).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeUndefined(); | |
| profileData.activeToolNames = ['Alpha', 'Beta']; | |
| await activation.activate(); | |
| expect(registry.resolve('Alpha')).toBe(alpha); | |
| expect(registry.resolve('Beta')).toBeInstanceOf(BetaTool); | |
| }); | |
| describe('collection fold (scoped tree)', () => { | |
| beforeEach(() => { | |
| _clearScopedRegistryForTests(); | |
| registerScopedService( | |
| LifecycleScope.App, | |
| IBuiltinToolAssemblyService, | |
| BuiltinToolAssemblyService, | |
| ScopeActivation.OnScopeCreated, | |
| 'toolRegistry', | |
| ); | |
| registerScopedService( | |
| LifecycleScope.App, | |
| ICollectionProbe, | |
| CollectionProbe, | |
| ScopeActivation.OnDemand, | |
| 'toolActivation', | |
| ); | |
| registerScopedService( | |
| LifecycleScope.Agent, | |
| IAgentToolRegistryService, | |
| AgentToolRegistryService, | |
| ScopeActivation.OnScopeCreated, | |
| 'toolRegistry', | |
| ); | |
| registerScopedService( | |
| LifecycleScope.Agent, | |
| IAgentToolActivationService, | |
| AgentToolActivationService, | |
| ScopeActivation.OnScopeCreated, | |
| 'toolActivation', | |
| ); | |
| registerScopedService( | |
| LifecycleScope.Agent, | |
| IDynamicToolProvider, | |
| DynamicToolProvider, | |
| ScopeActivation.OnDemand, | |
| 'toolActivation', | |
| ); | |
| }); | |
| function agentSeeds(extra: ScopeSeed = []): ScopeSeed { | |
| return [ | |
| [IAgentProfileService, { data: () => profileData as ProfileData }], | |
| [IEventBus, { subscribe: () => toDisposable(() => {}) }], | |
| [ | |
| IAgentRuntimeService, | |
| { | |
| _serviceBrand: undefined, | |
| onDidChange: runtimeChangeEmitter.event, | |
| isAvailable: (required: readonly RuntimeCapability[] = []) => | |
| runtimeData.available && required.every((capability) => runtimeData.capabilities.has(capability)), | |
| }, | |
| ], | |
| ...extra, | |
| ]; | |
| } | |
| function createScopeTree(agentExtra: ScopeSeed = []) { | |
| const app = createAppScope(); | |
| const session = app.createChild(LifecycleScope.Session, 'session', { | |
| seeds: [ | |
| [ | |
| ISessionToolPolicyGate, | |
| { | |
| _serviceBrand: undefined, | |
| get disabledTools() { | |
| return gateData.disabledTools; | |
| }, | |
| onDidChange: Event.None as Event<void>, | |
| } satisfies ISessionToolPolicyGate, | |
| ], | |
| ], | |
| }); | |
| const agent = session.createChild(LifecycleScope.Agent, 'agent', { | |
| seeds: agentSeeds(agentExtra), | |
| }); | |
| return { app, session, agent }; | |
| } | |
| it('activates the built-in records provided once at App scope, in every agent scope', async () => { | |
| registerAgentToolService(IAlphaTool, AlphaTool, { name: 'Alpha' }); | |
| registerAgentToolService(IBetaTool, BetaTool, { name: 'Beta' }); | |
| const { app, session, agent } = createScopeTree(); | |
| expect(alphaConstructions).toBe(0); | |
| await agent.accessor.get(IAgentToolActivationService).activate(); | |
| const registry = agent.accessor.get(IAgentToolRegistryService); | |
| expect(registry.resolve('Alpha')).toBeInstanceOf(AlphaTool); | |
| expect(registry.resolve('Beta')).toBeInstanceOf(BetaTool); | |
| const agent2 = session.createChild(LifecycleScope.Agent, 'agent-2', { | |
| seeds: agentSeeds(), | |
| }); | |
| await agent2.accessor.get(IAgentToolActivationService).activate(); | |
| expect(agent2.accessor.get(IAgentToolRegistryService).resolve('Alpha')).toBeInstanceOf( | |
| AlphaTool, | |
| ); | |
| app.dispose(); | |
| }); | |
| it('folds a unit-provided record incrementally and withdraws it when the provider dies', async () => { | |
| const { app, agent } = createScopeTree([[IGammaTool, new SyncDescriptor(GammaTool, [])]]); | |
| const registry = agent.accessor.get(IAgentToolRegistryService); | |
| const activation = agent.accessor.get(IAgentToolActivationService); | |
| await activation.activate(); | |
| expect(registry.resolve('Gamma')).toBeUndefined(); | |
| expect(gammaConstructions).toBe(0); | |
| const provider = agent.accessor.get(IDynamicToolProvider); | |
| expect(registry.resolve('Gamma')).toBeInstanceOf(GammaTool); | |
| expect(gammaConstructions).toBe(1); | |
| provider.dispose(); | |
| expect(registry.resolve('Gamma')).toBeUndefined(); | |
| await activation.activate(); | |
| expect(registry.resolve('Gamma')).toBeUndefined(); | |
| app.dispose(); | |
| }); | |
| it('feeds every built-in contribution through the App-scope assembly unchanged', async () => { | |
| expect(savedContributions).toHaveLength(14); | |
| for (const contribution of savedContributions) { | |
| registerAgentToolService(contribution.id, contribution.ctor, contribution.options); | |
| } | |
| profileData.activeToolNames = []; | |
| const { app, agent } = createScopeTree([ | |
| [IAgentToolSelectService, {} as IAgentToolSelectService], | |
| ]); | |
| const probe = app.accessor.get(ICollectionProbe); | |
| expect(probe.view.items).toHaveLength(savedContributions.length); | |
| const seenByName = new Map(probe.view.items.map((r) => [r.options.name, r] as const)); | |
| for (const contribution of savedContributions) { | |
| const seen = seenByName.get(contribution.options.name); | |
| expect(seen?.id).toBe(contribution.id); | |
| expect(seen?.ctor).toBe(contribution.ctor); | |
| expect(seen?.options).toBe(contribution.options); | |
| } | |
| await agent.accessor.get(IAgentToolActivationService).activate(); | |
| const registered = agent.accessor.get(IAgentToolRegistryService).list(); | |
| expect(registered.map((tool) => tool.name)).toEqual([SELECT_TOOLS_TOOL_NAME]); | |
| app.dispose(); | |
| }); | |
| }); | |
| }); | |