Merge remote-tracking branch 'origin/master' into codex/model-experience-readmes-20260712

# Conflicts:
#	packages/bash/bash-sandbox/README.md
#	packages/sandbox/sandbox-local/README.md
This commit is contained in:
Tianyi Cui
2026-07-14 11:28:08 +08:00
162 changed files with 3295 additions and 1661 deletions
+2 -2
View File
@@ -32,11 +32,11 @@ Because the package wires no logger entry, an ACP leaf has **nothing to get wron
| `skills` | owner defaults | registry-cache, local-provider, and model-facing skill-tool config, routed through `dsh-agent-core` |
| `persistenceRoot` | `./.sessions` | the JSONL backend's root directory |
The leaf supplies the swappable backends: an LLM adapter (`llm-deepseek` for the real model, `llm-replay` for keyless snapshot replay) and a bash executor (`bash-local`).
The leaf supplies the swappable backends: an LLM adapter (`llm-deepseek` for the real model, `llm-replay` for keyless snapshot replay) and a bash executor.
## The bin
`dsh-acp-agent [path-to-cordis.yml]` (default `./cordis.yml`):
`dsh-acp-agent [--config path-to-cordis.yml]` (short form `-c`; default `./cordis.yml`):
- loads a gitignored `.env` from the cwd — **skipped** in snapshot REPLAY so a stray key can never trigger a live call;
- honors `DSH_SNAPSHOT=replay` by booting the sibling `cordis.snapshot.yml` (the keyless replay tree, `llm-replay` in place of `llm-deepseek`);
+9 -2
View File
@@ -22,11 +22,13 @@
* STDERR only (the app plugin loads no stdout logger, and the shared guards
* write to stderr); a stray stdout write corrupts the protocol frames.
*
* Usage: `dsh-acp-agent [path-to-cordis.yml]` (default `./cordis.yml`).
* Usage: `dsh-acp-agent [--config path-to-cordis.yml]` (default
* `./cordis.yml`).
*
* @module @deepseek-ai/dsh-acp-agent/bin
*/
import { parseArgs } from 'node:util'
import { boot, installFailLoud, loadEnv, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
const NAME = 'dsh-acp-agent'
@@ -37,7 +39,12 @@ const NAME = 'dsh-acp-agent'
installFailLoud(NAME)
const snapshotMode = process.env['DSH_SNAPSHOT']
if (snapshotMode !== 'replay') loadEnv(NAME)
const ctx = await boot(NAME, resolveConfigPath(process.argv[2] ?? './cordis.yml', snapshotMode))
const { values } = parseArgs({
args: process.argv.slice(2),
options: { config: { type: 'string', short: 'c' } },
strict: true,
})
const ctx = await boot(NAME, resolveConfigPath(values.config ?? './cordis.yml', snapshotMode))
if (snapshotMode !== undefined) {
process.stdin.on('end', () => {
void ctx.fiber.dispose().then(() => { process.exit(0) })
+2 -2
View File
@@ -117,7 +117,7 @@ afterEach(async () => {
describe.skipIf(!existsSync(acpBin))('dsh-acp-agent BUILT bin (node lib/bin.js, no tsx)', () => {
it('boots the published bin and answers an initialize JSON-RPC frame on stdout', async () => {
consumer = await makeConsumer()
child = spawn(process.execPath, ['--expose-internals', acpBin, './cordis.yml'], {
child = spawn(process.execPath, ['--expose-internals', acpBin, '--config', './cordis.yml'], {
cwd: consumer,
// Dummy key: initialize never reaches the model, so it is never used.
env: {
@@ -183,7 +183,7 @@ describe.skipIf(!existsSync(acpBin))('dsh-acp-agent BUILT bin (node lib/bin.js,
/** Spawn the built acp bin against `configArg` and resolve with its exit code + stderr. */
function runBinExpectingExit(configArg: string, cwd: string = tmpdir()): Promise<{ code: number; stderr: string }> {
return new Promise((resolve, reject) => {
const proc = spawn(process.execPath, ['--expose-internals', acpBin, configArg], {
const proc = spawn(process.execPath, ['--expose-internals', acpBin, '--config', configArg], {
cwd,
env: {
...process.env,
+1 -1
View File
@@ -82,7 +82,7 @@ async function boot(): Promise<Spawned & { cwd: string }> {
await writeFile(configPath, CORDIS_YML)
const child = spawn(
process.execPath,
['--import', tsxLoader, binScript, configPath],
['--import', tsxLoader, binScript, '--config', configPath],
{
cwd,
env: {