Merge origin/master into feat/website-docs

Conflict resolution notes:
- package.json/run-gates: both sides' new doc-sync gates kept (master's
  scoped-events/readme gates + this branch's website-api/website-yaml);
  js-yaml devDeps deduped (master added them independently).
- pnpm-workspace/knip: website AND python/sdk-runtime entries kept.
- doc-typecheck/verify-type-equiv: master's condensed headers kept, website
  glob retained in both scan scopes.
- vendor/cordis/src/fiber.ts: master's lifecycle-hardening code taken; this
  branch's richer FiberState JSDoc reapplied on top. vendor/README.md logs
  both local modifications (hardening = 6, JSDoc enrichment = 7).
- pnpm-lock: regenerated from master's side (pnpm install).

Post-merge sync the gates forced (the system working as designed):
- verify-website-yaml caught 4 stale plugin names from master's package
  reorg (dsh-stdio-agent -> dsh-stdio-demo, dsh-acp-agent -> dsh-acp-demo);
  8 references fixed across guide/ and develop/.
- gen-website-api picked up master's 6 new services automatically
  (ctx.approval/permission/sandbox/sessionQuery/skills/tasks -> 6 new pages
  + sidebar); api/index.md hub updated to list them.
- AGENTS.md budget ceiling 1370 -> 1400: the website rows (layout line + two
  command lines) and master's own growth collided with the old ceiling; all
  three website rows are load-bearing (new top-level dir, new CI command).
This commit is contained in:
lintianle
2026-07-16 21:36:43 +08:00
1132 changed files with 71533 additions and 19566 deletions

View File

@@ -4,13 +4,9 @@
`CompactService` (abstract seam) — provided by `@deepseek-ai/dsh-compact`.
Abstract compaction service. Subclass implement the two abstract methods, and load the subclass as a plugin — it registers as `ctx.compact` (one implementation per context; loading a second throws, which is cordis' standard duplicate-service behavior).
Both core methods are abstract: the contract states WHAT compaction does, while the entire strategy — token estimation, retention policy, event sequencing, summarization — is a HOW decision owned by the implementation.
Implementations MUST honor:
- **Surface contract**: a successful compaction shadows the compacted surface nodes with a SINGLE replacement node carrying the summary. Because `SurfaceEventType` is a closed union, that node is a `user/message` with `surfaceOp: { op:'replace', start, end }`; the `compact/*` events are log-only (lock + provenance).
- **Blocking**: no compaction begins while another is in progress for the same session. The recommended mechanism is the log-recorded lock — append `compact/start` before the slow work and `compact/end` after (even on failure) — so the lock is visible to replay and crash recovery.
Abstract compaction service. Implementations own token estimation, retention, and summarization, but a successful run must replace the selected surface span with one summary node and prevent concurrent compaction of the same session. Load one implementation per context as `ctx.compact`.
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L65)
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L36)
### ctx.compact.compactIfNeeded(agent, fullSystemPrompt, sessionPrefix, signal)
@@ -18,21 +14,16 @@ Implementations MUST honor:
abstract compactIfNeeded( agent: CompactAgentContext, fullSystemPrompt: string, sessionPrefix: readonly Message[], signal: AbortSignal, ): Promise<CompactionResult | null>
```
Check token pressure and compact if the conversation is too large.
Estimates the NEXT request's size — the session prefix, the surface-derived history, and the system prompt — and if it exceeds the backend's threshold, compacts an older range via compactRegion, keeping recent context intact. Returns `null` when no compaction is needed.
Scope and guarantees a backend MUST honor:
- **Compaction acts on surface-derived history only**, but the ESTIMATE counts everything the request carries: the loop composes the session prefix before the pre-step seam fires and hands it here, so the gate sees the prefix this instance will actually send (`EpochHeader.messagePrefix` — request-only, never derived history). Non-surface context injected downstream (into the request `messages` by a later listener) is out of this accounting by construction.
- **Head-anchored, best-effort.** Auto-compaction consolidates from the surface HEAD up to a balanced tool-pairing cutoff, so a prior head checkpoint is re-summarized into one fresh checkpoint (the surface holds at most one auto-generated checkpoint, always at the head). It is best-effort over CLOSED steps: when the only compactable content left is an un-splittable open tail step, it declines (`null`) and retries once that step closes.
- **Single-unit overflow is out of scope.** If a single retained unit (one closed step, or a large free node such as a pasted `user/message`) ALONE exceeds the budget, compaction cannot help and the call may go out over-budget. Bounding an individual unit's size is a separate concern — as is a session prefix that alone approaches the window (a configuration error no compactor fixes: compaction cannot shrink the prefix).
Check token pressure and compact if the conversation is too large. Estimate the next request, including its session prefix, derived history, and system prompt. Above threshold, compact a head-anchored range ending at a balanced tool boundary and reconsolidate any prior automatic checkpoint. Return `null` when no compaction is needed or an open tail leaves no safe cutoff. A single oversized retained unit or prefix cannot be repaired here.
- `agent` — agent context owning the session surface and model options.
- `fullSystemPrompt` — assembled system prompt, counted toward the estimate.
- `sessionPrefix` — the instance's composed session prefix, counted toward the estimate.
- `signal` — cancellation signal. A backend summarizing via `ctx.llm.stream()` MUST forward this into the call's `GenerateOptions.signal` so an abort/dispose tears down the in-flight summarization rather than leaving an orphaned model call running past the cancellation.
- `signal` — cancellation signal; model-backed implementations must forward it.
**Returns** the compaction result, or `null` if no compaction was needed.
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L111)
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L56)
### ctx.compact.compactRegion(session, start, end, agent, signal?)
@@ -40,16 +31,14 @@ Scope and guarantees a backend MUST honor:
abstract compactRegion( session: Session, start: number, end: number, agent: CompactAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>
```
Forcibly compact a range of surface nodes into a single summary node.
`start` and `end` are inclusive seqs of surface nodes to shadow; the backend summarizes their content and appends a replacement surface node. Used by the (future) `/compact` tool and internally by compactIfNeeded.
The region MUST NOT split a step's `assistant/message` tool-calls from their `tool/result`s, leaving the rehydrated transcript with a dangling tool-call or an orphaned tool-result that every provider rejects. A region is safe iff both its edges are balanced cuts on the surface: the cut before `start` and the cut after `end` each have no unanswered tool-call before them. A node that belongs to no step (a pre-step user message, inter-step steering, or an injection context message) is a balanced (free) boundary; an `end` inside an open (unclosed) tail step is invalid — its tool-calls have no results yet. `dsh-session` exports `isToolPairingBalanced` for this check.
Forcibly compact a range of surface nodes into a single summary node. `start` and `end` name an inclusive span by surface position, not numeric seq order; replacements can make visible seqs non-monotonic. Both edges must be balanced so assistant tool calls remain paired with their results. A model- backed implementation forwards cancellation and rejects active, missing, reversed, or unbalanced ranges.
- `session` — the session whose surface is mutated.
- `start` — inclusive seq of the first surface node to compact.
- `end` — inclusive seq of the last surface node to compact.
- `agent` — agent context used by router-aware summarizers.
- `signal` — optional cancellation signal. A backend that summarizes via `ctx.llm.stream()` MUST forward this into the call's `GenerateOptions.signal` so an abort/dispose tears down the in-flight summarization rather than leaving an orphaned model call running past the cancellation.
- `session` — session to mutate.
- `start` — first surface seq, inclusive.
- `end` — last surface seq, inclusive.
- `agent` — summarizer context.
- `signal` — optional cancellation; model-backed implementations must forward it.
**Returns** what the compaction did (the replaced range and its summary node).
**Returns** the replaced range and summary.
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L151)
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L79)