docs: rebalance prose cleanup and add trimming skill

This commit is contained in:
Tianyi Cui
2026-07-13 23:27:00 +08:00
parent fcdc318dda
commit 148046b9c8
392 changed files with 2801 additions and 1754 deletions

View File

@@ -1,8 +1,10 @@
#!/usr/bin/env node
/**
* The `dsh-acp-agent` bin: boot the ACP server from a leaf `cordis.yml` that loads the {@link
* @deepseek-ai/dsh-acp-agent} app plugin (plus an LLM adapter and a bash executor), speaking
* ACP JSON-RPC on stdio.
* Boot an ACP stdio server from `cordis.yml`; usage is `dsh-acp-agent [config]`, defaulting to the
* cwd file. Shared env loading, Loader guards, snapshot config selection, and settled-tree boot live
* in dsh-app-boot. Replay skips `.env` and selects sibling `cordis.snapshot.yml` so a stray key
* cannot trigger a model call. EOF disposes and flushes snapshot runs; editors normally own process
* lifetime. Stdout is reserved for JSON-RPC—write diagnostics only to stderr.
* @module @deepseek-ai/dsh-acp-agent/bin
*/

View File

@@ -2,6 +2,10 @@
* The ACP server app: the default agent spine ({@link @deepseek-ai/dsh-agent-core}) plus the
* coupled front-door cluster an ACP server needs — JSONL session persistence and the {@link
* @deepseek-ai/dsh-acp} bridge, and deliberately NOTHING that writes to stdout.
* It pre-creates no agents and leaves adapters, executors, and optional tools to
* the leaf, which must likewise avoid stdout loggers. Named exports are
* required so Loader retains this plugin's `Config` schema (see
* docs/postmortem/0001).
* @module @deepseek-ai/dsh-acp-agent
*/

View File

@@ -139,7 +139,8 @@ describe('dsh-acp-agent composition', () => {
})
it('has the namespace-plugin export shape (no stray default) so the Loader keeps name/Config/apply', () => {
// Loader must retain the namespace so name, Config, and apply survive unwrapping.
// A default export would make `unwrapExports` collapse this inject-less namespace and silently
// drop `name`/`Config` while the app still boots. Guard the postmortem-0001 shape directly.
expect('default' in acpAgent).toBe(false)
expect(typeof acpAgent.apply).toBe('function')

View File

@@ -18,9 +18,10 @@ import { Readable, Writable } from 'node:stream'
import { afterEach, describe, expect, it } from 'vitest'
/**
* Built-ARTIFACT smoke for the published `dsh-acp-agent` bin. `load-path.e2e.ts` boots
* `src/bin.ts` under tsx — but the package's `bin` field points at `lib/bin.js`, run under
* plain `node` by a real consumer.
* Published-entry smoke: run `lib/bin.js` under plain Node in a symlinked external consumer and
* require a valid initialize response. This catches built-only settle races and stdout protocol
* leaks that the tsx source-path smoke cannot. It skips before build; initialize is keyless, with a
* dummy key used only to boot the adapter. `--expose-internals` enables Cordis bare-plugin loading.
*/
const repoRoot = fileURLToPath(new URL('../../../../', import.meta.url))
@@ -37,7 +38,8 @@ const vendorPackages = [
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
'schemastery', 'cosmokit',
]
// Third-party deps the ACP bridge needs at runtime.
// Resolve ACP's declared third-party dependencies from that package, not this test: pnpm's strict
// layout need not hoist them. Symlink those exact paths into the plain-Node consumer.
const npmDeps = ['@agentclientprotocol/sdk', 'zod']
const acpPkgDir = join(repoRoot, 'packages/ui/acp')
@@ -145,7 +147,8 @@ describe.skipIf(!existsSync(acpBin))('dsh-acp-agent BUILT bin (node lib/bin.js,
}, 30_000)
it('fails LOUD (non-zero exit + stderr) on a config whose directory does not exist', async () => {
// A typo'd config path must fail clearly, not exit 0.
// A nonexistent directory prevents even the include plugin import. Loader logs the failure and
// leaves no fiber; boot's settled-entry guard must convert that state into non-zero exit.
const { code, stderr } = await runBinExpectingExit('/nonexistent/dir/cordis.yml')
expect(code).not.toBe(0)
expect(stderr).toContain('failed to load')

View File

@@ -17,9 +17,11 @@ import {
} from '@agentclientprotocol/sdk'
/**
* real-load-path smoke for @deepseek-ai/dsh-acp-agent: boot the app through its own `bin` (the
* demo:acp entry) as a subprocess, driving the cordis Loader and `unwrapExports` over a
* minimal `cordis.yml` that loads THIS package.
* Source-path Loader smoke through the package's own bin, covering initialize, session/new, and
* session/load across the `unwrapExports` path implicated by postmortem 0001. Session creation and
* unknown-id loading reach factories but not the model, so a dummy key is sufficient. The temp cwd
* is also the session workspace, and an explicit root tsconfig keeps unbuilt path aliases resolvable
* when the child starts outside the repository.
*/
const binScript = fileURLToPath(new URL('../src/bin.ts', import.meta.url))
@@ -119,7 +121,9 @@ describe('dsh-acp-agent real-load-path smoke (bin + Loader, keyless)', () => {
expect(sessionId).toBeTruthy()
// session/load reaches the resume FACTORY + persistence without the model: load an UNKNOWN
// id (loading the live `sessionId` would correctly reject as "already loaded").
// id (loading the live `sessionId` would correctly reject as "already loaded"). Persistence
// and resume run from the JSON-RPC loop outside bridge injection; a healthy tree reaches
// not-found, while a collapsed export would fail earlier with missing injection.
const unknownId = '00000000-0000-4000-8000-000000000000'
await client.loadSession({ sessionId: unknownId, cwd, mcpServers: [] }).then(
() => { throw new Error('expected session/load of an unknown id to reject') },