dsh-super-code 0.3.5 → 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.
package/README.md CHANGED
@@ -14,15 +14,21 @@ 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.5`:
17
+ 版本号采用 **主版本.效果优化版本.维护版本**,例如 `0.3.6`:
18
18
 
19
- Version numbers follow **major.performance-improvement.maintenance**, for example `0.3.5`:
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 (`5`) | 维护版本,记录问题修复、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)
26
32
 
27
33
  ## 0.3.5 · What's New
28
34
 
@@ -93,7 +99,7 @@ dsh plugin --profile web add dsh-super-code
93
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.
94
100
 
95
101
  ```bash
96
- dsh plugin --profile web add ./dsh-super-code-0.3.5.tgz
102
+ dsh plugin --profile web add ./dsh-super-code-0.3.6.tgz
97
103
  ```
98
104
 
99
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.',
@@ -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.5
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,11 @@
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
+
3
9
  - **0.3.5 · 2026-10-18**:适配 Harness `0.2.1-rc.2`,修复 v4 日志迁移后旧任务记录不可见的问题,保留 `0.1.5-alpha.1` 起的兼容性,并补齐官方桌面安装说明。[验证范围](Compatibility.md)
4
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)
5
11
 
@@ -1,5 +1,47 @@
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
+
3
45
  ## 0.3.5 · Harness 0.2.1-rc.2 · 2026-10-18
4
46
 
5
47
  兼容范围扩展至 `0.2.1-rc.2`,最低保持 `0.1.5-alpha.1`。本次基于主干 0.3.4,逐版固定并审计宿主依赖,在独立 profile 中真实安装和运行。现有 peer 依赖范围已覆盖这些预发布版本;补充 v4 日志迁移检查后,修复旧插件来源记录的识别及投影缓存失效,未增加依赖,发布版本为 0.3.5。
@@ -24,6 +24,57 @@ The default guidance calls for parallel reads when useful, ordered writes, tests
24
24
 
25
25
  Batching reduces round trips between the model and tools. It does not guarantee that every operation runs faster or change model, permission, or memory settings.
26
26
 
27
+ ## 运行预算 · Runtime Budgets
28
+
29
+ 打开设置中的“Super Code 模式”(部分版本位于“插件”→“插件配置”)。顶部“预设状态”用于查看和安装预设;“上下文配置”用于调整预算。插件默认已使用此前 Pro 测试中的旧预算,无需手动填写。界面使用百分数和秒;括号内仍显示当前宿主的默认值,便于与输入框中的实际配置比较。
30
+
31
+ Open “Super Code” in Settings (under “Plugins” → “Plugin configuration” in some versions). “Preset status” shows and installs the preset; “Context settings” contains the budgets. The plugin already uses the older Pro-test budgets without manual setup. The form uses percentages and seconds; parentheses still show the current host defaults for comparison with the effective values in the inputs.
32
+
33
+ | 类型 / Type | 配置 / Settings | 生效范围 / Applies to |
34
+ |---|---|---|
35
+ | 通用预算 / Common budgets | 压缩比例、摘要上限、PTC 时限及重试次数 / Compression ratios, summary limit, PTC deadlines, and retries | 默认仅 Super Code;打开“同时应用到官方预设”后,也用于标准、PTC、极简、创造模式 / Super Code by default; also Standard, PTC, Minimal, and Create when “Also apply to official presets” is enabled |
36
+ | Super Code 专属预算 / Super Code budgets | 活跃任务记录上限、任务记忆上下文容量 / Active task record limit and task-memory context capacity | 始终仅 Super Code / Always Super Code only |
37
+
38
+ 官方预设开关默认关闭,不影响自定义预设;开启后也只修改通用预算,不改变官方预设的工具和提示词。修改保存后对新建 Agent 生效,运行中的 Agent 保留原配置。切换顶部标签不会丢失尚未保存的输入。
39
+
40
+ The official-preset switch is off by default and leaves custom presets untouched. When enabled, it changes only common budgets, preserving official tools and prompts. Saved changes apply to new Agents; running Agents keep their configuration. Switching tabs retains unsaved input.
41
+
42
+ 留空沿用插件默认预算;“恢复默认”会清除界面的覆盖,回到插件加载配置,未配置的字段使用旧预算。用户已保存的配置优先生效。保存失败时保留输入,若提示预算已在别处修改,先重新读取再调整。
43
+
44
+ Leave fields blank to inherit plugin defaults. “Reset to defaults” clears UI overrides and restores the plugin configuration, using the older budgets for unconfigured fields. Saved user values take precedence. Failed saves retain your input. If budgets changed elsewhere, reload before editing again.
45
+
46
+ 也可以通过插件的 `budgets` 配置调整通用预算;将 `applyToOfficialPresets` 设为 `true` 可同时应用到上述四种官方预设。保存预算不会重启 Agent。
47
+
48
+ You can also set common budgets in the plugin's `budgets` configuration. Set `applyToOfficialPresets: true` to include the four official presets above. Saving budgets does not restart Agents.
49
+
50
+ 旧宿主未提供 `ptcRuntime` 时,“批量工具执行”的时限输入框会禁用;压缩预算和任务记忆容量仍可设置。
51
+
52
+ On older hosts without `ptcRuntime`, batch-tool deadline inputs are disabled; compression and task-memory budgets remain configurable.
53
+
54
+ 下面是插件已默认使用的旧预算,无需再将它手动添加到 `name: dsh-super-code` 的加载配置中。需要自定义时,可以在界面或加载项的 `config.budgets` 中修改对应字段。
55
+
56
+ The plugin already uses these older budgets by default; there is no need to add them manually to the `dsh-super-code` entry. Customize individual fields in the UI or the entry's `config.budgets` when needed.
57
+
58
+ ```yaml
59
+ budgets:
60
+ pressureBasis: window
61
+ thresholdRatio: 0.8
62
+ retainRatio: 0.16
63
+ summaryMaxTokens: 8192
64
+ compactionRetries: 1
65
+ maxOverflowRetries: 1
66
+ ptcTimeoutMs: 600000
67
+ ptcMaxTimeoutMs: 600000
68
+ ```
69
+
70
+ `pressureBasis: window` 为插件默认,按完整上下文窗口计算;选择 `host` 则按当前宿主策略计算。`retainRatio` 必须小于 `thresholdRatio`。PTC 两项的单位是毫秒,包含工具等待时间;显式更短的调用期限仍然生效,上限不会超过宿主允许值。PTC 时间覆盖需要提供 `ptcRuntime` 的新版宿主;旧版的 CPU 忙碌计时与新版总耗时计时不能等同。这些配置不改变执行后端、权限或取消行为。
71
+
72
+ `pressureBasis: window` is the plugin default and uses the full context window; choose `host` to follow the current host budget policy. `retainRatio` must be lower than `thresholdRatio`. PTC values are milliseconds, including tool waits; explicit shorter call deadlines still apply, and the host ceiling remains authoritative. PTC overrides require a newer host with `ptcRuntime`. The old busy-CPU timer and the new elapsed timer are different. These settings preserve the host execution backend, permissions, and cancellation.
73
+
74
+ Super Code 专属的 `maxTasks`(默认 32)和 `maxContextBytes`(默认 32,768),分别控制会话中活跃任务记录数量和任务记忆上下文的字节预算。增加预算会占用更多上下文;通常保持默认即可。
75
+
76
+ Super Code also has `maxTasks` (default 32) and `maxContextBytes` (default 32,768), which bound the active task records and task-memory context bytes per conversation. Larger budgets use more context; the defaults are usually sufficient.
77
+
27
78
  ## 找不到预设 · Can't Find the Preset?
28
79
 
29
80
  先确认插件已启用,并按[兼容矩阵](Compatibility.md)核对宿主版本与实际依赖。插件按宿主提供的预设机制选择以下两条路径。