@crazx/dsh-compaction-basic 0.1.5-alpha.1.zw.2 → 0.1.5-rc.1.zw.1
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 +2 -2
- package/README.md +10 -13
- package/README.zh.md +19 -22
- package/lib/index.js +46 -42
- package/lib/types/summarizer.d.ts +1 -15
- package/package.json +22 -22
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:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 03fe2811a94ea128fffbd3a6b4678b6d944fc1d9
|
|
6
|
+
README.zh.md: 2a5f9562d5ff30c97129e5a880d25bedc45bcd82
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
This package keeps long agent conversations working near the model's context limit. As token pressure builds, it condenses the oldest history into a summary while preserving recent messages; after a context-overflow error, it condenses and retries. You can also request condensation with `/compact` and optionally trim oversized tool outputs first.
|
|
12
|
+
This package keeps long agent conversations working near the model's context limit. As token pressure builds, it condenses the oldest history into a summary while preserving recent messages; after a context-overflow error, it condenses and retries. You can also request condensation with `/compact` and optionally trim oversized tool outputs first. Condensation uses one extra model request and retains only its summary text. It cannot reduce the system prompt, tools, or session prefix, or split one indivisible unit such as a single huge tool call.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -109,7 +109,7 @@ The backend is built on four commitments:
|
|
|
109
109
|
|
|
110
110
|
- **One measurement service prices every decision.** The singleton `ctx.tokenMeter` measures the latest canonical logged envelope and current surface at one consumed-log revision. When the routed adapter declares request-image pricing, the meter applies it to image history. Pressure, recent-tail retention, range selection, and shrink validation use the same route-priced node figures; logged replacement shadow prices stay on the route-independent heuristic so pure projection folds remain consistent.
|
|
111
111
|
- **The log-recorded bracket is the transaction.** All entry points share one bracket-first region transaction: validate the range and live lock, append `compaction/start` synchronously, prepare and await the summary, revalidate, append `compaction/summary` plus the replacement, and make exactly one closing attempt. Automatic and explicit-region calls require a numeric open-turn owner and whole-surface stability; `compactNow()` reserves idle admission, uses `turn: null`, accepts append-only context outside its selected span, flushes every closed attempt, and releases admission in `finally`.
|
|
112
|
-
- **Summarization
|
|
112
|
+
- **Summarization reuses the provider's warm prefix.** Replaying the system prompt held by the `system/message` at surface node 0, the last routed request's tools, and the shadowed-region messages byte-for-byte makes the auxiliary call a genuine prefix of the conversation, so only the trailing instruction and the summary output are uncached.
|
|
113
113
|
- **`summarize()` is the sole subclass hook.** A template- or remote-summarizer subclass can override it while pressure, retention, cited source events, shrink validation, and shadowed-token accounting stay on the token meter.
|
|
114
114
|
|
|
115
115
|
### Automatic triggers and overflow recovery
|
|
@@ -120,7 +120,7 @@ Pressure policy resolves capacity from the adapter that owns the durable route.
|
|
|
120
120
|
|
|
121
121
|
### Summarization mechanics
|
|
122
122
|
|
|
123
|
-
A direct `ctx.llm.stream()` call uses the configured provider/model pair and cap, falling back to the latest logged request target and then the `AgentOptions` pair, without running the loop-only `agent/request` extension point.
|
|
123
|
+
A direct `ctx.llm.stream()` call uses the configured provider/model pair and cap, falling back to the latest logged request target and then the `AgentOptions` pair, without running the loop-only `agent/request` extension point. The call replays the derived `system/message` at surface node 0 as the leading entry of `messages`, followed by the shadowed-region messages (including a shadowed in-history `system/message` in its surface position), and carries the header's tools verbatim — including image references, which the selected adapter must resolve or explicitly reject — and appends the compaction instruction as the final user message, so it reuses the provider's warm prefix cache instead of invalidating it. An empty-content system head contributes no message but remains outside the compacted range. The call sets `GenerateOptions.purpose` to `compaction`; only returned text enters the checkpoint, excluding reasoning and tool calls. Image output fails with `UNSUPPORTED_CONTENT` rather than disappearing. The replacement user message frames the summary with `<compacted-summary>` tags; the raw summary remains on the `compaction/summary` event.
|
|
124
124
|
|
|
125
125
|
### The region transaction
|
|
126
126
|
|
|
@@ -136,13 +136,10 @@ The transaction validates the surface span and the durable lock, appends `compac
|
|
|
136
136
|
|---|---|
|
|
137
137
|
| [`src/index.ts`](src/index.ts) | Plugin entry: `BasicCompactionEngine`, automatic listeners, entry-point dispatch |
|
|
138
138
|
| [`src/region.ts`](src/region.ts) | Retention selection and the shared bracket-first compaction transaction |
|
|
139
|
-
| [`src/summarizer.ts`](src/summarizer.ts) | Default `ctx.llm.stream()`
|
|
140
|
-
| [`src/hierarchical.ts`](src/hierarchical.ts) | Bounded map-reduce fallback, adaptive splitting, stage usage aggregation |
|
|
141
|
-
| [`src/hierarchical-planner.ts`](src/hierarchical-planner.ts) | Tool-balanced units and greedy token-budget planning |
|
|
142
|
-
| [`src/hierarchical-prompts.ts`](src/hierarchical-prompts.ts) | Structured map/reduce prompts and output validation |
|
|
139
|
+
| [`src/summarizer.ts`](src/summarizer.ts) | Default `ctx.llm.stream()` summarization, checkpoint framing, safe-summary projection |
|
|
143
140
|
| [`src/config.ts`](src/config.ts) | Load-time validation and routed-model policy resolution |
|
|
144
141
|
| [`src/types.ts`](src/types.ts) | `BasicCompactionConfig` and resolved policy vocabulary |
|
|
145
|
-
| — | No runtime invariant companion is published; this package exposes no independent event sequence or mutable data relation beyond contracts enforced at its owning seam. |
|
|
142
|
+
| — | 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. |
|
|
146
143
|
|
|
147
144
|
</details>
|
|
148
145
|
|
|
@@ -189,7 +186,7 @@ Replacing rather than append-only. Each checkpoint invalidates reuse from the fi
|
|
|
189
186
|
|
|
190
187
|
#### What the model sees
|
|
191
188
|
|
|
192
|
-
When the complete request fits, the summarization model receives the conversation replayed verbatim — the same system
|
|
189
|
+
When the complete request fits, the summarization model receives the conversation replayed verbatim — the same system prompt, tool schemas, and messages the last routed request sent for the shadowed region — followed by one final user message: the compaction instruction below. For hierarchy, each map request receives the same system prompt, an ordered tool-balanced source span, and a structured map instruction; reduce requests receive ordered `<partial-summary>` frames and a structured reduce instruction. Tool schemas accompany hierarchy calls only when `replayTools: true`. The conversation model never sees these private requests or their reasoning; only the final text is stored.
|
|
193
190
|
|
|
194
191
|
##### Compaction instruction (final user message)
|
|
195
192
|
|
|
@@ -236,7 +233,7 @@ A fitting input costs one separate model call: the replayed conversation prefix
|
|
|
236
233
|
|
|
237
234
|
#### KV Cache effect
|
|
238
235
|
|
|
239
|
-
The fitting one-shot
|
|
236
|
+
The fitting one-shot request matches the conversation's replayed system prompt, tools, and shadowed-region messages byte-for-byte, so the provider's warm prefix cache is reused up to the trailing instruction. Routing to another model or compacting a non-head range forgoes that reuse. Hierarchy intentionally bounds each call and therefore cannot preserve one full warm prefix: map calls may reuse their leading system/message prefix where the Provider permits, while reduce calls operate on newly generated partials. `replayTools: false` also omits the tool-schema prefix to leave more room for source messages.
|
|
240
237
|
|
|
241
238
|
## Known Limitations and Deferred Work
|
|
242
239
|
|
|
@@ -247,9 +244,9 @@ These limits define when automatic condensation is a poor fit or needs special c
|
|
|
247
244
|
|
|
248
245
|
- **Meter accuracy follows the fixed heuristic** — missing reusable provider usage falls back to character count plus structural overhead rather than exact tokenization; image occurrences carry provider-exact visual tokens only on routes whose adapter declares request-image pricing.
|
|
249
246
|
- **Overflow classification is adapter-maintained** — provider wording can change; both DeepSeek adapters normalize recognized context-limit failures to `CONTEXT_WINDOW_EXCEEDED`.
|
|
247
|
+
- **Bounded recovery requires summary-model capacity metadata** — an adapter that omits `contextWindow` keeps the legacy one-shot path. If that request succeeds, behavior is unchanged; if it overflows, hierarchy cannot derive safe chunk budgets and fails with an actionable capacity error.
|
|
248
|
+
- **Hierarchy output is a strict checkpoint protocol** — every map and reduce stage must return all required headings. Truncation, visual output, malformed structure, exhausted `maxDepth`, or an indivisible source/partial that still overflows fails the complete compaction transaction without installing a partial checkpoint.
|
|
250
249
|
- **Some indivisible-unit and envelope-only overflow remains outside surface compaction** — recovery cannot shrink system/tools/prefix, split an indivisible non-tool node, or repair a tool unit whose non-prunable remainder still exceeds the window. The optional pruner can shrink text-bearing tool-result bulk inside an otherwise indivisible pair.
|
|
251
|
-
- **Hierarchy requires declared summary-model capacity** — without a positive integer `contextWindow`, fitting input still uses one-shot summarization, but a confirmed one-shot overflow fails clearly because bounded chunk planning has no trustworthy window.
|
|
252
|
-
- **Hierarchy is intentionally bounded** — a Provider-rejected indivisible tool-balanced span, fixed system/tools/instruction overhead that exhausts the stage budget, a reduction round that does not reduce partial count, or reaching `maxDepth` fails instead of looping.
|
|
253
250
|
- **`compactRegion` requires an open turn** — a manual call on a fully-closed session throws ("no open turn") rather than compacting.
|
|
254
251
|
- **Summarization failure preserves the latest durable surface** — before any replacement, the auto path logs a warning and proceeds with full over-budget history. If pruning already landed, a later summarization failure proceeds from that durable pruned surface. Summarization truncation at `maxTokens`, which hidden reasoning tokens can consume, follows the same rule.
|
|
255
252
|
|
|
@@ -262,7 +259,7 @@ These limits define when automatic condensation is a poor fit or needs special c
|
|
|
262
259
|
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.
|
|
263
260
|
|
|
264
261
|
- **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.
|
|
265
|
-
- **Tokenizer-accurate measurement, deferred** — the token meter's four-characters-per-token heuristic underprices CJK text and JSON
|
|
262
|
+
- **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.
|
|
266
263
|
- **Overflow recovery beyond canonical errors, undecided** — recovery triggers on `CONTEXT_WINDOW_EXCEEDED` only; other provider-side context failures are not classified.
|
|
267
264
|
|
|
268
265
|
</details>
|
package/README.zh.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "
|
|
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
|
|
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
|
-
- [
|
|
20
|
+
- [已知限制与暂缓事项](#known-limitations-and-deferred-work)
|
|
21
21
|
- [开发备注](#dev-note)
|
|
22
22
|
|
|
23
23
|
-----
|
|
@@ -29,7 +29,7 @@ kind: "package-reference"
|
|
|
29
29
|
|
|
30
30
|
### 你会得到什么
|
|
31
31
|
|
|
32
|
-
默认设置下你会获得四种行为:会话向模型上下文上限增长时自动压缩;提供方确认上下文溢出错误后的恢复(先压缩再重试该请求);通过 `/compact`
|
|
32
|
+
默认设置下你会获得四种行为:会话向模型上下文上限增长时自动压缩;提供方确认上下文溢出错误后的恢复(先压缩再重试该请求);通过 `/compact` 命令按需压缩;以及——挂载修剪器时——压缩前对超大工具输出的修剪。
|
|
33
33
|
|
|
34
34
|
### 最小可用组合
|
|
35
35
|
|
|
@@ -71,11 +71,11 @@ kind: "package-reference"
|
|
|
71
71
|
| `maxTokens` | `8192` | 摘要请求的输出上限;可包含推理 token。 |
|
|
72
72
|
| `compactionRetries` | `1` | 压力仍高于阈值时,在首次压缩后进行的额外尝试次数。 |
|
|
73
73
|
| `maxOverflowRetries` | `1` | 已确认上下文窗口溢出后的最大重试次数;`0` 只禁用恢复。 |
|
|
74
|
-
| `chunkInputRatio` | `0.6` |
|
|
74
|
+
| `chunkInputRatio` | `0.6` | 每个层次阶段输入可用的摘要模型窗口比例;有效范围 `[0.1, 0.9]`。 |
|
|
75
75
|
| `mapMaxTokens` | `4096` | 单次层次 map 调用的提供方生成上限。 |
|
|
76
76
|
| `reduceMaxTokens` | `8192` | 单次层次 reduce 调用的提供方生成上限。 |
|
|
77
|
-
| `maxDepth` | `4` |
|
|
78
|
-
| `replayTools` | `false` |
|
|
77
|
+
| `maxDepth` | `4` | 递归 reduce 轮次上限;有效范围 `1..8`。 |
|
|
78
|
+
| `replayTools` | `false` | 在层次阶段回放工具 schema。严格提供方可能需要打开此项,但会占用 chunk 输入并降低前缀复用。 |
|
|
79
79
|
| `modelPolicies` | `[]` | 针对个别模型路由的精确 `{ provider, model, ...partialPolicy }` 覆盖。 |
|
|
80
80
|
| `auto` | `true` | 启用自动压缩与溢出恢复;设为 `false` 则仅手动执行。 |
|
|
81
81
|
|
|
@@ -109,18 +109,18 @@ kind: "package-reference"
|
|
|
109
109
|
|
|
110
110
|
- **一个测量服务为每个决策定价。** 单例 `ctx.tokenMeter` 会在同一个已消费日志 revision 上测量最新规范已记录 envelope 与当前表层。路由适配器声明请求图片定价时,meter 会将其应用于图片历史。压力、近期尾部保留、范围选择与缩减验证使用同一套路由定价的节点数值;已记录的替换影子价仍使用与路由无关的启发式规则,使纯投影 fold 保持一致。
|
|
111
111
|
- **日志记录的标记对就是事务。** 所有入口点共享一个先记录标记的区域事务:验证范围与活动锁,同步追加 `compaction/start`,准备并等待摘要,重新验证,再追加 `compaction/summary` 与替换,最后恰好进行一次闭合尝试。自动调用与显式范围调用要求数字标识的开放轮次归属与整个表层稳定;`compactNow()` 会预留空闲接纳,使用 `turn: null`,允许所选 span 之外追加仅追加上下文,flush 每次已闭合尝试,并在 `finally` 中释放接纳预留。
|
|
112
|
-
-
|
|
112
|
+
- **摘要复用提供方的热前缀。** 逐字回放 surface 节点 0 处 `system/message` 所承载的系统提示词、上次已路由请求的工具与已遮蔽区域消息,使辅助调用成为会话的真正前缀,因此只有尾随指令与摘要输出未缓存。
|
|
113
113
|
- **`summarize()` 是唯一的子类钩子。** 基于模板或远程摘要器的子类可以覆盖它,同时压力、保留、被引用的源事件、缩减验证与已遮蔽 token 计量仍由 token meter 负责。
|
|
114
114
|
|
|
115
115
|
### 自动触发与溢出恢复
|
|
116
116
|
|
|
117
|
-
当 `auto: true` 时,串行 `agent/pre-step` listener 会在请求派生前检查压力:它通过 `ctx.tokenMeter` 为最新持久路由请求 envelope 定价,当压力越过路由模型的阈值时,先剪枝,再在保留已定价近期尾部的同时摘要最旧的平衡范围。每个选定范围都从第一个不是 `system/message` 的 surface 节点开始,因此位于 surface 节点 0 的系统提示词永不会被遮蔽;由历史内提示词更新追加的后续 `system/message` 是普通历史,范围可以遮蔽它,agent loop
|
|
117
|
+
当 `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 前进后才授权重试。取消全程保持最终决定权。
|
|
118
118
|
|
|
119
119
|
压力策略从拥有持久路由的适配器解析容量。适配器无法为有效动态路由返回容量时,手动压力路径会抛出目标特定配置错误;自动 listener 会对该精确目标警告一次,并携带完整历史继续。
|
|
120
120
|
|
|
121
121
|
### 摘要机制
|
|
122
122
|
|
|
123
|
-
直接 `ctx.llm.stream()` 调用使用已配置的提供方/模型对与上限,回退到最新已记录请求目标,然后再回退到 `AgentOptions` 对,而不运行仅用于 agent loop 的 `agent/request`
|
|
123
|
+
直接 `ctx.llm.stream()` 调用使用已配置的提供方/模型对与上限,回退到最新已记录请求目标,然后再回退到 `AgentOptions` 对,而不运行仅用于 agent loop 的 `agent/request` 扩展点。该调用将 surface 节点 0 处派生的 `system/message` 作为 `messages` 的首项回放,后接已遮蔽区域消息(包括位于其 surface 位置的被遮蔽历史内 `system/message`),并逐字携带 header 的工具——包括所选适配器必须解析或明确拒绝的图片引用——并将压缩指令作为最后一条 user 消息追加,从而复用提供方的热前缀 cache,而非使它失效。空内容系统头节点不贡献消息,但仍处于压缩范围之外。调用将 `GenerateOptions.purpose` 设为 `compaction`;只有返回文本进入检查点,推理与工具调用都会被排除。图片输出会以 `UNSUPPORTED_CONTENT` 失败,而不是消失。替换 user 消息用 `<compacted-summary>` 标签框定摘要;原始摘要保留在 `compaction/summary` 事件上。
|
|
124
124
|
|
|
125
125
|
### 区域事务
|
|
126
126
|
|
|
@@ -136,13 +136,10 @@ kind: "package-reference"
|
|
|
136
136
|
|---|---|
|
|
137
137
|
| [`src/index.ts`](src/index.ts) | 插件入口:`BasicCompactionEngine`、自动 listener、入口点分发 |
|
|
138
138
|
| [`src/region.ts`](src/region.ts) | 保留选择与共享的先记录标记压缩事务 |
|
|
139
|
-
| [`src/summarizer.ts`](src/summarizer.ts) | 默认 `ctx.llm.stream()`
|
|
140
|
-
| [`src/hierarchical.ts`](src/hierarchical.ts) | 有界 map-reduce 回退、自适应拆分与阶段用量聚合 |
|
|
141
|
-
| [`src/hierarchical-planner.ts`](src/hierarchical-planner.ts) | 工具配对平衡单元与贪心 token 预算规划 |
|
|
142
|
-
| [`src/hierarchical-prompts.ts`](src/hierarchical-prompts.ts) | 结构化 map/reduce 提示词与输出验证 |
|
|
139
|
+
| [`src/summarizer.ts`](src/summarizer.ts) | 默认 `ctx.llm.stream()` 摘要、检查点框定、安全摘要投影 |
|
|
143
140
|
| [`src/config.ts`](src/config.ts) | 加载时验证与路由模型策略解析 |
|
|
144
141
|
| [`src/types.ts`](src/types.ts) | `BasicCompactionConfig` 与已解析策略词汇 |
|
|
145
|
-
| — |
|
|
142
|
+
| — | 不发布运行时不变式配套条目;除所属 seam 强制执行的约定外,本包不公开独立事件序列或可变数据关系。持久标记对仍可在会话日志中观察。 |
|
|
146
143
|
|
|
147
144
|
</details>
|
|
148
145
|
|
|
@@ -189,7 +186,7 @@ This is an automatically generated checkpoint condensing an earlier span of the
|
|
|
189
186
|
|
|
190
187
|
#### 模型看到的内容
|
|
191
188
|
|
|
192
|
-
|
|
189
|
+
摘要模型会接收逐字回放的会话:与上次已路由请求为已遮蔽区域发送的相同系统提示词、工具 schema 与消息,后面跟随一条最终 user 消息,即下方压缩指令。会话模型绝不会看到该私有请求或其推理;只有返回文本会被存储。
|
|
193
190
|
|
|
194
191
|
##### 压缩指令(最终 user 消息)
|
|
195
192
|
|
|
@@ -232,13 +229,13 @@ Rules:
|
|
|
232
229
|
|
|
233
230
|
#### Token 影响
|
|
234
231
|
|
|
235
|
-
|
|
232
|
+
这是一次独立模型调用:输入是已回放会话前缀加固定指令,输出受 `maxTokens` 限制。收敛重试可能多次支付这项成本。
|
|
236
233
|
|
|
237
234
|
#### KV Cache 影响
|
|
238
235
|
|
|
239
|
-
|
|
236
|
+
已回放系统提示词、工具与已遮蔽区域消息与会话最后一个已路由请求逐字匹配,因此提供方的热前缀 cache 可复用至尾随指令之前;只有该指令与摘要输出未缓存。将摘要器路由到不同提供方/模型,或压缩非头部范围,都会放弃该复用。
|
|
240
237
|
|
|
241
|
-
##
|
|
238
|
+
## 已知限制与暂缓事项
|
|
242
239
|
|
|
243
240
|
<a id="known-limitations-and-deferred-work"></a>
|
|
244
241
|
|
|
@@ -247,9 +244,9 @@ Rules:
|
|
|
247
244
|
|
|
248
245
|
- **计量准确度取决于固定启发式规则**——可复用提供方用量缺失时,会回退到字符数加结构开销,而非精确的 token 化;只有在适配器声明了请求图片定价的路由上,图片出现处才携带提供方精确的视觉 token。
|
|
249
246
|
- **溢出分类由适配器维护**——提供方措辞可能改变;两个 DeepSeek 适配器将可识别的上下文限制失败规范化为 `CONTEXT_WINDOW_EXCEEDED`。
|
|
247
|
+
- **有界恢复需要摘要模型的容量元数据**——省略 `contextWindow` 的适配器继续走旧的一次性路径。该请求成功则行为不变;若溢出,层次无法推导安全 chunk 预算,并以可操作的容量错误失败。
|
|
248
|
+
- **层次输出是严格的检查点协议**——每个 map 与 reduce 阶段必须返回全部必需标题。截断、视觉输出、结构畸形、耗尽 `maxDepth`,或仍溢出的不可分源/部分摘要,都会让整次压缩事务失败,不安装部分检查点。
|
|
250
249
|
- **部分不可分单元与仅 envelope 溢出仍不在表层压缩范围内**——恢复无法缩减系统/工具/前缀、拆分不可分的非工具节点,或修复不可剪枝剩余部分仍超出窗口的工具单元。可选 pruner 可以缩减原本不可分工具对内的文本型工具结果主体。
|
|
251
|
-
- **层次模式要求声明摘要模型容量**——没有正整数 `contextWindow` 时,能容纳的输入仍可 one-shot 摘要;但 one-shot 被确认 overflow 后会清晰失败,因为有界分块规划没有可信窗口。
|
|
252
|
-
- **层次模式刻意有界**——提供方拒绝不可分的工具配对平衡 span、固定 system/tools/instruction 开销耗尽阶段预算、reduce 轮次未减少 partial 数量,或达到 `maxDepth` 时都会失败,而不会循环。
|
|
253
250
|
- **`compactRegion` 要求存在未结束的轮次**——在完全关闭的会话上手动调用会抛出异常(「no open turn」),而不是执行压缩。
|
|
254
251
|
- **摘要失败会保留最新持久表层**——任何替换前,自动路径会记录警告,并携带完整超预算历史继续。如果剪枝已落地,后续摘要失败会从该持久剪枝表层继续。因达到 `maxTokens` 而发生的摘要截断(隐藏推理 token 可能会耗尽该额度)遵循同一规则。
|
|
255
252
|
|
|
@@ -262,7 +259,7 @@ Rules:
|
|
|
262
259
|
本开发备注是维护者的工作上下文,明确不具权威性;已交付行为以上文、包代码与所链接的 Agent Note 为准。
|
|
263
260
|
|
|
264
261
|
- **默认比例,尚未决定**——`thresholdRatio: 0.8` 与 `retainRatio: 0.16` 是固定默认值;存在通过 `modelPolicies` 进行的按模型调优,但没有基于语料的理想值指引记录。
|
|
265
|
-
- **tokenizer 精确测量,暂缓**——token meter 每 token 四字符的启发式对 CJK 文本与 JSON
|
|
262
|
+
- **tokenizer 精确测量,暂缓**——token meter 每 token 四字符的启发式对 CJK 文本与 JSON Schema 定价偏低;精确 token 化仍是测量服务的开放方向。
|
|
266
263
|
- **规范错误之外的溢出恢复,尚未决定**——恢复仅针对 `CONTEXT_WINDOW_EXCEEDED` 触发;其他提供方侧上下文失败不参与分类。
|
|
267
264
|
|
|
268
265
|
</details>
|
package/lib/index.js
CHANGED
|
@@ -344,7 +344,7 @@ async function summarizeWithLlm(ctx, config, input, agent, signal) {
|
|
|
344
344
|
...signal === void 0 ? {} : { signal }
|
|
345
345
|
};
|
|
346
346
|
for await (const chunk of ctx.llm.stream(options)) assembler.push(chunk);
|
|
347
|
-
const error = finishError(assembler.finish);
|
|
347
|
+
const error = finishError$1(assembler.finish);
|
|
348
348
|
if (error !== void 0) throw error;
|
|
349
349
|
const rawOutput = assembler.blocks();
|
|
350
350
|
const summary = summaryText(rawOutput);
|
|
@@ -377,12 +377,8 @@ function frameSummary(summary) {
|
|
|
377
377
|
}
|
|
378
378
|
];
|
|
379
379
|
}
|
|
380
|
-
/**
|
|
381
|
-
|
|
382
|
-
* @param finish - terminal stream finish emitted by the summary request.
|
|
383
|
-
* @returns the corresponding error, or `undefined` for a complete stop.
|
|
384
|
-
*/
|
|
385
|
-
function finishError(finish) {
|
|
380
|
+
/** Map a terminal summarization finish to its fail-closed error. */
|
|
381
|
+
function finishError$1(finish) {
|
|
386
382
|
switch (finish.kind) {
|
|
387
383
|
case "error":
|
|
388
384
|
case "aborted": {
|
|
@@ -398,11 +394,7 @@ function finishError(finish) {
|
|
|
398
394
|
default: return;
|
|
399
395
|
}
|
|
400
396
|
}
|
|
401
|
-
/**
|
|
402
|
-
* Reject visual output and keep only text before synthesizing a user message.
|
|
403
|
-
* @param blocks - raw content blocks emitted by the summary request.
|
|
404
|
-
* @returns the text-only blocks safe to persist as a compaction checkpoint.
|
|
405
|
-
*/
|
|
397
|
+
/** Reject visual output and keep only text before synthesizing a user message. */
|
|
406
398
|
function summaryText(blocks) {
|
|
407
399
|
if (contentHasImage(blocks)) throw new LlmError("compaction summary cannot contain image output", "UNSUPPORTED_CONTENT");
|
|
408
400
|
return blocks.filter((block) => block.type === "text");
|
|
@@ -1002,8 +994,7 @@ var HierarchicalSummarizer = class {
|
|
|
1002
994
|
/* v8 ignore next -- LlmRuntime validates defined capacity before returning model info. */
|
|
1003
995
|
if (!Number.isSafeInteger(contextWindow) || contextWindow < 1) throw new Error(`hierarchical compaction: no positive integer context capacity for summary target ${target.provider}/${target.model}`);
|
|
1004
996
|
const estimate = (message) => this.ctx.tokenMeter.estimateMessage(message);
|
|
1005
|
-
const
|
|
1006
|
-
const oneShotTokens = this.estimateCallInput(input, replay, COMPACTION_INSTRUCTION, true, estimate);
|
|
997
|
+
const oneShotTokens = this.estimateCallInput(input, COMPACTION_INSTRUCTION, true, estimate);
|
|
1007
998
|
let hadFailedLlmAttempt = false;
|
|
1008
999
|
if (oneShotTokens + target.oneShotMaxTokens <= contextWindow) try {
|
|
1009
1000
|
return await oneShot();
|
|
@@ -1013,10 +1004,11 @@ var HierarchicalSummarizer = class {
|
|
|
1013
1004
|
}
|
|
1014
1005
|
const inputBudget = Math.floor(contextWindow * this.hierarchy.chunkInputRatio);
|
|
1015
1006
|
this.assertStageOutputReserve(contextWindow, inputBudget, this.hierarchy.mapMaxTokens, "map");
|
|
1016
|
-
const
|
|
1017
|
-
const
|
|
1018
|
-
const
|
|
1019
|
-
const
|
|
1007
|
+
const systemMessage = input.messages[0]?.role === "system" ? input.messages[0] : void 0;
|
|
1008
|
+
const sourceMessages = systemMessage === void 0 ? input.messages : input.messages.slice(1);
|
|
1009
|
+
const totalUnits = toolBalancedUnits(sourceMessages).length;
|
|
1010
|
+
const mapReserve = this.estimateFixedInput(input, mapInstruction(totalUnits, totalUnits, totalUnits), this.hierarchy.replayTools, estimate);
|
|
1011
|
+
const chunks = planMessageChunks(sourceMessages, this.messageBudget(inputBudget, mapReserve, "map"), estimate);
|
|
1020
1012
|
/* v8 ignore next -- stock range selection never submits an empty shadowed region. */
|
|
1021
1013
|
if (chunks.length === 0) throw new Error("hierarchical compaction: oversized input produced no map chunks");
|
|
1022
1014
|
const calls = [];
|
|
@@ -1028,7 +1020,10 @@ var HierarchicalSummarizer = class {
|
|
|
1028
1020
|
/* v8 ignore next -- the loop condition proves shift has an entry. */
|
|
1029
1021
|
if (span === void 0) break;
|
|
1030
1022
|
try {
|
|
1031
|
-
const result = await this.runStage(
|
|
1023
|
+
const result = await this.runStage({
|
|
1024
|
+
...input,
|
|
1025
|
+
messages: systemMessage === void 0 ? span.messages : [systemMessage, ...span.messages]
|
|
1026
|
+
}, mapInstruction(span.start, span.end, totalUnits), target, this.hierarchy.mapMaxTokens, agent, signal);
|
|
1032
1027
|
calls.push(result);
|
|
1033
1028
|
partials.push(this.partial(result, span.start, span.end, `map source units ${span.start}-${span.end}`));
|
|
1034
1029
|
} catch (error) {
|
|
@@ -1045,7 +1040,7 @@ var HierarchicalSummarizer = class {
|
|
|
1045
1040
|
let usedReduce = false;
|
|
1046
1041
|
for (let round = 1; partials.length > 1; round += 1) {
|
|
1047
1042
|
if (round > this.hierarchy.maxDepth) throw new Error(`hierarchical compaction: reduction did not converge within ${this.hierarchy.maxDepth} round(s)`);
|
|
1048
|
-
const reduceReserve = this.estimateFixedInput(input,
|
|
1043
|
+
const reduceReserve = this.estimateFixedInput(input, reduceInstruction(round, totalUnits, totalUnits, totalUnits), this.hierarchy.replayTools, estimate);
|
|
1049
1044
|
const reduceMessageBudget = this.messageBudget(inputBudget, reduceReserve, `reduce round ${round}`);
|
|
1050
1045
|
let groups;
|
|
1051
1046
|
try {
|
|
@@ -1066,7 +1061,10 @@ var HierarchicalSummarizer = class {
|
|
|
1066
1061
|
/* v8 ignore next -- the loop condition proves shift has an entry. */
|
|
1067
1062
|
if (span === void 0) break;
|
|
1068
1063
|
try {
|
|
1069
|
-
const result = await this.runStage(
|
|
1064
|
+
const result = await this.runStage({
|
|
1065
|
+
...input,
|
|
1066
|
+
messages: systemMessage === void 0 ? span.messages : [systemMessage, ...span.messages]
|
|
1067
|
+
}, reduceInstruction(round, span.start, span.end, totalUnits), target, this.hierarchy.reduceMaxTokens, agent, signal);
|
|
1070
1068
|
calls.push(result);
|
|
1071
1069
|
next.push(this.partial(result, span.start, span.end, `reduce round ${round} source units ${span.start}-${span.end}`));
|
|
1072
1070
|
} catch (error) {
|
|
@@ -1190,12 +1188,13 @@ var HierarchicalSummarizer = class {
|
|
|
1190
1188
|
if (inputBudget + outputTokens > contextWindow) throw new Error(`hierarchical compaction: ${stage} input budget ${inputBudget} plus output reserve ${outputTokens} exceeds summary context ${contextWindow}`);
|
|
1191
1189
|
}
|
|
1192
1190
|
/** Price a complete auxiliary call input. */
|
|
1193
|
-
estimateCallInput(input,
|
|
1194
|
-
|
|
1191
|
+
estimateCallInput(input, instruction, includeTools, estimate) {
|
|
1192
|
+
const sourceMessages = input.messages[0]?.role === "system" ? input.messages.slice(1) : input.messages;
|
|
1193
|
+
return this.estimateFixedInput(input, instruction, includeTools, estimate) + estimateMessages(sourceMessages, estimate);
|
|
1195
1194
|
}
|
|
1196
|
-
/** Price the repeated
|
|
1197
|
-
estimateFixedInput(input,
|
|
1198
|
-
return (
|
|
1195
|
+
/** Price the repeated header and final instruction for one stage. */
|
|
1196
|
+
estimateFixedInput(input, instruction, includeTools, estimate) {
|
|
1197
|
+
return (input.messages[0]?.role === "system" ? estimate(input.messages[0]) : 0) + (!includeTools || input.tools === void 0 || input.tools.length === 0 ? 0 : Math.ceil(JSON.stringify(input.tools).length / CHARS_PER_TOKEN) + ENVELOPE_OVERHEAD) + estimate(this.instructionMessage(instruction));
|
|
1199
1198
|
}
|
|
1200
1199
|
/** Derive positive room for stage messages after fixed input. */
|
|
1201
1200
|
messageBudget(inputBudget, fixedTokens, stage) {
|
|
@@ -1204,17 +1203,13 @@ var HierarchicalSummarizer = class {
|
|
|
1204
1203
|
return budget;
|
|
1205
1204
|
}
|
|
1206
1205
|
/** Run one private map or reduce model call and require structured text. */
|
|
1207
|
-
async runStage(input,
|
|
1206
|
+
async runStage(input, instruction, target, maxTokens, agent, signal) {
|
|
1208
1207
|
signal?.throwIfAborted();
|
|
1209
1208
|
const assembler = new BlockAssembler();
|
|
1210
1209
|
const options = {
|
|
1211
1210
|
provider: target.provider,
|
|
1212
1211
|
model: target.model,
|
|
1213
|
-
messages: [
|
|
1214
|
-
...systemHead === void 0 ? [] : [systemHead],
|
|
1215
|
-
...messages,
|
|
1216
|
-
this.instructionMessage(instruction)
|
|
1217
|
-
],
|
|
1212
|
+
messages: [...input.messages, this.instructionMessage(instruction)],
|
|
1218
1213
|
...this.hierarchy.replayTools && input.tools !== void 0 ? { tools: [...input.tools] } : {},
|
|
1219
1214
|
maxTokens,
|
|
1220
1215
|
sessionId: agent.session.id,
|
|
@@ -1225,7 +1220,8 @@ var HierarchicalSummarizer = class {
|
|
|
1225
1220
|
const finishFailure = finishError(assembler.finish);
|
|
1226
1221
|
if (finishFailure !== void 0) throw finishFailure;
|
|
1227
1222
|
const rawOutput = assembler.blocks();
|
|
1228
|
-
|
|
1223
|
+
if (contentHasImage(rawOutput)) throw new LlmError("hierarchical compaction summary cannot contain image output", "UNSUPPORTED_CONTENT");
|
|
1224
|
+
const summary = rawOutput.filter((block) => block.type === "text");
|
|
1229
1225
|
validateStructuredSummary(summary, "hierarchical compaction stage");
|
|
1230
1226
|
return {
|
|
1231
1227
|
summary,
|
|
@@ -1265,15 +1261,6 @@ var HierarchicalSummarizer = class {
|
|
|
1265
1261
|
});
|
|
1266
1262
|
}
|
|
1267
1263
|
};
|
|
1268
|
-
/** Separate the fixed surface system head from chronological source history. */
|
|
1269
|
-
function hierarchyReplay(messages) {
|
|
1270
|
-
const [first, ...rest] = messages;
|
|
1271
|
-
if (first?.role === "system") return {
|
|
1272
|
-
systemHead: first,
|
|
1273
|
-
sourceMessages: rest
|
|
1274
|
-
};
|
|
1275
|
-
return { sourceMessages: messages };
|
|
1276
|
-
}
|
|
1277
1264
|
/** Build the terminal diagnostic for a provider-rejected atomic span. */
|
|
1278
1265
|
function indivisibleOverflow(stage, cause) {
|
|
1279
1266
|
const error = new OversizedCompactionUnitError(`hierarchical compaction: ${stage} still exceeds the provider context window and is indivisible`, { cause });
|
|
@@ -1284,6 +1271,23 @@ function indivisibleOverflow(stage, cause) {
|
|
|
1284
1271
|
function hasErrorCode(error, code) {
|
|
1285
1272
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
1286
1273
|
}
|
|
1274
|
+
/** Map a terminal stage finish to a fail-closed error. */
|
|
1275
|
+
function finishError(finish) {
|
|
1276
|
+
switch (finish.kind) {
|
|
1277
|
+
case "error":
|
|
1278
|
+
case "aborted": {
|
|
1279
|
+
const error = new Error(finish.failure.message);
|
|
1280
|
+
error.code = finish.failure.code;
|
|
1281
|
+
return error;
|
|
1282
|
+
}
|
|
1283
|
+
case "max-tokens": {
|
|
1284
|
+
const error = /* @__PURE__ */ new Error("hierarchical compaction stage truncated at the token cap");
|
|
1285
|
+
error.code = "MAX_TOKENS";
|
|
1286
|
+
return error;
|
|
1287
|
+
}
|
|
1288
|
+
default: return;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1287
1291
|
/**
|
|
1288
1292
|
* Sum disjoint provider usage across every successful map and reduce call.
|
|
1289
1293
|
* @param usages - stage usage values in call order.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module @deepseek-ai/dsh-compaction-basic/summarizer
|
|
5
5
|
*/
|
|
6
6
|
import type { Context } from '@deepseek-ai/cordis';
|
|
7
|
-
import type { ContentBlock,
|
|
7
|
+
import type { ContentBlock, Message, TokenUsage, ToolSchema } from '@deepseek-ai/dsh-llm';
|
|
8
8
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
9
9
|
interface SummaryConfig {
|
|
10
10
|
readonly summarizationProvider: string;
|
|
@@ -68,19 +68,5 @@ export declare function summarizeWithLlm(ctx: Context, config: SummaryConfig, in
|
|
|
68
68
|
* @returns content for the synthesized replacement user message.
|
|
69
69
|
*/
|
|
70
70
|
export declare function frameSummary(summary: readonly ContentBlock[]): ContentBlock[];
|
|
71
|
-
/**
|
|
72
|
-
* Map a terminal summarization finish to its fail-closed error.
|
|
73
|
-
* @param finish - terminal stream finish emitted by the summary request.
|
|
74
|
-
* @returns the corresponding error, or `undefined` for a complete stop.
|
|
75
|
-
*/
|
|
76
|
-
export declare function finishError(finish: FinishReason): Error | undefined;
|
|
77
|
-
/**
|
|
78
|
-
* Reject visual output and keep only text before synthesizing a user message.
|
|
79
|
-
* @param blocks - raw content blocks emitted by the summary request.
|
|
80
|
-
* @returns the text-only blocks safe to persist as a compaction checkpoint.
|
|
81
|
-
*/
|
|
82
|
-
export declare function summaryText(blocks: readonly ContentBlock[]): Array<Extract<ContentBlock, {
|
|
83
|
-
type: 'text';
|
|
84
|
-
}>>;
|
|
85
71
|
export {};
|
|
86
72
|
//# sourceMappingURL=summarizer.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crazx/dsh-compaction-basic",
|
|
3
3
|
"description": "Token-meter-driven compaction policy and LLM summarization backend for the DeepSeek Harness",
|
|
4
|
-
"version": "0.1.5-
|
|
4
|
+
"version": "0.1.5-rc.1.zw.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
31
|
-
"@deepseek-ai/dsh-agent": "^0.1.5-
|
|
32
|
-
"@deepseek-ai/dsh-commands": "^0.1.5-
|
|
33
|
-
"@deepseek-ai/dsh-compaction": "^0.1.5-
|
|
34
|
-
"@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.5-
|
|
35
|
-
"@deepseek-ai/dsh-llm": "^0.1.5-
|
|
36
|
-
"@deepseek-ai/dsh-session": "^0.1.5-
|
|
37
|
-
"@deepseek-ai/dsh-token-meter": "^0.1.5-
|
|
31
|
+
"@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
|
|
32
|
+
"@deepseek-ai/dsh-commands": "^0.1.5-rc.1",
|
|
33
|
+
"@deepseek-ai/dsh-compaction": "^0.1.5-rc.1",
|
|
34
|
+
"@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.5-rc.1",
|
|
35
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
|
|
36
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
37
|
+
"@deepseek-ai/dsh-token-meter": "^0.1.5-rc.1"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@deepseek-ai/dsh-compaction-tool-result-pruner": {
|
|
@@ -42,25 +42,25 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@deepseek-ai/dsh-util-values": "^0.1.5-
|
|
45
|
+
"@deepseek-ai/dsh-util-values": "^0.1.5-rc.1",
|
|
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-
|
|
53
|
-
"@deepseek-ai/dsh-agent-loop": "^0.1.5-
|
|
54
|
-
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.5-
|
|
55
|
-
"@deepseek-ai/dsh-commands": "^0.1.5-
|
|
56
|
-
"@deepseek-ai/dsh-compaction": "^0.1.5-
|
|
57
|
-
"@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.5-
|
|
58
|
-
"@deepseek-ai/dsh-invariants": "^0.1.5-
|
|
59
|
-
"@deepseek-ai/dsh-llm": "^0.1.5-
|
|
60
|
-
"@deepseek-ai/dsh-llm-retry": "^0.1.5-
|
|
61
|
-
"@deepseek-ai/dsh-session": "^0.1.5-
|
|
62
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.5-
|
|
63
|
-
"@deepseek-ai/dsh-token-meter": "^0.1.5-
|
|
64
|
-
"@deepseek-ai/dsh-tools": "^0.1.5-
|
|
52
|
+
"@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-agent-loop": "^0.1.5-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.5-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-commands": "^0.1.5-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-compaction": "^0.1.5-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.5-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.1",
|
|
59
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
|
|
60
|
+
"@deepseek-ai/dsh-llm-retry": "^0.1.5-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.5-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-token-meter": "^0.1.5-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-tools": "^0.1.5-rc.1"
|
|
65
65
|
}
|
|
66
66
|
}
|