docs: trim generated prose

This commit is contained in:
Tianyi Cui
2026-07-12 03:36:43 +08:00
parent 3dca90261c
commit 75838e10b5
323 changed files with 2857 additions and 11833 deletions

View File

@@ -1,47 +1,5 @@
/**
* The default executor-less, UI-less agent spine as ONE bundle plugin.
*
* Loads the fixed set of services every harness agent needs — `timer`, the LLM
* service, the session store, system-prompt assembly, the tool registry, the
* skill registry plus local skill provider, the agent registry, the dev-mode
* invariants, the model-facing `bash` and `skill` tool schemas, and the concrete `agent-loop` — and forwards the loop's `agents`
* list as its OWN config (default `[]`), so each app supplies its own
* pre-created agents.
*
* It is deliberately NOT the whole app: the swappable choices stay OUTSIDE the
* bundle, picked by whatever loads it.
* - the LLM ADAPTER (`llm-deepseek`/`llm-pi-ai`/`llm-replay`) — the bundle
* ships the abstract `llm` service + `tool-bash` consumer schema; the leaf
* registers a concrete adapter on `ctx.llm`.
* - the bash EXECUTOR (`bash-local` or a sandboxed impl) — the bundle ships
* the `bash` tool consumer; the leaf provides `ctx.bash`.
* - the PRESENTATION (stdio UI / ACP bridge / a logger) and the per-app infra
* (a console logger, `hmr`) — these are the coupled "front-door cluster" the
* app packages ({@link @deepseek-ai/dsh-stdio-agent},
* {@link @deepseek-ai/dsh-acp-agent}) bake in, NOT the shared spine.
* - additional SKILL PROVIDERS; the bundle ships the local filesystem provider
* because local skills are default agent behavior, while embedded or remote
* providers remain deployment choices.
*
* This is the interface/implementation/consumer seam at the composition level:
* the bundle owns the shared spine, the leaf owns the backends, the app package
* owns the front door. `timer` is in the spine (common to every front door — it
* writes nothing to stdout); the console logger is NOT (it writes to stdout,
* which the ACP bridge reserves for its JSON-RPC channel).
*
* Services register in the root store keyed by their isolate symbol, so a child
* loaded here via `ctx.plugin(...)` is visible to the bundle's SIBLINGS (the
* leaf's adapter and executor) exactly as a nested `plugin-include` subtree's
* services were before this bundle existed — cordis gates every read on
* `inject`, never on load order, so the fixed child set resolves regardless of
* which entry loads first.
*
* Plugin export shape: named `name`/`Config`/`apply`, NO default export — the
* cordis Loader's `unwrapExports` does `exports.default ?? exports`, so a stray
* default would collapse the module to the bare `apply` function and drop the
* `Config` schema (see docs/postmortem/0001). The keyless Loader-path smokes in
* the app packages guard this end-to-end.
*
* The default executor-less, UI-less agent spine as one bundle plugin.
* @module @deepseek-ai/dsh-agent-core
*/
@@ -73,16 +31,11 @@ export interface SkillConfig {
}
/**
* Bundle config: each field forwarded verbatim to the child that owns it —
* `agents` to the agent loop (an app that pre-creates no agents, like the ACP
* bridge, simply omits it), `persona` and `toolOrder` to the system-prompt
* plugin (the deployment's persona section and the explicit model-facing tool
* order), the `tools` object to the tool registry (its presentation `mode`),
* and `skills` to the skill registry/local provider/tool consumer. Every field
* is optional INPUT here because each owner's schema supplies the default;
* the schema is the INTERSECTION of the owners' own schemas (with registry
* schemas nested under their bundle keys), so validation and defaulting can
* never drift from them.
* Bundle config: each field forwarded verbatim to the child that owns it — `agents` to the
* agent loop (an app that pre-creates no agents, like the ACP bridge, simply omits it),
* `persona` and `toolOrder` to the system-prompt plugin (the deployment's persona section and
* the explicit model-facing tool order), the `tools` object to the tool registry (its
* presentation `mode`), and `skills` to the skill registry/local provider/tool consumer.
*/
export interface Config {
/** The agent-loop `agents` list (see dsh-agent-loop's `Config`). */
@@ -124,12 +77,7 @@ export function apply(ctx: Context, config: Config): void {
ctx.plugin(Timer)
ctx.plugin(LlmService)
ctx.plugin(SessionStore)
// The forwarded fields are validated + defaulted by this bundle's intersected
// schema before apply runs, so the ?? fallbacks only narrow the
// optional-input TYPES — they mirror the owners' schema defaults, never
// introduce different ones. toolOrder has no owner-supplied default value —
// ABSENT means "lexicographic order" — so it is forwarded conditionally
// rather than via ??.
// Owner schemas resolve defaults; forward toolOrder only when explicitly set.
ctx.plugin(SystemPrompt, {
persona: config.persona ?? '',
...config.toolOrder !== undefined ? { toolOrder: config.toolOrder } : {},

View File

@@ -187,15 +187,7 @@ describe('dsh-agent-core bundle', () => {
})
it('has the namespace-plugin export shape (no stray default) so the Loader keeps name/Config/apply', () => {
// Postmortem 0001 guard: a stray `export default apply` makes the Loader's
// `unwrapExports` (`exports.default ?? exports`) collapse the module to the
// bare `apply` function, DROPPING the named `name`/`Config`. This package has
// no `inject` export (it mounts children that carry their own), so that
// collapse would NOT crash at load — the plugin would boot but silently lose
// its config schema. This bundle is also never Loader-unwrapped by any smoke
// (the apps import it directly; the mount test namespace-mounts it), so this
// is its ONLY export-shape guard. Assert directly AND through the real
// `unwrapExports` so adding `export default` to src/index.ts fails here.
// A default export would make Loader discard this namespace's plugin metadata.
expect('default' in agentCore).toBe(false)
expect(typeof agentCore.apply).toBe('function')

View File

@@ -1,18 +1,5 @@
/**
* Negative-path tests for the config catalog generator (`scripts/gen-config-catalog.ts`).
*
* The generated catalog is frozen by a regenerate-and-diff freshness gate, so
* the freshness half is exercised by `pnpm run verify-config-catalog` in CI.
* What a freshness diff CANNOT prove is that the generator REJECTS malformed
* source the way it promises to — an unclassifiable package, an undocumented
* config field, a schema key the config type does not declare, or a referenced
* type name that resolves nowhere. These tests drive `collectConfigCatalog()`
* against synthetic fixture packages to prove each guard fires (and that
* well-formed packages classify and extract correctly), mirroring the
* negative tests for gen-cordis-catalog. The spec lives in this package
* because agent-core is the config-composition plugin (its schema is the
* intersection of its children's), the shape the generator's cross-package
* folding exists for.
*/
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'