cleanup(cli): remove dsh-cli-demo

This commit is contained in:
Tianyi Cui
2026-08-08 03:08:37 +08:00
parent bdd2f49df7
commit dc57f7d854
90 changed files with 539 additions and 2238 deletions

View File

@@ -12,15 +12,21 @@
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
disabled: true
- id: cli-agent
name: '@deepseek-ai/dsh-cli-demo'
- id: agent-spine
name: '@deepseek-ai/dsh-agent-spine-demo'
config:
provider: cli-mock
model: cli-mock
persistenceRoot: './.sessions'
agents:
- id: main
provider: cli-mock
model: cli-mock
cwd: !!js process.cwd()
workspaceContext: false
dshHome: './.dsh-home'
skills:
local:
agentsHome: './.agents-home'
persona: 'Keyless headless-agent smoke.'
- id: persistence
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './.sessions'

View File

@@ -7,10 +7,15 @@
config:
baseURL: !!js process.env.DSH_SNAPSHOT_BASE_URL
thinking: disabled
- id: cli-agent
- id: agent-spine
config:
provider: deepseek-official
model: deepseek-v4-flash
persistenceRoot: './.sessions'
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
cwd: !!js process.cwd()
workspaceContext: false
persona: 'Keyless DeepSeek adapter defaults snapshot.'
- id: persistence
config:
root: './.sessions'

View File

@@ -17,12 +17,22 @@
- id: seed-goal
name: './seed-goal.ts'
- id: cli-agent
name: '@deepseek-ai/dsh-cli-demo'
- id: agent-spine
name: '@deepseek-ai/dsh-agent-spine-demo'
config:
provider: cli-mock
model: cli-mock
agents:
- id: main
provider: cli-mock
model: cli-mock
cwd: !!js process.cwd()
persona: 'Test the persisted goal domain.'
persistenceRoot: './.sessions'
persistenceCompression: none
workspaceContext: false
- id: persistence
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './.sessions'
compression: none
- id: checkpoint-policy
name: '@deepseek-ai/dsh-session-checkpoint-policy'

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env node
/** Snapshot-only Loader driver: stream one fixture turn as canonical JSONL. */
import type { Context } from 'cordis'
import { boot, installFailLoud, loadEnv, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
import type { SessionEvent } from '@deepseek-ai/dsh-session'
import { runFixtureTurn } from './one-shot.ts'
const NAME = 'headless-test-driver'
const [configPath, ...taskParts] = process.argv.slice(2)
if (configPath === undefined || taskParts.length === 0 || taskParts.every(part => part.trim() === '')) {
throw new Error(`${NAME}: expected <config-path> <task...>`)
}
const uninstallFailLoud = installFailLoud(NAME)
let ctx: Context | undefined
try {
loadEnv(NAME)
ctx = await boot(NAME, resolveConfigPath(configPath, process.env.DSH_SNAPSHOT))
const result = await runFixtureTurn(ctx, {
task: taskParts.join(' '),
onEvent: (sessionId: string, event: SessionEvent) => {
process.stdout.write(`${JSON.stringify({ type: 'session_event', sessionId, event })}\n`)
},
})
process.stdout.write(`${JSON.stringify(result)}\n`)
} catch (error: unknown) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
process.exitCode = 1
} finally {
await ctx?.fiber.dispose()
uninstallFailLoud()
}

View File

@@ -0,0 +1,97 @@
/** Test-only direct-agent turn driver shared by assembled Loader fixtures. */
import type { Context } from 'cordis'
import type { Agent } from '@deepseek-ai/dsh-agent'
import { createUserMessage, type TokenUsage } from '@deepseek-ai/dsh-llm'
import type { SessionEvent } from '@deepseek-ai/dsh-session'
/** Result envelope consumed only by snapshot and composition tests. */
export interface FixtureTurnResult {
readonly type: 'result'
readonly sessionId: string
readonly output: string
readonly usage?: TokenUsage
}
/** Options for one fixture turn against exactly one configured root agent. */
export interface FixtureTurnOptions {
readonly task: string
readonly onEvent?: (sessionId: string, event: SessionEvent) => void
}
function addUsage(total: TokenUsage | undefined, step: TokenUsage): TokenUsage {
const next: TokenUsage = {
inputTokens: (total?.inputTokens ?? 0) + step.inputTokens,
outputTokens: (total?.outputTokens ?? 0) + step.outputTokens,
}
for (const key of ['cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens'] as const) {
if (total?.[key] !== undefined || step[key] !== undefined) next[key] = (total?.[key] ?? 0) + (step[key] ?? 0)
}
return next
}
function assistantText(event: Extract<SessionEvent, { type: 'assistant/message' }>): string | undefined {
const blocks = event.data.message.content.filter(block => block.type === 'text')
return blocks.length === 0 ? undefined : blocks.map(block => block.text).join('')
}
function onlyRootAgent(ctx: Context): Agent {
const agents = ctx.get('agents')?.roots() ?? []
const [agent] = agents
if (agent === undefined || agents.length !== 1) {
throw new Error(`headless fixture requires exactly one top-level agent, found ${agents.length}`)
}
return agent
}
/**
* Drive one task from its durable inbox receipt through whole-agent idle.
* @param ctx - settled Loader context with exactly one configured root agent.
* @param options - task and optional canonical-event observer.
* @returns the final assistant text and accumulated model usage.
*/
export async function runFixtureTurn(ctx: Context, options: FixtureTurnOptions): Promise<FixtureTurnResult> {
const agent = onlyRootAgent(ctx)
await agent.whenIdle()
const message = createUserMessage({
content: [{ type: 'text', text: options.task }],
source: { kind: 'user' },
})
let received = false
let output = ''
const usageByStep = new Map<string, TokenUsage>()
const disposeListener = ctx.on('session/event', (session, event) => {
if (session !== agent.session) return
if (!received) {
if (event.type !== 'agent/inbox/spliced'
|| !event.data.inserted.some(inserted => inserted.id === message.id)) return
received = true
}
options.onEvent?.(session.id, event)
if (event.type === 'assistant/chunk' && event.data.chunk.type === 'usage') {
usageByStep.set(`${event.data.turn}/${event.data.step}`, event.data.chunk.usage)
}
if (event.type === 'assistant/message') {
output = assistantText(event) ?? output
if (event.data.usage !== undefined) {
usageByStep.set(`${event.data.turn}/${event.data.step}`, event.data.usage)
}
}
})
try {
agent.followup(message)
await agent.whenIdle()
} finally {
disposeListener()
}
await ctx.sessions.flush(agent.session)
const usage = [...usageByStep.values()].reduce<TokenUsage | undefined>(addUsage, undefined)
return {
type: 'result',
sessionId: agent.session.id,
output,
...usage === undefined ? {} : { usage },
}
}

View File

@@ -10,8 +10,8 @@ import { writeFile } from 'node:fs/promises'
import { createServer } from 'node:http'
import { once } from 'node:events'
import { boot, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
import { runOneShot } from '@deepseek-ai/dsh-cli-demo/src/cli.ts'
import { recordFeedback } from '@deepseek-ai/dsh-command-feedback'
import { runFixtureTurn } from './one-shot.ts'
const configPath = process.argv[2]
if (configPath === undefined) throw new Error('telemetry-otel driver requires a config path')
@@ -35,14 +35,14 @@ const ctx = await boot('telemetry-otel-e2e', resolveConfigPath(configPath, undef
try {
// The fixture credential rides the model-visible user message; the exported
// copy must scrub it while the canonical log keeps the original bytes.
await runOneShot(ctx, { task: 'prove telemetry with key sk-e2efixture1234567890' })
await runFixtureTurn(ctx, { task: 'prove telemetry with key sk-e2efixture1234567890' })
const mode = process.env.DSH_TELEMETRY_E2E_MODE ?? 'FULL'
if (mode !== 'FULL') {
const [agent] = ctx.get('agents')?.roots() ?? []
if (agent === undefined) throw new Error('telemetry-otel driver requires one root agent')
recordFeedback(agent.session, 'fixture feedback')
if (mode === 'FEEDBACK_ONLY') {
await runOneShot(ctx, { task: 'post-feedback private suffix' })
await runFixtureTurn(ctx, { task: 'post-feedback private suffix' })
}
}
} finally {

View File

@@ -30,12 +30,22 @@
exporter:
url: !!js process.env.DSH_TELEMETRY_E2E_URL
- id: cli-agent
name: '@deepseek-ai/dsh-cli-demo'
- id: agent-spine
name: '@deepseek-ai/dsh-agent-spine-demo'
config:
provider: cli-mock
model: cli-mock
agents:
- id: main
provider: cli-mock
model: cli-mock
cwd: !!js process.cwd()
persona: 'Test the session-telemetry-otel plugin.'
persistenceRoot: './.sessions'
persistenceCompression: 'none'
workspaceContext: false
- id: persistence
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './.sessions'
compression: 'none'
- id: checkpoint-policy
name: '@deepseek-ai/dsh-session-checkpoint-policy'

View File

@@ -2,15 +2,15 @@
/** Test driver that sends two turns through one Headless Loader composition. */
import { boot, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
import { runOneShot } from '@deepseek-ai/dsh-cli-demo/src/cli.ts'
import { runFixtureTurn } from './one-shot.ts'
const configPath = process.argv[2]
if (configPath === undefined) throw new Error('time-context driver requires a config path')
const ctx = await boot('time-context-e2e', resolveConfigPath(configPath, undefined))
try {
await runOneShot(ctx, { task: 'first' })
await runOneShot(ctx, { task: 'second' })
await runFixtureTurn(ctx, { task: 'first' })
await runFixtureTurn(ctx, { task: 'second' })
} finally {
await ctx.fiber.dispose()
}

View File

@@ -12,12 +12,22 @@
- id: time-context
name: '@deepseek-ai/dsh-time-context'
- id: cli-agent
name: '@deepseek-ai/dsh-cli-demo'
- id: agent-spine
name: '@deepseek-ai/dsh-agent-spine-demo'
config:
provider: time-context-mock
model: time-context-mock
agents:
- id: main
provider: time-context-mock
model: time-context-mock
cwd: !!js process.cwd()
persona: 'Test the time-context plugin.'
persistenceRoot: './.sessions'
persistenceCompression: 'none'
workspaceContext: false
- id: persistence
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './.sessions'
compression: 'none'
- id: checkpoint-policy
name: '@deepseek-ai/dsh-session-checkpoint-policy'