Files
deepseek-harness/apps/web/tests/scaffold-hermetic.e2e.ts
T
Yichen Jiang 2d1df8a9e2 fix(cli): declare the packages the shipped presets name
The bundle split emptied `apps/cli`'s plugin dependencies, and the flat module
fallback links only that manifest's closure — so a preset row naming
`@deepseek-ai/dsh-persona` resolved to nothing and every preset mount failed,
leaving each session with an agent that had no tools, persona, or token meter.
Which packages the shipped presets compose is not implied by any bundle: the
presets live beside this manifest, so this is where their closure is declared.

The hermetic skill test now addresses the registry through the composed agent,
the only shape that can see a preset's `isolate` realm.
2026-08-07 02:51:09 +08:00

76 lines
3.1 KiB
TypeScript

import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { expect, it } from 'vitest'
import type {} from '@deepseek-ai/dsh-skill'
import { SessionId } from '@deepseek-ai/dsh-session'
import type {} from '@deepseek-ai/dsh-agent-presets'
import { launchWebScaffold, type WebScaffold } from './scaffold.ts'
async function writeSkill(root: string, name: string): Promise<void> {
const bundle = join(root, name)
await mkdir(bundle, { recursive: true })
await writeFile(join(bundle, 'SKILL.md'), `---
name: ${name}
description: Must not enter the Web replay scaffold
---
Ambient host state.
`)
}
it('isolates replay skill discovery from every ambient host root', async () => {
const ambient = await mkdtemp(join(tmpdir(), 'dsh-web-ambient-skills-'))
const dshHome = join(ambient, 'dsh-home')
const agentsHome = join(ambient, 'agents-home')
const bundled = join(ambient, 'bundled')
await Promise.all([
writeSkill(join(dshHome, 'skills'), 'ambient-dsh'),
writeSkill(join(agentsHome, 'skills'), 'ambient-agents'),
writeSkill(bundled, 'ambient-bundled'),
])
const originalDshHome = process.env.DSH_HOME
const originalAgentsHome = process.env.DSH_AGENTS_HOME
const originalBundled = process.env.DSH_BUNDLED_SKILL_DIR
process.env.DSH_HOME = dshHome
process.env.DSH_AGENTS_HOME = agentsHome
process.env.DSH_BUNDLED_SKILL_DIR = bundled
let scaffold: WebScaffold | undefined
try {
scaffold = await launchWebScaffold()
const ctx = scaffold.ctx
// The skill registry belongs to one agent's preset, behind an `isolate`
// realm the host cannot resolve by name — so the roots under test are only
// reachable through a composed agent, which is also the only shape that
// ever asks. `serviceFor` is the same addressing the gateway's `skill.list`
// uses for a browser request about a session.
const handle = await ctx.agents.create({
sessionId: SessionId('hermetic-skills'),
setup: agentCtx => ctx.agentPresets.mount(agentCtx).then(() => undefined),
})
try {
const skills = ctx.agentPresets.serviceFor(handle.agent, 'skills')
if (skills === undefined) throw new Error('composed agent mounts no skill registry')
const names = (await skills.list({ cwd: scaffold.workspaceCwd })).map(skill => skill.name)
expect(names).not.toContain('ambient-dsh')
expect(names).not.toContain('ambient-agents')
expect(names).not.toContain('ambient-bundled')
} finally {
await handle.dispose()
}
} finally {
try {
await scaffold?.close()
} finally {
if (originalDshHome === undefined) delete process.env.DSH_HOME
else process.env.DSH_HOME = originalDshHome
if (originalAgentsHome === undefined) delete process.env.DSH_AGENTS_HOME
else process.env.DSH_AGENTS_HOME = originalAgentsHome
if (originalBundled === undefined) delete process.env.DSH_BUNDLED_SKILL_DIR
else process.env.DSH_BUNDLED_SKILL_DIR = originalBundled
await rm(ambient, { recursive: true, force: true })
}
}
})