Merge remote-tracking branch 'origin/master' into codex/rfc-subagent-background-tasks
# Conflicts: # docs/architecture.md # docs/config-catalog.md # docs/cordis-catalog/services.md # docs/core-data-structures/bash.md # docs/event-producer-consumer.md # docs/rfc/implemented/feature/2026-07-06-sandbox.md # docs/rfc/proposed/architecture/2026-06-20-generic-long-running-tool-runtime.md # examples/AGENTS.md # examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.golden.md # examples/acp-agent/tests/snapshots/both-mode-turn/session.jsonl # examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.golden.md # examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.golden.md # examples/acp-agent/tests/snapshots/permission-switching/system-prompt.golden.md # examples/acp-agent/tests/snapshots/skill-load/session.jsonl # examples/acp-agent/tests/snapshots/skill-load/system-prompt.golden.md # examples/acp-agent/tests/snapshots/text-turn/session.jsonl # examples/acp-agent/tests/snapshots/text-turn/system-prompt.golden.md # examples/coding-agent/cordis.yml # examples/sandbox-acp-agent/tests/snapshots/escalation-approved/session.jsonl # examples/sandbox-acp-agent/tests/snapshots/escalation-rejected/session.jsonl # examples/sandbox-acp-agent/tests/snapshots/mode-switching/session.jsonl # packages/bash/bash-local/README.md # packages/bash/bash-local/src/index.ts # packages/bash/bash-local/tests/executor.spec.ts # packages/bash/bash-sandbox/README.md # packages/bash/bash-sandbox/src/index.ts # packages/bash/bash/README.md # packages/bash/bash/src/index.ts # packages/bash/bash/src/types.ts # packages/bash/tool-bash/README.md # packages/bash/tool-bash/src/index.ts # packages/bash/tool-bash/tests/tools.spec.ts # packages/cordis/tool-cordis/src/api-catalog.ts # packages/core/agent-core/README.md # packages/core/agent-core/src/index.ts # packages/subagent/subagent/README.md # packages/subagent/tool-subagent/README.md # packages/subagent/tool-subagent/src/index.ts # packages/ui/acp-agent/README.md # packages/ui/acp/README.md # packages/ui/stdio-agent/README.md # packages/util/brand/src/index.ts # scripts/doc-budgets.manifest.json
This commit is contained in:
+12
-50
@@ -1,36 +1,9 @@
|
||||
/**
|
||||
* Generate (and verify) the tool-schema catalog in docs/tool-catalog.md.
|
||||
*
|
||||
* The catalog is the MODEL-FACING TOOL reference: every tool a shipped plugin
|
||||
* contributes to `ctx.tools`, with the exact `name` / `description` / JSON-Schema
|
||||
* `parameters` the model receives via the system-prompt assembly. It complements
|
||||
* the cordis events/services catalog (the wiring a plugin author works against)
|
||||
* and the core-data-structures catalog (the vocabulary those signatures move):
|
||||
* this page is the TOOLS the agent is offered.
|
||||
*
|
||||
* `tsx scripts/gen-tool-catalog.ts` → write the catalog
|
||||
* `tsx scripts/gen-tool-catalog.ts --check` → exit 1 if the committed file
|
||||
* is stale (CI / pre-push gate)
|
||||
*
|
||||
* Why this generator BOOTS PLUGINS instead of parsing source (unlike its AST
|
||||
* sibling `gen-cordis-catalog.ts`): a tool's schema is not statically knowable.
|
||||
* `tool-todo` writes `enum: [...STATUSES]` (a runtime spread), descriptions are
|
||||
* built by string concatenation, `tool-subagent`'s tool name is `config.toolName`,
|
||||
* and an MCP plugin can register RAW JSON Schema without `defineTool` at all. The
|
||||
* faithful source of truth is therefore the SHIPPED schema: mount each tool
|
||||
* plugin on a real cordis Context and read `ctx.tools.schemas()` — exactly the
|
||||
* `ToolSchema[]` the model is sent. See
|
||||
* docs/rfc/implemented/process/2026-07-02-tool-schema-catalog.md.
|
||||
*
|
||||
* Booting sacrifices the AST pass's structural "nothing can be silently omitted"
|
||||
* property (there is no source declaration to enumerate), so a COMPLETENESS GUARD
|
||||
* restores it: the generator globs every `tool-*` package under `packages/` and
|
||||
* hard-errors if any such package is absent from the boot manifest below. A new
|
||||
* tool package fails the generator — and thus the freshness gate — until it is
|
||||
* registered here, mirroring how a new event appears in the cordis regenerate.
|
||||
*
|
||||
* Schema blocks use a plain ` ```json ` fence: doc-typecheck only extracts `ts*`
|
||||
* fences, so no BlockKind wiring is needed there.
|
||||
* Generate `docs/tool-catalog.md` from schemas collected by booting each tool
|
||||
* plugin. Runtime registration is the source of truth for computed schemas;
|
||||
* the manifest is checked against every on-disk `tool-*` package. `--check`
|
||||
* verifies the committed artifact. Rationale and ownership live in
|
||||
* `docs/rfc/implemented/process/2026-07-02-tool-schema-catalog.md`.
|
||||
*/
|
||||
|
||||
import { globSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
@@ -66,17 +39,9 @@ const root = resolve(import.meta.dirname, '..')
|
||||
const OUT = 'docs/tool-catalog.md'
|
||||
|
||||
/**
|
||||
* One tool-plugin package to boot. `mount` is a per-entry recipe (async): it
|
||||
* plugs the injected seams the plugin's `apply` reads (an executor for
|
||||
* `ctx.bash`, a provider for `ctx.subagents`) BEFORE the tool plugin itself.
|
||||
* `SystemPrompt` + `ToolRegistry` are mounted for every entry by the caller
|
||||
* (`ToolRegistry` injects `systemPrompt`), so `mount` only handles the extras.
|
||||
*
|
||||
* The recipe is irreducible policy — WHICH seams a given tool needs and with
|
||||
* WHAT config is not derivable from the package layout — so it stays a hand-
|
||||
* maintained closure. The `dir` field is what the completeness guard matches
|
||||
* against the on-disk `tool-*` package glob, so a NEW tool package cannot be
|
||||
* silently omitted (see the module doc).
|
||||
* Tool package plus its hand-maintained boot recipe. The caller mounts the
|
||||
* prompt and registry; each recipe supplies only package-specific seams and
|
||||
* config, while `dir` participates in the completeness check.
|
||||
*/
|
||||
interface ToolPackage {
|
||||
/** The npm package name, used as the catalog section heading. */
|
||||
@@ -176,9 +141,8 @@ const TOOL_PACKAGES: ToolPackage[] = [
|
||||
requires: ['ctx.tools', 'ctx.fs', 'ctx.systemPrompt'],
|
||||
writes: ['tool/call', 'fs/write-intent or fs/edit-intent for mutations', 'fs/observed after successful file operations', 'tool/result'],
|
||||
async mount(ctx) {
|
||||
// The tool injects `fs`; boot the local backend to satisfy it. The schemas
|
||||
// do not depend on the policy plugin (an event gate that changes behavior,
|
||||
// not tool shape), so the bare provider is enough to harvest them.
|
||||
// The tool needs `fs`; the bare provider is sufficient because policy
|
||||
// changes behavior, not schema shape.
|
||||
await ctx.plugin(LocalFileSystem)
|
||||
await ctx.plugin(ToolFs)
|
||||
},
|
||||
@@ -264,10 +228,8 @@ const TOOL_PACKAGES: ToolPackage[] = [
|
||||
requires: ['ctx.tools', 'ctx.web', 'ctx.systemPrompt'],
|
||||
writes: ['tool/call', 'tool/result'],
|
||||
async mount(ctx) {
|
||||
// The tools inject `web`; boot the seam plus one search and one fetch
|
||||
// provider so both `web_search` and `web_fetch` register. The schemas do
|
||||
// not depend on which provider backs the seam (or on it being available),
|
||||
// so any registered provider is enough to harvest them.
|
||||
// Mount search and fetch providers so both tools register. Their schemas
|
||||
// do not depend on provider identity or availability.
|
||||
await ctx.plugin(WebService)
|
||||
await ctx.plugin(WebSearchExa)
|
||||
await ctx.plugin(WebFetchLocal)
|
||||
|
||||
Reference in New Issue
Block a user