docs: document package model experience

This commit is contained in:
Tianyi Cui
2026-07-12 02:12:36 +08:00
parent 3dca90261c
commit 027970043c
75 changed files with 561 additions and 5 deletions

View File

@@ -4,6 +4,13 @@ The **default executor-less, UI-less agent spine** as ONE Cordis bundle plugin.
This is the package to read to see **the whole plugin tree at once** — the teaching role the inlined `echo-agent` `cordis.yml` used to play before the spine moved behind this bundle.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| Composed system prompt and session prefix | Through its children, the bundle supplies the harness identity, configured persona, and the local skill catalog when skills exist. | The bundle adds no wrapper prose; input cost is exactly the sum of the child contributions, repeated on each request according to their lifecycles. |
| Composed tool surface | The `skill` schema is present, and the three bash schemas appear when a bash executor activates `dsh-tool-bash`; `tools` config can select normal, Code Mode, or both. | Fixed per-request schema or SDK cost for the visible composition. Tool results add data-dependent retained history. |
## The tree it loads
`apply(ctx, config)` mounts each of these as a child of the bundle fiber:

View File

@@ -4,6 +4,13 @@ THE concrete agent plugin: `ReactLoopAgent` and the loop driver. Implements the
This is the only package in the harness that contains concrete loop logic. Everything else is an abstract service or a plugin against extension seams — new behavior goes into plugins, not here.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| Complete conversation request | For each step, the loop sends the rendered per-agent system prompt, visible tool schemas, the frozen session prefix, and the session's derived messages. It supplies `model` and `cwd` variable values but no additional fixed prose. | System text, schemas, and prefix are paid again on every step. Per-agent scoping can substitute or remove individual contributions. |
| Retained message history | Accepted user messages, assistant messages, tool calls and results, injected context, and steering are logged and sent on later steps. Raw stream chunks, lifecycle boundaries, and other log-only events are excluded. | Input grows with every surface message until a compaction replacement shadows older nodes; a multi-step tool turn resends the accumulated prefix and history each step. |
## Service: `AgentLoop` (ctx key: `agentLoop`)
### Public API

View File

@@ -2,6 +2,13 @@
Agent interface, registry, and `agent/*` event vocabulary. Every plugin (UI, hooks, orchestrators) programs against the `Agent` handle defined here — it has zero loop dependency, so the loop is swappable.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| User, steering, and injected messages | `send`, `steer`, and `inject` feed the owning session. `agent/prompt-submit`, `agent/session-prefix`, and other declared events let plugins block a prompt or add request material; this interface contributes no fixed prose itself. | Accepted content becomes retained history or a repeated session prefix; blocked content contributes no request tokens. Size is caller- and plugin-dependent. |
| Agent-scoped request composition | Registrations through `agent.ctx` can shadow prompt sections or tools and can install agent-only interceptors during unpublished setup. | The package adds zero tokens itself; scoped contributions affect only that agent and disappear on disposal. |
## Service: `AgentRegistry` (ctx key: `agents`)
Tracks live agents so UI, hook, and orchestrator plugins can find them without importing the concrete loop package.

View File

@@ -2,6 +2,12 @@
Scoped-context registration primitive. `createScope(ctx, key)` mints a Cordis context that TAGS everything registered through it with an opaque `ScopeKey` and OWNS those registrations' lifetime (one backing fiber drives both facts); `scopeOf(ctx)` reads the tag; `scopeTarget(base, key)` builds the dispatch carrier that makes an event scope-filtered — listeners registered through a scoped context fire only for their key's subject, while plain plugin listeners keep firing for every subject. The agent loop is the one scope minter today (one scope per live agent, key = the `Agent` object — the `Agent.ctx` contract in `dsh-agent`), but the mechanism is key-agnostic so packages below the agent layer (`dsh-session`, `dsh-system-prompt`) depend on it without a dependency cycle.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| Per-agent visibility control | This package emits no text or schema. It decides whether agent-scoped prompt sections, variables, tools, restrictions, and listeners apply to one agent, can shadow same-named global contributions, and removes them with that agent. | Zero direct tokens. It can add, replace, or remove whole contributions for one agent without changing another agent's request. |
## Public API
- `createScope(ctx: Context, key: ScopeKey): Scope` Mint a scope under `ctx`'s fiber. Usable synchronously (effect collection is uid-gated; service resolution falls through to the minting plugin's dependency surface). Throws on a primitive key, or when `ctx`'s fiber is disposing (`INACTIVE_EFFECT`).

View File

@@ -2,6 +2,13 @@
Event-sourced session log and in-memory store. A `Session` is the append-only source of truth for an agent's whole interaction history — the LLM message history is *derived* from it. A **surface** layer (a linked list of message-producing events) is maintained on top of the raw log for efficient derivation and compaction.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| Derived message history | The model receives projections of `user/message`, `assistant/message`, `tool/result`, `context/message`, and `steering/message` surface nodes. Tool calls live inside assistant messages. Chunks, boundaries, usage, hook records, todo records, and other log-only events add no message. | Appended surface nodes are resent on later steps. A `replace` surface operation removes the shadowed nodes from future inputs without deleting their raw log records. |
| Logged request header | The session reconstructs the system prompt, tool schemas, call config, and session prefix that the loop actually sent. Header events do not add a second copy to message history; the prefix is prepended outside `deriveMessages()`. | Zero duplicate tokens from logging. The reconstructed prefix, system text, and schemas still incur their normal per-request cost. |
## Service: `SessionStore` (ctx key: `sessions`)
Creates and holds event-sourced `Session` instances. Persistence is intentionally not implemented here — plugins subscribe to `session/event` and flush on `session/flush`.

View File

@@ -2,6 +2,13 @@
System prompt assembly registry. Plugins contribute ordered text sections, tool-schema providers, named prompt variables, and authoritative named protections; the agent loop calls `assemble(context)` once per step, and `renderPrompt(assembly)` is the full system prompt the model sees. The plugin registers the harness-owned openers itself — the static `harness:identity` section and the deployment's `deployment:persona` section — so they exist for every agent regardless of which loop plugin drives it.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| System prompt | Every assembly starts with `You are an AI agent powered by the DeepSeek Harness SDK.`, then the configured persona and ordered plugin sections after strict variable interpolation. Empty sections disappear; scoped sections and variables can shadow globals for one agent. | Identity is a fixed per-request cost. Persona and plugin text are repeated per request and scale with their rendered content. |
| Tool schemas | The model receives the collected, per-agent-visible tool names, descriptions, and JSON schemas in configured or lexicographic order after restrictions and assembly interception. | Schema tokens repeat on every request. Restricting a tool removes its entire schema cost for that agent; reordering changes cache shape but not semantic content. |
## Config
| Key | Default | Meaning |

View File

@@ -2,6 +2,13 @@
Tool registry and execution pipeline. Tool plugins register their schemas and executors; the agent loop executes each call through `tools/pre-execute` (the extensible allow/deny gate) → monotonic registered guards → `tools/execute` (an around-dispatch wrapper for timeout/retry/metrics plugins) → `tools/post-execute` (inspect/replace the result, attach context) → the observe-only `tools/result` notification. The registry also owns HOW its tools are presented to the model — its `mode` config selects native function calling, [Code Mode](#code-mode), or both.
## Model Experience
| Context surface | What the model sees | Token effect |
|---|---|---|
| Tool schemas and Code Mode SDK | In normal mode the model sees each visible definition's name, description, and JSON schema. Code Mode instead protects one `run_code` wire schema and adds a generated TypeScript `tools` SDK section; `both` exposes both forms. Agent-scoped restrictions and shadows change that agent's set. | Fixed per-request cost proportional to the visible definitions. Code Mode trades end-tool schemas for generated SDK text plus one transport schema rather than promising a universal reduction. |
| Tool-call history and results | The loop retains model-emitted arguments and the registry's final normalized content or structured error. Post-execute listeners may append source-attributed context after the result. Code Mode exposes only the outer program's printed or returned value; inner dispatch events stay log-only. | Arguments, results, and additional context are data-dependent and resent until compaction. Restrictions that hide tools also remove their schemas before the model can call them. |
## Service: `ToolRegistry` (ctx key: `tools`)
### Config