mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
fix(web): compose a forked session, and give the shell realm its provider
Two consequences of moving the agent plane behind presets, both invisible until the host plane stopped carrying model-facing rows. `sessions.fork` built its child with a bare `installTarget` and a `meta` without `agentPreset`. That was harmless while every tool sat in the host plane — the child inherited them for free. It now comes up with an EMPTY tool set. The child composes the parent's preset instead, for the same reason a resumed session keeps its own: the seeded history was produced under those tools. `bashEnv` lives in its own `dsh-bash-env` row rather than inside `tool-bash`, so a preset that isolates the realm must compose the provider beside its consumer; the host row is disabled here like every other model-facing one. Nothing outside the agent plane injects `bashEnv`, so it stays per-session.
This commit is contained in:
@@ -22,6 +22,11 @@
|
||||
isolate:
|
||||
bashEnv: true
|
||||
config:
|
||||
# The registry and its consumer share the realm: a consumer left outside
|
||||
# would resolve the host's `bashEnv`, which this plane no longer provides.
|
||||
- id: bash-env
|
||||
name: '@deepseek-ai/dsh-bash-env'
|
||||
|
||||
- id: tool-bash
|
||||
name: '@deepseek-ai/dsh-tool-bash'
|
||||
|
||||
|
||||
@@ -40,6 +40,11 @@
|
||||
isolate:
|
||||
bashEnv: true
|
||||
config:
|
||||
# The registry and its consumer share the realm: a consumer left outside
|
||||
# would resolve the host's `bashEnv`, which this plane no longer provides.
|
||||
- id: bash-env
|
||||
name: '@deepseek-ai/dsh-bash-env'
|
||||
|
||||
- id: tool-bash
|
||||
name: '@deepseek-ai/dsh-tool-bash'
|
||||
|
||||
|
||||
@@ -154,6 +154,36 @@ describe('the shipped Web composition', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('a forked session', () => {
|
||||
it('inherits the composition its seeded history was produced under', async () => {
|
||||
const parent = await ctx.agents.create({
|
||||
sessionId: SessionId('preset-fork-parent'),
|
||||
meta: { agentPreset: 'core-web' },
|
||||
setup: agentCtx => ctx.agentPresets.mount(agentCtx, 'core-web').then(() => undefined),
|
||||
})
|
||||
const inherited = parent.agent.session.header.agentPreset
|
||||
const child = await ctx.agents.create({
|
||||
sessionId: SessionId('preset-fork-child'),
|
||||
meta: {
|
||||
parentSession: SessionId('preset-fork-parent'),
|
||||
seedLength: 0,
|
||||
...inherited === undefined ? {} : { agentPreset: inherited },
|
||||
},
|
||||
setup: agentCtx => ctx.agentPresets.mount(agentCtx, inherited).then(() => undefined),
|
||||
})
|
||||
try {
|
||||
// Composing nothing would leave the child empty: this layer moved every
|
||||
// model-facing row out of the host plane, so there is nothing to inherit
|
||||
// for free any more.
|
||||
expect(toolNames(ctx, child.agent)).toEqual(toolNames(ctx, parent.agent))
|
||||
expect(toolNames(ctx, child.agent).length).toBeGreaterThan(0)
|
||||
} finally {
|
||||
await child.dispose()
|
||||
await parent.dispose()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('a session keeps the preset it was created with', () => {
|
||||
it('refuses to adopt a live session under a different preset', async () => {
|
||||
const handle = await ctx.agents.create({
|
||||
|
||||
@@ -201,6 +201,9 @@
|
||||
# absent from a surface overlay would silently reappear the day someone reorders
|
||||
# the composition.
|
||||
|
||||
- id: bash-env
|
||||
disabled: true
|
||||
|
||||
- id: tool-bash
|
||||
disabled: true
|
||||
|
||||
|
||||
@@ -1898,6 +1898,12 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
||||
})
|
||||
}
|
||||
const childId = `session-${randomUUID()}` as SessionId
|
||||
// The child inherits the parent's composition for the same reason a
|
||||
// resumed session keeps its own: the seeded history was produced under
|
||||
// those tools, and composing anything else would strand the tool calls
|
||||
// it already carries. Now that no model-facing row sits in the host
|
||||
// plane, composing nothing would leave the child with no tools at all.
|
||||
const forkComposition = await composeAgent(source.header.agentPreset)
|
||||
try {
|
||||
await ctx.agents.create({
|
||||
sessionId: childId,
|
||||
@@ -1906,9 +1912,12 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
||||
...source.header.cwd === undefined ? {} : { cwd: source.header.cwd },
|
||||
parentSession: source.id,
|
||||
seedLength: cut,
|
||||
...forkComposition.agentPreset === undefined
|
||||
? {}
|
||||
: { agentPreset: forkComposition.agentPreset },
|
||||
},
|
||||
agentOptions,
|
||||
setup: installTarget,
|
||||
setup: forkComposition.setup,
|
||||
})
|
||||
} catch (error: unknown) {
|
||||
return err(request, {
|
||||
|
||||
Reference in New Issue
Block a user