fix(web): keep the subagent registry in the host plane
`dsh web` failed to boot: the aggressive plane split moved `subagents` and its spawn/fork backends into the preset's entry-local realm, but `dsh-host-apiproxy` is a host row that injects `subagents` to answer the browser's cross-session queries, so it waited forever for a service only sessions now provided. A per-session copy is wrong twice over — a provider name registers once, so the second session would have collided anyway. The registry and its backends go back to the host composition; the presets keep the delegation TOOLS, which resolve that host registry. `workflows` stays entry-local: nothing outside an agent reads it. The web real-composition test could not have caught this, because it disabled `api-gateway` — the very row whose pending injection names the break. It now boots with the api-proxy enabled and the browse directory picker substituted, so the boot audit covers the whole host-plane injection graph. Re-introducing the old split makes it fail with the three pending entries, which is how this was verified.
This commit is contained in:
@@ -30,19 +30,22 @@ async function bootWeb(settingsFile: string, extra: PatchOptions[] = []): Promis
|
||||
// outcome. Point it at a temp file for the same reason the roster below
|
||||
// names only the shipped root.
|
||||
{ id: 'settings', config: { path: settingsFile, watch: false } },
|
||||
// Host rows with side effects outside this process: a bound port, a
|
||||
// served asset tree, a telemetry exporter.
|
||||
// Host rows with side effects outside this process: a bound port, a served
|
||||
// asset tree, a telemetry exporter. `api-gateway` and `directory-picker`
|
||||
// stay ENABLED on purpose — the api-proxy is the host row that injects
|
||||
// `subagents`, `workspace`, and the rest of the agent plane, so disabling
|
||||
// it would hide exactly the breakage this file exists to catch: a service
|
||||
// moved into the presets that a host row still waits for. The boot audit
|
||||
// is that assertion.
|
||||
{ id: 'webserver', disabled: true },
|
||||
{ id: 'telemetry-otel', disabled: true },
|
||||
{ id: 'modules', disabled: true },
|
||||
{ id: 'connection', disabled: true },
|
||||
// NOT a side-effect row: the api-proxy cannot mount in THIS layer at all,
|
||||
// because it injects `subagents` and the subagent registry moved into the
|
||||
// presets here. That is the breakage a later layer returns to the host
|
||||
// plane; when it does, this line comes out and the boot audit covers the
|
||||
// whole host-plane injection graph again.
|
||||
{ id: 'api-gateway', disabled: true },
|
||||
// The shipped `-auto` chooser resolves its interaction from a running
|
||||
// host and so waits for the webserver disabled above; the browse variant
|
||||
// supplies `directoryPicker` without one.
|
||||
{ id: 'directory-picker', disabled: true },
|
||||
{ insert: [{ id: 'directory-picker-browse', name: '@deepseek-ai/dsh-host-directory-picker-browse' }] },
|
||||
// The roster AppCLIEntry would patch in; only the shipped root, so a
|
||||
// developer's own `~/.dsh/.preset` cannot change this test's outcome.
|
||||
// `default` here is the COMPOSITION default — the base layer the settings
|
||||
@@ -401,7 +404,7 @@ describe('the default preset as a user setting', () => {
|
||||
})
|
||||
|
||||
describe('a session keeps the preset it was created with', () => {
|
||||
it('records the preset the gateway guard reads', async () => {
|
||||
it('refuses to adopt a live session under a different preset', async () => {
|
||||
const handle = await ctx.agents.create({
|
||||
sessionId: SessionId('preset-locked'),
|
||||
meta: { agentPreset: 'core-web' },
|
||||
|
||||
Reference in New Issue
Block a user