dsh-super-code 0.3.4 → 0.3.6

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 (43) hide show
  1. package/README.md +20 -8
  2. package/client/index.js +251 -20
  3. package/cordis.patch.yml +2 -2
  4. package/docs/Changelog.md +9 -0
  5. package/docs/Compatibility.md +86 -0
  6. package/docs/UsageGuide.md +51 -0
  7. package/lib/dsh/budget-settings.d.ts +51 -0
  8. package/lib/dsh/budget-settings.d.ts.map +1 -0
  9. package/lib/dsh/budget-settings.js +188 -0
  10. package/lib/dsh/budget-settings.js.map +1 -0
  11. package/lib/dsh/budgets.d.ts +34 -0
  12. package/lib/dsh/budgets.d.ts.map +1 -0
  13. package/lib/dsh/budgets.js +65 -0
  14. package/lib/dsh/budgets.js.map +1 -0
  15. package/lib/dsh/compaction.d.ts +40 -0
  16. package/lib/dsh/compaction.d.ts.map +1 -0
  17. package/lib/dsh/compaction.js +146 -0
  18. package/lib/dsh/compaction.js.map +1 -0
  19. package/lib/dsh/index.d.ts +4 -1
  20. package/lib/dsh/index.d.ts.map +1 -1
  21. package/lib/dsh/index.js +7 -1
  22. package/lib/dsh/index.js.map +1 -1
  23. package/lib/dsh/official-budgets.d.ts +3 -0
  24. package/lib/dsh/official-budgets.d.ts.map +1 -0
  25. package/lib/dsh/official-budgets.js +114 -0
  26. package/lib/dsh/official-budgets.js.map +1 -0
  27. package/lib/dsh/ptc-budget.d.ts +5 -0
  28. package/lib/dsh/ptc-budget.d.ts.map +1 -0
  29. package/lib/dsh/ptc-budget.js +65 -0
  30. package/lib/dsh/ptc-budget.js.map +1 -0
  31. package/lib/dsh/super-code.d.ts.map +1 -1
  32. package/lib/dsh/super-code.js +26 -8
  33. package/lib/dsh/super-code.js.map +1 -1
  34. package/lib/index.d.ts +5 -1
  35. package/lib/index.d.ts.map +1 -1
  36. package/lib/index.js +5 -2
  37. package/lib/index.js.map +1 -1
  38. package/lib/task-memory-projection.d.ts +1 -1
  39. package/lib/task-memory-projection.d.ts.map +1 -1
  40. package/lib/task-memory-projection.js +7 -4
  41. package/lib/task-memory-projection.js.map +1 -1
  42. package/package.json +17 -7
  43. package/presets/super-code/agent.cordis.yml +2 -2
package/README.md CHANGED
@@ -14,15 +14,27 @@ On the same SWE-bench Pro hard-100 set, the evaluation candidate for 0.3.0 uses
14
14
 
15
15
  Extensive testing and regression checks are needed to verify each release's effectiveness. This takes time, so release cycles may be longer.
16
16
 
17
- 版本号采用 **主版本.效果优化版本.维护版本**,例如 `0.3.4`:
17
+ 版本号采用 **主版本.效果优化版本.维护版本**,例如 `0.3.6`:
18
18
 
19
- Version numbers follow **major.performance-improvement.maintenance**, for example `0.3.4`:
19
+ Version numbers follow **major.performance-improvement.maintenance**, for example `0.3.6`:
20
20
 
21
21
  | 位置 / Position | 含义 / Meaning |
22
22
  |---|---|
23
23
  | 第一位 / First (`0`) | 主版本,仅在大范围重构时调整。 / Major version; changes only for extensive refactoring. |
24
24
  | 第二位 / Second (`3`) | 效果优化版本,记录编码效果、效率等方面的优化。 / Performance-improvement version; tracks improvements to coding results, efficiency, and related capabilities. |
25
- | 第三位 / Third (`4`) | 维护版本,记录问题修复、UI 优化、兼容性适配等更新。 / Maintenance version; tracks bug fixes, UI improvements, compatibility updates, and similar changes. |
25
+ | 第三位 / Third (`6`) | 维护版本,记录问题修复、UI 优化、兼容性适配等更新。 / Maintenance version; tracks bug fixes, UI improvements, compatibility updates, and similar changes. |
26
+
27
+ ## 0.3.6 · What's New
28
+
29
+ 针对新版 Harness 预算收紧后的效果退化,新增预算配置并默认恢复此前效果更好的旧预算,无需手动填写。[更新详情](docs/Changelog.md)
30
+
31
+ Adds configurable budgets and restores the older, better-performing budgets without manual setup to address regressions observed after newer Harness versions reduced them. [Changelog](docs/Changelog.md)
32
+
33
+ ## 0.3.5 · What's New
34
+
35
+ 适配 Harness `0.2.1-rc.2`,修复 v4 会话日志升级后旧任务记录不可见的问题。[更新详情](docs/Changelog.md)
36
+
37
+ Supports Harness `0.2.1-rc.2` and restores legacy task records after v4 session-log upgrades. [Changelog](docs/Changelog.md)
26
38
 
27
39
  ## 0.3.4 · What's New
28
40
 
@@ -56,17 +68,17 @@ Adds batched tool calls and parallel reads to reduce model round trips. [Changel
56
68
 
57
69
  # 2 开始使用 · Get Started
58
70
 
59
- 请使用[已验证的 Harness 版本](docs/Compatibility.md),按所用客户端选择安装方式。
71
+ 支持 Harness `0.1.5-alpha.1` 至 `0.2.1-rc.2`,按所用客户端选择安装方式;[各版本与客户端的验证范围](docs/Compatibility.md)。
60
72
 
61
- Use a [verified Harness version](docs/Compatibility.md) and choose the installation method for your client.
73
+ Supports Harness `0.1.5-alpha.1` through `0.2.1-rc.2`. Choose the installation method for your client; see [validation coverage by version and client](docs/Compatibility.md).
62
74
 
63
75
  ## 2.1 安装 · Install
64
76
 
65
77
  ### 官方桌面版 · Official Desktop
66
78
 
67
- 打开左侧 **插件 → 添加插件**,在“包名或地址”中输入 `dsh-super-code`,点击 **安装**,完成后按提示重新加载或重启。桌面版自带运行环境,无需另外安装 Node.js。
79
+ 打开左侧 **插件 → 添加插件**,在“包名或地址”中输入 `dsh-super-code`,点击 **安装**。新版安装完成后点击 **立即启用**;其他版本按提示重新加载或重启。桌面版自带运行环境,无需另外安装 Node.js。
68
80
 
69
- Open **Plugins → Add plugin**, enter `dsh-super-code` in “Package name or address”, and click **Install**. Reload or restart if prompted. The desktop app includes its runtime; no separate Node.js installation is needed.
81
+ Open **Plugins → Add plugin**, enter `dsh-super-code` in “Package name or address”, and click **Install**. On newer hosts, click **Enable now** when installation finishes; on other versions, reload or restart if prompted. The desktop app includes its runtime; no separate Node.js installation is needed.
70
82
 
71
83
  ### Web / 命令行版 · Web / CLI
72
84
 
@@ -87,7 +99,7 @@ dsh plugin --profile web add dsh-super-code
87
99
  Download a `.tgz` package from [GitHub Releases](https://github.com/ArtlexYoung/dsh-super-code/releases). On desktop, enter its full path in “Package name or address”. For Web, run the command below with the filename you downloaded.
88
100
 
89
101
  ```bash
90
- dsh plugin --profile web add ./dsh-super-code-0.3.4.tgz
102
+ dsh plugin --profile web add ./dsh-super-code-0.3.6.tgz
91
103
  ```
92
104
 
93
105
  </details>
package/client/index.js CHANGED
@@ -256,6 +256,29 @@ const ActionButton = React.forwardRef(function ActionButton({ children, title, .
256
256
 
257
257
  const LOCALE_NS = 'dshSuperCode'
258
258
  const zh = {
259
+ 'settings.presetTab': '预设状态', 'settings.contextTab': '上下文配置', 'settings.tabs': 'Super Code 配置',
260
+ 'budget.common': '通用预算', 'budget.superCode': 'Super Code 专属预算',
261
+ 'budget.applyToOfficialPresets': '同时应用到官方预设', 'budget.officialHint': '开启后,通用预算也用于标准、PTC、极简和创造模式;不包含下方的 Super Code 专属预算。',
262
+ 'budget.superCodeHint': '仅用于 Super Code 的任务记录和任务记忆,始终不影响官方预设。',
263
+ 'budget.defaultValue': '(默认:{value})', 'budget.off': '关闭', 'budget.managed': '宿主管理',
264
+ 'budget.title': '上下文配置', 'budget.scope': '保存后对新建 Agent 生效,运行中的任务保留原配置。',
265
+ 'budget.defaults': '留空沿用默认值,括号内显示默认值;通用预算随宿主版本变化。恢复默认会清除这里的覆盖,回到插件加载配置;未配置时跟随宿主。',
266
+ 'budget.context': '上下文压缩', 'budget.execution': '批量工具执行', 'budget.advanced': '更多预算',
267
+ 'budget.pressureBasis': '压缩预算基准', 'budget.inherit': '跟随默认', 'budget.host': '宿主策略', 'budget.window': '完整上下文窗口',
268
+ 'budget.thresholdRatio': '压缩触发比例(%)', 'budget.retainRatio': '最近原文保留比例(%)', 'budget.summaryMaxTokens': '摘要输出上限(Token)',
269
+ 'budget.compactionRetries': '压缩追加尝试次数', 'budget.maxOverflowRetries': '上下文溢出重试次数',
270
+ 'budget.ptcTimeoutMs': '默认执行时限(秒)', 'budget.ptcMaxTimeoutMs': '执行时限上限(秒)',
271
+ 'budget.maxTasks': '活跃任务记录上限', 'budget.maxContextBytes': '任务记忆上下文(字节)',
272
+ 'budget.contextHint': '保留比例需小于触发比例。较大的预算会占用更多上下文。',
273
+ 'budget.ptcHint': '包含工具等待时间;默认时限不能超过上限,也不能超过宿主允许值。',
274
+ 'budget.ptcUnavailable': '此宿主的 PTC 计时由宿主管理;其他预算仍可配置。', 'budget.ptcCeiling': '宿主允许的最长时限:{seconds} 秒。',
275
+ 'budget.save': '保存预算', 'budget.reset': '恢复默认', 'budget.reload': '重新读取', 'budget.saving': '正在保存…',
276
+ 'budget.saved': '已保存,对新建 Agent 生效。', 'budget.resetDone': '已恢复默认,对新建 Agent 生效。',
277
+ 'budget.error.connection': '暂时无法读取预算,请重试。', 'budget.error.invalid': '请检查数值范围、保留比例和执行时限。',
278
+ 'budget.error.retain': '保留比例必须小于压缩触发比例;未填写时分别按 16% 和 80% 校验。', 'budget.error.ptc-order': '默认执行时限不能超过执行时限上限。',
279
+ 'budget.error.conflict': '预算已在别处修改。草稿已保留,请重新读取后再修改。', 'budget.error.read-only': '当前宿主的设置只读,无法保存。',
280
+ 'budget.error.ptc-unavailable': '此宿主不支持覆盖 PTC 总执行时限。', 'budget.error.ptc-ceiling': '执行时限超过了宿主允许的上限。',
281
+ 'budget.error.save-failed': '保存失败,草稿已保留,请重试。',
259
282
  'memory.add': '新增记忆', 'memory.edit': '编辑', 'memory.cancel': '取消', 'memory.save': '保存', 'memory.delete': '删除', 'memory.deleting': '正在删除…', 'memory.saving': '正在保存…',
260
283
  'memory.topic': '主题', 'memory.kind': '类型', 'memory.summaryLabel': '标题', 'memory.detailLabel': '内容', 'memory.manual': '手动维护',
261
284
  'memory.topicHint': '字母、数字、点、下划线或短横线,最多 96 个字符。',
@@ -326,6 +349,29 @@ const zh = {
326
349
  'detail.path': 'Agent 路径', 'detail.title': 'Agent 详情', 'detail.refresh': '刷新对话详情', 'detail.task': '任务', 'detail.agent': 'Agent', 'detail.interrupted': 'Agent · 已中断', 'detail.error': '执行错误', 'detail.incomplete': '执行未完成,请稍后重试。', 'detail.input': '输入', 'detail.output': '输出', 'detail.cacheRead': '缓存读取', 'detail.cacheWrite': '缓存写入', 'detail.total': 'Token 总量', 'detail.hitRate': '缓存命中率', 'detail.moreUsage': '用量详情', 'detail.unavailable': '未提供', 'detail.reading': '正在读取对话…', 'detail.read': '读取中…', 'detail.older': '加载更早记录', 'detail.latest': '回到最新', 'detail.empty': '暂无执行内容', 'detail.new': '有新内容 · 查看最新', 'detail.loadError': '对话详情读取失败', 'detail.connection': '连接中断,正在重连', 'detail.historyError': '历史记录读取失败', 'detail.open': '展开全文', 'detail.noAccess': '无法打开详情,请重试', 'tree.loadError': '部分执行记录读取失败,请刷新重试', 'detail.unknown': '用量未知', 'main.agent': '主 Agent', 'tree.open': '点击查看详情', 'tree.expand': '展开', 'tree.collapse': '收起', 'image': '[图片]'
327
350
  }
328
351
  const en = {
352
+ 'settings.presetTab': 'Preset status', 'settings.contextTab': 'Context settings', 'settings.tabs': 'Super Code settings',
353
+ 'budget.common': 'Common budgets', 'budget.superCode': 'Super Code budgets',
354
+ 'budget.applyToOfficialPresets': 'Also apply to official presets', 'budget.officialHint': 'Apply common budgets to Standard, PTC, Minimal and Create. Super Code task and memory limits below remain exclusive to Super Code.',
355
+ 'budget.superCodeHint': 'Task records and task memory for Super Code. These limits never affect official presets.',
356
+ 'budget.defaultValue': '(default: {value})', 'budget.off': 'off', 'budget.managed': 'host-managed',
357
+ 'budget.title': 'Context settings', 'budget.scope': 'Changes apply to new Agents. Running tasks keep their current settings.',
358
+ 'budget.defaults': 'Leave fields blank to inherit defaults. Parentheses show defaults; common budgets follow the host version. Reset clears overrides and restores the plugin configuration, or host defaults when unconfigured.',
359
+ 'budget.context': 'Context compression', 'budget.execution': 'Batched tool execution', 'budget.advanced': 'More budgets',
360
+ 'budget.pressureBasis': 'Compression budget basis', 'budget.inherit': 'Inherit default', 'budget.host': 'Host policy', 'budget.window': 'Full context window',
361
+ 'budget.thresholdRatio': 'Compress at (%)', 'budget.retainRatio': 'Keep recent context (%)', 'budget.summaryMaxTokens': 'Summary output limit (tokens)',
362
+ 'budget.compactionRetries': 'Additional compression attempts', 'budget.maxOverflowRetries': 'Context overflow retries',
363
+ 'budget.ptcTimeoutMs': 'Default deadline (seconds)', 'budget.ptcMaxTimeoutMs': 'Maximum deadline (seconds)',
364
+ 'budget.maxTasks': 'Active task record limit', 'budget.maxContextBytes': 'Task-memory context (bytes)',
365
+ 'budget.contextHint': 'Retention must be below the compression threshold. Larger budgets use more context.',
366
+ 'budget.ptcHint': 'Includes tool waits. The default deadline must fit within both the configured maximum and the host ceiling.',
367
+ 'budget.ptcUnavailable': 'This host manages PTC timing. Other budgets remain configurable.', 'budget.ptcCeiling': 'Host deadline ceiling: {seconds} seconds.',
368
+ 'budget.save': 'Save budgets', 'budget.reset': 'Reset to defaults', 'budget.reload': 'Reload settings', 'budget.saving': 'Saving…',
369
+ 'budget.saved': 'Saved. New Agents will use these settings.', 'budget.resetDone': 'Defaults restored for new Agents.',
370
+ 'budget.error.connection': 'Budgets could not be loaded. Try again.', 'budget.error.invalid': 'Check the ranges, retention ratio, and deadlines.',
371
+ 'budget.error.retain': 'Retention must be below the compression threshold. Blank values are checked as 16% and 80%, respectively.', 'budget.error.ptc-order': 'The default deadline must not exceed the maximum deadline.',
372
+ 'budget.error.conflict': 'Budgets changed elsewhere. Your draft is retained; reload before editing again.', 'budget.error.read-only': 'This host has read-only settings.',
373
+ 'budget.error.ptc-unavailable': 'This host cannot override PTC elapsed deadlines.', 'budget.error.ptc-ceiling': 'The deadline exceeds the host ceiling.',
374
+ 'budget.error.save-failed': 'Save failed. Your draft is retained; try again.',
329
375
  'memory.add': 'Add memory', 'memory.edit': 'Edit', 'memory.cancel': 'Cancel', 'memory.save': 'Save', 'memory.delete': 'Delete', 'memory.deleting': 'Deleting…', 'memory.saving': 'Saving…',
330
376
  'memory.topic': 'Topic', 'memory.kind': 'Type', 'memory.summaryLabel': 'Title', 'memory.detailLabel': 'Content', 'memory.manual': 'Manually maintained',
331
377
  'memory.topicHint': 'Letters, digits, dots, underscores or hyphens; up to 96 characters.',
@@ -1057,7 +1103,7 @@ function detailRecord(entry, t = key => zh[key] || key) {
1057
1103
  }
1058
1104
  if (event.type === 'tool/result') {
1059
1105
  const blocks = (data.message?.content || []).filter(block => block.type === 'tool-result')
1060
- // Older journals store a direct tool message; newer ones nest its content.
1106
+ // Harness journals use both direct tool messages (v4) and nested results.
1061
1107
  const direct = data.message?.role === 'tool'
1062
1108
  if (!blocks.length && !direct) return { kind: 'skip' }
1063
1109
  const failed = direct ? data.message.isError : blocks.some(block => block.isError)
@@ -1533,27 +1579,178 @@ const memoryRemoteContribution = {
1533
1579
  })),
1534
1580
  }
1535
1581
 
1582
+ // Budget settings use the same public Remote transport as the preset settings.
1583
+ const budgetRemoteContribution = {
1584
+ package: 'dsh-super-code', descriptors: ['readConfig', 'saveConfig', 'resetConfig'].map(method => ({
1585
+ id: `dsh-super-code:superCodeBudgets/${method}`, service: 'superCodeBudgets', namespace: 'superCodeBudgets', method, invocation: { kind: 'direct' },
1586
+ parameters: (method === 'saveConfig' ? ['content', 'expected'] : method === 'resetConfig' ? ['expected'] : [])
1587
+ .map(name => ({ name, wire: name, source: 'json', codec: remoteStringCodec })), result: { mode: 'src-json' },
1588
+ })),
1589
+ }
1590
+
1591
+ const budgetFields = [
1592
+ { key: 'thresholdRatio', group: 'context', factor: 0.01, min: 1, max: 100, step: 'any' },
1593
+ { key: 'retainRatio', group: 'context', factor: 0.01, min: 0, max: 100, step: 'any' },
1594
+ { key: 'summaryMaxTokens', group: 'context', factor: 1, min: 1, step: 1 },
1595
+ { key: 'ptcTimeoutMs', group: 'execution', factor: 1000, min: 0.001, step: 0.001 },
1596
+ { key: 'ptcMaxTimeoutMs', group: 'execution', factor: 1000, min: 0.001, step: 0.001 },
1597
+ { key: 'compactionRetries', group: 'advanced', factor: 1, min: 0, max: 10, step: 1 },
1598
+ { key: 'maxOverflowRetries', group: 'advanced', factor: 1, min: 0, max: 10, step: 1 },
1599
+ { key: 'maxTasks', group: 'superCode', root: true, factor: 1, min: 1, max: 128, step: 1 },
1600
+ { key: 'maxContextBytes', group: 'superCode', root: true, factor: 1, min: 1024, max: 262144, step: 1 },
1601
+ ]
1602
+ function budgetDraft(configuration) {
1603
+ return Object.fromEntries([['applyToOfficialPresets', configuration.applyToOfficialPresets ?? false], ['pressureBasis', configuration.budgets?.pressureBasis ?? ''],
1604
+ ...budgetFields.map(field => {
1605
+ const value = field.root ? configuration[field.key] : configuration.budgets?.[field.key]
1606
+ return [field.key, value === undefined ? '' : String(value / field.factor)]
1607
+ })])
1608
+ }
1609
+ function budgetConfiguration(draft) {
1610
+ const config = {}, budgets = {}
1611
+ if (draft.applyToOfficialPresets !== undefined) {
1612
+ if (typeof draft.applyToOfficialPresets !== 'boolean') return { ok: false, error: 'invalid' }
1613
+ config.applyToOfficialPresets = draft.applyToOfficialPresets
1614
+ }
1615
+ if (draft.pressureBasis) {
1616
+ if (!['host', 'window'].includes(draft.pressureBasis)) return { ok: false, error: 'invalid' }
1617
+ budgets.pressureBasis = draft.pressureBasis
1618
+ }
1619
+ for (const field of budgetFields) {
1620
+ const input = draft[field.key]?.trim()
1621
+ if (!input) continue
1622
+ const value = Number(input)
1623
+ if (!Number.isFinite(value) || value < field.min || (field.max !== undefined && value > field.max)) return { ok: false, error: 'invalid' }
1624
+ const scaled = value * field.factor
1625
+ const selected = field.step === 'any' ? scaled : Math.round(scaled)
1626
+ if (field.step !== 'any' && (Math.abs(selected - scaled) > 1e-7 || !Number.isSafeInteger(selected))) return { ok: false, error: 'invalid' }
1627
+ ;(field.root ? config : budgets)[field.key] = selected
1628
+ }
1629
+ if ((budgets.retainRatio ?? 0.16) >= (budgets.thresholdRatio ?? 0.8)) return { ok: false, error: 'retain' }
1630
+ if (budgets.ptcTimeoutMs !== undefined && budgets.ptcMaxTimeoutMs !== undefined && budgets.ptcTimeoutMs > budgets.ptcMaxTimeoutMs) return { ok: false, error: 'ptc-order' }
1631
+ if (Object.keys(budgets).length) config.budgets = budgets
1632
+ return { ok: true, configuration: config }
1633
+ }
1634
+
1635
+ function BudgetSettings({ api, t, active }) {
1636
+ const [snapshot, setSnapshot] = useState(null)
1637
+ const [draft, setDraft] = useState(() => budgetDraft({})), [busy, setBusy] = useState(false)
1638
+ const [error, setError] = useState(''), [notice, setNotice] = useState('')
1639
+ const alive = useRef(false), pending = useRef(false)
1640
+ const receive = value => { setSnapshot(value); setDraft(budgetDraft(value.configuration)) }
1641
+ const read = async () => {
1642
+ if (pending.current) return
1643
+ pending.current = true; setBusy(true); setError(''); setNotice('')
1644
+ try {
1645
+ const response = await api.readConfig()
1646
+ if (!response.ok) throw new Error('Remote unavailable')
1647
+ if (alive.current) receive(response.value)
1648
+ } catch { if (alive.current) setError('connection') }
1649
+ finally { pending.current = false; if (alive.current) setBusy(false) }
1650
+ }
1651
+ useEffect(() => { alive.current = true; return () => { alive.current = false } }, [api])
1652
+ useEffect(() => { if (active && !snapshot && !error) read() }, [api, active])
1653
+ const save = async reset => {
1654
+ if (pending.current || !snapshot?.writable) return
1655
+ const parsed = reset ? { ok: true } : budgetConfiguration(draft)
1656
+ if (!parsed.ok) { setError(parsed.error); setNotice(''); return }
1657
+ pending.current = true; setBusy(true); setError(''); setNotice('')
1658
+ try {
1659
+ const response = reset ? await api.resetConfig(String(snapshot.revision))
1660
+ : await api.saveConfig(JSON.stringify(parsed.configuration), String(snapshot.revision))
1661
+ if (!response.ok) throw new Error('Remote unavailable')
1662
+ if (!alive.current) return
1663
+ if (response.value.ok) { receive(response.value.snapshot); setNotice(reset ? 'resetDone' : 'saved') }
1664
+ else setError(response.value.error)
1665
+ } catch { if (alive.current) setError('save-failed') }
1666
+ finally { pending.current = false; if (alive.current) setBusy(false) }
1667
+ }
1668
+ const disabled = busy || !snapshot?.writable
1669
+ const dirty = snapshot && JSON.stringify(draft) !== JSON.stringify(budgetDraft(snapshot.configuration))
1670
+ const edit = (key, value) => { setDraft(current => ({ ...current, [key]: value })); setError(''); setNotice('') }
1671
+ const defaultLabel = (key, field) => {
1672
+ const value = field?.root ? snapshot?.defaults?.[key] : snapshot?.defaults?.budgets?.[key]
1673
+ const shown = key === 'pressureBasis' ? t('budget.host') : value === undefined ? t('budget.managed') : Number(value / field.factor).toLocaleString('en-US', { maximumFractionDigits: 3 })
1674
+ return React.createElement('span', { className: 'dsh-super-code-budget-default' }, text(t, 'budget.defaultValue', { value: shown }))
1675
+ }
1676
+ const fields = group => budgetFields.filter(field => field.group === group).map(field => {
1677
+ const id = `super-code-budget-${field.key}`
1678
+ return React.createElement('div', { className: 'dsh-super-code-settings-field', key: field.key },
1679
+ React.createElement('label', { htmlFor: id }, t(`budget.${field.key}`), ' ', defaultLabel(field.key, field)),
1680
+ React.createElement('input', { id, type: 'number', inputMode: 'decimal', value: draft[field.key],
1681
+ min: field.min, max: group === 'execution' && snapshot?.ptcMaxTimeoutMs ? snapshot.ptcMaxTimeoutMs / 1000 : field.max,
1682
+ step: field.step, placeholder: t('budget.inherit'), disabled: disabled || (group === 'execution' && snapshot?.ptcMaxTimeoutMs === false),
1683
+ onChange: event => edit(field.key, event.target.value) }))
1684
+ })
1685
+ return React.createElement('section', { className: 'dsh-super-code-budgets' },
1686
+ React.createElement('form', { 'aria-label': t('budget.title'), 'aria-busy': busy, onSubmit: event => { event.preventDefault(); save(false) } },
1687
+ React.createElement('p', { className: 'dsh-super-code-budget-hint' }, t('budget.scope')),
1688
+ React.createElement('section', { className: 'dsh-super-code-budget-group', 'aria-labelledby': 'super-code-common-title' },
1689
+ React.createElement('h3', { id: 'super-code-common-title' }, t('budget.common')),
1690
+ React.createElement('label', { className: 'dsh-super-code-budget-switch' },
1691
+ React.createElement('input', { type: 'checkbox', role: 'switch', checked: draft.applyToOfficialPresets, disabled,
1692
+ 'aria-describedby': 'super-code-official-hint', onChange: event => edit('applyToOfficialPresets', event.target.checked) }),
1693
+ React.createElement('span', null, t('budget.applyToOfficialPresets'), ' ', React.createElement('span', { className: 'dsh-super-code-budget-default' }, text(t, 'budget.defaultValue', { value: t('budget.off') })))),
1694
+ React.createElement('p', { id: 'super-code-official-hint', className: 'dsh-super-code-budget-hint' }, t('budget.officialHint')),
1695
+ React.createElement('p', { className: 'dsh-super-code-budget-hint' }, t('budget.defaults')),
1696
+ React.createElement('fieldset', null, React.createElement('legend', null, t('budget.context')),
1697
+ React.createElement('div', { className: 'dsh-super-code-budget-grid' },
1698
+ React.createElement('div', { className: 'dsh-super-code-settings-field' },
1699
+ React.createElement('label', { id: 'super-code-budget-basis-label' }, t('budget.pressureBasis'), ' ', defaultLabel('pressureBasis')),
1700
+ React.createElement(SelectControl, { id: 'super-code-budget-basis', label: t('budget.pressureBasis'), value: draft.pressureBasis,
1701
+ choices: [['', t('budget.inherit')], ['host', t('budget.host')], ['window', t('budget.window')]], disabled,
1702
+ onChange: value => edit('pressureBasis', value) })), fields('context')),
1703
+ React.createElement('small', null, t('budget.contextHint'))),
1704
+ React.createElement('fieldset', null, React.createElement('legend', null, t('budget.execution')),
1705
+ React.createElement('div', { className: 'dsh-super-code-budget-grid' }, fields('execution')),
1706
+ React.createElement('small', null, t(snapshot?.ptcMaxTimeoutMs === false ? 'budget.ptcUnavailable' : 'budget.ptcHint')),
1707
+ snapshot?.ptcMaxTimeoutMs && React.createElement('small', null, text(t, 'budget.ptcCeiling', { seconds: snapshot.ptcMaxTimeoutMs / 1000 }))),
1708
+ React.createElement('details', { className: 'dsh-super-code-budget-more' },
1709
+ React.createElement('summary', null, t('budget.advanced')),
1710
+ React.createElement('div', { className: 'dsh-super-code-budget-grid' }, fields('advanced')))),
1711
+ React.createElement('section', { className: 'dsh-super-code-budget-group dsh-super-code-budget-exclusive', 'aria-labelledby': 'super-code-exclusive-title' },
1712
+ React.createElement('h3', { id: 'super-code-exclusive-title' }, t('budget.superCode')),
1713
+ React.createElement('p', { className: 'dsh-super-code-budget-hint' }, t('budget.superCodeHint')),
1714
+ React.createElement('div', { className: 'dsh-super-code-budget-grid' }, fields('superCode'))),
1715
+ !busy && snapshot && !snapshot.writable && React.createElement('small', null, t('budget.error.read-only')),
1716
+ error && React.createElement('p', { role: 'alert' }, t(`budget.error.${error}`)),
1717
+ notice && React.createElement('p', { role: 'status', className: 'dsh-super-code-budget-hint' }, t(`budget.${notice}`)),
1718
+ React.createElement('div', { className: 'dsh-super-code-settings-form-actions' },
1719
+ error && React.createElement(ActionButton, { type: 'button', disabled: busy, onClick: read }, t('budget.reload')),
1720
+ React.createElement(ActionButton, { type: 'button', disabled, onClick: () => save(true) }, t('budget.reset')),
1721
+ React.createElement(ActionButton, { type: 'submit', className: 'dsh-super-code-primary-button', disabled: disabled || !dirty }, t(busy ? 'budget.saving' : 'budget.save')))))
1722
+ }
1723
+
1536
1724
  // Old hosts render file metadata. Synchronize through our own Remote, then
1537
1725
  // reload their cached roster only when a managed field actually changed.
1538
1726
  function synchronizePresetDisplay(api, locale, reload, onError, preferenceScope) {
1539
1727
  let disposed = false, running = false, pending = '', last = '', needsReload = false
1728
+ let observed = locale.getSnapshot().active, awaitingPreference = false, settled = false
1540
1729
  const changed = () => {
1541
- // A provisional browser locale can precede the host's saved preference.
1542
- // Do not rewrite the preset or reload while that public scope is loading.
1543
- if (preferenceScope?.getSnapshot().status === 'loading') return
1544
- pending = locale.getSnapshot().active
1545
- if (running || pending === last) return
1730
+ const language = locale.getSnapshot().active
1731
+ if (language !== observed) { observed = language; awaitingPreference = !!preferenceScope }
1732
+ const preference = preferenceScope?.getSnapshot()
1733
+ // Locale publishes optimistically, before its host write starts. A reload
1734
+ // must wait for that preference to appear in the accepted public snapshot.
1735
+ settled = preference?.status !== 'loading'
1736
+ if (preference?.status === 'ready' && preference.mode !== 'memory') {
1737
+ if (preference.value?.preference === language) awaitingPreference = false
1738
+ else if (awaitingPreference || preference.value?.preference !== undefined) settled = false
1739
+ }
1740
+ if (!settled) return
1741
+ pending = language
1742
+ if (running || (pending === last && !needsReload)) return
1546
1743
  running = true
1547
1744
  void (async () => {
1548
1745
  try {
1549
- while (!disposed && pending !== last) {
1746
+ while (!disposed && settled && pending !== last) {
1550
1747
  const language = pending
1551
1748
  const result = await api.synchronize(language)
1552
1749
  if (!result.ok) throw new Error('Preset display synchronization failed')
1553
1750
  last = language
1554
1751
  needsReload ||= result.value.changed
1555
- if (!disposed && needsReload && pending === language) { reload(); return }
1556
1752
  }
1753
+ if (!disposed && settled && needsReload && pending === last) reload()
1557
1754
  } catch (error) { if (!disposed) onError(error) }
1558
1755
  finally { running = false }
1559
1756
  })()
@@ -1564,7 +1761,8 @@ function synchronizePresetDisplay(api, locale, reload, onError, preferenceScope)
1564
1761
  return () => { disposed = true; unsubscribe(); unsubscribePreference() }
1565
1762
  }
1566
1763
 
1567
- function PresetSettings({ api, t }) {
1764
+ function PresetSettings({ api, budgetApi, t }) {
1765
+ const [tab, setTab] = useState('preset')
1568
1766
  const [status, setStatus] = useState(null), [customId, setCustomId] = useState(null)
1569
1767
  const reinstall = status?.reinstallable ?? status?.state === 'installed'
1570
1768
  const name = customId ?? (reinstall ? status.id : 'super-code')
@@ -1630,12 +1828,22 @@ function PresetSettings({ api, t }) {
1630
1828
  const available = status && ['available', 'installed'].includes(status.state)
1631
1829
  const versionState = status?.presetVersion ? status.presetVersion === status.pluginVersion ? 'match' : 'mismatch' : 'unknown'
1632
1830
  return React.createElement('section', { className: 'dsh-super-code-settings' },
1633
- React.createElement('header', { className: 'dsh-super-code-settings-header' },
1634
- React.createElement('span', { className: 'dsh-super-code-settings-mark', 'aria-hidden': true }, React.createElement(Glyph, { type: 'code' })),
1635
- React.createElement('div', { className: 'dsh-super-code-settings-head-text' },
1636
- React.createElement('h2', { className: 'dsh-super-code-settings-name' }, t('preset.title')),
1637
- React.createElement('p', { className: 'dsh-super-code-settings-description' }, t('preset.description')))),
1831
+ React.createElement('div', { className: 'dsh-super-code-settings-tabs', role: 'tablist', 'aria-label': t('settings.tabs'), onKeyDown: event => {
1832
+ if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return
1833
+ event.preventDefault()
1834
+ const selected = event.key === 'Home' ? 'preset' : event.key === 'End' ? 'context' : tab === 'preset' ? 'context' : 'preset'
1835
+ setTab(selected)
1836
+ event.currentTarget.querySelector(`#super-code-tab-${selected}`)?.focus()
1837
+ } }, ...['preset', 'context'].map(value => React.createElement('button', { key: value, type: 'button', role: 'tab',
1838
+ id: `super-code-tab-${value}`, 'aria-selected': tab === value, 'aria-controls': `super-code-panel-${value}`,
1839
+ tabIndex: tab === value ? 0 : -1, onClick: () => setTab(value) }, t(`settings.${value}Tab`)))),
1638
1840
  React.createElement('div', { className: 'dsh-super-code-settings-body' },
1841
+ React.createElement('div', { role: 'tabpanel', id: 'super-code-panel-preset', 'aria-labelledby': 'super-code-tab-preset', hidden: tab !== 'preset' },
1842
+ React.createElement('header', { className: 'dsh-super-code-settings-header' },
1843
+ React.createElement('span', { className: 'dsh-super-code-settings-mark', 'aria-hidden': true }, React.createElement(Glyph, { type: 'code' })),
1844
+ React.createElement('div', { className: 'dsh-super-code-settings-head-text' },
1845
+ React.createElement('h2', { className: 'dsh-super-code-settings-name' }, t('preset.title')),
1846
+ React.createElement('p', { className: 'dsh-super-code-settings-description' }, t('preset.description')))),
1639
1847
  React.createElement('div', { className: 'dsh-super-code-settings-summary' },
1640
1848
  React.createElement('div', { className: 'dsh-super-code-settings-status-row' },
1641
1849
  status ? React.createElement('p', { className: 'dsh-super-code-preset-status', role: 'status', 'data-available': available },
@@ -1672,6 +1880,8 @@ function PresetSettings({ api, t }) {
1672
1880
  status?.delivery === 'declaration' && !status.authorable && React.createElement('p', { role: 'note' }, t('preset.declaredReadonly')),
1673
1881
  status?.delivery === 'directory' && !status.authorable && React.createElement('p', { role: 'note' }, t('preset.readonly'))),
1674
1882
  error && React.createElement('p', { role: 'alert' }, t(error))),
1883
+ React.createElement('div', { role: 'tabpanel', id: 'super-code-panel-context', 'aria-labelledby': 'super-code-tab-context', hidden: tab !== 'context' },
1884
+ React.createElement(BudgetSettings, { api: budgetApi, t, active: tab === 'context' }))),
1675
1885
  confirmation && React.createElement('dialog', { ref: dialog, className: 'dsh-super-code-confirm',
1676
1886
  'aria-labelledby': 'super-code-confirm-title', 'aria-describedby': 'super-code-confirm-hint',
1677
1887
  onKeyDown: event => { if (event.key === 'Escape') event.stopPropagation() },
@@ -1709,20 +1919,20 @@ function apply(ctx) {
1709
1919
  // $mount creates a lifecycle effect on this same fiber; awaiting it from
1710
1920
  // another effect would stall the namespace and the settings contribution.
1711
1921
  void ctx.remote.$mount({ package: 'dsh-super-code', descriptors: [
1712
- ...presetRemoteContribution.descriptors, ...memoryRemoteContribution.descriptors,
1922
+ ...presetRemoteContribution.descriptors, ...memoryRemoteContribution.descriptors, ...budgetRemoteContribution.descriptors,
1713
1923
  ] }).catch(error => console.warn('Super Code Remote:', error))
1714
1924
  const memoryStates = new WeakMap(), workspaceStates = new WeakMap()
1715
1925
  // Locale already requires its host's preference service. Declare that same
1716
1926
  // service here: Cordis rejects even optional reads without an injection.
1717
1927
  const preferenceService = 'configForms' in ctx ? 'configForms' : 'settingsScope'
1718
- ctx.inject(['remote.superCodePresets', preferenceService], ready => {
1928
+ ctx.inject(['remote.superCodePresets', 'remote.superCodeBudgets', preferenceService], ready => {
1719
1929
  const preferenceScope = preferenceService === 'configForms'
1720
1930
  ? ready.configForms.get('locale') : ready.settingsScope.bind({ namespace: 'locale' })
1721
1931
  ready.effect(() => synchronizePresetDisplay(ready.remote.superCodePresets, locale,
1722
1932
  () => window.location.reload(), error => console.warn('Super Code preset display:', error), preferenceScope), 'super-code: preset display')
1723
1933
  ready.slots.inject('settings.section', () => ready.slots.register({
1724
1934
  name: 'settings.section', id: 'super-code', order: 120, label: () => t('preset.title'), locale: LOCALE_NS,
1725
- inject: () => ({ api: ready.remote.superCodePresets }),
1935
+ inject: () => ({ api: ready.remote.superCodePresets, budgetApi: ready.remote.superCodeBudgets }),
1726
1936
  }, PresetSettings))
1727
1937
  })
1728
1938
  ctx.effect(() => {
@@ -1766,7 +1976,7 @@ function apply(ctx) {
1766
1976
 
1767
1977
  /* Settings. */
1768
1978
  .dsh-super-code-settings{container-type:inline-size;border:1px solid var(--sc-line);border-radius:12px;background:var(--sc-bg);overflow:hidden}
1769
- .dsh-super-code-settings-header{display:flex;align-items:center;gap:12px;padding:20px 24px;border-bottom:1px solid var(--sc-line)}
1979
+ .dsh-super-code-settings-header{display:flex;align-items:center;gap:12px;padding-bottom:20px;margin-bottom:20px;border-bottom:1px solid var(--sc-line)}
1770
1980
  .dsh-super-code-settings-mark{display:grid;place-items:center;flex:none;width:40px;height:40px;background:var(--sc-surface);border:1px solid var(--sc-line);border-radius:10px}
1771
1981
  .dsh-super-code-settings-mark svg{width:22px;height:22px;color:var(--sc-text)}
1772
1982
  .dsh-super-code-settings-head-text{display:grid;gap:4px;min-width:0}
@@ -1803,8 +2013,29 @@ function apply(ctx) {
1803
2013
  .dsh-super-code-settings-guidance:empty{display:none}
1804
2014
  .dsh-super-code-settings-guidance{margin-top:20px;padding-top:12px;border-top:1px solid var(--sc-line);color:var(--sc-muted);font-size:12px}
1805
2015
  .dsh-super-code-settings-guidance p{margin:0 0 4px}
2016
+ .dsh-super-code-settings-tabs{display:flex;gap:24px;padding:0 24px;border-bottom:1px solid var(--sc-line)}
2017
+ .dsh-super-code-settings-tabs>[role=tab]{border:0;border-bottom:2px solid transparent;background:none;color:var(--sc-muted);padding:12px 0;font-size:13px;cursor:pointer}
2018
+ .dsh-super-code-settings-tabs>[role=tab][aria-selected=true]{border-bottom-color:var(--sc-text);color:var(--sc-text);font-weight:600}
2019
+ .dsh-super-code-settings-tabs>[role=tab]:focus-visible{outline:2px solid var(--sc-active);outline-offset:3px;border-radius:2px}
2020
+ .dsh-super-code-settings [role=tabpanel][hidden]{display:none}
2021
+ .dsh-super-code-budgets form{gap:24px}
2022
+ .dsh-super-code-budget-hint{margin:0;color:var(--sc-muted);font-size:12px;line-height:1.65}
2023
+ .dsh-super-code-budget-group{display:flex;flex-direction:column;gap:16px;min-width:0}
2024
+ .dsh-super-code-budget-group h3{margin:0;font-size:14px;font-weight:600}
2025
+ .dsh-super-code-budget-exclusive{border-top:1px solid var(--sc-line);padding-top:24px}
2026
+ .dsh-super-code-budget-switch{display:flex;align-items:center;gap:10px;font-size:13px;cursor:pointer}
2027
+ .dsh-super-code-budget-switch input{width:30px;height:17px;flex:none;accent-color:var(--sc-active);cursor:pointer}
2028
+ .dsh-super-code-budget-default{color:var(--sc-muted);font-weight:400;font-size:12px}
2029
+ .dsh-super-code-budgets fieldset{min-width:0;margin:0;border:0;padding:0}
2030
+ .dsh-super-code-budgets legend{font-size:13px;font-weight:500;margin-bottom:12px;padding:0}
2031
+ .dsh-super-code-budget-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 16px}
2032
+ .dsh-super-code-budgets fieldset>small{margin-top:8px}
2033
+ .dsh-super-code-budget-more>summary{cursor:pointer;color:var(--sc-muted);font-size:13px;margin-bottom:12px}
2034
+ .dsh-super-code-budgets .dsh-super-code-settings-form-actions>button{margin-left:0}
2035
+ .dsh-super-code-budgets .dsh-super-code-settings-form-actions{border-top:1px solid var(--sc-line);padding-top:16px}
2036
+ @container(max-width:420px){.dsh-super-code-budget-grid{grid-template-columns:1fr}.dsh-super-code-settings-tabs{padding:0 16px}}
1806
2037
  .dsh-super-code-settings [role=alert],.dsh-super-code-detail [role=alert],.dsh-super-code-tree-error{font-size:13px;color:var(--sc-error);overflow-wrap:anywhere}
1807
- @container(max-width:420px){.dsh-super-code-settings-header{padding:16px}.dsh-super-code-settings-body{padding:16px}.dsh-super-code-settings-summary{padding:12px}.dsh-super-code-settings-status-row{gap:8px}.dsh-super-code-preset-status{flex-basis:100%}.dsh-super-code-settings-form-actions>small{min-width:0;flex-basis:100%}}
2038
+ @container(max-width:420px){.dsh-super-code-settings-header{padding-bottom:16px;margin-bottom:16px}.dsh-super-code-settings-body{padding:16px}.dsh-super-code-settings-summary{padding:12px}.dsh-super-code-settings-status-row{gap:8px}.dsh-super-code-preset-status{flex-basis:100%}.dsh-super-code-settings-form-actions>small{min-width:0;flex-basis:100%}}
1808
2039
 
1809
2040
  /* Confirmation. */
1810
2041
  .dsh-super-code-confirm{width:min(520px,calc(100vw - 32px));max-height:calc(100dvh - 48px);overflow:auto;border:1px solid var(--sc-line);border-radius:16px;padding:24px;background:var(--sc-bg);box-shadow:0 12px 48px #0003}
@@ -2173,5 +2404,5 @@ function apply(ctx) {
2173
2404
  ctx.effect(() => disposeMemoryType, 'super-code: memory library tab')
2174
2405
  }
2175
2406
 
2176
- return { inject, apply, synchronizePresetDisplay, agentSessionState, buildAgentView, visibleAgentRows, agentTreeDisplay, agentTreeTotals, agentTreeLayout, agentExecutionStatus, agentDetailAddress, agentDetailTarget, agentPath, detailRecord, createAgentInspector, agentHistoryRange, agentHistoryRows, agentHistoryWindow, memoryLibraryAddress, memoryLibraryTarget, memoryLibraryNavigation, memoryLibraryWindow, createMemoryEditor }
2407
+ return { inject, apply, budgetDraft, budgetConfiguration, synchronizePresetDisplay, agentSessionState, buildAgentView, visibleAgentRows, agentTreeDisplay, agentTreeTotals, agentTreeLayout, agentExecutionStatus, agentDetailAddress, agentDetailTarget, agentPath, detailRecord, createAgentInspector, agentHistoryRange, agentHistoryRows, agentHistoryWindow, memoryLibraryAddress, memoryLibraryTarget, memoryLibraryNavigation, memoryLibraryWindow, createMemoryEditor }
2177
2408
  } })
package/cordis.patch.yml CHANGED
@@ -17,7 +17,7 @@
17
17
  - id: super-code
18
18
  name: dsh-super-code/super-code
19
19
  config:
20
- presetVersion: 0.3.4
20
+ presetVersion: 0.3.6
21
21
  presetInstallation: bundle:dsh-super-code
22
22
  - id: compaction
23
23
  name: cordis:group
@@ -26,7 +26,7 @@
26
26
  compaction: true
27
27
  config:
28
28
  - id: compaction-basic
29
- name: '@deepseek-ai/dsh-compaction-basic'
29
+ name: dsh-super-code/compaction
30
30
  - id: command-compact
31
31
  name: '@deepseek-ai/dsh-command-compact'
32
32
  - id: agent-instructions
package/docs/Changelog.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # 版本记录 · Changelog
2
2
 
3
+ - **0.3.6 · 2026-10-20**:排查发现新版 Harness 预算收紧后出现效果退化,因此增加插件内预算配置,并默认使用此前 Pro 测试中效果更好的旧预算,无需用户手动填写:按完整上下文窗口计算、80% 触发压缩、保留最近 16% 原文、摘要上限 8,192 Token,压缩追加尝试与溢出重试各 1 次,支持新版 PTC 的宿主默认执行时限和上限均为 600 秒。保留原有宿主默认值提示、用户自定义覆盖及运行中 Agent 的配置快照;旧宿主按能力禁用时限覆盖,始终遵守宿主时限上限。官方预设仍需手动开启应用。该修复不代表新增或改写历史评测成绩。[预算设置](UsageGuide.md#运行预算--runtime-budgets)
4
+ **0.3.6 · 2026-10-20**: Investigation found regressions after newer Harness versions reduced their budgets. Adds in-plugin budget settings and defaults to the older budgets that performed better in the Pro tests, without manual setup: full-context-window accounting, compression at 80%, 16% recent verbatim retention, an 8,192-token summary cap, one additional compression attempt and one overflow retry, and 600-second default/maximum deadlines on hosts with the newer PTC provider. Preserves host-default hints, user overrides, and running Agents' configuration snapshots. Older hosts disable unsupported deadline overrides, and host ceilings always apply. Official presets remain opt-in. This fix does not add or revise historical evaluation scores. [Budget settings](UsageGuide.md#运行预算--runtime-budgets)
5
+
6
+ 设置页按“预设状态 / 上下文配置”分组,预算支持保存、恢复默认和并发编辑冲突检查;修复语言偏好尚未保存时提前重载导致语言回退的问题。完成 20 个 Web 版本、5 个官方 macOS arm64 Desktop 版本与 DSH NEXT 的兼容复验;[验证范围与限制](Compatibility.md)。
7
+ Groups settings into Preset status / Context settings, with budget saving, reset, and concurrent-edit conflict checks. Fixes language changes being lost when the page reloads before the host saves the preference. Revalidated 20 Web versions, five official macOS arm64 Desktop versions, and DSH NEXT; [coverage and limits](Compatibility.md).
8
+
9
+ - **0.3.5 · 2026-10-18**:适配 Harness `0.2.1-rc.2`,修复 v4 日志迁移后旧任务记录不可见的问题,保留 `0.1.5-alpha.1` 起的兼容性,并补齐官方桌面安装说明。[验证范围](Compatibility.md)
10
+ **0.3.5 · 2026-10-18**: Supports Harness `0.2.1-rc.2`, restores legacy task records after v4 log migration, retains support from `0.1.5-alpha.1`, and clarifies official Desktop installation. [Validation coverage](Compatibility.md)
11
+
3
12
  - **0.3.4 · 2026-10-15**:补充官方预设在同一批 100 题上的成绩、用量与耗时核算说明;新增 README 致谢表格和[详细致谢文档](Acknowledgements.md),说明宿主、界面设计、Skill、无障碍资料、评测项目与运行依赖的贡献和借鉴范围,并将文档纳入 npm 包。
4
13
  **0.3.4 · 2026-10-15**: Adds official preset results on the same 100 tasks, with usage and timing methodology. Adds a README acknowledgements table and [detailed acknowledgements](Acknowledgements.md) covering the host, UI design, Skills, accessibility resources, evaluation projects, and runtime dependencies; includes the document in the npm package.
5
14
 
@@ -1,5 +1,91 @@
1
1
  # 宿主兼容性 · Host Compatibility
2
2
 
3
+ ## 0.3.6 · 旧预算默认配置 · Legacy Budget Defaults · 2026-10-20
4
+
5
+ 0.3.6 默认使用此前 Pro 测试的旧预算:完整上下文窗口、80% 压缩触发、16% 原文保留、8,192 Token 摘要、压缩追加与溢出重试各 1 次;提供新版 PTC 的宿主默认/上限为 600 秒,仍受宿主上限约束。用户保存值和加载配置优先,运行中的 Agent 保留快照,恢复默认会回到旧预算。括号内宿主默认值提示保持不变,官方预设仍默认不应用。
6
+
7
+ Version 0.3.6 uses the older Pro-test budgets by default: full-context-window accounting, compression at 80%, 16% verbatim retention, an 8,192-token summary cap, and one additional compression attempt and overflow retry. Hosts with the newer PTC provider use 600-second default/maximum deadlines within the host ceiling. Saved values and plugin configuration take precedence; running Agents retain their snapshots, and reset restores the older budgets. Host-default hints in parentheses remain unchanged, and official presets remain opt-in.
8
+
9
+ 对下方同一组 **20 个 Web、5 个官方 macOS arm64 Desktop 和 DSH NEXT** 完成默认策略的增量复验,每个目标通过 6 项页面/实际 Agent 检查和 1 项进程冷重启检查,135 个运行文件与新候选逐字节一致。195 项测试、类型、构建和客户端语法检查通过;20 个实际 Web 宿主与 NEXT 各 11 项引擎检查通过。旧宿主无 `ptcRuntime` 时不会补入不支持的时限字段。客户端源文件字节未变。
10
+
11
+ The same **20 Web versions, five official macOS arm64 Desktop versions, and DSH NEXT** listed below passed incremental checks for the new default policy: six UI/actual-Agent checks and one cold-process-restart check per target, with all 135 runtime files matching the new candidate. All 195 tests, type checking, build, and client syntax checks passed, along with 11 engine checks on each actual Web host and NEXT. Older hosts without `ptcRuntime` receive no unsupported deadline fields. The client source remains byte-identical.
12
+
13
+ 本次复制此前隔离 profile 并加载新候选,未重跑未变的安装器或全部语言/冲突/布局组合;下方完整矩阵保留为上一候选的历史证据。平台限制不变,测试使用本地确定性模型,无外部模型调用或新增 SWE-bench 成绩。上述验收候选标记为 `0.3.5`;发布包改为 `0.3.6`,运行文件仅更新包版本与两种预设版本标记,其余运行内容逐文件核对一致。
14
+
15
+ This delta run cloned prior isolated profiles and loaded the new candidate. It did not rerun the unchanged installer or every language/conflict/layout combination; the complete matrix below remains evidence for the preceding candidate. Platform limits are unchanged. Tests use a local deterministic model with no external model calls or new SWE-bench scores. The tested candidate was labeled `0.3.5`. The `0.3.6` release changes only the package version and both preset-version markers; all other runtime content is verified file by file as identical.
16
+
17
+ ## 运行预算 · Runtime Budgets · 2026-10-19
18
+
19
+ 页面优化后已重新打包,对此前支持的 **20 个官方 Web 版本、5 个官方 macOS arm64 Desktop 版本及 DSH NEXT** 完成同一候选包复验。每个目标均通过 11 项页面功能检查、6 项真实会话检查和 3 项进程冷启动检查;安装副本的 133 个运行文件与冻结候选逐字节一致。该轮测试使用当时尚未发布、版本标记为 `0.3.5` 的开发候选。
20
+
21
+ After the settings-page changes, the same packaged candidate passed revalidation on **20 supported official Web versions, five official macOS arm64 Desktop versions, and DSH NEXT**. Each target passed 11 UI behavior checks, six real-conversation checks, and three cold-process-restart checks. All 133 installed runtime files match the frozen candidate. That run used the then-unreleased development candidate labeled `0.3.5`.
22
+
23
+ | 宿主 / Host | 本轮通过版本 / Versions revalidated |
24
+ |---|---|
25
+ | 官方 Web / Official Web | `0.1.5-alpha.1`、`alpha.2`、`rc.1`、`rc.2`、`rc.3`;`0.1.6-alpha.1`、`alpha.2`;`0.1.7-alpha.1`、`alpha.2`、`rc.1`、`rc.2`;`0.2.0-rc.1`、`rc.2`;`0.2.1-alpha.1`、`alpha.2`、`alpha.3`、`alpha.4`、`alpha.5`、`rc.1`、`rc.2` |
26
+ | 官方 Desktop / Official Desktop | `0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-rc.2` |
27
+ | DSH NEXT | `2.0.17-next`(内置 Harness / bundled Harness `0.2.0-rc.2`)|
28
+
29
+ 全部 20 个 Web 在 800px 宽窗口追加控件边界、滚动可见性和指针命中检查,均通过。440px 宽时宿主固定侧栏仅给插件留下 156px 内容区,不计入可用性通过范围;最低、最高版不加载插件的通用设置也存在相同限制。原先仅检查内部 scrollWidth 的第 12 项已剔除,避免误称窄窗口可用。
30
+
31
+ All 20 Web versions also pass control-boundary, scroll-visibility, and pointer-hit checks at an 800px viewport. At 440px the host navigation leaves only 156px for plugin content; narrow-window usability is not accepted. Plugin-free baselines on the earliest and latest hosts show the same settings-layout limitation. The original internal-scrollWidth check is excluded from the acceptance count.
32
+
33
+ 覆盖“预设状态 / 上下文配置”标签页、按需读取、键盘切换、草稿保留、实际宿主默认值和单位、自定义选择器、保存、无效输入、并发修改冲突、重新读取、恢复默认、中英文、重载与冷启动持久化。官方预设开关默认关闭,开启与关闭后的新旧 Agent 预算隔离通过真实 Standard 会话验证,Super Code 的任务容量限制通过实际 PTC 工具调用验证;标准、PTC、极简和创造四种预设的选择、压缩、并发及卸载边界另由每版 10 项引擎专项覆盖。
34
+
35
+ Checks cover the Preset status / Context settings tabs, lazy reads, keyboard navigation, retained drafts, actual host defaults and units, custom selectors, save, invalid input, concurrent-edit conflicts, reload, reset, Chinese/English, and cold-start persistence. The official-preset switch defaults off. Real Standard conversations verify opt-in and creation-time snapshots; actual PTC calls verify Super Code task-capacity limits. Ten engine checks per Web version separately cover selection, compaction, concurrency, and disposal for Standard, PTC, Minimal, and Create.
36
+
37
+ 本轮修复语言偏好尚未保存时插件提前重载、导致语言回退的问题。192 项测试、类型检查、构建及客户端语法检查通过;20 个 Web 宿主各 10 项压缩专项、NEXT 10 项压缩专项通过。15 个 Web 宿主及 NEXT 的实际 Node PTC 均验证默认预算与显式较短时限;`0.1.5` 五版没有新版 `ptcRuntime`,页面正确禁用这些时限字段,其余预算和旧版 run_code 正常使用。
38
+
39
+ A fix waits for the accepted language preference before preset synchronization can reload the page, preventing optimistic language changes from being lost. All 192 tests, type checking, build, and client syntax checks pass, along with ten compaction checks on each Web version and ten on NEXT. Actual Node PTC tests on 15 Web hosts and NEXT verify the plugin default and an explicit shorter deadline. The five `0.1.5` hosts lack the newer `ptcRuntime`; their deadline fields are correctly disabled while other budgets and legacy run_code remain usable.
40
+
41
+ 官方桌面使用应用内插件页安装、启用,未修改日常应用或配置。测试使用本地确定性模型,没有外部模型调用或新增 SWE-bench 成绩。原生实测范围为 macOS arm64,Web 使用 Chromium;未覆盖原生 Windows/macOS x64 或 Safari 专属行为。逐宿主真实官方会话为 Standard,专项组合测试不代表所有内置工具、权限和终端场景均已逐一实测。
42
+
43
+ Official Desktop packages were installed and enabled through their native plugin pages without changing daily apps or profiles. A local deterministic model supplied responses, with no external model calls or new SWE-bench scores. Native testing covers macOS arm64 and Web testing uses Chromium; Windows/macOS x64 native apps and Safari-specific behavior were not checked. Per-host real official-preset conversations use Standard; the engine composition checks do not establish every built-in tool, permission, or terminal scenario.
44
+
45
+ ## 0.3.5 · Harness 0.2.1-rc.2 · 2026-10-18
46
+
47
+ 兼容范围扩展至 `0.2.1-rc.2`,最低保持 `0.1.5-alpha.1`。本次基于主干 0.3.4,逐版固定并审计宿主依赖,在独立 profile 中真实安装和运行。现有 peer 依赖范围已覆盖这些预发布版本;补充 v4 日志迁移检查后,修复旧插件来源记录的识别及投影缓存失效,未增加依赖,发布版本为 0.3.5。
48
+
49
+ Compatibility extends through `0.2.1-rc.2`, with the minimum remaining `0.1.5-alpha.1`. Based on main at plugin version 0.3.4, candidates were installed and run in isolated profiles, with each host's dependency graph pinned and audited. Existing peer ranges already cover these prereleases. Additional v4 migration checks identified and fixed legacy plugin-source recognition and projection-cache invalidation without adding dependencies. The release version is 0.3.5.
50
+
51
+ | Harness | Web/CLI 与真实浏览器 / Web/CLI and real browser | 原生 Skill 加载 / Native Skill loading |
52
+ |---|---|---|
53
+ | `0.2.1-alpha.3` | 通过 / Pass | 组合与持久化 profile 均通过 / Bundle and persisted profile pass |
54
+ | `0.2.1-alpha.4` | 通过 / Pass | 组合与持久化 profile 均通过 / Bundle and persisted profile pass |
55
+ | `0.2.1-alpha.5` | 通过 / Pass | 组合与持久化 profile 均通过 / Bundle and persisted profile pass |
56
+ | `0.2.1-rc.1` | 通过 / Pass | 组合与持久化 profile 均通过 / Bundle and persisted profile pass |
57
+ | `0.2.1-rc.2` | 通过 / Pass | 组合与持久化 profile 均通过 / Bundle and persisted profile pass |
58
+
59
+ 五版均验证原生 PTC、主/子 Agent、任务记忆、项目/全局记忆与归属、跨工作区隔离及冷重启后无需恢复会话的历史读取。真实浏览器覆盖执行树运行/完成动画、节点间距、减弱动态效果、320/400/560px 与缩放、互斥侧栏及状态恢复、记忆新增/编辑/取消/保存/删除、详情页记忆定位、中英文和明暗主题切换。十条 Skill 路径覆盖摘要目录、按需正文与三份参考文件读取、用户/项目同名覆盖。
60
+
61
+ All five passed native PTC, main/child Agents, task memory, project/global memory and attribution, workspace isolation, and historical reads after a cold restart without resuming the session. Real-browser checks cover running/completed tree animation, node spacing, reduced motion, 320/400/560px widths and zoom, exclusive sidebar sections and retained state, memory creation/editing/cancellation/saving/deletion, memory links from Agent details, and Chinese/English and light/dark switching. Ten Skill paths cover summary catalogs, on-demand content and three reference reads, and user/project overrides.
62
+
63
+ 最低版本 `0.1.5-alpha.1` 另通过同一候选包的目录预设安装、主/子 Agent、PTC、记忆归属/隔离/重启和真实浏览器回归。171 项测试、类型检查、构建、客户端语法检查通过。
64
+
65
+ The minimum `0.1.5-alpha.1` also passed directory-preset installation, main/child Agents, PTC, memory attribution/isolation/restart, and real-browser regression with the same candidate. All 171 tests, type checking, build, and client syntax checks passed.
66
+
67
+ 官方 macOS arm64 Desktop `0.2.1-rc.2` 从[官方下载地址](https://download.deepseek.com/dsh-desk/bin/mac-arm64/deepseek-harness-0.2.1-rc.2-mac-arm64.zip)获取,并按官方更新源校验 SHA-512。在独立应用身份、DSH_HOME 和 userData 中,通过原生插件页安装并点击“立即启用”;设置页验证未安装预设的安装、重装确认/取消、从清单移除、按新标识符和中文名称重装、旧预设移除与恢复备份。真实原生主/子 Agent 的 PTC 和记忆流程、执行树动画、统一侧栏、记忆维护及中英文/明暗切换通过,保留截图;冷启动后确认改名预设、自定义名称与项目/全局记忆保留,历史子会话无需恢复即可读取记忆。正式应用和日常配置未修改。
68
+
69
+ Official macOS arm64 Desktop `0.2.1-rc.2` was obtained from the [official download](https://download.deepseek.com/dsh-desk/bin/mac-arm64/deepseek-harness-0.2.1-rc.2-mac-arm64.zip) and SHA-512 verified against its update feed. In an isolated app identity, DSH_HOME, and userData, the native plugin page installed and enabled the plugin. Settings checks cover missing-preset installation, reinstall confirmation/cancellation, removing confirmation rows, reinstallation with a new identifier and Chinese name, removal of the old preset, and recovery backups. Real native main/child PTC and memory flows, tree animation, unified sections, memory maintenance, and Chinese/English and light/dark switching passed with screenshots. A cold start preserved the renamed preset, custom name, and project/global memory, with historical child memory readable without resuming the session. The official app and daily configuration were not changed.
70
+
71
+ 截至本次检查,官方 npm `latest` 为 `0.2.0-rc.2`、`alpha` 为 `0.2.1-alpha.5`、`next` 为 `0.2.1-rc.2`;桌面 nightly 同为 `0.2.1-rc.2`。[官方发布说明](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-rc.2)。本次模型响应由本地确定性程序提供,没有调用外部模型、没有新增 SWE-bench 成绩,也不代表 Windows、macOS x64 或其他新增版本的原生桌面已复验;其他版本保留以下历史记录。
72
+
73
+ At this check, official npm tags point to `latest: 0.2.0-rc.2`, `alpha: 0.2.1-alpha.5`, and `next: 0.2.1-rc.2`; Desktop nightly is also `0.2.1-rc.2`. [Official release notes](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-rc.2). A local deterministic fixture supplied model responses, without external model calls or new SWE-bench scores. This does not establish native Desktop revalidation on Windows, macOS x64, or the other newly covered versions; earlier records remain below.
74
+
75
+ ### v4 会话日志补充验证 · 2026-10-18
76
+
77
+ 物理日志解压、格式迁移、分页与游标由 Harness 的 Session 和官方 journal API 处理;插件不直接解析用户的日志文件。v4 会把旧的 `{kind: "plugin", plugin: "…"}` 来源迁移为 `{kind: "plugin:…"}`。原读取器会跳过其中的任务记录,导致升级后的任务状态、历史与归档不可见。现已识别新旧包名对应的精确来源,同时保留原有直接来源和旧包装形式;任务投影版本由 1 提升到 2,使此前遗漏记录的缓存重新回放。无需为此依赖实验性的 plugin-record API,仍兼容旧宿主。
78
+
79
+ Harness Session and official journal APIs own physical decompression, migration, pagination, and cursors; the plugin does not parse users' log files directly. V4 migrates `{kind: "plugin", plugin: "…"}` to `{kind: "plugin:…"}`. The previous reader skipped these task records, hiding task state, history, and archives after an upgrade. It now recognizes the exact current and legacy package sources while preserving direct sources and old wrappers. The task projection version increases from 1 to 2 to replay caches that previously missed those records. This does not require the experimental plugin-record API or remove older-host support.
80
+
81
+ 使用官方 rc.2 格式迁移器与真实 v3 会话(含历史子会话事实)验证直接来源、新包名旧包装、旧包名旧包装三条路径;对照原生 v4 日志,核对任务状态、11 对工具证据、9 条记忆使用记录、按模型用量和历史详情。另验证旧空缓存失效、全量重建及后续尾部回放,并增加任务保存、归档、聚焦与无关插件隔离回归;173 项测试、类型检查、构建和客户端语法检查通过。本补充不代表已遍历所有历史损坏或中断日志;上方五版和原生桌面界面记录来自首轮候选包。
82
+
83
+ The official rc.2 format migrator restored real v3 sessions with historical child facts for direct sources and wrappers using both current and legacy package names. Comparisons with native v4 logs cover task state, 11 tool-evidence pairs, nine memory-usage rows, per-model usage, and historical details. Checks also cover invalidating stale empty caches, full replay, and subsequent tail replay. Added regressions cover task saving, archiving, focus, and unrelated-plugin isolation. All 173 tests, type checking, build, and client syntax checks passed. This supplement does not cover every damaged or interrupted historical log; the five-version and native Desktop UI records above used the initial candidate.
84
+
85
+ 修复后的安装包另在 `0.1.5-alpha.1` 和 `0.2.1-rc.2` 中通过真实安装、激活、主/子 Agent、PTC、记忆归属、工作区隔离和冷重启历史读取回归;实际安装的任务投影实现与候选包一致。本补充未重跑浏览器及原生桌面界面,客户端仅更正日志格式注释。
86
+
87
+ The fixed package also passed real installation, activation, main/child Agents, PTC, memory attribution, workspace isolation, and historical reads after a cold restart on `0.1.5-alpha.1` and `0.2.1-rc.2`. The installed task projection matches the candidate. This supplement did not rerun browser or native Desktop UI checks; the client change only corrects a log-format comment.
88
+
3
89
  ## 0.3.4 · 2026-10-15
4
90
 
5
91
  本次更新评测文档、公开结果快照与致谢,宿主依赖和运行行为不变。构建后 112 个运行文件与 0.3.3 发布包逐字节一致,两份预设组合仅将版本标记更新为 0.3.4;此前 0.3.3 的宿主验收记录继续适用,本轮未重跑 Web / 原生 Desktop 界面,也未新增模型效果评测。