|
|
@@ -634,6 +634,66 @@ describe('a delegated child', () => {
|
|
|
})
|
|
|
})
|
|
|
|
|
|
+describe('a launcher that configures no writable root', () => {
|
|
|
+ // The claim this default exists for, asserted through the real shipped
|
|
|
+ // bundles rather than a hand-built context: `apps/cli` patches in only the
|
|
|
+ // system root, and a person's own presets are found anyway because the
|
|
|
+ // roster derives `<dshHome>/.agent-presets` itself. `$DSH_HOME` is pointed
|
|
|
+ // at a temp home BEFORE boot — the derived root is resolved when the plugin
|
|
|
+ // is constructed, and an unpinned run would read the developer's own.
|
|
|
+ let derivedCtx: Context
|
|
|
+ let previousHome: string | undefined
|
|
|
+
|
|
|
+ beforeAll(async () => {
|
|
|
+ const home = await mkdtemp(join(tmpdir(), 'dsh-preset-derived-'))
|
|
|
+ previousHome = process.env.DSH_HOME
|
|
|
+ process.env.DSH_HOME = home
|
|
|
+ await mkdir(join(home, '.agent-presets', 'derived-mine'), { recursive: true })
|
|
|
+ await writeFile(
|
|
|
+ join(home, '.agent-presets', 'derived-mine', 'agent.cordis.yml'),
|
|
|
+ '- id: tool-todo\n name: \'@deepseek-ai/dsh-tool-todo\'\n config:\n allowParallelInProgress: true\n',
|
|
|
+ )
|
|
|
+ const settingsFile = join(await mkdtemp(join(tmpdir(), 'dsh-preset-derived-settings-')), 'settings.yaml')
|
|
|
+ await writeFile(settingsFile, '{}\n')
|
|
|
+ // Only the shipped root, exactly what `composeProfile` supplies; the
|
|
|
+ // writable one is the roster's own default rather than this patch's job.
|
|
|
+ derivedCtx = await bootWeb(settingsFile, [{
|
|
|
+ id: 'agent-presets',
|
|
|
+ config: {
|
|
|
+ default: 'standard',
|
|
|
+ roots: [{ path: join(CONFIG_DIR, 'agent-presets'), trust: 'system' }],
|
|
|
+ includeUserRoot: true,
|
|
|
+ },
|
|
|
+ }])
|
|
|
+ }, 120_000)
|
|
|
+
|
|
|
+ afterAll(async () => {
|
|
|
+ if (previousHome === undefined) delete process.env.DSH_HOME
|
|
|
+ else process.env.DSH_HOME = previousHome
|
|
|
+ await derivedCtx.fiber.dispose()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('discovers and mounts a preset the person authored under the harness home', async () => {
|
|
|
+ const listed = await derivedCtx.agentPresets.list()
|
|
|
+
|
|
|
+ const mine = listed.find(preset => preset.id === 'derived-mine')
|
|
|
+ expect(mine).toMatchObject({ trust: 'user' })
|
|
|
+ // Omitted rather than undefined: a healthy row carries no `broken` key.
|
|
|
+ expect(mine?.broken).toBeUndefined()
|
|
|
+ expect(derivedCtx.agentPresets.authorable).toBe(true)
|
|
|
+
|
|
|
+ const handle = await derivedCtx.agents.create({
|
|
|
+ sessionId: SessionId('preset-derived-root'),
|
|
|
+ setup: agentCtx => derivedCtx.agentPresets.mount(agentCtx, 'derived-mine').then(() => undefined),
|
|
|
+ })
|
|
|
+ try {
|
|
|
+ expect(toolNames(derivedCtx, handle.agent)).toContain('todo_write')
|
|
|
+ } finally {
|
|
|
+ await handle.dispose()
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
describe('authoring a preset on the shipped composition', () => {
|
|
|
let authorCtx: Context
|
|
|
let userRoot: string
|