fix(agent-presets): re-link recompose through the mount-time binding
The auto-merge kept recompose on the removed open re-link. It now moves the binding this roster kept from the agent's mount; an agent that never composed one has nothing to re-link, so the switch is its first bind — exactly a mount — and once bound only the kept binding can move it.
This commit is contained in:
@@ -225,7 +225,10 @@ export class AgentPresets extends Service {
|
|||||||
* and permanent, so the old composition stays for its other agents and the
|
* and permanent, so the old composition stays for its other agents and the
|
||||||
* new one is ensured BEFORE the link moves. An unknown or unusable preset
|
* new one is ensured BEFORE the link moves. An unknown or unusable preset
|
||||||
* therefore throws with the agent exactly as it was — there is no torn-down
|
* therefore throws with the agent exactly as it was — there is no torn-down
|
||||||
* state to restore.
|
* state to restore. The re-link runs through the binding this roster kept
|
||||||
|
* from the agent's mount — dsh-scope's only re-link authority. An agent
|
||||||
|
* that never composed one has nothing to re-link: the switch is then the
|
||||||
|
* agent's first bind, exactly a mount.
|
||||||
* @param agentCtx - the agent's scope context.
|
* @param agentCtx - the agent's scope context.
|
||||||
* @param id - the preset to compose the agent from instead.
|
* @param id - the preset to compose the agent from instead.
|
||||||
* @returns the preset now installed.
|
* @returns the preset now installed.
|
||||||
@@ -238,7 +241,12 @@ export class AgentPresets extends Service {
|
|||||||
}
|
}
|
||||||
const preset = await this.resolve(id)
|
const preset = await this.resolve(id)
|
||||||
const standing = await this.ensureStanding(preset)
|
const standing = await this.ensureStanding(preset)
|
||||||
setScopeParent(agentKey, standing.key)
|
const binding = this.bindings.get(agentKey)
|
||||||
|
if (binding === undefined) {
|
||||||
|
this.bindings.set(agentKey, bindScopeParent(agentKey, standing.key))
|
||||||
|
} else {
|
||||||
|
binding.rebind(standing.key)
|
||||||
|
}
|
||||||
return preset
|
return preset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -368,9 +368,19 @@ describe('replacing a composition', () => {
|
|||||||
expect(toolNames(ctx, handle.agent)).toEqual(['alpha'])
|
expect(toolNames(ctx, handle.agent)).toEqual(['alpha'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('leaves an agent that never composed one with nothing to restore', async () => {
|
it('binds an agent that never composed one as its first mount', async () => {
|
||||||
|
// No binding exists to re-link, so the switch is the agent's first bind
|
||||||
|
// — and once bound, only this roster's kept binding can move it again.
|
||||||
const handle = await ctx.agents.create({ sessionId: SessionId('sess-bare') })
|
const handle = await ctx.agents.create({ sessionId: SessionId('sess-bare') })
|
||||||
|
|
||||||
|
await ctx.agentPresets.recompose(handle.agent.ctx, 'standard')
|
||||||
|
|
||||||
|
expect(toolNames(ctx, handle.agent)).toEqual(['alpha'])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('leaves an agent that never composed one with nothing to restore', async () => {
|
||||||
|
const handle = await ctx.agents.create({ sessionId: SessionId('sess-bare-broken') })
|
||||||
|
|
||||||
await expect(ctx.agentPresets.recompose(handle.agent.ctx, 'broken'))
|
await expect(ctx.agentPresets.recompose(handle.agent.ctx, 'broken'))
|
||||||
.rejects.toThrow(/failed to mount/)
|
.rejects.toThrow(/failed to mount/)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user