diff --git a/packages/compact/compact/README.md b/packages/compact/compact/README.md index 51ba50382f..0e0b63d765 100644 --- a/packages/compact/compact/README.md +++ b/packages/compact/compact/README.md @@ -21,6 +21,8 @@ Both methods are **abstract** — the backend owns the entire strategy (token es | `compactIfNeeded(agent, fullSystemPrompt, sessionPrefix, signal)` | Estimate the surface-derived history size; if over the backend's threshold, compact an older range via `compactRegion`, keeping recent context intact. Returns the `CompactionResult`, or `null` if nothing needed compacting. All parameters required — the loop's `agent/pre-step` checkpoint supplies the agent, assembled `fullSystemPrompt`, composed `sessionPrefix` (request-only messages every request carries but the derived history omits — the pressure estimate must count them), and turn `signal`. A backend's summarization request is a direct `ctx.llm.stream()` call (not a loop step), so per-call interception happens at `llm/stream`. | | `compactRegion(start, end, agent, signal?)` | Forcibly summarize surface nodes `[start, end]` (inclusive seqs) from `agent.session` into a single replacement node. **Throws** if a compaction is already in progress, if `start`/`end` aren't surface nodes, or if `start` is positioned after `end` on the surface. The range is a SURFACE-POSITION span, not a numeric seq interval — after a prior replace lands a fresh high-seq summary node at the shadowed range's position, surface order no longer tracks seq order. | +`CompactionResult` keeps the raw summary and bookkeeping-event seqs available to callers alongside the shadowed range and token accounting; its drift-checked shape lives in the [compaction data-structure reference](../../../docs/core-data-structures/compaction.md#compactionresult). + `compactIfNeeded` takes a required `signal`; `compactRegion`'s is optional. A backend that summarizes via `ctx.llm.stream()` **must** forward it into the call's `GenerateOptions.signal`, so an abort or fiber dispose tears down the in-flight summarization instead of leaving an orphaned model call running past the cancellation. The session being compacted comes from the agent context; the turn that the `compact/*` events belong to is recoverable from the log (the currently-open turn), so the backend stamps it from the log rather than trusting a caller-supplied value. ## Surface contract diff --git a/packages/cordis/tool-cordis/src/api-catalog.ts b/packages/cordis/tool-cordis/src/api-catalog.ts index bfa494f829..25e87b3d02 100644 --- a/packages/cordis/tool-cordis/src/api-catalog.ts +++ b/packages/cordis/tool-cordis/src/api-catalog.ts @@ -259,13 +259,13 @@ export const EVENT_API: readonly EventApiEntry[] = [ name: 'agent/created', mode: 'emit', signature: '\'agent/created\'(this: Scoped, agent: Agent): void', - summary: 'An agent\'s fully composed scoped world was published in the AgentRegistry.', + summary: 'A fully configured agent and live session were published.', }, { name: 'agent/disposed', mode: 'emit', signature: '\'agent/disposed\'(this: Scoped, agent: Agent): void', - summary: 'An agent was removed from the registry.', + summary: 'An agent left the registry; AgentLoop emits this after driver quiescence but before session detachment and scoped-registration unwind.', }, { name: 'agent/error', @@ -277,37 +277,37 @@ export const EVENT_API: readonly EventApiEntry[] = [ name: 'agent/pre-step', mode: 'serial', signature: '\'agent/pre-step\'(this: Scoped, agent: Agent, turn: number, step: number, fullSystemPrompt: string, sessionPrefix: readonly Message[], signal: AbortSignal): Promise | void', - summary: 'Awaited pre-step surface-mutation checkpoint, fired once per step AFTER `turn/start` (and after the prior step closed) but BEFORE this step\'s `step/start` — so anything a listener appends lands OUTSIDE the step, between `turn/start`/`step/end` and the upcoming `step/start`.', + summary: 'Awaited serial checkpoint for session-surface mutation after prompt assembly and before `step/start`; appends land outside the pending step.', }, { name: 'agent/prompt-submit', mode: 'waterfall', signature: '\'agent/prompt-submit\'(this: Scoped, agent: Agent, content: ContentBlock[], source: MessageSource, next: () => Promise): Promise', - summary: 'Waterfall: decide what happens to ONE drained queued message before it becomes a `user/message` — allow (optionally rewriting the prompt bytes or attaching `additionalContext`) or block it.', + summary: 'Allow, rewrite, or block one drained prompt before it becomes a user message.', }, { name: 'agent/queued', mode: 'emit', signature: '\'agent/queued\'(this: Scoped, agent: Agent, content: ContentBlock[], info: { source: MessageSource; steering: boolean }): void', - summary: 'A message entered the agent\'s inbox (queued or steering).', + summary: 'Detached, frozen content entered the agent\'s inbox.', }, { name: 'agent/request', mode: 'waterfall', signature: '\'agent/request\'(this: Scoped, agent: Agent, turn: number, step: number, config: LlmCallConfig, next: () => Promise): Promise', - summary: 'Waterfall: shape the step\'s call configuration — model switching, sampling overrides — by returning a replacement LlmCallConfig (the frozen seed is the config the loop would otherwise use).', + summary: 'Replace the frozen call configuration.', }, { name: 'agent/session-prefix', mode: 'waterfall', signature: '\'agent/session-prefix\'(this: Scoped, agent: Agent, prefix: Message[], signal: AbortSignal, next: () => Promise): Promise', - summary: 'Waterfall: compose the SESSION PREFIX — request-only messages placed in front of the ENTIRE derived history (directly after the provider\'s system slot) on every request this loop instance sends.', + summary: 'Compose request-only messages placed before derived history.', }, { name: 'agent/session-start', mode: 'emit', signature: '\'agent/session-start\'(this: Scoped, agent: Agent, source: SessionStartSource): void', - summary: 'The agent\'s session lifecycle began, fired once before its first turn.', + summary: 'The session lifecycle began, once before the first turn.', }, { name: 'agent/status', @@ -325,13 +325,13 @@ export const EVENT_API: readonly EventApiEntry[] = [ name: 'agent/turn-continuation', mode: 'waterfall', signature: '\'agent/turn-continuation\'(this: Scoped, agent: Agent, turn: number, defaultDecision: ContinuationDecision, next: () => Promise): Promise', - summary: 'Waterfall: override the turn-continuation decision via a typed ContinuationDecision.', + summary: 'Override whether the turn continues.', }, { name: 'agent/turn-stop', mode: 'serial', signature: '\'agent/turn-stop\'(this: Scoped, agent: Agent, turn: number): ContinuationStop | undefined', - summary: 'Serial terminal-stop checkpoint after the ordinary `agent/turn-continuation` waterfall, any `continue.reason`, and the pending-steering continuation override have been folded.', + summary: 'Monotonic terminal-stop checkpoint after continuation and steering are folded; a stop remains authoritative through turn close and flush: steering queued in that window is discarded, while ordinary sends survive.', }, { name: 'approval/request',