Merge latest origin/master into parallel-tool-call
# Conflicts: # docs/architecture.md # examples/acp-agent/tests/snapshots/bash-spill/session.jsonl # examples/acp-agent/tests/snapshots/escalation-approved/session.jsonl # examples/acp-agent/tests/snapshots/escalation-rejected/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # packages/core/agent-loop/src/loop.ts
This commit is contained in:
@@ -98,6 +98,10 @@
|
||||
"text": "ctx.tasks",
|
||||
"link": "/zh-CN/api/harness/tasks"
|
||||
},
|
||||
{
|
||||
"text": "ctx.tokenMeter",
|
||||
"link": "/zh-CN/api/harness/token-meter"
|
||||
},
|
||||
{
|
||||
"text": "ctx.tools",
|
||||
"link": "/zh-CN/api/harness/tools"
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
`CompactService` (abstract seam) — provided by `@deepseek-ai/dsh-compact`.
|
||||
|
||||
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`.
|
||||
Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents 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#L37)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L38)
|
||||
|
||||
### ctx.compact.compactIfNeeded(agent, fullSystemPrompt, sessionPrefix, signal)
|
||||
|
||||
@@ -23,7 +23,7 @@ Check token pressure and compact if the conversation is too large. Estimate the
|
||||
|
||||
**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#L57)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L58)
|
||||
|
||||
### ctx.compact.compactRegion(session, start, end, agent, signal?)
|
||||
|
||||
@@ -31,14 +31,14 @@ Check token pressure and compact if the conversation is too large. Estimate the
|
||||
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` 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. Use toolPairingBalancedBefore and toolPairingBalancedAfter for the edge checks.
|
||||
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. The agent must own the exact target session object; implementations reject an ownership mismatch before model resolution, lock acquisition, summarization, or log mutation, and reject active, missing, reversed, or unbalanced ranges. Use toolPairingBalancedBefore and toolPairingBalancedAfter for the edge checks.
|
||||
|
||||
- `session` — session to mutate.
|
||||
- `session` — session to mutate; must be identical to `agent.session`.
|
||||
- `start` — first surface seq, inclusive.
|
||||
- `end` — last surface seq, inclusive.
|
||||
- `agent` — summarizer context.
|
||||
- `agent` — owner of the target session and summarizer context.
|
||||
- `signal` — optional cancellation; model-backed implementations must forward it.
|
||||
|
||||
**Returns** the replaced range and summary.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L82)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact/src/index.ts#L85)
|
||||
|
||||
@@ -18,7 +18,7 @@ A fully configured agent and live session were published. Setup is composition-o
|
||||
|
||||
- `agent` — the newly registered agent with its live session and completed setup. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L153)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L154)
|
||||
|
||||
### agent/disposed
|
||||
|
||||
@@ -32,7 +32,7 @@ An agent left the registry; AgentLoop emits this after driver quiescence but bef
|
||||
|
||||
- `agent` — the exact agent removed from the registry. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L162)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L163)
|
||||
|
||||
### agent/error
|
||||
|
||||
@@ -49,7 +49,7 @@ A step or turn errored. The loop reports a failure here (plus the logger) even w
|
||||
- `step` — the step at which the failure surfaced.
|
||||
- `error` — the failure, verbatim. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L297)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L298)
|
||||
|
||||
### agent/pre-step
|
||||
|
||||
@@ -68,7 +68,7 @@ Awaited serial checkpoint for session-surface mutation after prompt assembly and
|
||||
- `sessionPrefix` — the frozen request prefix.
|
||||
- `signal` — the turn abort signal.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L216)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L217)
|
||||
|
||||
### agent/prompt-submit
|
||||
|
||||
@@ -84,7 +84,7 @@ Allow, rewrite, or block one drained prompt before it becomes a user message. Ca
|
||||
- `content` — the drained message's blocks, as queued.
|
||||
- `source` — the message's resolved source. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L226)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L227)
|
||||
|
||||
### agent/queued
|
||||
|
||||
@@ -100,7 +100,7 @@ Detached, frozen content entered the agent's inbox. Source defaults have already
|
||||
- `content` — the accepted content blocks retained by the inbox.
|
||||
- `info` — the accepted source plus whether it entered as steering. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L181)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L182)
|
||||
|
||||
### agent/request
|
||||
|
||||
@@ -117,7 +117,7 @@ Replace the frozen call configuration. Model-visible content must use logged cha
|
||||
- `step` — the step whose request this is.
|
||||
- `config` — the config the loop would use (frozen); return a replacement to switch. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L238)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L239)
|
||||
|
||||
### agent/session-prefix
|
||||
|
||||
@@ -133,7 +133,7 @@ Compose request-only messages placed before derived history. The frozen result i
|
||||
- `prefix` — the frozen seed; return an extended replacement.
|
||||
- `signal` — aborts composition when the step is torn down.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L253)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L254)
|
||||
|
||||
### agent/session-start
|
||||
|
||||
@@ -148,7 +148,7 @@ The session lifecycle began, once before the first turn. Use `agent.inject()` to
|
||||
- `agent` — the agent whose session lifecycle began.
|
||||
- `source` — why the session started (fresh startup, resume, …). Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L194)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L195)
|
||||
|
||||
### agent/status
|
||||
|
||||
@@ -163,7 +163,7 @@ Agent status changed (`idle` ⇄ `running`, or → `disposed`). `send()` does no
|
||||
- `agent` — the agent whose status flipped.
|
||||
- `status` — the status just entered (the transition's destination). Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L171)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L172)
|
||||
|
||||
### agent/step-result
|
||||
|
||||
@@ -180,7 +180,7 @@ Waterfall: post-process the assembled assistant Message before tool dispatch (va
|
||||
- `step` — the step that produced the message.
|
||||
- `message` — the assistant message as assembled from the stream. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L264)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L265)
|
||||
|
||||
### agent/turn-continuation
|
||||
|
||||
@@ -196,7 +196,7 @@ Override whether the turn continues. The default continues after tool calls or s
|
||||
- `turn` — the turn being continued or stopped.
|
||||
- `defaultDecision` — what the loop would do absent an override. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L274)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L275)
|
||||
|
||||
### agent/turn-stop
|
||||
|
||||
@@ -211,7 +211,7 @@ Monotonic terminal-stop checkpoint after continuation and steering are folded; a
|
||||
- `agent` — the agent whose composed continuation outcome may be stopped.
|
||||
- `turn` — the turn at its terminal-stop checkpoint. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L284)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/agent/src/types.ts#L285)
|
||||
|
||||
## approval/*
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
In-memory session store (`ctx.sessions`).
|
||||
Persistence is intentionally not implemented here — persistence plugins subscribe to `session/event` and flush on `session/flush` / dispose.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L566)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L580)
|
||||
|
||||
### ctx.sessions.create(id?, options?)
|
||||
|
||||
@@ -23,7 +23,7 @@ For an agent whose session must be torn down IN ORDER with its loop (so the loop
|
||||
|
||||
**Returns** the live session, already entered and announced.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L595)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L609)
|
||||
|
||||
### ctx.sessions.prepare(id?, options?)
|
||||
|
||||
@@ -38,7 +38,7 @@ Build a session WITHOUT entering it into the store — validate the id/cwd and c
|
||||
|
||||
**Returns** the constructed session, NOT yet in the store.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L624)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L638)
|
||||
|
||||
### ctx.sessions.enter(session)
|
||||
|
||||
@@ -53,7 +53,7 @@ Re-checks the id for a duplicate: `prepare` and `enter` are public cross-package
|
||||
|
||||
**Returns** the detach disposer (publication hooks + store removal). When called from a synchronous `session/created` listener, removal and disposal wait until that creation dispatch unwinds.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L668)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L682)
|
||||
|
||||
### ctx.sessions.announce(session)
|
||||
|
||||
@@ -65,7 +65,7 @@ Emit `session/created` exactly once for an entered session (with the carrier ent
|
||||
|
||||
- `session` — the entered session to announce to listeners.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L723)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L737)
|
||||
|
||||
### ctx.sessions.flush(session)
|
||||
|
||||
@@ -79,7 +79,7 @@ Dispatch the awaited `session/flush` durability checkpoint for `session`, with t
|
||||
|
||||
**Returns** resolves when every flush listener has settled; after all settle, rejects with the first registered listener failure if any listener failed.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L775)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L789)
|
||||
|
||||
### ctx.sessions.get(id)
|
||||
|
||||
@@ -93,7 +93,7 @@ Look up a live session.
|
||||
|
||||
**Returns** the session, or undefined when no live session has that id.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L807)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L821)
|
||||
|
||||
### ctx.sessions.list()
|
||||
|
||||
@@ -105,7 +105,7 @@ All live sessions, in creation order.
|
||||
|
||||
**Returns** a fresh array; mutating it does not affect the store.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L815)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L829)
|
||||
|
||||
### ctx.sessions.fork(source, boundary?, childSessionId?)
|
||||
|
||||
@@ -121,4 +121,4 @@ Create a live child session from a turn-enclosed prefix of a live source. `bound
|
||||
|
||||
**Returns** The created live child session.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L832)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/core/session/src/index.ts#L846)
|
||||
|
||||
50
website/zh-CN/api/harness/token-meter.md
Normal file
50
website/zh-CN/api/harness/token-meter.md
Normal file
@@ -0,0 +1,50 @@
|
||||
<!-- Generated by scripts/gen-website-api.ts — do not edit by hand. Run `pnpm run gen-website-api` to regenerate. -->
|
||||
|
||||
# ctx.tokenMeter
|
||||
|
||||
`TokenMeterService` — provided by `@deepseek-ai/dsh-token-meter`.
|
||||
|
||||
Replay owner for one service-wide estimator and isolated per-session folds.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/llm/token-meter/src/index.ts#L106)
|
||||
|
||||
### ctx.tokenMeter.contextWindow
|
||||
|
||||
```ts website-api
|
||||
readonly contextWindow: number
|
||||
```
|
||||
|
||||
Provider context-window capacity used by pressure consumers.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/llm/token-meter/src/index.ts#L112)
|
||||
|
||||
### ctx.tokenMeter.measure(session, requestHeader?)
|
||||
|
||||
```ts website-api
|
||||
measure(session: Session, requestHeader?: EpochHeader): TokenMeasurement
|
||||
```
|
||||
|
||||
Measure current request pressure and surface through the durable tail.
|
||||
Provider usage is reused only when the latest successful call's canonical request envelope matches `requestHeader` and its total is no lower than that call's full heuristic anchor; otherwise the complete envelope and surface are heuristically repriced.
|
||||
`requestHeader` affects request pressure only; surface fields always describe the current session surface. Every call clones those positional nodes, so measurement is O(surface).
|
||||
|
||||
- `session` — session to replay through its current durable tail.
|
||||
- `requestHeader` — optional effective request envelope replacing the latest logged header.
|
||||
|
||||
**Returns** a detached deeply immutable pressure and surface measurement.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/llm/token-meter/src/index.ts#L143)
|
||||
|
||||
### ctx.tokenMeter.estimateMessage(message)
|
||||
|
||||
```ts website-api
|
||||
estimateMessage(message: Message): number
|
||||
```
|
||||
|
||||
Heuristically price one model-visible message.
|
||||
|
||||
- `message` — message to price without mutation.
|
||||
|
||||
**Returns** content and role-framing tokens under the fixed service heuristic.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/llm/token-meter/src/index.ts#L181)
|
||||
@@ -84,14 +84,18 @@ Harness 使用 `cordis.yml` 描述一个 Agent 加载哪些插件、以什么参
|
||||
You are coding-agent, a coding assistant powered by the {{model}} model.
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
# Token 计量:统一定义模型能看到的 token 上限
|
||||
- id: token-meter
|
||||
name: '@deepseek-ai/dsh-token-meter'
|
||||
config:
|
||||
contextWindow: 128000
|
||||
|
||||
# 自动压缩:对话太长时自动总结旧内容,腾出上下文空间
|
||||
# contextWindow 是模型能看到的 token 上限
|
||||
# thresholdRatio 超过这个比例就触发压缩
|
||||
# compactionRetries 是压缩后仍超标时的额外重试次数
|
||||
- id: compact-basic
|
||||
name: '@deepseek-ai/dsh-compact-basic'
|
||||
config:
|
||||
contextWindow: 128000
|
||||
thresholdRatio: 0.8
|
||||
retainTokens: 20480
|
||||
maxTokens: 8192
|
||||
@@ -214,8 +218,6 @@ config:
|
||||
- id: compact-basic
|
||||
name: '@deepseek-ai/dsh-compact-basic'
|
||||
disabled: true
|
||||
config:
|
||||
contextWindow: 128000
|
||||
```
|
||||
|
||||
## 各插件配置参考
|
||||
|
||||
Reference in New Issue
Block a user