refactor(repo): retire top-level examples

This commit is contained in:
Tianyi Cui
2026-08-24 22:02:44 +08:00
parent e25463bc0a
commit 4125514a08
376 changed files with 701 additions and 1780 deletions
+2 -2
View File
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/shell/README.md
README.md: f075db4fbe57c6052fea89b30e35126117f75a7c
README.zh.md: 21425afbaf237887134ed29152e46ad699c9f639
README.md: 9326ba1a4aaf91577efc427a3c1603eef1d3da2b
README.zh.md: 146190f3595561f8fad49559023f39d6dee5c9ed
+1 -1
View File
@@ -14,6 +14,6 @@ The capability family spans the canonical executor seam, its implementations, th
| [`tool-bash/`](tool-bash/README.md) | Exposes Bash execution and background-job integration to the model. | (registers on `ctx.tools`) |
| [`tool-pwsh/`](tool-pwsh/README.md) | Exposes PowerShell execution to the model. | (registers on `ctx.tools`) |
A leaf `cordis.yml` selects one executor implementation and the model-facing tools it needs. A sandboxed composition also selects a `ctx.sandbox` provider; the [ACP example](../../examples/acp-agent/) shows one complete wiring.
A profile layer selects one executor implementation and the model-facing tools it needs. A sandboxed composition also selects a `ctx.sandbox` provider; the [base bundle](../bundle/base/cordis.patch.yml) owns the shipped wiring.
The subsystem reference — request/spec vocabulary, results, background processes, the service, and events — is [docs/subsystems/shell.md](../../docs/subsystems/shell.md).
+1 -1
View File
@@ -14,6 +14,6 @@
| [`tool-bash/`](tool-bash/README.zh.md) | 向模型公开 Bash 执行和后台任务集成。 | (注册到 `ctx.tools` |
| [`tool-pwsh/`](tool-pwsh/README.zh.md) | 向模型公开 PowerShell 执行。 | (注册到 `ctx.tools` |
叶节点 `cordis.yml` 选择一个执行器实现和所需的面向模型工具。沙箱化组合还会选择一个 `ctx.sandbox` 提供方;[ACPAgent Client Protocol)示例](../../examples/acp-agent/)展示一套完整接线。
Profile 层选择一个执行器实现和所需的面向模型工具。沙箱化组合还会选择一个 `ctx.sandbox` 提供方;[base bundle](../bundle/base/cordis.patch.yml)负责交付接线。
子系统参考——请求/spec 词汇、结果、后台进程、服务与事件——见 [docs/subsystems/shell.md](../../docs/subsystems/shell.zh.md)。
@@ -0,0 +1,27 @@
# Minimal tool-pwsh composition: real app boot path, real pwsh executor, real
# foreground + background tool calls; driven by the package's loader.spec.ts.
- id: system-prompt
name: '@deepseek-ai/dsh-system-prompt'
- id: tools
name: '@deepseek-ai/dsh-tools'
- id: subprocess
name: '@deepseek-ai/dsh-subprocess-local'
- id: bash
name: '@deepseek-ai/dsh-pwsh-local'
config:
graceMs: 200
- id: shell-env
name: '@deepseek-ai/dsh-shell-env'
- id: tasks
name: '@deepseek-ai/dsh-jobs-local'
- id: tool-jobs
name: '@deepseek-ai/dsh-tool-jobs'
- id: tool-pwsh
name: '@deepseek-ai/dsh-tool-pwsh'
@@ -0,0 +1,67 @@
#!/usr/bin/env node
/**
* Test driver: boot the tool-pwsh Loader composition, execute one real
* foreground and one real background pwsh command through the tool registry,
* and persist the observed model-visible output to `./pwsh-loader-report.json`
* for the package spec's inspect step.
*/
import { writeFile } from 'node:fs/promises'
import { boot, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
import { CallId } from '@deepseek-ai/dsh-llm'
const configPath = process.argv[2]
if (configPath === undefined) throw new Error('tool-pwsh driver requires a config path')
const ctx = await boot('tool-pwsh-loader-smoke', resolveConfigPath(configPath, undefined))
try {
const schema = ctx.tools.schemas().find(tool => tool.name === 'pwsh')
if (schema === undefined) throw new Error('pwsh tool not registered by the composition')
const prompt = (await ctx.systemPrompt.assemble()).sections.find(section => section.name === 'tool:pwsh')
const foreground = await ctx.tools.execute({
signal: new AbortController().signal,
callId: CallId('loader-fg'),
name: 'pwsh',
arguments: { command: 'Write-Output loader-ok', description: 'loader foreground' },
})
const foregroundText = foreground.content.filter(block => block.type === 'text').map(block => block.text).join('')
const background = await ctx.tools.execute({
signal: new AbortController().signal,
callId: CallId('loader-bg'),
name: 'pwsh',
arguments: {
command: 'Start-Sleep -Milliseconds 200; Write-Output loader-bg-ok',
description: 'loader background',
run_in_background: true,
},
})
const jobId = (background.value as { jobId: string }).jobId
// The output delta and the terminal status can land in separate reads
// (Windows flushes the child pipe at exit), so accumulate both.
let backgroundText = ''
const deadline = Date.now() + 10_000
while (Date.now() < deadline) {
const read = await ctx.tools.execute({
signal: new AbortController().signal,
callId: CallId('loader-bg-read'),
name: 'job_output',
arguments: { job_id: jobId },
})
backgroundText += read.content.filter(block => block.type === 'text').map(block => block.text).join('')
if (backgroundText.includes('loader-bg-ok') && backgroundText.includes('[status: completed')) break
await new Promise(resolve => setTimeout(resolve, 50))
}
await writeFile('./pwsh-loader-report.json', JSON.stringify({
schemaHasRunInBackground: Object.hasOwn(schema.parameters.properties as object, 'run_in_background'),
promptHasMarkerSection: prompt?.text.includes('Non-zero exits are reported as `[exit code: N]` markers') === true,
// Normalize PowerShell's platform line endings (CRLF on Windows, LF elsewhere).
foregroundText: foregroundText.replace(/\r\n/g, '\n'),
backgroundText: backgroundText.replace(/\r\n/g, '\n'),
}))
} finally {
await ctx.fiber.dispose()
}
@@ -20,11 +20,11 @@ import { resolvePwshPath } from '@deepseek-ai/dsh-pwsh-local'
const hasPwsh = spawnSync(resolvePwshPath(), ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', '$true'], { encoding: 'utf8' }).status === 0
const driver = fileURLToPath(new URL(
'../../../../examples/acp-agent/tests/fixtures/shell/tool-pwsh/driver.ts',
'./fixtures/loader/driver.ts',
import.meta.url,
))
const configPath = fileURLToPath(new URL(
'../../../../examples/acp-agent/tests/fixtures/shell/tool-pwsh/cordis.yml',
'./fixtures/loader/cordis.yml',
import.meta.url,
))
const repoTsconfig = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url))