dsh-context-compression-improved 0.5.0 → 0.5.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.
Files changed (50) hide show
  1. package/CHANGELOG.ja.md +51 -0
  2. package/CHANGELOG.ko.md +51 -0
  3. package/CHANGELOG.md +55 -0
  4. package/CHANGELOG.zh.md +45 -0
  5. package/package.json +1 -1
  6. package/packages/selector/lib/advisor-state.js +4 -231
  7. package/packages/selector/lib/client.d.ts +0 -24
  8. package/packages/selector/lib/client.js +6 -501
  9. package/packages/selector/lib/index.d.ts +4 -10
  10. package/packages/selector/lib/index.js +65 -235
  11. package/packages/selector/lib/pruner.d.ts +13 -248
  12. package/packages/selector/lib/pruner.js +148 -552
  13. package/packages/selector/src/client/EstimatorControls.tsx +277 -378
  14. package/packages/selector/src/client/index.ts +0 -17
  15. package/packages/selector/src/client/locales.ts +196 -234
  16. package/packages/selector/src/client/preset-options.ts +3 -2
  17. package/packages/selector/src/client/settings-section.tsx +8 -17
  18. package/packages/selector/src/index.ts +463 -710
  19. package/packages/selector/src/preset-overlay.ts +60 -1
  20. package/packages/selector/src/profiles.ts +4 -27
  21. package/packages/selector/src/pruner/state.ts +50 -73
  22. package/packages/selector/src/pruner.ts +2402 -2730
  23. package/packages/selector/src/runtime/audit.ts +27 -21
  24. package/packages/selector/src/runtime/config.ts +6 -32
  25. package/packages/selector/src/runtime/tokenpilot/advisor-state.ts +16 -0
  26. package/packages/selector/src/runtime/tokenpilot/benefit.ts +200 -0
  27. package/packages/selector/src/runtime/types.ts +0 -17
  28. package/packages/selector/tests/built/client-artifact.spec.ts +9 -5
  29. package/packages/selector/tests/preset-options-write.client.spec.ts +7 -23
  30. package/packages/selector/tests/runtime/advice-never-withholds.host.spec.ts +232 -0
  31. package/packages/selector/tests/runtime/audit.spec.ts +35 -21
  32. package/packages/selector/tests/runtime/deprecated-preset-options.spec.ts +96 -0
  33. package/packages/selector/tests/runtime/tokenpilot/benefit.spec.ts +217 -0
  34. package/packages/selector/tests/runtime/tokenpilot/profile-baseline.spec.ts +4 -5
  35. package/packages/selector/tests/settings-seat.client.spec.ts +16 -10
  36. package/packages/selector/tests/standing-generation.host.spec.ts +54 -5
  37. package/scripts/packed-components-smoke.mjs +30 -8
  38. package/scripts/packed-install-e2e.mjs +69 -15
  39. package/packages/selector/src/client/ReviewOverlay.tsx +0 -320
  40. package/packages/selector/src/client/review-scope.ts +0 -16
  41. package/packages/selector/src/runtime/tokenpilot/proposal.ts +0 -267
  42. package/packages/selector/src/runtime/tokenpilot/review-queue.ts +0 -231
  43. package/packages/selector/src/runtime/tokenpilot/review-registry.ts +0 -117
  44. package/packages/selector/src/runtime/tokenpilot/review-storage.ts +0 -122
  45. package/packages/selector/tests/review-overlay.client.spec.tsx +0 -118
  46. package/packages/selector/tests/review-routes-registry.host.spec.ts +0 -142
  47. package/packages/selector/tests/review-routes.host.spec.ts +0 -290
  48. package/packages/selector/tests/runtime/tokenpilot/proposal.spec.ts +0 -393
  49. package/packages/selector/tests/runtime/tokenpilot/pruner-review.spec.ts +0 -382
  50. package/packages/selector/tests/runtime/tokenpilot/review-queue.spec.ts +0 -168
@@ -12,7 +12,6 @@ import { DEFAULT_CUSTOM_COMPRESSION_POLICY } from '../profiles.ts'
12
12
  import { decodeSettings } from './decode.ts'
13
13
  import { en, zh } from './locales.ts'
14
14
  import { planPresetOptionsOps, presetOptionsOpsAccepted } from './preset-options.ts'
15
- import { renderReviewOverlay } from './ReviewOverlay.tsx'
16
15
 
17
16
  /**
18
17
  * Harness 0.1.5 mounts the web core's `slots` service on the client context
@@ -142,22 +141,6 @@ export function apply(ctx: ClientContext): void {
142
141
  } catch (error) {
143
142
  console.warn('[dsh-context-compression-improved] settings.section 注册失败(新宿主已收编):', error)
144
143
  }
145
-
146
- // TokenPilot-inspired R4:审查浮窗挂在 shell.overlay(dsh-tidychat 先例:
147
- // 该层默认点击穿透,卡片自持指针事件)。reviewMode 关闭或无 pending 时组件
148
- // 渲染 null —— 与 0.1.2 宿主(无此 slot)同构的降级语义:注册失败不影响设置卡。
149
- // (本文件是 .ts:元素构造在 ReviewOverlay.renderReviewOverlay,不能内联 JSX。)
150
- try {
151
- ctx.slots.inject('shell.overlay', () => ctx.slots.register(
152
- { name: 'shell.overlay', id: 'context-compression-review' },
153
- () => {
154
- const scope = ctx.settingsScope.bind<ContextCompressionSettings>({ namespace: NS, decode: decodeSettings })
155
- return renderReviewOverlay(scope, ctx.locale.bind(NS) as (key: string) => string)
156
- },
157
- ))
158
- } catch (error) {
159
- console.warn('[dsh-context-compression-improved] shell.overlay 注册失败(宿主无浮层或已收编):', error)
160
- }
161
144
  }
162
145
 
163
146
  export type {
@@ -1,234 +1,196 @@
1
- /** Simplified Chinese copy for the context-compression selector. */
2
- export const zh = {
3
- 'nav': '上下文压缩选择器',
4
- 'settings.title': '上下文压缩选择器',
5
- 'settings.description': '为当前会话选择压缩 Profile,并配置该 Profile 提供的参数。',
6
- 'label': '上下文压缩',
7
- 'status.loading': '加载中',
8
- 'status.unavailable': '不可用',
9
- 'status.presetUnavailable': '此会话的 preset 未提供上下文压缩,或能力尚未确认。',
10
- 'status.minimalUnavailable': '极简模式不会为此会话加载上下文压缩能力,因此选择器在本会话中等效为关闭,仅保留 Harness 原生行为。切换到标准、PTC/Coding、创造模式,或支持该能力的自定义 preset 后即可配置。',
11
- 'status.saveFailed': '保存失败,请重试',
12
- 'pricing.disclosure': 'DeepSeek 官方价格目录复核于 2026-08-25。Asia/Shanghai 周一至周五 09:00–12:00、14:00–18:00 为峰时,其余为谷时;跨边界请求按成本区间处理。',
13
- 'profile.balanced': '平衡模式',
14
- 'profile.cache-strict': 'Cache Strict(前缀保护)',
15
- 'profile.savings': '节省模式',
16
- 'profile.adaptive': 'Adaptive(保守成本)',
17
- 'profile.tokenpilot-inspired': 'TokenPilot 启发模式',
18
- 'estimator.title': '估计器(可选)',
19
- 'estimator.description': '辅助小模型零样本判断旧文件读取是否仍有引用价值,仅建议性加速历史清理;未配置或失败时自动退回纯规则通道,不影响主流程。',
20
- 'estimator.mode': '通道',
21
- 'estimator.mode.off': '关闭(纯规则)',
22
- 'estimator.mode.host': '宿主模型(复用已配置供应商)',
23
- 'estimator.mode.direct': '直连 OpenAI 兼容端点',
24
- 'estimator.inactive': '估计器只随「TokenPilot 启发模式」提供:该模式的预设选项(去重指针、摘要定位块、读取状态语义与估计器通道)不会合并进其他 Profile,因此当前 Profile「{profile}」下没有可配置的估计器通道。选择「TokenPilot 启发模式」后,本区块会出现「通道」选择,可复用已配置供应商(宿主模型)或直连 OpenAI 兼容端点。',
25
- 'estimator.provider': '供应商',
26
- 'estimator.provider.placeholder': '留空则跟随会话默认模型,可从下拉选择或自定义输入',
27
- 'estimator.model.placeholder': '留空则跟随会话默认模型,可从下拉选择或自定义输入',
28
- 'estimator.hostReuse': '宿主通道直接复用你在 DSH 中已配置的供应商与凭据,无需填写 API Key;此通道也不接收 API Key。',
29
- 'estimator.hostRoute': '当前生效路由:{route}。',
30
- 'estimator.hostUnresolved': '尚未确定(请在 DSH 设置中选择默认模型,或在此指定供应商与模型)',
31
- 'estimator.baseUrl': '端点地址(/v1)',
32
- 'estimator.model': '模型',
33
- 'estimator.apiKey': 'API Key(仅写入,不回显)',
34
- 'estimator.apiKey.placeholder': '输入端点密钥并失焦保存',
35
- 'estimator.apiKey.set': '已设置 · 输入新值覆盖',
36
- 'estimator.apiKey.clear': '清除',
37
- 'estimator.apiKey.overwrite': '已设置保密值,输入新值并失焦即可覆盖。',
38
- 'review.title': '人工审查(beta)',
39
- 'review.description': '开启后,边缘区间与高影响的压缩候选不再自动执行,而是进入待审队列并在你批准后的下一个回合边界批量执行;未处理的提案超过过期轮数后自动作废。仅随「TokenPilot 启发模式」提供,默认关闭。',
40
- 'review.enabled': '审查模式',
41
- 'review.enabled.on': '开(提案等待人工批准)',
42
- 'review.enabled.off': '关(默认,全自动)',
43
- 'review.timeoutTurns': '提案过期轮数',
44
- 'review.alpha': '缓存命中折扣 α',
45
- 'review.highImpact': '高影响门槛(tokens)',
46
- 'review.badge': '待审',
47
- 'review.summary.autoApplied': '自动应用',
48
- 'review.summary.reviewApplied': '审查应用',
49
- 'review.summary.expired': '已过期',
50
- 'review.summary.voided': '已作废',
51
- 'review.row.payback': '回本轮数',
52
- 'review.row.expectedSaving': '预期节省',
53
- 'review.row.estimated': '估计',
54
- 'review.action.approve': '批准',
55
- 'review.action.reject': '驳回',
56
- 'review.action.ignore': '本会话忽略',
57
- 'detail.tokenpilot-inspired': '在平衡模式之上叠加去重指针、恢复豁免、摘要定位块、前缀稳定与读取状态语义;估计器需另行配置端点',
58
- 'profile.custom': 'Custom/实验模式',
59
- 'profile.native': '原生对照',
60
- 'profile.off': '插件关闭',
61
- 'profile.current': '当前选择',
62
- 'detail.balanced': '确定性压缩新工具结果;高水位时老化旧结果',
63
- 'detail.cache-strict': '仅在确认容量压力时老化已发送历史;服务端缓存命中仍是 best-effort',
64
- 'detail.savings': '使用更小目标并更早清理旧工具结果;不保证每个请求更便宜',
65
- 'detail.adaptive': 'Fresh/Aggregate 与平衡模式一致;仅当紧邻官方 usage 与当前官方价格证明历史压缩明确更省钱时老化历史,否则保留',
66
- 'detail.custom': '为新会话选择已实现的压缩阶段和计量阈值',
67
- 'detail.native': '只使用 DeepSeek Harness 原生头尾裁剪',
68
- 'detail.off': '关闭确定性选择器;原生 auto-compact 仍由 Harness 配置决定',
69
- 'autoCompact.title': 'Auto Compact 触发水位',
70
- 'autoCompact.description': '模型驱动 Auto Compact 在请求占用达到该水位时触发。调整后,标准 Profile 的 History 触发值、最小回收量与近期尾窗随水位联动;修改只影响新会话。',
71
- 'autoCompact.inputLabel': 'Auto Compact 阈值(%)',
72
- 'autoCompact.sliderLabel': 'Auto Compact 阈值滑杆',
73
- 'autoCompact.quick': '快捷值',
74
- 'autoCompact.riskLow': '低于推荐范围:更早触发会增加摘要调用与前缀重建。',
75
- 'autoCompact.riskHigh': '高于推荐范围:上下文容量为请求与输出共享,过晚触发会减少单次大输出、推理与工具 schema 的余量。',
76
- 'autoCompact.invalid': 'Auto Compact 阈值必须是 50–90 之间的整数。',
77
- 'autoCompact.save': '保存 Auto Compact 阈值',
78
- 'autoCompact.summaryHint': 'Auto Compact 阈值:{percent}%。可在设置中修改。',
79
- 'codeSkeleton.title': '代码骨架压缩(备选)',
80
- 'codeSkeleton.description': '正交开关:独立于上方 Profile。开启后,首次曝光的超大源码类工具结果会先尝试保留导入与声明的骨架(省略函数体并保留错误行),失败时自动回退到原头部裁剪;需要精确 tokenizer,修改只影响新会话。',
81
- 'codeSkeleton.enabled': '代码骨架压缩',
82
- 'codeSkeleton.enabled.on': '',
83
- 'codeSkeleton.enabled.off': '关(默认)',
84
- 'custom.title': 'Custom 策略',
85
- 'custom.settingsHint': '具体参数请前往“设置 > 上下文压缩选择器”中编辑。',
86
- 'custom.sessionScope': '保存后的修改会在当前压缩运行时随后首次观察某个 Session 时生效;已被该运行时观察的 Session 继续使用其冻结策略。',
87
- 'custom.measurement': '首选 DeepSeek 精确 tokenizer;不可用时回退到带校准的 tokenizer estimate,绝不使用 chars/4。缓存归因仍未知。',
88
- 'custom.unit': '规范单位',
89
- 'custom.unit.tokens': 'Tokens',
90
- 'custom.unit.contextPercent': '上下文百分比',
91
- 'custom.enabled': '是否启用',
92
- 'custom.enabled.on': '',
93
- 'custom.enabled.off': '',
94
- 'custom.fresh.enabled': '启用 Fresh',
95
- 'custom.fresh.trigger': 'Fresh 触发值',
96
- 'custom.fresh.target': 'Fresh 目标值',
97
- 'custom.aggregate.enabled': '启用 Aggregate',
98
- 'custom.aggregate.trigger': 'Aggregate 触发值',
99
- 'custom.aggregate.target': 'Aggregate 目标值',
100
- 'custom.history.enabled': '启用 History',
101
- 'custom.history.trigger': 'History 触发值',
102
- 'custom.history.keepRecentToolCalls': '保护近期工具调用数',
103
- 'custom.history.keepRecentTokens': '保护近期工具结果尾窗',
104
- 'custom.history.minReclaim': '最小回收量',
105
- 'custom.prefixPolicy': '已发送前缀策略',
106
- 'custom.prefixPolicy.preserve': '仅在容量压力时改写',
107
- 'custom.prefixPolicy.pressureBreak': '允许常规历史老化',
108
- 'custom.experimental': 'Experimental:以下功能仅用于 Custom,不会加入标准 Profile。',
109
- 'custom.tailTrim.enabled': '启用 TailTrim(实验)',
110
- 'custom.tailTrim.trigger': 'TailTrim 触发值',
111
- 'custom.tailTrim.warning': 'TailTrim 只在精确 tokenizer 可用时,把一个完整、已结束且非错误的纯工具组替换为可恢复引用;它与 History 共用近期工具调用数、工具结果尾窗和最小回收参数。它会改写已发送前缀,可能降低缓存命中。',
112
- 'custom.save': '保存 Custom 策略',
113
- 'custom.reset': '重置 Custom 策略',
114
- 'custom.invalid': 'Custom 策略参数无效。',
115
- } satisfies Record<string, string>
116
-
117
- /** Locale keys that every context-compression selector dictionary must provide. */
118
- export type ContextCompressionLocaleKey = keyof typeof zh
119
-
120
- /** English copy matching every simplified Chinese selector key. */
121
- export const en = {
122
- 'nav': 'Context compression selector',
123
- 'settings.title': 'Context compression selector',
124
- 'settings.description': 'Choose a compression profile for the current session and configure the parameters it provides.',
125
- 'label': 'Context compression',
126
- 'status.loading': 'Loading',
127
- 'status.unavailable': 'Unavailable',
128
- 'status.presetUnavailable': 'This session’s preset does not provide context compression, or availability is not yet confirmed.',
129
- 'status.minimalUnavailable': 'Minimal mode does not load context compression for this session. The selector is effectively off and Harness native behavior remains. Switch to Standard, PTC / Coding, Creative, or a capable custom preset to configure it.',
130
- 'status.saveFailed': 'Save failed. Try again.',
131
- 'pricing.disclosure': 'DeepSeek official prices checked 2026-08-25. Peak Mon–Fri 09:00–12:00 and 14:00–18:00 Asia/Shanghai; otherwise off-peak. Cross-boundary requests use a cost range.',
132
- 'profile.balanced': 'Balanced',
133
- 'profile.cache-strict': 'Cache Strict (prefix protection)',
134
- 'profile.savings': 'Savings',
135
- 'profile.adaptive': 'Adaptive (conservative cost)',
136
- 'profile.tokenpilot-inspired': 'TokenPilot-inspired',
137
- 'estimator.title': 'Estimator (optional)',
138
- 'estimator.description': 'A small auxiliary model zero-shots whether old file reads are still likely referenced, advisory-only for history aging; unconfigured or failing endpoints fall back to rule-only behavior.',
139
- 'estimator.mode': 'Channel',
140
- 'estimator.mode.off': 'Off (rule-only)',
141
- 'estimator.mode.host': 'Host model (reuse configured providers)',
142
- 'estimator.mode.direct': 'Direct OpenAI-compatible endpoint',
143
- 'estimator.inactive': 'The estimator ships only with the TokenPilot-inspired profile: that profile’s preset options (dedupe pointers, summary locators, read-state semantics, and the estimator channel) are never merged into another profile, so the current profile “{profile}” has no estimator channel to configure. Select TokenPilot-inspired and this section gains a Channel choice — reuse configured providers (host model) or a direct OpenAI-compatible endpoint.',
144
- 'estimator.provider': 'Provider',
145
- 'estimator.provider.placeholder': 'Empty follows the session default model; pick from the dropdown or type a custom id',
146
- 'estimator.model.placeholder': 'Empty follows the session default model; pick from the dropdown or type a custom id',
147
- 'estimator.hostReuse': 'The host channel reuses the providers and credentials you already configured in DSH, so no API key is needed — and none is accepted here.',
148
- 'estimator.hostRoute': 'Effective route: {route}.',
149
- 'estimator.hostUnresolved': 'not determined yet (choose a default model in DSH settings, or name a provider and model here)',
150
- 'estimator.baseUrl': 'Endpoint base URL (/v1)',
151
- 'estimator.model': 'Model',
152
- 'estimator.apiKey': 'API key (write-only, never echoed)',
153
- 'estimator.apiKey.placeholder': 'Type the endpoint key; blur to save',
154
- 'estimator.apiKey.set': 'Set · type a new value to overwrite',
155
- 'estimator.apiKey.clear': 'Clear',
156
- 'estimator.apiKey.overwrite': 'A secret is stored; type a new value and blur to overwrite it.',
157
- 'review.title': 'Review mode (beta)',
158
- 'review.description': 'When enabled, edge-band and high-impact reduction candidates no longer apply automatically: they queue for manual approval and execute in one merged batch at the next turn boundary after approval. Unhandled proposals expire after the configured number of turns. Ships with the TokenPilot-inspired profile only, off by default.',
159
- 'review.enabled': 'Review mode',
160
- 'review.enabled.on': 'On (proposals wait for manual approval)',
161
- 'review.enabled.off': 'Off (default, fully automatic)',
162
- 'review.timeoutTurns': 'Proposal expiry (turns)',
163
- 'review.alpha': 'Cache-hit discount α',
164
- 'review.highImpact': 'High-impact threshold (tokens)',
165
- 'review.badge': 'Review',
166
- 'review.summary.autoApplied': 'Auto-applied',
167
- 'review.summary.reviewApplied': 'Review-applied',
168
- 'review.summary.expired': 'Expired',
169
- 'review.summary.voided': 'Voided',
170
- 'review.row.payback': 'Payback',
171
- 'review.row.expectedSaving': 'Expected saving',
172
- 'review.row.estimated': 'estimated',
173
- 'review.action.approve': 'Approve',
174
- 'review.action.reject': 'Reject',
175
- 'review.action.ignore': 'Ignore',
176
- 'detail.tokenpilot-inspired': 'Layered on Balanced: dedupe pointers, recovery exemption, summary locators, prefix stabilization, and read-state semantics; the estimator needs an endpoint configured separately',
177
- 'profile.custom': 'Custom / Experimental',
178
- 'profile.native': 'Native baseline',
179
- 'profile.off': 'Plugin off',
180
- 'profile.current': 'Current profile',
181
- 'detail.balanced': 'Reduce fresh tool results deterministically; age old results at high watermarks',
182
- 'detail.cache-strict': 'Age sent history only under confirmed capacity pressure; provider cache hits remain best-effort',
183
- 'detail.savings': 'Use smaller targets and age old tool results earlier; does not guarantee a cheaper request',
184
- 'detail.adaptive': 'Use Balanced Fresh/Aggregate; age history only when adjacent official usage and current official prices prove a clear saving',
185
- 'detail.custom': 'Choose implemented stages and measured thresholds for new sessions',
186
- 'detail.native': 'Use only the Harness native head/tail pruner',
187
- 'detail.off': 'Disable the deterministic selector; native auto-compact remains separately configured',
188
- 'autoCompact.title': 'Auto Compact trigger level',
189
- 'autoCompact.description': 'Model-driven Auto Compact triggers once request usage crosses this level. Standard-profile History triggers, minimum reclaim, and the recent tail follow the level; changes affect new sessions only.',
190
- 'autoCompact.inputLabel': 'Auto Compact threshold (%)',
191
- 'autoCompact.sliderLabel': 'Auto Compact threshold slider',
192
- 'autoCompact.quick': 'Quick values',
193
- 'autoCompact.riskLow': 'Below the recommended band: triggering earlier increases summarization calls and prefix rebuilds.',
194
- 'autoCompact.riskHigh': 'Above the recommended band: context capacity is shared by requests and output, so triggering later reduces headroom for single large outputs, reasoning, and tool schemas.',
195
- 'autoCompact.invalid': 'The Auto Compact threshold must be an integer between 50 and 90.',
196
- 'autoCompact.save': 'Save Auto Compact threshold',
197
- 'autoCompact.summaryHint': 'Auto Compact threshold: {percent}%. Change it in Settings.',
198
- 'codeSkeleton.title': 'Code skeleton compression (opt-in)',
199
- 'codeSkeleton.description': 'Orthogonal switch, independent of the profiles above. When enabled, an oversized fresh source-code tool result first tries a skeleton that keeps imports and declarations (bodies elided, error lines kept) and falls back to the original head pruning on failure. Requires the exact tokenizer; changes affect new sessions only.',
200
- 'codeSkeleton.enabled': 'Code skeleton compression',
201
- 'codeSkeleton.enabled.on': 'On',
202
- 'codeSkeleton.enabled.off': 'Off (default)',
203
- 'custom.title': 'Custom policy',
204
- 'custom.settingsHint': 'Edit detailed parameters in Settings > Context compression selector.',
205
- 'custom.sessionScope': 'Saved changes apply when the current compression runtime next observes a Session for the first time. A Session already observed by that runtime keeps its frozen policy.',
206
- 'custom.measurement': 'Exact DeepSeek tokenizer first; tokenizer estimate with calibration fallback. Never chars/4. Cache attribution remains unknown.',
207
- 'custom.unit': 'Canonical unit',
208
- 'custom.unit.tokens': 'Tokens',
209
- 'custom.unit.contextPercent': 'Context percent',
210
- 'custom.enabled': 'Enabled',
211
- 'custom.enabled.on': 'On',
212
- 'custom.enabled.off': 'Off',
213
- 'custom.fresh.enabled': 'Enable Fresh',
214
- 'custom.fresh.trigger': 'Fresh trigger',
215
- 'custom.fresh.target': 'Fresh target',
216
- 'custom.aggregate.enabled': 'Enable Aggregate',
217
- 'custom.aggregate.trigger': 'Aggregate trigger',
218
- 'custom.aggregate.target': 'Aggregate target',
219
- 'custom.history.enabled': 'Enable History',
220
- 'custom.history.trigger': 'History trigger',
221
- 'custom.history.keepRecentToolCalls': 'Protected recent tool calls',
222
- 'custom.history.keepRecentTokens': 'Protected recent tool-result tail',
223
- 'custom.history.minReclaim': 'Minimum reclaim',
224
- 'custom.prefixPolicy': 'Sent-prefix policy',
225
- 'custom.prefixPolicy.preserve': 'Preserve until capacity pressure',
226
- 'custom.prefixPolicy.pressureBreak': 'Allow routine history aging',
227
- 'custom.experimental': 'Experimental: these controls are Custom-only and never added to standard profiles.',
228
- 'custom.tailTrim.enabled': 'Enable TailTrim (experimental)',
229
- 'custom.tailTrim.trigger': 'TailTrim trigger',
230
- 'custom.tailTrim.warning': 'TailTrim requires the exact tokenizer and replaces at most one complete, finished, non-error tool-only group with a recoverable reference. It shares Protected recent tool calls, Protected recent tool-result tail, and Minimum reclaim with History. It rewrites a sent prefix and may reduce cache hits.',
231
- 'custom.save': 'Save Custom policy',
232
- 'custom.reset': 'Reset Custom policy',
233
- 'custom.invalid': 'Custom policy values are invalid.',
234
- } satisfies Record<ContextCompressionLocaleKey, string>
1
+ /** Simplified Chinese copy for the context-compression selector. */
2
+ export const zh = {
3
+ 'nav': '上下文压缩选择器',
4
+ 'settings.title': '上下文压缩选择器',
5
+ 'settings.description': '为当前会话选择压缩 Profile,并配置该 Profile 提供的参数。',
6
+ 'label': '上下文压缩',
7
+ 'status.loading': '加载中',
8
+ 'status.unavailable': '不可用',
9
+ 'status.presetUnavailable': '此会话的 preset 未提供上下文压缩,或能力尚未确认。',
10
+ 'status.minimalUnavailable': '极简模式不会为此会话加载上下文压缩能力,因此选择器在本会话中等效为关闭,仅保留 Harness 原生行为。切换到标准、PTC/Coding、创造模式,或支持该能力的自定义 preset 后即可配置。',
11
+ 'status.saveFailed': '保存失败,请重试',
12
+ 'pricing.disclosure': 'DeepSeek 官方价格目录复核于 2026-08-25。Asia/Shanghai 周一至周五 09:00–12:00、14:00–18:00 为峰时,其余为谷时;跨边界请求按成本区间处理。',
13
+ 'profile.balanced': '平衡模式',
14
+ 'profile.cache-strict': 'Cache Strict(前缀保护)',
15
+ 'profile.savings': '节省模式',
16
+ 'profile.adaptive': 'Adaptive(保守成本)',
17
+ 'profile.tokenpilot-inspired': 'TokenPilot 启发模式',
18
+ 'estimator.title': '估计器(可选)',
19
+ 'estimator.description': '辅助小模型零样本判断旧文件读取是否仍有引用价值,仅建议性加速历史清理;未配置或失败时自动退回纯规则通道,不影响主流程。',
20
+ 'estimator.mode': '通道',
21
+ 'estimator.mode.off': '关闭(纯规则)',
22
+ 'estimator.mode.host': '宿主模型(复用已配置供应商)',
23
+ 'estimator.mode.direct': '直连 OpenAI 兼容端点',
24
+ 'estimator.inactive': '估计器只随「TokenPilot 启发模式」提供:该模式的预设选项(去重指针、摘要定位块、读取状态语义与估计器通道)不会合并进其他 Profile,因此当前 Profile「{profile}」下没有可配置的估计器通道。选择「TokenPilot 启发模式」后,本区块会出现「通道」选择,可复用已配置供应商(宿主模型)或直连 OpenAI 兼容端点。',
25
+ 'estimator.provider': '供应商',
26
+ 'estimator.provider.placeholder': '留空则跟随会话默认模型,可从下拉选择或自定义输入',
27
+ 'estimator.model.placeholder': '留空则跟随会话默认模型,可从下拉选择或自定义输入',
28
+ 'estimator.hostReuse': '宿主通道直接复用你在 DSH 中已配置的供应商与凭据,无需填写 API Key;此通道也不接收 API Key。',
29
+ 'estimator.hostRoute': '当前生效路由:{route}。',
30
+ 'estimator.hostUnresolved': '尚未确定(请在 DSH 设置中选择默认模型,或在此指定供应商与模型)',
31
+ 'estimator.baseUrl': '端点地址(/v1)',
32
+ 'estimator.model': '模型',
33
+ 'estimator.apiKey': 'API Key(仅写入,不回显)',
34
+ 'estimator.apiKey.placeholder': '输入端点密钥并失焦保存',
35
+ 'estimator.apiKey.set': '已设置 · 输入新值覆盖',
36
+ 'estimator.apiKey.clear': '清除',
37
+ 'estimator.apiKey.overwrite': '已设置保密值,输入新值并失焦即可覆盖。',
38
+ 'detail.tokenpilot-inspired': '在平衡模式之上叠加去重指针、恢复豁免、摘要定位块、前缀稳定与读取状态语义;估计器需另行配置端点',
39
+ 'profile.custom': 'Custom/实验模式',
40
+ 'profile.native': '原生对照',
41
+ 'profile.off': '插件关闭',
42
+ 'profile.current': '当前选择',
43
+ 'detail.balanced': '确定性压缩新工具结果;高水位时老化旧结果',
44
+ 'detail.cache-strict': '仅在确认容量压力时老化已发送历史;服务端缓存命中仍是 best-effort',
45
+ 'detail.savings': '使用更小目标并更早清理旧工具结果;不保证每个请求更便宜',
46
+ 'detail.adaptive': 'Fresh/Aggregate 与平衡模式一致;仅当紧邻官方 usage 与当前官方价格证明历史压缩明确更省钱时老化历史,否则保留',
47
+ 'detail.custom': '为新会话选择已实现的压缩阶段和计量阈值',
48
+ 'detail.native': '只使用 DeepSeek Harness 原生头尾裁剪',
49
+ 'detail.off': '关闭确定性选择器;原生 auto-compact 仍由 Harness 配置决定',
50
+ 'autoCompact.title': 'Auto Compact 触发水位',
51
+ 'autoCompact.description': '模型驱动 Auto Compact 在请求占用达到该水位时触发。调整后,标准 Profile 的 History 触发值、最小回收量与近期尾窗随水位联动;修改只影响新会话。',
52
+ 'autoCompact.inputLabel': 'Auto Compact 阈值(%)',
53
+ 'autoCompact.sliderLabel': 'Auto Compact 阈值滑杆',
54
+ 'autoCompact.quick': '快捷值',
55
+ 'autoCompact.riskLow': '低于推荐范围:更早触发会增加摘要调用与前缀重建。',
56
+ 'autoCompact.riskHigh': '高于推荐范围:上下文容量为请求与输出共享,过晚触发会减少单次大输出、推理与工具 schema 的余量。',
57
+ 'autoCompact.invalid': 'Auto Compact 阈值必须是 50–90 之间的整数。',
58
+ 'autoCompact.save': '保存 Auto Compact 阈值',
59
+ 'autoCompact.summaryHint': 'Auto Compact 阈值:{percent}%。可在设置中修改。',
60
+ 'codeSkeleton.title': '代码骨架压缩(备选)',
61
+ 'codeSkeleton.description': '正交开关:独立于上方 Profile。开启后,首次曝光的超大源码类工具结果会先尝试保留导入与声明的骨架(省略函数体并保留错误行),失败时自动回退到原头部裁剪;需要精确 tokenizer,修改只影响新会话。',
62
+ 'codeSkeleton.enabled': '代码骨架压缩',
63
+ 'codeSkeleton.enabled.on': '',
64
+ 'codeSkeleton.enabled.off': '关(默认)',
65
+ 'custom.title': 'Custom 策略',
66
+ 'custom.settingsHint': '具体参数请前往“设置 > 上下文压缩选择器”中编辑。',
67
+ 'custom.sessionScope': '保存后的修改会在当前压缩运行时随后首次观察某个 Session 时生效;已被该运行时观察的 Session 继续使用其冻结策略。',
68
+ 'custom.measurement': '首选 DeepSeek 精确 tokenizer;不可用时回退到带校准的 tokenizer estimate,绝不使用 chars/4。缓存归因仍未知。',
69
+ 'custom.unit': '规范单位',
70
+ 'custom.unit.tokens': 'Tokens',
71
+ 'custom.unit.contextPercent': '上下文百分比',
72
+ 'custom.enabled': '是否启用',
73
+ 'custom.enabled.on': '',
74
+ 'custom.enabled.off': '',
75
+ 'custom.fresh.enabled': '启用 Fresh',
76
+ 'custom.fresh.trigger': 'Fresh 触发值',
77
+ 'custom.fresh.target': 'Fresh 目标值',
78
+ 'custom.aggregate.enabled': '启用 Aggregate',
79
+ 'custom.aggregate.trigger': 'Aggregate 触发值',
80
+ 'custom.aggregate.target': 'Aggregate 目标值',
81
+ 'custom.history.enabled': '启用 History',
82
+ 'custom.history.trigger': 'History 触发值',
83
+ 'custom.history.keepRecentToolCalls': '保护近期工具调用数',
84
+ 'custom.history.keepRecentTokens': '保护近期工具结果尾窗',
85
+ 'custom.history.minReclaim': '最小回收量',
86
+ 'custom.prefixPolicy': '已发送前缀策略',
87
+ 'custom.prefixPolicy.preserve': '仅在容量压力时改写',
88
+ 'custom.prefixPolicy.pressureBreak': '允许常规历史老化',
89
+ 'custom.experimental': 'Experimental:以下功能仅用于 Custom,不会加入标准 Profile。',
90
+ 'custom.tailTrim.enabled': '启用 TailTrim(实验)',
91
+ 'custom.tailTrim.trigger': 'TailTrim 触发值',
92
+ 'custom.tailTrim.warning': 'TailTrim 只在精确 tokenizer 可用时,把一个完整、已结束且非错误的纯工具组替换为可恢复引用;它与 History 共用近期工具调用数、工具结果尾窗和最小回收参数。它会改写已发送前缀,可能降低缓存命中。',
93
+ 'custom.save': '保存 Custom 策略',
94
+ 'custom.reset': '重置 Custom 策略',
95
+ 'custom.invalid': 'Custom 策略参数无效。',
96
+ } satisfies Record<string, string>
97
+
98
+ /** Locale keys that every context-compression selector dictionary must provide. */
99
+ export type ContextCompressionLocaleKey = keyof typeof zh
100
+
101
+ /** English copy matching every simplified Chinese selector key. */
102
+ export const en = {
103
+ 'nav': 'Context compression selector',
104
+ 'settings.title': 'Context compression selector',
105
+ 'settings.description': 'Choose a compression profile for the current session and configure the parameters it provides.',
106
+ 'label': 'Context compression',
107
+ 'status.loading': 'Loading',
108
+ 'status.unavailable': 'Unavailable',
109
+ 'status.presetUnavailable': 'This session’s preset does not provide context compression, or availability is not yet confirmed.',
110
+ 'status.minimalUnavailable': 'Minimal mode does not load context compression for this session. The selector is effectively off and Harness native behavior remains. Switch to Standard, PTC / Coding, Creative, or a capable custom preset to configure it.',
111
+ 'status.saveFailed': 'Save failed. Try again.',
112
+ 'pricing.disclosure': 'DeepSeek official prices checked 2026-08-25. Peak Mon–Fri 09:00–12:00 and 14:00–18:00 Asia/Shanghai; otherwise off-peak. Cross-boundary requests use a cost range.',
113
+ 'profile.balanced': 'Balanced',
114
+ 'profile.cache-strict': 'Cache Strict (prefix protection)',
115
+ 'profile.savings': 'Savings',
116
+ 'profile.adaptive': 'Adaptive (conservative cost)',
117
+ 'profile.tokenpilot-inspired': 'TokenPilot-inspired',
118
+ 'estimator.title': 'Estimator (optional)',
119
+ 'estimator.description': 'A small auxiliary model zero-shots whether old file reads are still likely referenced, advisory-only for history aging; unconfigured or failing endpoints fall back to rule-only behavior.',
120
+ 'estimator.mode': 'Channel',
121
+ 'estimator.mode.off': 'Off (rule-only)',
122
+ 'estimator.mode.host': 'Host model (reuse configured providers)',
123
+ 'estimator.mode.direct': 'Direct OpenAI-compatible endpoint',
124
+ 'estimator.inactive': 'The estimator ships only with the TokenPilot-inspired profile: that profile’s preset options (dedupe pointers, summary locators, read-state semantics, and the estimator channel) are never merged into another profile, so the current profile “{profile}” has no estimator channel to configure. Select TokenPilot-inspired and this section gains a Channel choice — reuse configured providers (host model) or a direct OpenAI-compatible endpoint.',
125
+ 'estimator.provider': 'Provider',
126
+ 'estimator.provider.placeholder': 'Empty follows the session default model; pick from the dropdown or type a custom id',
127
+ 'estimator.model.placeholder': 'Empty follows the session default model; pick from the dropdown or type a custom id',
128
+ 'estimator.hostReuse': 'The host channel reuses the providers and credentials you already configured in DSH, so no API key is needed and none is accepted here.',
129
+ 'estimator.hostRoute': 'Effective route: {route}.',
130
+ 'estimator.hostUnresolved': 'not determined yet (choose a default model in DSH settings, or name a provider and model here)',
131
+ 'estimator.baseUrl': 'Endpoint base URL (/v1)',
132
+ 'estimator.model': 'Model',
133
+ 'estimator.apiKey': 'API key (write-only, never echoed)',
134
+ 'estimator.apiKey.placeholder': 'Type the endpoint key; blur to save',
135
+ 'estimator.apiKey.set': 'Set · type a new value to overwrite',
136
+ 'estimator.apiKey.clear': 'Clear',
137
+ 'estimator.apiKey.overwrite': 'A secret is stored; type a new value and blur to overwrite it.',
138
+ 'detail.tokenpilot-inspired': 'Layered on Balanced: dedupe pointers, recovery exemption, summary locators, prefix stabilization, and read-state semantics; the estimator needs an endpoint configured separately',
139
+ 'profile.custom': 'Custom / Experimental',
140
+ 'profile.native': 'Native baseline',
141
+ 'profile.off': 'Plugin off',
142
+ 'profile.current': 'Current profile',
143
+ 'detail.balanced': 'Reduce fresh tool results deterministically; age old results at high watermarks',
144
+ 'detail.cache-strict': 'Age sent history only under confirmed capacity pressure; provider cache hits remain best-effort',
145
+ 'detail.savings': 'Use smaller targets and age old tool results earlier; does not guarantee a cheaper request',
146
+ 'detail.adaptive': 'Use Balanced Fresh/Aggregate; age history only when adjacent official usage and current official prices prove a clear saving',
147
+ 'detail.custom': 'Choose implemented stages and measured thresholds for new sessions',
148
+ 'detail.native': 'Use only the Harness native head/tail pruner',
149
+ 'detail.off': 'Disable the deterministic selector; native auto-compact remains separately configured',
150
+ 'autoCompact.title': 'Auto Compact trigger level',
151
+ 'autoCompact.description': 'Model-driven Auto Compact triggers once request usage crosses this level. Standard-profile History triggers, minimum reclaim, and the recent tail follow the level; changes affect new sessions only.',
152
+ 'autoCompact.inputLabel': 'Auto Compact threshold (%)',
153
+ 'autoCompact.sliderLabel': 'Auto Compact threshold slider',
154
+ 'autoCompact.quick': 'Quick values',
155
+ 'autoCompact.riskLow': 'Below the recommended band: triggering earlier increases summarization calls and prefix rebuilds.',
156
+ 'autoCompact.riskHigh': 'Above the recommended band: context capacity is shared by requests and output, so triggering later reduces headroom for single large outputs, reasoning, and tool schemas.',
157
+ 'autoCompact.invalid': 'The Auto Compact threshold must be an integer between 50 and 90.',
158
+ 'autoCompact.save': 'Save Auto Compact threshold',
159
+ 'autoCompact.summaryHint': 'Auto Compact threshold: {percent}%. Change it in Settings.',
160
+ 'codeSkeleton.title': 'Code skeleton compression (opt-in)',
161
+ 'codeSkeleton.description': 'Orthogonal switch, independent of the profiles above. When enabled, an oversized fresh source-code tool result first tries a skeleton that keeps imports and declarations (bodies elided, error lines kept) and falls back to the original head pruning on failure. Requires the exact tokenizer; changes affect new sessions only.',
162
+ 'codeSkeleton.enabled': 'Code skeleton compression',
163
+ 'codeSkeleton.enabled.on': 'On',
164
+ 'codeSkeleton.enabled.off': 'Off (default)',
165
+ 'custom.title': 'Custom policy',
166
+ 'custom.settingsHint': 'Edit detailed parameters in Settings > Context compression selector.',
167
+ 'custom.sessionScope': 'Saved changes apply when the current compression runtime next observes a Session for the first time. A Session already observed by that runtime keeps its frozen policy.',
168
+ 'custom.measurement': 'Exact DeepSeek tokenizer first; tokenizer estimate with calibration fallback. Never chars/4. Cache attribution remains unknown.',
169
+ 'custom.unit': 'Canonical unit',
170
+ 'custom.unit.tokens': 'Tokens',
171
+ 'custom.unit.contextPercent': 'Context percent',
172
+ 'custom.enabled': 'Enabled',
173
+ 'custom.enabled.on': 'On',
174
+ 'custom.enabled.off': 'Off',
175
+ 'custom.fresh.enabled': 'Enable Fresh',
176
+ 'custom.fresh.trigger': 'Fresh trigger',
177
+ 'custom.fresh.target': 'Fresh target',
178
+ 'custom.aggregate.enabled': 'Enable Aggregate',
179
+ 'custom.aggregate.trigger': 'Aggregate trigger',
180
+ 'custom.aggregate.target': 'Aggregate target',
181
+ 'custom.history.enabled': 'Enable History',
182
+ 'custom.history.trigger': 'History trigger',
183
+ 'custom.history.keepRecentToolCalls': 'Protected recent tool calls',
184
+ 'custom.history.keepRecentTokens': 'Protected recent tool-result tail',
185
+ 'custom.history.minReclaim': 'Minimum reclaim',
186
+ 'custom.prefixPolicy': 'Sent-prefix policy',
187
+ 'custom.prefixPolicy.preserve': 'Preserve until capacity pressure',
188
+ 'custom.prefixPolicy.pressureBreak': 'Allow routine history aging',
189
+ 'custom.experimental': 'Experimental: these controls are Custom-only and never added to standard profiles.',
190
+ 'custom.tailTrim.enabled': 'Enable TailTrim (experimental)',
191
+ 'custom.tailTrim.trigger': 'TailTrim trigger',
192
+ 'custom.tailTrim.warning': 'TailTrim requires the exact tokenizer and replaces at most one complete, finished, non-error tool-only group with a recoverable reference. It shares Protected recent tool calls, Protected recent tool-result tail, and Minimum reclaim with History. It rewrites a sent prefix and may reduce cache hits.',
193
+ 'custom.save': 'Save Custom policy',
194
+ 'custom.reset': 'Reset Custom policy',
195
+ 'custom.invalid': 'Custom policy values are invalid.',
196
+ } satisfies Record<ContextCompressionLocaleKey, string>
@@ -20,11 +20,12 @@ import type { PresetOptionsSettings } from '../profiles.ts'
20
20
  /** The namespace key holding every tokenpilot-inspired sub-capability override. */
21
21
  const PRESET_OPTIONS_KEY = 'presetOptions'
22
22
 
23
- /** Every field a patch may address, in the schema's own order. */
23
+ /** Every field a patch may address, in the schema's own order. The retired
24
+ * review-gate keys are deliberately absent: nothing writes them any more, and
25
+ * a stored document that still carries them is tolerated by the decoders. */
24
26
  const PRESET_OPTION_KEYS = [
25
27
  'dedupeToolResults', 'summaryLocator', 'prefixStabilizer', 'readState', 'estimatorMode',
26
28
  'estimatorProvider', 'estimatorModel', 'estimatorBaseUrl', 'estimatorApiKey', 'estimatorTimeoutMs',
27
- 'reviewMode', 'reviewTimeoutTurns', 'cacheHitDiscountAlpha', 'reviewHighImpactTokens',
28
29
  'advisorMode', 'advisorTimeoutMs', 'advisorRefreshTurns', 'advisorScoreThreshold', 'advisorSampleLimit',
29
30
  'advisorMinTokens',
30
31
  ] as const
@@ -16,7 +16,7 @@ import {
16
16
  } from '../profiles.ts'
17
17
  import type { CompressionProfileSelectorProps } from './CompressionProfileSelector.tsx'
18
18
  import { AutoCompactThresholdControls, CodeSkeletonControls } from './CompressionProfileControls.tsx'
19
- import { EstimatorControls, EstimatorInactiveNotice, ReviewModeControls } from './EstimatorControls.tsx'
19
+ import { EstimatorControls, EstimatorInactiveNotice } from './EstimatorControls.tsx'
20
20
  import { CustomPolicyEditor, editableCustom } from './CustomPolicyEditor.tsx'
21
21
 
22
22
  /** Full-page Settings surface backed by the same durable selector state. */
@@ -105,22 +105,13 @@ export function SettingsCompressionProfileControls({
105
105
  {current !== 'tokenpilot-inspired' ? (
106
106
  <EstimatorInactiveNotice profile={t(`profile.${current}`)} t={t} />
107
107
  ) : (
108
- <>
109
- <EstimatorControls
110
- options={state.value?.presetOptions ?? {}}
111
- disabled={busy || !state.writable || !selectorAvailable}
112
- save={savePresetOptions}
113
- settle={settle}
114
- t={t}
115
- />
116
- <ReviewModeControls
117
- options={state.value?.presetOptions ?? {}}
118
- disabled={busy || !state.writable || !selectorAvailable}
119
- save={savePresetOptions}
120
- settle={settle}
121
- t={t}
122
- />
123
- </>
108
+ <EstimatorControls
109
+ options={state.value?.presetOptions ?? {}}
110
+ disabled={busy || !state.writable || !selectorAvailable}
111
+ save={savePresetOptions}
112
+ settle={settle}
113
+ t={t}
114
+ />
124
115
  )}
125
116
  <div className={css.pricing}>{t('pricing.disclosure')}</div>
126
117
  {current !== 'custom' || draft === null || !selectorAvailable ? null : (