@deepseek-ai/dsh-compaction-basic 0.1.5-rc.2 → 0.1.6-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/compaction/compaction-basic/README.md
5
- README.md: f4045f99f55ba77a1f3741717141baa52d94d742
6
- README.zh.md: f8d7f62165ab63215f225550dbc5916bfe7942d6
5
+ README.md: 68d5a321e04a90bfb726392d1fb179612f6e0626
6
+ README.zh.md: f941cac74053a680cad859b68c7836e181065bc9
package/README.md CHANGED
@@ -119,6 +119,8 @@ A direct `ctx.llm.stream()` call uses the configured provider/model pair and cap
119
119
 
120
120
  ### The region transaction
121
121
 
122
+ Failed summary requests dispatch synchronous `compaction/summary-error` after checking cancellation and selection stability. A recovery listener must record a durable input change before requesting retry. The backend re-derives the selected messages and refreshes their token prices and shrink baseline. The image-offload plugin owns image selection; its recorded omissions remain effective if the summary later fails or is cancelled.
123
+
122
124
  The transaction validates the surface span and the durable lock, appends `compaction/start`, summarizes through the hook, revalidates stability (whole-surface for automatic calls, selected-span for manual calls), rejects a summary that does not shrink its source, appends `compaction/summary` plus the replacement `user/message`, and makes exactly one `compaction/end` attempt. A live unmatched start is the durable lock: an unmatched marker before a newer `session/end-seed` is stale evidence from a prior lifecycle and does not block; one after that boundary reports `busy`. A failed close deliberately leaves a blocking orphan. Cancellation remains authoritative after cleanup and durability.
123
125
 
124
126
  ### Config resolution
@@ -134,7 +136,7 @@ The transaction validates the surface span and the durable lock, appends `compac
134
136
  | [`src/summarizer.ts`](src/summarizer.ts) | Default `ctx.llm.stream()` summarization, checkpoint framing, safe-summary projection |
135
137
  | [`src/config.ts`](src/config.ts) | Load-time validation and routed-model policy resolution |
136
138
  | [`src/types.ts`](src/types.ts) | `BasicCompactionConfig` and resolved policy vocabulary |
137
- | — | No runtime invariant companion is published; this package exposes no independent event sequence or mutable data relation beyond contracts enforced at its owning seam. |
139
+ | — | No runtime invariant companion is published; this package exposes no independent event sequence or mutable data relation beyond contracts enforced at its owning seam. The durable bracket remains observable in the session log. |
138
140
 
139
141
  </details>
140
142
 
@@ -252,7 +254,7 @@ These limits define when automatic condensation is a poor fit or needs special c
252
254
  This Dev Note is working context for maintainers and is explicitly non-authoritative; shipped behavior lives in the sections above, the package code, and the linked Agent Notes.
253
255
 
254
256
  - **Default ratios, undecided** — `thresholdRatio: 0.8` and `retainRatio: 0.16` are fixed defaults; per-model tuning via `modelPolicies` exists, but no corpus-backed guidance on ideal values is recorded.
255
- - **Tokenizer-accurate measurement, deferred** — the token meter's four-characters-per-token heuristic underprices CJK text and JSON schemas; exact tokenization remains an open direction for the measurement service.
257
+ - **Tokenizer-accurate measurement, deferred** — the token meter's four-characters-per-token heuristic underprices CJK text and JSON Schema documents; exact tokenization remains an open direction for the measurement service.
256
258
  - **Overflow recovery beyond canonical errors, undecided** — recovery triggers on `CONTEXT_WINDOW_EXCEEDED` only; other provider-side context failures are not classified.
257
259
 
258
260
  </details>
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "面向部署方的自动会话压缩:选择、调优或排查随 token 压力上升如何把较早历史摘要为总结。"
2
+ description: "面向部署场景的自动会话压缩(compaction):用于选择、调优或排查随 token 压力上升对较早历史进行摘要的方式。"
3
3
  kind: "package-reference"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- 本包让长时 agent 会话在接近模型上下文上限时仍能正常工作。token 压力上升时,它会把最旧的历史压缩为摘要并保留近期消息;上下文溢出错误发生后,它会压缩并重试。你也可以通过 `/compact` 按需压缩,并选择先修剪超大工具输出。压缩使用一次额外的模型请求,并且只保留该请求返回的摘要文本。它无法缩减系统提示词、工具或会话前缀,也无法拆分单个不可分单元(例如一次超大工具调用)。
12
+ 本包让长时 agent(智能体)会话在接近模型上下文上限时仍能正常工作。token 压力上升时,它会把最旧的历史压缩为摘要并保留近期消息;上下文溢出错误发生后,它会压缩并重试。你也可以通过 `/compact` 按需压缩,并选择先修剪超大工具输出。压缩使用一次额外的模型请求,并且只保留该请求返回的摘要文本。它无法缩减系统提示词、工具或会话前缀,也无法拆分单个不可分单元(例如一次超大工具调用)。
13
13
 
14
14
  ## 目录
15
15
 
@@ -17,7 +17,7 @@ kind: "package-reference"
17
17
  - [理解实现](#understand-the-implementation)
18
18
  - [进一步探索](#further-exploration)
19
19
  - [模型体验](#model-experience)
20
- - [已知限制与延期工作](#known-limitations-and-deferred-work)
20
+ - [已知限制与暂缓事项](#known-limitations-and-deferred-work)
21
21
  - [开发备注](#dev-note)
22
22
 
23
23
  -----
@@ -109,7 +109,7 @@ kind: "package-reference"
109
109
 
110
110
  ### 自动触发与溢出恢复
111
111
 
112
- 当 `auto: true` 时,串行 `agent/pre-step` listener 会在请求派生前检查压力:它通过 `ctx.tokenMeter` 为最新持久路由请求 envelope 定价,当压力越过路由模型的阈值时,先剪枝,再在保留已定价近期尾部的同时摘要最旧的平衡范围。每个选定范围都从第一个不是 `system/message` 的 surface 节点开始,因此位于 surface 节点 0 的系统提示词永不会被遮蔽;由历史内提示词更新追加的后续 `system/message` 是普通历史,范围可以遮蔽它,agent loop 的投影随后会在二者文本不同时用当前提示词替换节点 0([决策规则](../../core/agent-loop/README.zh.md#understand-the-implementation))。`agent/request-error` listener 响应提供方确认的 `CONTEXT_WINDOW_EXCEEDED`:它绕过常规阈值与保留策略,尝试一次最大平衡头部缩减,并且只在表层替换 generation 前进后才授权重试。取消全程保持最终决定权。
112
+ 当 `auto: true` 时,串行 `agent/pre-step` listener 会在请求派生前检查压力:它通过 `ctx.tokenMeter` 为最新持久路由请求 envelope 定价,当压力越过路由模型的阈值时,先剪枝,再在保留已定价近期尾部的同时摘要最旧的平衡范围。每个选定范围都从第一个不是 `system/message` 的 surface 节点开始,因此位于 surface 节点 0 的系统提示词永不会被遮蔽;由历史内提示词更新追加的后续 `system/message` 是普通历史,范围可以遮蔽它,agent loop(智能体循环)的投影随后会在二者文本不同时用当前提示词替换节点 0([决策规则](../../core/agent-loop/README.zh.md#understand-the-implementation))。`agent/request-error` listener 响应提供方确认的 `CONTEXT_WINDOW_EXCEEDED`:它绕过常规阈值与保留策略,尝试一次最大平衡头部缩减,并且只在表层替换 generation 前进后才授权重试。取消全程保持最终决定权。
113
113
 
114
114
  压力策略从拥有持久路由的适配器解析容量。适配器无法为有效动态路由返回容量时,手动压力路径会抛出目标特定配置错误;自动 listener 会对该精确目标警告一次,并携带完整历史继续。
115
115
 
@@ -119,6 +119,8 @@ kind: "package-reference"
119
119
 
120
120
  ### 区域事务
121
121
 
122
+ 摘要请求失败后,后端先检查取消和选区稳定性,再触发同步的 `compaction/summary-error`。恢复监听器必须先记录持久的输入变更,才能请求重试。后端重新派生所选消息,更新 token 价格及判断摘要是否缩短输入的基准。图片省略插件负责选图;后续摘要失败或取消后,已经记录的省略仍然有效。
123
+
122
124
  事务验证表层范围与持久锁,追加 `compaction/start`,通过钩子生成摘要,重新验证稳定性(自动调用要求整个表层、手动调用只要求所选范围),拒绝不缩小源内容的摘要,追加 `compaction/summary` 与替换 `user/message`,并恰好进行一次 `compaction/end` 尝试。活动的未匹配 start 是持久锁:位于较新 `session/end-seed` 之前的未匹配标记是先前生命周期留下的陈旧证据,不会阻塞;位于该边界之后的标记报告 `busy`。闭合失败会有意留下阻塞性的未匹配标记。完成清理与持久化后,取消仍具有最终决定权。
123
125
 
124
126
  ### 配置解析
@@ -134,7 +136,7 @@ kind: "package-reference"
134
136
  | [`src/summarizer.ts`](src/summarizer.ts) | 默认 `ctx.llm.stream()` 摘要、检查点框定、安全摘要投影 |
135
137
  | [`src/config.ts`](src/config.ts) | 加载时验证与路由模型策略解析 |
136
138
  | [`src/types.ts`](src/types.ts) | `BasicCompactionConfig` 与已解析策略词汇 |
137
- | — | 不发布运行时不变式伴生入口;持久标记对可在会话日志中观察。 |
139
+ | — | 不发布运行时不变式配套条目;除所属 seam 强制执行的约定外,本包不公开独立事件序列或可变数据关系。持久标记对仍可在会话日志中观察。 |
138
140
 
139
141
  </details>
140
142
 
@@ -230,7 +232,7 @@ Rules:
230
232
 
231
233
  已回放系统提示词、工具与已遮蔽区域消息与会话最后一个已路由请求逐字匹配,因此提供方的热前缀 cache 可复用至尾随指令之前;只有该指令与摘要输出未缓存。将摘要器路由到不同提供方/模型,或压缩非头部范围,都会放弃该复用。
232
234
 
233
- ## 已知限制与延期工作
235
+ ## 已知限制与暂缓事项
234
236
 
235
237
  <a id="known-limitations-and-deferred-work"></a>
236
238
 
@@ -252,7 +254,7 @@ Rules:
252
254
  本开发备注是维护者的工作上下文,明确不具权威性;已交付行为以上文、包代码与所链接的 Agent Note 为准。
253
255
 
254
256
  - **默认比例,尚未决定**——`thresholdRatio: 0.8` 与 `retainRatio: 0.16` 是固定默认值;存在通过 `modelPolicies` 进行的按模型调优,但没有基于语料的理想值指引记录。
255
- - **tokenizer 精确测量,暂缓**——token meter 每 token 四字符的启发式对 CJK 文本与 JSON schema 定价偏低;精确 token 化仍是测量服务的开放方向。
257
+ - **tokenizer 精确测量,暂缓**——token meter 每 token 四字符的启发式对 CJK 文本与 JSON Schema 定价偏低;精确 token 化仍是测量服务的开放方向。
256
258
  - **规范错误之外的溢出恢复,尚未决定**——恢复仅针对 `CONTEXT_WINDOW_EXCEEDED` 触发;其他提供方侧上下文失败不参与分类。
257
259
 
258
260
  </details>
package/lib/index.js CHANGED
@@ -337,11 +337,7 @@ function frameSummary(summary) {
337
337
  function finishError(finish) {
338
338
  switch (finish.kind) {
339
339
  case "error":
340
- case "aborted": {
341
- const error = new Error(finish.failure.message);
342
- error.code = finish.failure.code;
343
- return error;
344
- }
340
+ case "aborted": return new LlmError(finish.failure.message, finish.failure.code, finish.failure);
345
341
  case "max-tokens": {
346
342
  const error = /* @__PURE__ */ new Error("summarization truncated at the token cap (incomplete checkpoint)");
347
343
  error.code = "MAX_TOKENS";
@@ -458,7 +454,7 @@ async function compactSurfaceRegion(dependencies, session, start, end, agent, op
458
454
  let closing = false;
459
455
  let stage = "summary";
460
456
  try {
461
- const summarized = await summarizeCompaction(dependencies, prepareCompaction(dependencies, session, selection), agent, compactionId, options.sourceCommandId, signal);
457
+ const summarized = await summarizeCompaction(dependencies, prepareCompaction(dependencies, session, selection), agent, compactionId, options.sourceCommandId, assertStable, signal);
462
458
  if (options.owner === null) signal?.throwIfAborted();
463
459
  assertStable(dependencies, session, summarized);
464
460
  stage = "commit";
@@ -562,8 +558,20 @@ function prepareCompaction(dependencies, session, selection) {
562
558
  };
563
559
  }
564
560
  /** Run the summarizer and frame its replacement checkpoint. */
565
- async function summarizeCompaction(dependencies, prepared, agent, compactionId, sourceCommandId, signal) {
566
- const summaryResult = await dependencies.summarize(prepared.input, agent, signal);
561
+ async function summarizeCompaction(dependencies, prepared, agent, compactionId, sourceCommandId, assertStable, signal) {
562
+ let summaryResult;
563
+ for (;;) {
564
+ signal?.throwIfAborted();
565
+ try {
566
+ summaryResult = await dependencies.summarize(prepared.input, agent, signal);
567
+ break;
568
+ } catch (error) {
569
+ if (signal?.aborted === true) throw error;
570
+ assertStable(dependencies, agent.session, prepared);
571
+ if (!dependencies.recover(error, agent, prepared.shadowedSeqs, signal)) throw error;
572
+ prepared = prepareCompaction(dependencies, agent.session, validateSurfaceRegion(agent.session, prepared.start, prepared.end));
573
+ }
574
+ }
567
575
  const checkpointMessage = createUserMessage({
568
576
  content: frameSummary(summaryResult.summary),
569
577
  source: compactCheckpointSource(compactionId, sourceCommandId)
@@ -598,7 +606,7 @@ function assertSelectedSpanStable(dependencies, session, prepared) {
598
606
  /** Append one completed summary record and replacement body without yielding. */
599
607
  function commitCompactionBody(session, startEvent, summarized) {
600
608
  const { start, end, shadowedSeqs, shadowedTokenCount, summary, provider, model, maxTokens, usage, checkpointMessage } = summarized;
601
- const callProvenance = summarized.llmStreamCall === true ? {
609
+ const callRecord = summarized.llmStreamCall === true ? {
602
610
  rawOutput: summarized.rawOutput,
603
611
  llmStreamCall: true
604
612
  } : summarized.rawOutput === void 0 ? {} : { rawOutput: summarized.rawOutput };
@@ -606,7 +614,7 @@ function commitCompactionBody(session, startEvent, summarized) {
606
614
  compactionId: startEvent.data.compactionId,
607
615
  ...startEvent.data.sourceCommandId === void 0 ? {} : { sourceCommandId: startEvent.data.sourceCommandId },
608
616
  summary,
609
- ...callProvenance,
617
+ ...callRecord,
610
618
  shadowedRange: {
611
619
  start,
612
620
  end
@@ -972,7 +980,13 @@ var BasicCompactionEngine = class extends CompactionEngine {
972
980
  regionDependencies() {
973
981
  return {
974
982
  meter: this.ctx.tokenMeter,
975
- summarize: (input, owner, abort) => this.summarize(input, owner, abort)
983
+ summarize: (input, owner, abort) => this.summarize(input, owner, abort),
984
+ recover: (error, agent, sourceEventSeqs, signal) => this.ctx.waterfall("compaction/summary-error", {
985
+ session: agent.session,
986
+ sourceEventSeqs,
987
+ error,
988
+ ...signal === void 0 ? {} : { signal }
989
+ }, () => false)
976
990
  };
977
991
  }
978
992
  };
@@ -13,6 +13,7 @@ import type { SummarizationInput, SummaryResult } from './summarizer.ts';
13
13
  interface RegionDependencies {
14
14
  readonly meter: TokenMeter;
15
15
  summarize(input: SummarizationInput, agent: Agent, signal?: AbortSignal): Promise<SummaryResult>;
16
+ recover(error: unknown, agent: Agent, sourceEventSeqs: readonly SessionSeq[], signal?: AbortSignal): boolean;
16
17
  }
17
18
  interface CompactionTransactionOptions {
18
19
  /** `current-turn` derives a numbered owner; `null` writes a standalone bracket. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-compaction-basic",
3
3
  "description": "Token-meter-driven compaction policy and LLM summarization backend for the DeepSeek Harness",
4
- "version": "0.1.5-rc.2",
4
+ "version": "0.1.6-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,14 +27,14 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
+ "@deepseek-ai/dsh-agent": "^0.1.6-alpha.2",
30
31
  "@deepseek-ai/cordis": "^4.0.2",
31
- "@deepseek-ai/dsh-agent": "^0.1.5-rc.2",
32
- "@deepseek-ai/dsh-commands": "^0.1.5-rc.2",
33
- "@deepseek-ai/dsh-compaction": "^0.1.5-rc.2",
34
- "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.5-rc.2",
35
- "@deepseek-ai/dsh-llm": "^0.1.5-rc.2",
36
- "@deepseek-ai/dsh-token-meter": "^0.1.5-rc.2",
37
- "@deepseek-ai/dsh-session": "^0.1.5-rc.2"
32
+ "@deepseek-ai/dsh-compaction": "^0.1.6-alpha.2",
33
+ "@deepseek-ai/dsh-commands": "^0.1.6-alpha.2",
34
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.6-alpha.2",
35
+ "@deepseek-ai/dsh-llm": "^0.1.6-alpha.2",
36
+ "@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
37
+ "@deepseek-ai/dsh-token-meter": "^0.1.6-alpha.2"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@deepseek-ai/dsh-compaction-tool-result-pruner": {
@@ -42,25 +42,26 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@deepseek-ai/dsh-util-values": "^0.1.5-rc.2",
45
+ "@deepseek-ai/dsh-util-values": "^0.1.6-alpha.2",
46
46
  "@deepseek-ai/schemastery": "^3.18.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@deepseek-ai/cordis": "^4.0.2",
50
50
  "@deepseek-ai/cordis-plugin-include": "^1.0.7",
51
51
  "@deepseek-ai/cordis-plugin-loader": "^1.0.3",
52
- "@deepseek-ai/dsh-agent": "^0.1.5-rc.2",
53
- "@deepseek-ai/dsh-agent-loop": "^0.1.5-rc.2",
54
- "@deepseek-ai/dsh-commands": "^0.1.5-rc.2",
55
- "@deepseek-ai/dsh-compaction": "^0.1.5-rc.2",
56
- "@deepseek-ai/dsh-agent-loop-testkit": "^0.1.5-rc.2",
57
- "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.5-rc.2",
58
- "@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
59
- "@deepseek-ai/dsh-llm": "^0.1.5-rc.2",
60
- "@deepseek-ai/dsh-session": "^0.1.5-rc.2",
61
- "@deepseek-ai/dsh-session-projection": "^0.1.5-rc.2",
62
- "@deepseek-ai/dsh-token-meter": "^0.1.5-rc.2",
63
- "@deepseek-ai/dsh-tools": "^0.1.5-rc.2",
64
- "@deepseek-ai/dsh-llm-retry": "^0.1.5-rc.2"
52
+ "@deepseek-ai/dsh-agent": "^0.1.6-alpha.2",
53
+ "@deepseek-ai/dsh-agent-loop-testkit": "^0.1.6-alpha.2",
54
+ "@deepseek-ai/dsh-agent-loop": "^0.1.6-alpha.2",
55
+ "@deepseek-ai/dsh-commands": "^0.1.6-alpha.2",
56
+ "@deepseek-ai/dsh-compaction": "^0.1.6-alpha.2",
57
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.6-alpha.2",
58
+ "@deepseek-ai/dsh-invariants": "^0.1.6-alpha.2",
59
+ "@deepseek-ai/dsh-llm": "^0.1.6-alpha.2",
60
+ "@deepseek-ai/dsh-llm-retry": "^0.1.6-alpha.2",
61
+ "@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
62
+ "@deepseek-ai/dsh-session-projection": "^0.1.6-alpha.2",
63
+ "@deepseek-ai/dsh-compaction-image-offload": "^0.1.6-alpha.2",
64
+ "@deepseek-ai/dsh-tools": "^0.1.6-alpha.2",
65
+ "@deepseek-ai/dsh-token-meter": "^0.1.6-alpha.2"
65
66
  }
66
67
  }