fix: complete scoped lifecycle simplification

This commit is contained in:
Tianyi Cui
2026-07-12 23:15:07 +08:00
parent ed5304fb6d
commit 738054562d
16 changed files with 261 additions and 50 deletions

View File

@@ -843,7 +843,8 @@ export class ToolRegistry extends Service {
// invariant assertion as well as protection against future layer changes.
if (this.codeTransport !== undefined) {
visible.set(RUN_CODE_NAME, this.codeTransport)
if (this.codeTransport.ownerFinal === true) ownerFinalNames.add(RUN_CODE_NAME)
// createRunCodeTool() owns this internal transport and always marks it owner-final.
ownerFinalNames.add(RUN_CODE_NAME)
}
return { visible, knownNames, restrictableNames, ownerFinalNames }
}

View File

@@ -103,6 +103,21 @@ describe('scoped tool registration', () => {
.toThrow(/owner-final tool "reserved" cannot be registered while a scoped shadow exists/)
})
it('restores global and scoped owner-final tools removed by assembly middleware', async () => {
const ctx = await mount()
const { scope, key } = await mintAgentScope(ctx, 'owner-final')
ctx.tools.register({ ...tool('required'), ownerFinal: true })
scope.ctx.tools.register({ ...tool('scoped-required'), ownerFinal: true })
ctx.on('system-prompt/assemble', async assembly => ({
...assembly,
tools: assembly.tools.filter(schema => !schema.name.includes('required')),
}))
expect((await ctx.systemPrompt.assemble()).tools.map(schema => schema.name)).toContain('required')
expect((await ctx.systemPrompt.assemble({ scope: key })).tools.map(schema => schema.name))
.toEqual(expect.arrayContaining(['required', 'scoped-required']))
})
it('disposing the scope unwinds its registrations and leaves no residue', async () => {
const ctx = await mount()
const { scope, key } = await mintAgentScope(ctx, 'a')