dsh-super-code 0.3.10 → 0.3.11
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.en.md +4 -4
- package/README.md +4 -4
- package/client/index.js +106 -47
- package/cordis.patch.yml +1 -1
- package/docs/Changelog.md +43 -0
- package/docs/Compatibility.md +13 -0
- package/docs/UsageGuide.md +30 -8
- package/docs/en/Changelog.md +43 -0
- package/docs/en/Compatibility.md +13 -0
- package/docs/en/UsageGuide.md +30 -8
- package/lib/connection/directories.d.ts.map +1 -1
- package/lib/connection/directories.js +14 -5
- package/lib/connection/directories.js.map +1 -1
- package/lib/connection/guidance.d.ts.map +1 -1
- package/lib/connection/guidance.js +7 -0
- package/lib/connection/guidance.js.map +1 -1
- package/lib/connection/http.d.ts.map +1 -1
- package/lib/connection/http.js +59 -30
- package/lib/connection/http.js.map +1 -1
- package/lib/connection/service.d.ts +3 -0
- package/lib/connection/service.d.ts.map +1 -1
- package/lib/connection/service.js +82 -33
- package/lib/connection/service.js.map +1 -1
- package/lib/connection/store.d.ts +2 -0
- package/lib/connection/store.d.ts.map +1 -1
- package/lib/connection/store.js +95 -30
- package/lib/connection/store.js.map +1 -1
- package/lib/connection/tasks.d.ts +6 -3
- package/lib/connection/tasks.d.ts.map +1 -1
- package/lib/connection/tasks.js +125 -53
- package/lib/connection/tasks.js.map +1 -1
- package/lib/connection/types.d.ts +1 -0
- package/lib/connection/types.d.ts.map +1 -1
- package/lib/connection/types.js.map +1 -1
- package/lib/core/deletion-command.d.ts.map +1 -1
- package/lib/core/deletion-command.js +84 -24
- package/lib/core/deletion-command.js.map +1 -1
- package/lib/dsh/compaction.d.ts.map +1 -1
- package/lib/dsh/compaction.js +1 -0
- package/lib/dsh/compaction.js.map +1 -1
- package/lib/dsh/connection-history.d.ts.map +1 -1
- package/lib/dsh/connection-history.js +3 -0
- package/lib/dsh/connection-history.js.map +1 -1
- package/lib/dsh/connection-host.js +1 -1
- package/lib/dsh/connection-host.js.map +1 -1
- package/lib/dsh/connection.d.ts.map +1 -1
- package/lib/dsh/connection.js +24 -3
- package/lib/dsh/connection.js.map +1 -1
- package/lib/dsh/deletion-protection.d.ts.map +1 -1
- package/lib/dsh/deletion-protection.js +18 -10
- package/lib/dsh/deletion-protection.js.map +1 -1
- package/lib/dsh/index.d.ts.map +1 -1
- package/lib/dsh/index.js +2 -0
- package/lib/dsh/index.js.map +1 -1
- package/lib/dsh/official-budgets.d.ts.map +1 -1
- package/lib/dsh/official-budgets.js +15 -3
- package/lib/dsh/official-budgets.js.map +1 -1
- package/lib/dsh/preset-declaration.d.ts +3 -0
- package/lib/dsh/preset-declaration.d.ts.map +1 -1
- package/lib/dsh/preset-declaration.js +68 -45
- package/lib/dsh/preset-declaration.js.map +1 -1
- package/lib/dsh/preset-installation.d.ts +10 -7
- package/lib/dsh/preset-installation.d.ts.map +1 -1
- package/lib/dsh/preset-installation.js +66 -30
- package/lib/dsh/preset-installation.js.map +1 -1
- package/lib/dsh/preset-metadata.d.ts.map +1 -1
- package/lib/dsh/preset-metadata.js +2 -1
- package/lib/dsh/preset-metadata.js.map +1 -1
- package/lib/dsh/preset-recovery-runtime.d.ts +76 -0
- package/lib/dsh/preset-recovery-runtime.d.ts.map +1 -0
- package/lib/dsh/preset-recovery-runtime.js +322 -0
- package/lib/dsh/preset-recovery-runtime.js.map +1 -0
- package/lib/dsh/preset-recovery.d.ts +14 -0
- package/lib/dsh/preset-recovery.d.ts.map +1 -0
- package/lib/dsh/preset-recovery.js +140 -0
- package/lib/dsh/preset-recovery.js.map +1 -0
- package/lib/dsh/ptc-budget.d.ts.map +1 -1
- package/lib/dsh/ptc-budget.js +20 -10
- package/lib/dsh/ptc-budget.js.map +1 -1
- package/lib/dsh/windows-shell.d.ts.map +1 -1
- package/lib/dsh/windows-shell.js +18 -4
- package/lib/dsh/windows-shell.js.map +1 -1
- package/lib/long-memory.d.ts.map +1 -1
- package/lib/long-memory.js +3 -2
- package/lib/long-memory.js.map +1 -1
- package/lib/super-agent-usage.d.ts +2 -0
- package/lib/super-agent-usage.d.ts.map +1 -1
- package/lib/super-agent-usage.js +16 -11
- package/lib/super-agent-usage.js.map +1 -1
- package/lib/task-feedback-projection.d.ts +11 -0
- package/lib/task-feedback-projection.d.ts.map +1 -1
- package/lib/task-feedback-projection.js +37 -12
- package/lib/task-feedback-projection.js.map +1 -1
- package/package.json +1 -1
- package/presets/super-code/agent.cordis.yml +1 -1
package/README.en.md
CHANGED
|
@@ -40,7 +40,7 @@ Desktop: enter the full path of the package in "Package name or address", then c
|
|
|
40
40
|
Web: run the following command (use the actual file name):
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
dsh plugin --profile web add ./dsh-super-code-0.3.
|
|
43
|
+
dsh plugin --profile web add ./dsh-super-code-0.3.11.tgz
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
</details>
|
|
@@ -70,7 +70,7 @@ Select **Super Code** in the right sidebar. It contains three sections:
|
|
|
70
70
|
- **Collaborative execution**: the Agent execution tree. Click a node to view details.
|
|
71
71
|
- **Memory**: view, add, edit, and delete project memory and global preferences.
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Exactly one of the three sections stays open. Tasks opens by default; clicking its heading keeps it expanded.
|
|
74
74
|
|
|
75
75
|
[](docs/images/task-status.png)
|
|
76
76
|
|
|
@@ -94,9 +94,9 @@ See the [usage guide](docs/en/UsageGuide.md).
|
|
|
94
94
|
|
|
95
95
|
## Recent releases
|
|
96
96
|
|
|
97
|
+
- **0.3.11**: Fixed numerous bugs.
|
|
97
98
|
- **0.3.10**: Added bundled Bash on Windows and an official-preset switch, with legacy-host compatibility and tooltip fixes.
|
|
98
99
|
- **0.3.9**: Polished Settings and the task sidebar, improved MCP conversation control, fixed PTC child-tool approvals, and verified rc.4 Web compatibility.
|
|
99
|
-
- **0.3.8**: Added MCP connection; external clients can delegate, inspect, continue, and cancel DSH conversations. Added a Home overview in Settings.
|
|
100
100
|
|
|
101
101
|
[Full changelog](docs/en/Changelog.md)
|
|
102
102
|
|
|
@@ -148,7 +148,7 @@ These are earlier evaluation runs and are not pooled with the plugin comparison
|
|
|
148
148
|
|
|
149
149
|
- Each configuration was run once. The same task can pass in one run and fail in another; run-to-run variance for a fixed configuration has not been estimated.
|
|
150
150
|
- The default-budget and legacy-budget runs used different plugin versions (`0.3.4` → `0.3.5`), so the gain cannot be attributed entirely to budgets.
|
|
151
|
-
- `0.3.6` – `0.3.
|
|
151
|
+
- `0.3.6` – `0.3.11` have not been re-evaluated on the 100 tasks.
|
|
152
152
|
- The cross-model comparison is between two complete systems and cannot isolate the plugin's contribution.
|
|
153
153
|
|
|
154
154
|
[Results and methodology](docs/en/EvaluationResults.md) · [All result tables](eval/results/swebench-pro-final-100/ResultsTables.md)
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ dsh plugin --profile web add dsh-super-code
|
|
|
40
40
|
Web 版:运行以下命令(文件名以实际下载的为准):
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
dsh plugin --profile web add ./dsh-super-code-0.3.
|
|
43
|
+
dsh plugin --profile web add ./dsh-super-code-0.3.11.tgz
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
</details>
|
|
@@ -70,7 +70,7 @@ dsh plugin --profile web add ./dsh-super-code-0.3.10.tgz
|
|
|
70
70
|
- **协作执行**:Agent 执行树,点击节点可查看详情。
|
|
71
71
|
- **记忆**:查看、新增、编辑和删除项目记忆与全局偏好。
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
三个部分始终只展开一项,默认显示任务;再次点击当前标题会保持展开。
|
|
74
74
|
|
|
75
75
|
[](docs/images/task-status.png)
|
|
76
76
|
|
|
@@ -94,9 +94,9 @@ dsh plugin --profile web add ./dsh-super-code-0.3.10.tgz
|
|
|
94
94
|
|
|
95
95
|
## 最近更新
|
|
96
96
|
|
|
97
|
+
- **0.3.11**:修复了大量 bug。
|
|
97
98
|
- **0.3.10**:新增 Windows 内置 Bash 和官方预设开关,修复旧宿主兼容与提示气泡样式。
|
|
98
99
|
- **0.3.9**:美化设置和任务侧栏,完善 MCP 对话控制并修复 PTC 子工具审批,验证 rc.4 Web 兼容性。
|
|
99
|
-
- **0.3.8**:新增 MCP 连接,外部客户端可委派、查看、继续和取消 DSH 对话;设置页新增首页概览。
|
|
100
100
|
|
|
101
101
|
[完整版本记录](docs/Changelog.md)
|
|
102
102
|
|
|
@@ -148,7 +148,7 @@ M 为百万 Token,包含思考 Token;耗时包含部分运行内服务等待
|
|
|
148
148
|
|
|
149
149
|
- 每组配置只运行一轮。同一道题在不同轮次中结果可能不同,目前尚未估计固定配置下的随机波动。
|
|
150
150
|
- 默认预算与旧预算两组的插件版本不同(`0.3.4` → `0.3.5`),收益不能全部归因于预算。
|
|
151
|
-
- `0.3.6` ~ `0.3.
|
|
151
|
+
- `0.3.6` ~ `0.3.11` 未重新运行 100 题评测。
|
|
152
152
|
- 跨模型对比是两套完整系统之间的比较,无法单独分离插件的贡献。
|
|
153
153
|
|
|
154
154
|
[评测结果与口径](docs/EvaluationResults.md) · [完整成绩表](eval/results/swebench-pro-final-100/ResultsTables.md)
|
package/client/index.js
CHANGED
|
@@ -173,8 +173,8 @@ function AgentMessage({ record, saved, t, toolName }) {
|
|
|
173
173
|
if (event.currentTarget.open) saved.open.add(item.seq); else saved.open.delete(item.seq)
|
|
174
174
|
} },
|
|
175
175
|
React.createElement('summary', null, label, React.createElement(Glyph, { type: 'chevron' })),
|
|
176
|
-
React.createElement(DetailText, { text: item.text, t }))
|
|
177
|
-
: React.createElement(React.Fragment, null, label, React.createElement(DetailText, { text: item.text, t }))))
|
|
176
|
+
React.createElement(DetailText, { text: item.text, format: item.format, t }))
|
|
177
|
+
: React.createElement(React.Fragment, null, label, React.createElement(DetailText, { text: item.text, format: item.format, t }))))
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
/* Keep native controls and their refs/events; mount name bubbles outside clipped
|
|
@@ -268,6 +268,9 @@ const zh = {
|
|
|
268
268
|
'feedback.source.record': '任务记录',
|
|
269
269
|
'feedback.source.request': '用户原文',
|
|
270
270
|
'feedback.latest': '本轮要求',
|
|
271
|
+
'feedback.previous': '此前要求',
|
|
272
|
+
'feedback.historicalStatus': '{status}(历史记录)',
|
|
273
|
+
'feedback.historyPartial': '部分较早的要求或步骤未展示,完整记录见执行记录。',
|
|
271
274
|
'feedback.progress': '步骤 {done} / {total}',
|
|
272
275
|
'feedback.progressPartial': '已记录步骤 {done} / {total}',
|
|
273
276
|
'feedback.steps': '步骤进度',
|
|
@@ -347,7 +350,7 @@ const zh = {
|
|
|
347
350
|
'connection.tokenHint': '请将凭证安全保存在客户端。更换凭证后,旧凭证立即失效。',
|
|
348
351
|
'connection.rotated': '已更换凭证,请更新客户端。', 'connection.copied': '已复制。',
|
|
349
352
|
'connection.error.unavailable': '连接服务尚未就绪或当前配置目录不可写,请重新读取。', 'connection.error.invalid': '请检查端口、最大连接数和目录。启用连接至少需要一个有效目录。', 'connection.error.new-conversation-disabled': 'MCP 新增对话已关闭,请选择已有对话继续。',
|
|
350
|
-
'connection.error.conflict': '连接设置已在别处修改。草稿已保留,请重新读取。', 'connection.error.save-failed': '保存失败,草稿已保留。', 'connection.error.port-unavailable': '
|
|
353
|
+
'connection.error.conflict': '连接设置已在别处修改。草稿已保留,请重新读取。', 'connection.error.save-failed': '保存失败,草稿已保留。', 'connection.error.port-unavailable': '端口被占用或无法监听。请更换端口,或稍后重试。', 'connection.error.cleanup-failed': '设置已保存,但连接清理失败。请点击“重试”恢复连接。', 'connection.error.storage-unavailable': '任务状态保存失败,请检查配置目录。', 'connection.error.clipboard': '复制失败,请手动复制。',
|
|
351
354
|
'settings.contextTab': '上下文配置', 'settings.tabs': 'Super Code 配置',
|
|
352
355
|
'budget.common': '通用预算', 'budget.superCode': 'Super Code 专属预算',
|
|
353
356
|
'budget.applyToOfficialPresets': '同时应用到官方预设', 'budget.officialHint': '开启后,通用预算也用于标准、PTC、极简和创造模式;不包含下方的 Super Code 专属预算。',
|
|
@@ -388,6 +391,8 @@ const zh = {
|
|
|
388
391
|
'workspace.title': 'Super Code', 'workspace.description': '任务状态、Agent 执行树与记忆库', 'workspace.resize': '调整执行树与记忆库高度',
|
|
389
392
|
'tree.collapsedLabel': '已收起', 'tree.organizeLabel': '自动整理',
|
|
390
393
|
'detail.toolCall': '工具调用', 'detail.toolResult': '工具结果', 'detail.toolError': '工具失败',
|
|
394
|
+
'detail.authError': '模型身份验证失败,请检查模型配置。',
|
|
395
|
+
'detail.copy': '复制', 'detail.copied': '已复制', 'detail.footnotes': '脚注',
|
|
391
396
|
'detail.cache': '缓存', 'detail.info': '详情', 'tree.countCompact': '{shown}/{total} · 运行 {running}',
|
|
392
397
|
'memory.loading': '正在读取记忆…', 'memory.topics': '知识主题', 'memory.allTopics': '全部主题', 'memory.related': '同主题知识', 'preset.configuration': '预设配置',
|
|
393
398
|
'memory.title': '记忆', 'memory.project': '当前项目', 'memory.global': '全局偏好', 'memory.search': '搜索主题或记忆',
|
|
@@ -457,6 +462,9 @@ const en = {
|
|
|
457
462
|
'feedback.source.record': 'Recorded objective',
|
|
458
463
|
'feedback.source.request': 'User request',
|
|
459
464
|
'feedback.latest': 'Latest request',
|
|
465
|
+
'feedback.previous': 'Earlier request',
|
|
466
|
+
'feedback.historicalStatus': '{status} (historical record)',
|
|
467
|
+
'feedback.historyPartial': 'Some earlier requests or steps are omitted; open the execution log for the full record.',
|
|
460
468
|
'feedback.progress': 'Steps {done} / {total}',
|
|
461
469
|
'feedback.progressPartial': 'Recorded steps {done} / {total}',
|
|
462
470
|
'feedback.steps': 'Step progress',
|
|
@@ -536,7 +544,7 @@ const en = {
|
|
|
536
544
|
'connection.tokenHint': 'Store the token securely in the client. Rotation invalidates the previous token immediately.',
|
|
537
545
|
'connection.rotated': 'Token rotated. Update your client.', 'connection.copied': 'Copied.',
|
|
538
546
|
'connection.error.unavailable': 'The service is not ready or the profile directory is not writable. Reload to retry.', 'connection.error.invalid': 'Check the port, maximum connections and directories. Enabling requires at least one valid directory.', 'connection.error.new-conversation-disabled': 'MCP new conversations are disabled. Choose an existing conversation to continue.',
|
|
539
|
-
'connection.error.conflict': 'Connection settings changed elsewhere. Your draft is retained; reload to continue.', 'connection.error.save-failed': 'Save failed. Your draft is retained.', 'connection.error.port-unavailable': 'The port is occupied or cannot be opened.
|
|
547
|
+
'connection.error.conflict': 'Connection settings changed elsewhere. Your draft is retained; reload to continue.', 'connection.error.save-failed': 'Save failed. Your draft is retained.', 'connection.error.port-unavailable': 'The port is occupied or cannot be opened. Choose another port or retry later.', 'connection.error.cleanup-failed': 'Settings were saved, but connection cleanup failed. Click Retry to restore the connection.', 'connection.error.storage-unavailable': 'Task state could not be saved. Check the profile directory.', 'connection.error.clipboard': 'Copy failed. Copy the text manually.',
|
|
540
548
|
'settings.contextTab': 'Context settings', 'settings.tabs': 'Super Code settings',
|
|
541
549
|
'budget.common': 'Common budgets', 'budget.superCode': 'Super Code budgets',
|
|
542
550
|
'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.',
|
|
@@ -577,6 +585,8 @@ const en = {
|
|
|
577
585
|
'workspace.title': 'Super Code', 'workspace.description': 'Task status, Agent tree and memory library', 'workspace.resize': 'Resize agent tree and memory library',
|
|
578
586
|
'tree.collapsedLabel': 'Collapsed', 'tree.organizeLabel': 'Organize',
|
|
579
587
|
'detail.toolCall': 'Tool call', 'detail.toolResult': 'Tool result', 'detail.toolError': 'Tool failed',
|
|
588
|
+
'detail.authError': 'Model authentication failed. Check the model settings.',
|
|
589
|
+
'detail.copy': 'Copy', 'detail.copied': 'Copied', 'detail.footnotes': 'Footnotes',
|
|
580
590
|
'detail.cache': 'Cache', 'detail.info': 'Details', 'tree.countCompact': '{shown}/{total} · Running {running}',
|
|
581
591
|
'memory.loading': 'Loading memories…', 'memory.topics': 'Knowledge topics', 'memory.allTopics': 'All topics', 'memory.related': 'More in this topic', 'preset.configuration': 'Preset configuration',
|
|
582
592
|
'memory.title': 'Memory', 'memory.project': 'This project', 'memory.global': 'Global preferences', 'memory.search': 'Search topics or memories',
|
|
@@ -1024,19 +1034,24 @@ function FeedbackTools({ tools, t }) {
|
|
|
1024
1034
|
function feedbackListItems(model, root, partial) {
|
|
1025
1035
|
const items = []
|
|
1026
1036
|
const add = (kind, key, data = {}, row) => items.push({ kind, key: JSON.stringify(key), row, ...data,
|
|
1027
|
-
signature: JSON.stringify([kind, data.content, data.todo, data.tools, data.label, data.count,
|
|
1037
|
+
signature: JSON.stringify([kind, data.content, data.todo, data.historical, data.tools, data.label, data.count,
|
|
1028
1038
|
data.file && [data.file.name, data.file.directory, [...data.file.operations]], kind === 'task' &&
|
|
1029
1039
|
[row.title, row.owner, row.done, row.total, row.complete, row.taskStatus, row.facts?.phase, row.node.running]]) })
|
|
1030
1040
|
for (const row of model.tasks) {
|
|
1031
1041
|
const facts = row.facts
|
|
1032
1042
|
add('task', [row.id, 'task'], {}, row)
|
|
1033
1043
|
if (row.goal && row.goal !== row.title) add('text', [row.id, 'goal'], { content: row.goal }, row)
|
|
1034
|
-
if (facts?.latestRequest && facts.latestRequest !== facts.
|
|
1044
|
+
if (facts?.latestRequest && (facts.latestRequest !== row.title || facts.history?.length)) add('request', [row.id, 'request'], { content: facts.latestRequest }, row)
|
|
1035
1045
|
row.todos.forEach((todo, index) => add('step', [row.id, 'step', index], { todo }, row))
|
|
1036
1046
|
const tools = feedbackToolSummary(facts?.activities)
|
|
1037
1047
|
if (tools.length) add('tools', [row.id, 'tools'], { tools }, row)
|
|
1038
1048
|
if (!row.total && !tools.length) add('note', [row.id, 'empty'], { label: facts ? 'feedback.noSteps' : 'feedback.loading' }, row)
|
|
1039
1049
|
if (facts?.omittedActivities) add('note', [row.id, 'recent'], { label: 'feedback.recentOnly' }, row)
|
|
1050
|
+
for (const previous of [...(facts?.history || [])].reverse()) {
|
|
1051
|
+
add('request', [row.id, 'history', previous.seq], { content: previous.request, historical: true }, row)
|
|
1052
|
+
previous.todos.forEach((todo, index) => add('step', [row.id, 'history', previous.seq, index], { todo, historical: true }, row))
|
|
1053
|
+
}
|
|
1054
|
+
if (facts?.omittedRequests || facts?.history?.some(previous => previous.omittedTodos)) add('note', [row.id, 'historyPartial'], { label: 'feedback.historyPartial' }, row)
|
|
1040
1055
|
add('open', [row.id, 'open'], { focusable: !row.node.unavailable }, row)
|
|
1041
1056
|
}
|
|
1042
1057
|
if (root) {
|
|
@@ -1096,8 +1111,9 @@ function FeedbackRowContent({ item, root, openDetail, t }) {
|
|
|
1096
1111
|
row.total > 0 && React.createElement('span', { className: 'dsh-super-code-feedback-count', 'aria-label': progressLabel, title: progressLabel }, `${row.done}/${row.total}${row.complete ? '' : '+'}`),
|
|
1097
1112
|
row.total > 0 && row.complete && React.createElement('progress', { max: row.total, value: row.done, 'aria-label': text(t, 'feedback.steps') }))
|
|
1098
1113
|
}
|
|
1099
|
-
if (item.kind === 'step') return React.createElement('div', { className: 'dsh-super-code-feedback-step', 'data-step-state': item.todo.status },
|
|
1100
|
-
React.createElement(FeedbackMark, { tone: item.todo.status === 'completed' ? 'success' : item.todo.status === 'in_progress' ? 'active' : 'pending',
|
|
1114
|
+
if (item.kind === 'step') return React.createElement('div', { className: 'dsh-super-code-feedback-step', 'data-step-state': item.todo.status, 'data-step-history': item.historical || undefined },
|
|
1115
|
+
React.createElement(FeedbackMark, { tone: item.todo.status === 'completed' ? 'success' : !item.historical && item.todo.status === 'in_progress' ? 'active' : 'pending',
|
|
1116
|
+
label: item.historical ? text(t, 'feedback.historicalStatus', { status: text(t, 'feedback.todo.' + item.todo.status) }) : text(t, 'feedback.todo.' + item.todo.status) }),
|
|
1101
1117
|
React.createElement('span', null, item.todo.content))
|
|
1102
1118
|
if (item.kind === 'tools') return React.createElement(FeedbackTools, { tools: item.tools, t })
|
|
1103
1119
|
if (item.kind === 'open') return React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-feedback-open', disabled: !item.focusable,
|
|
@@ -1115,7 +1131,7 @@ function FeedbackRowContent({ item, root, openDetail, t }) {
|
|
|
1115
1131
|
if (item.label === 'tree.empty') return React.createElement('p', { className: 'dsh-super-code-state', 'data-tone': 'empty' }, React.createElement(Glyph, { type: 'context' }), text(t, item.label))
|
|
1116
1132
|
if (item.kind === 'note') return React.createElement('p', { className: 'dsh-super-code-feedback-muted' }, text(t, item.label))
|
|
1117
1133
|
return React.createElement('p', { className: 'dsh-super-code-feedback-text' },
|
|
1118
|
-
item.kind === 'request' && React.createElement('small', null, text(t, 'feedback.latest')), item.content)
|
|
1134
|
+
item.kind === 'request' && React.createElement('small', null, text(t, item.historical ? 'feedback.previous' : 'feedback.latest')), item.content)
|
|
1119
1135
|
}
|
|
1120
1136
|
|
|
1121
1137
|
/** One measured, variable-height viewport for tasks, steps, activity and files. */
|
|
@@ -1272,7 +1288,7 @@ function WorkspaceSectionToggle({ section, expanded, onToggle, children, t }) {
|
|
|
1272
1288
|
React.createElement('strong', null, label), children)
|
|
1273
1289
|
}
|
|
1274
1290
|
|
|
1275
|
-
/** Accordion:
|
|
1291
|
+
/** Accordion: exactly one open view. Tab state retains drafts across section switches. */
|
|
1276
1292
|
function SuperCodeWorkspace(props) {
|
|
1277
1293
|
const { tab } = props.useTabInfo()
|
|
1278
1294
|
const address = typeof tab.navigation?.params?.memory === 'string' ? tab.navigation.params.memory : tab.contentId
|
|
@@ -1280,6 +1296,7 @@ function SuperCodeWorkspace(props) {
|
|
|
1280
1296
|
const memoryTarget = memoryLibraryTarget(address, '')
|
|
1281
1297
|
const saved = useMemo(() => {
|
|
1282
1298
|
const value = props.workspaceStates.get(tab.signal) || { active: 'tasks' }
|
|
1299
|
+
if (!['tasks', 'tree', 'memory'].includes(value.active)) value.active = 'tasks'
|
|
1283
1300
|
if (value.navigationKey !== navigationKey) {
|
|
1284
1301
|
value.navigationKey = navigationKey
|
|
1285
1302
|
if (memoryTarget.id) value.active = 'memory'
|
|
@@ -1287,11 +1304,11 @@ function SuperCodeWorkspace(props) {
|
|
|
1287
1304
|
props.workspaceStates.set(tab.signal, value)
|
|
1288
1305
|
return value
|
|
1289
1306
|
}, [props.workspaceStates, tab.signal])
|
|
1290
|
-
const [active, setActive] = useState(
|
|
1307
|
+
const [active, setActive] = useState(saved.active)
|
|
1291
1308
|
const layout = useRef(null), focusSection = useRef('')
|
|
1292
1309
|
const toggle = section => {
|
|
1293
|
-
|
|
1294
|
-
saved.active =
|
|
1310
|
+
if (active === section) return
|
|
1311
|
+
saved.active = section; focusSection.current = section; setActive(section)
|
|
1295
1312
|
}
|
|
1296
1313
|
useLayoutEffect(() => {
|
|
1297
1314
|
if (saved.navigationKey === navigationKey) return
|
|
@@ -1591,27 +1608,44 @@ function detailRecord(entry, t = key => zh[key] || key) {
|
|
|
1591
1608
|
const base = { seq: event.seq, time: event.time, entry }
|
|
1592
1609
|
if (event.type === 'user/message') {
|
|
1593
1610
|
if (data.source?.kind !== 'user') return { kind: 'skip' }
|
|
1594
|
-
return { ...base, kind: 'message', label: text(t, 'detail.task'), text: contentText(data.content, t) }
|
|
1595
|
-
}
|
|
1596
|
-
if (event.type === 'assistant/message') return { ...base, kind: 'message', label: data.interrupted ? text(t, 'detail.interrupted') : text(t, 'detail.agent'), text: contentText(data.message?.content, t) }
|
|
1597
|
-
|
|
1598
|
-
|
|
1611
|
+
return { ...base, kind: 'message', format: 'text', label: text(t, 'detail.task'), text: contentText(data.content, t) }
|
|
1612
|
+
}
|
|
1613
|
+
if (event.type === 'assistant/message') return { ...base, kind: 'message', format: 'markdown', label: data.interrupted ? text(t, 'detail.interrupted') : text(t, 'detail.agent'), text: contentText(data.message?.content, t) }
|
|
1614
|
+
const nestedCall = event.type === 'tool/ptc-dispatch-start'
|
|
1615
|
+
if ((event.type === 'tool/call' || nestedCall) && typeof data.name === 'string' && data.name) {
|
|
1616
|
+
// Native arguments are raw JSON; PTC arguments are already decoded values.
|
|
1617
|
+
let value = !nestedCall && typeof data.arguments === 'string' ? data.arguments
|
|
1618
|
+
: JSON.stringify(data.arguments === undefined ? {} : data.arguments)
|
|
1599
1619
|
try { value = JSON.stringify(JSON.parse(value), null, 2) } catch { /* Incomplete arguments remain readable. */ }
|
|
1600
|
-
return { ...base, kind: 'tool', collapsed: true, toolName: data.name,
|
|
1620
|
+
return { ...base, kind: 'tool', format: 'json', collapsed: true, toolName: data.name,
|
|
1621
|
+
callId: nestedCall ? data.subCallId : data.callId, ...(nestedCall ? { parentCallId: data.parentCallId } : {}),
|
|
1601
1622
|
label: text(t, 'detail.toolCall') + ' · ' + data.name, text: value }
|
|
1602
1623
|
}
|
|
1624
|
+
if (event.type === 'tool/ptc-dispatch' && typeof data.name === 'string' && data.name) {
|
|
1625
|
+
return { ...base, kind: data.isError ? 'error' : 'tool', format: 'code', collapsed: true,
|
|
1626
|
+
callId: data.subCallId, parentCallId: data.parentCallId, toolName: data.name,
|
|
1627
|
+
label: text(t, data.isError ? 'detail.toolError' : 'detail.toolResult') + ' · ' + data.name,
|
|
1628
|
+
text: contentText(data.content, t) }
|
|
1629
|
+
}
|
|
1603
1630
|
if (event.type === 'tool/result') {
|
|
1604
1631
|
const blocks = (data.message?.content || []).filter(block => block.type === 'tool-result')
|
|
1605
1632
|
// Harness journals use both direct tool messages (v4) and nested results.
|
|
1606
1633
|
const direct = data.message?.role === 'tool'
|
|
1607
1634
|
if (!blocks.length && !direct) return { kind: 'skip' }
|
|
1608
1635
|
const failed = direct ? data.message.isError : blocks.some(block => block.isError)
|
|
1609
|
-
return { ...base, kind: failed ? 'error' : 'tool', collapsed: true,
|
|
1636
|
+
return { ...base, kind: failed ? 'error' : 'tool', format: 'code', collapsed: true,
|
|
1610
1637
|
callId: direct ? data.message.toolCallId : blocks[0]?.toolCallId,
|
|
1611
1638
|
label: text(t, failed ? 'detail.toolError' : 'detail.toolResult'),
|
|
1612
1639
|
text: contentText(direct ? data.message.content : blocks.flatMap(block => block.content || []), t) }
|
|
1613
1640
|
}
|
|
1614
|
-
if (event.type === 'turn/
|
|
1641
|
+
if (event.type === 'turn/end' && data.reason?.kind === 'error') {
|
|
1642
|
+
const failure = data.reason.error
|
|
1643
|
+
// Match the host's AUTH handling: provider diagnostics can echo credentials.
|
|
1644
|
+
const message = failure?.code === 'AUTH' ? text(t, 'detail.authError')
|
|
1645
|
+
: (typeof failure?.message === 'string' && failure.message) || text(t, 'detail.incomplete')
|
|
1646
|
+
return { ...base, kind: 'error', format: 'text', label: text(t, 'detail.error'), text: message }
|
|
1647
|
+
}
|
|
1648
|
+
if (event.type === 'turn/error') return { ...base, kind: 'error', format: 'text', label: text(t, 'detail.error'), text: data.message || text(t, 'detail.incomplete') }
|
|
1615
1649
|
return { kind: 'skip' }
|
|
1616
1650
|
}
|
|
1617
1651
|
|
|
@@ -1620,7 +1654,7 @@ function detailRecord(entry, t = key => zh[key] || key) {
|
|
|
1620
1654
|
function createAgentInspector(createStream, address, readPage, initial, t = key => zh[key] || key) {
|
|
1621
1655
|
let snapshot = initial || { status: 'loading', items: [], hasMore: false, earlier: false, truncated: false, projections: {}, error: '', firstSeq: 0, cursor: -1 }
|
|
1622
1656
|
let cursor = snapshot.cursor
|
|
1623
|
-
let disposed = false, stream
|
|
1657
|
+
let disposed = false, paging = false, stream
|
|
1624
1658
|
const listeners = new Set()
|
|
1625
1659
|
const publish = patch => {
|
|
1626
1660
|
if (disposed) return
|
|
@@ -1634,7 +1668,7 @@ function createAgentInspector(createStream, address, readPage, initial, t = key
|
|
|
1634
1668
|
if (disposed) return
|
|
1635
1669
|
if (change.type === 'replace') {
|
|
1636
1670
|
if (snapshot.earlier) {
|
|
1637
|
-
publish({ status: 'ready', projections: change.page.projections?.values || {}, error: '' })
|
|
1671
|
+
publish({ status: paging ? 'paging' : 'ready', projections: change.page.projections?.values || {}, error: '' })
|
|
1638
1672
|
return
|
|
1639
1673
|
}
|
|
1640
1674
|
const fresh = itemsOf(change.entries)
|
|
@@ -1643,7 +1677,7 @@ function createAgentInspector(createStream, address, readPage, initial, t = key
|
|
|
1643
1677
|
// A resumed tail page can start later than the user's reading window.
|
|
1644
1678
|
// Immutable journal records can be merged without moving that window.
|
|
1645
1679
|
const items = overlaps ? [...new Map([...snapshot.items, ...fresh].map(item => [item.seq, item])).values()].sort((a, b) => a.seq - b.seq) : fresh
|
|
1646
|
-
publish({ status: 'ready', items: items.slice(-200), hasMore: (overlaps ? snapshot.hasMore : change.hasMore) || items.length > 200, earlier: false, truncated: items.length > 200,
|
|
1680
|
+
publish({ status: paging ? 'paging' : 'ready', items: items.slice(-200), hasMore: (overlaps ? snapshot.hasMore : change.hasMore) || items.length > 200, earlier: false, truncated: items.length > 200,
|
|
1647
1681
|
firstSeq: items.length > 200 ? items.at(-200).seq : overlaps ? snapshot.firstSeq : change.entries[0]?.event.seq ?? 0,
|
|
1648
1682
|
cursor: change.entries.at(-1)?.event.seq ?? -1,
|
|
1649
1683
|
projections: change.page.projections?.values || {}, error: '' })
|
|
@@ -1665,7 +1699,8 @@ function createAgentInspector(createStream, address, readPage, initial, t = key
|
|
|
1665
1699
|
subscribe: listener => { listeners.add(listener); return () => listeners.delete(listener) },
|
|
1666
1700
|
start: () => { stream.open({ maxMessages: 40 }).catch(() => publish({ status: 'error', error: 'detail.loadError' })) },
|
|
1667
1701
|
older: async () => {
|
|
1668
|
-
if (
|
|
1702
|
+
if (disposed || paging || !snapshot.hasMore) return
|
|
1703
|
+
paging = true
|
|
1669
1704
|
publish({ status: 'paging', error: '' })
|
|
1670
1705
|
const throughSeq = cursor
|
|
1671
1706
|
try {
|
|
@@ -1677,15 +1712,23 @@ function createAgentInspector(createStream, address, readPage, initial, t = key
|
|
|
1677
1712
|
hasMore: result.value.hasMore || items.length > 200 })
|
|
1678
1713
|
}
|
|
1679
1714
|
catch { publish({ status: 'error', error: 'detail.historyError' }) }
|
|
1715
|
+
finally { paging = false }
|
|
1680
1716
|
},
|
|
1681
1717
|
dispose: () => { disposed = true; listeners.clear(); void stream.dispose() },
|
|
1682
1718
|
}
|
|
1683
1719
|
}
|
|
1684
1720
|
|
|
1685
|
-
function DetailText({ text: value, t = key => zh[key] || key }) {
|
|
1721
|
+
function DetailText({ text: value, format = 'text', t = key => zh[key] || key }) {
|
|
1686
1722
|
const [full, setFull] = useState(false)
|
|
1723
|
+
const copyLabel = text(t, 'detail.copy'), copiedLabel = text(t, 'detail.copied'), footnotes = text(t, 'detail.footnotes')
|
|
1724
|
+
const labels = useMemo(() => ({ code: { copyLabel, copiedLabel }, footnotes }), [copyLabel, copiedLabel, footnotes])
|
|
1725
|
+
const content = full ? value : value.slice(0, 12000)
|
|
1687
1726
|
return React.createElement(React.Fragment, null,
|
|
1688
|
-
React.createElement('
|
|
1727
|
+
React.createElement('div', { className: 'dsh-super-code-detail-content' },
|
|
1728
|
+
format === 'markdown' ? React.createElement(icons.MarkdownText, { text: content, labels })
|
|
1729
|
+
: format === 'json' || format === 'code' ? React.createElement(icons.CodeBlock, { code: content,
|
|
1730
|
+
lang: format === 'json' ? 'json' : 'text', copyLabel, copiedLabel })
|
|
1731
|
+
: React.createElement('pre', { className: 'dsh-super-code-detail-plain' }, content)),
|
|
1689
1732
|
!full && value.length > 12000 && React.createElement(ActionButton, { type: 'button', onClick: () => setFull(true) }, text(t, 'detail.open')))
|
|
1690
1733
|
}
|
|
1691
1734
|
|
|
@@ -1743,7 +1786,10 @@ function memoryLibraryWindow(items, query, top, height) {
|
|
|
1743
1786
|
|
|
1744
1787
|
/** Drafts and in-flight operations survive the host unmounting a hidden tab. */
|
|
1745
1788
|
function createMemoryEditor(saved, api) {
|
|
1746
|
-
if (saved.editorStore)
|
|
1789
|
+
if (saved.editorStore) {
|
|
1790
|
+
saved.editorStore.bindApi(api)
|
|
1791
|
+
return saved.editorStore
|
|
1792
|
+
}
|
|
1747
1793
|
let snapshot = { draft: null, confirmation: null, busy: false, error: '', refresh: 0 }
|
|
1748
1794
|
const listeners = new Set()
|
|
1749
1795
|
const update = patch => { snapshot = { ...snapshot, ...patch }; for (const listener of listeners) listener() }
|
|
@@ -1771,6 +1817,8 @@ function createMemoryEditor(saved, api) {
|
|
|
1771
1817
|
}
|
|
1772
1818
|
}
|
|
1773
1819
|
saved.editorStore = { getSnapshot: () => snapshot, subscribe: listener => { listeners.add(listener); return () => listeners.delete(listener) },
|
|
1820
|
+
// The host may replace its Remote while the retained draft is still open.
|
|
1821
|
+
bindApi: value => { api = value },
|
|
1774
1822
|
update, save: () => run('save', snapshot.draft), remove: () => run('remove', snapshot.confirmation) }
|
|
1775
1823
|
return saved.editorStore
|
|
1776
1824
|
}
|
|
@@ -2248,15 +2296,16 @@ function BudgetSettings({ api, t, active, section = 'context', onSaved = () => {
|
|
|
2248
2296
|
const reset = async () => {
|
|
2249
2297
|
setConfirmReset(false)
|
|
2250
2298
|
if (pending.current) return
|
|
2251
|
-
|
|
2252
|
-
const current = editor.getSnapshot().snapshot
|
|
2253
|
-
if (!alive.current || !current?.writable) return
|
|
2254
|
-
const base = current.configuration
|
|
2255
|
-
const configuration = protection
|
|
2256
|
-
? { ...base, deletionProtection: 'relaxed', deletionProtectionForOfficialPresets: false }
|
|
2257
|
-
: { windowsBash: base.windowsBash, windowsBashForOfficialPresets: base.windowsBashForOfficialPresets, deletionProtection: base.deletionProtection, deletionProtectionForOfficialPresets: base.deletionProtectionForOfficialPresets }
|
|
2299
|
+
// Claim the whole operation, including the wait for an earlier autosave.
|
|
2258
2300
|
pending.current = true; setLoading(true); setFailure(''); setNotice('')
|
|
2259
2301
|
try {
|
|
2302
|
+
await editor.flush()
|
|
2303
|
+
const current = editor.getSnapshot().snapshot
|
|
2304
|
+
if (!alive.current || !current?.writable) return
|
|
2305
|
+
const base = current.configuration
|
|
2306
|
+
const configuration = protection
|
|
2307
|
+
? { ...base, deletionProtection: 'relaxed', deletionProtectionForOfficialPresets: false }
|
|
2308
|
+
: { windowsBash: base.windowsBash, windowsBashForOfficialPresets: base.windowsBashForOfficialPresets, deletionProtection: base.deletionProtection, deletionProtectionForOfficialPresets: base.deletionProtectionForOfficialPresets }
|
|
2260
2309
|
const response = await api.saveConfig(JSON.stringify(configuration), String(current.revision))
|
|
2261
2310
|
if (!response.ok) throw new Error('Remote unavailable')
|
|
2262
2311
|
if (!alive.current) return
|
|
@@ -2543,7 +2592,7 @@ function ConnectionSettings({ api, t, active, openSession, onSaved = () => {} })
|
|
|
2543
2592
|
const editor = useMemo(() => createConnectionAutosave(api), [api])
|
|
2544
2593
|
const editing = useSyncExternalStore(editor.subscribe, editor.getSnapshot, editor.getSnapshot)
|
|
2545
2594
|
const { snapshot, draft, saving } = editing
|
|
2546
|
-
const [catalog, setCatalog] = useState({ items: [], picker: 'unavailable' }), [
|
|
2595
|
+
const [catalog, setCatalog] = useState({ items: [], picker: 'unavailable' }), [browser, setBrowser] = useState(false)
|
|
2547
2596
|
const [busy, setBusy] = useState(false), [error, setError] = useState(''), [notice, setNotice] = useState(''), [token, setToken] = useState('')
|
|
2548
2597
|
const alive = useRef(false), pending = useRef(false), visible = useRef(active)
|
|
2549
2598
|
visible.current = active
|
|
@@ -2603,7 +2652,7 @@ function ConnectionSettings({ api, t, active, openSession, onSaved = () => {} })
|
|
|
2603
2652
|
const edit = (key, value) => change({ [key]: value }, ['port', 'maxConnections'].includes(key) ? 350 : 0)
|
|
2604
2653
|
const choose = path => {
|
|
2605
2654
|
if (!draft.allowedDirectories.includes(path) && draft.allowedDirectories.length >= 32) { setError('directory-limit'); return }
|
|
2606
|
-
|
|
2655
|
+
change({ allowedDirectories: [...new Set([...draft.allowedDirectories, path])], knownDirectories: [...new Set([...draft.knownDirectories, path])].slice(-128) }); setNotice(''); setError(''); setBrowser(false)
|
|
2607
2656
|
}
|
|
2608
2657
|
const addDirectory = async () => {
|
|
2609
2658
|
if (pending.current) return
|
|
@@ -2617,7 +2666,7 @@ function ConnectionSettings({ api, t, active, openSession, onSaved = () => {} })
|
|
|
2617
2666
|
finally { pending.current = false; if (alive.current) setBusy(false) }
|
|
2618
2667
|
}
|
|
2619
2668
|
const rows = [...catalog.items]
|
|
2620
|
-
for (const path of [...
|
|
2669
|
+
for (const path of [...draft.knownDirectories, ...draft.allowedDirectories]) if (!rows.some(row => row.path === path)) rows.push({ path, title: '', available: true, workspace: false })
|
|
2621
2670
|
const copy = async value => {
|
|
2622
2671
|
try { await navigator.clipboard.writeText(value); if (alive.current) { setNotice('copied'); setError('') } }
|
|
2623
2672
|
catch { if (alive.current) setError('clipboard') }
|
|
@@ -2628,7 +2677,10 @@ function ConnectionSettings({ api, t, active, openSession, onSaved = () => {} })
|
|
|
2628
2677
|
React.createElement('p', { className: 'dsh-super-code-preset-status', role: 'status', 'data-available': snapshot?.state === 'listening' },
|
|
2629
2678
|
React.createElement('i', { 'aria-hidden': true }), t(`connection.state.${snapshot?.state || 'loading'}`)),
|
|
2630
2679
|
React.createElement('div', { className: 'dsh-super-code-settings-actions' }, React.createElement(ActionButton, { type: 'button', disabled: busy, onClick: () => load(true) }, t('connection.reload')))),
|
|
2631
|
-
snapshot?.error && React.createElement('
|
|
2680
|
+
snapshot?.error && React.createElement('div', { className: 'dsh-super-code-settings-actions' },
|
|
2681
|
+
React.createElement('p', { role: 'alert' }, t(`connection.error.${snapshot.error}`)),
|
|
2682
|
+
snapshot.state === 'error' && React.createElement(ActionButton, { type: 'button', disabled: disabled || dirty,
|
|
2683
|
+
onClick: () => { if (!disabled && !editor.hasChanges()) change({}) } }, t('save.retry'))),
|
|
2632
2684
|
React.createElement(ConnectionActivity, { api, t, active, openSession }),
|
|
2633
2685
|
React.createElement('form', { 'aria-label': t('connection.title'), 'aria-busy': saving, onSubmit: event => { event.preventDefault(); void editor.flush() } },
|
|
2634
2686
|
React.createElement(ConnectionSwitch, { checked: draft.enabled, disabled, onChange: value => edit('enabled', value) }, t('connection.enabled')),
|
|
@@ -2655,7 +2707,7 @@ function ConnectionSettings({ api, t, active, openSession, onSaved = () => {} })
|
|
|
2655
2707
|
React.createElement('span', null, row.title && React.createElement('strong', null, row.title), React.createElement('code', null, row.path),
|
|
2656
2708
|
React.createElement('small', { 'data-unavailable': !row.available }, t(!row.available ? 'connection.directoryUnavailable' : row.workspace ? 'connection.workspaceDirectory' : 'connection.customDirectory')))),
|
|
2657
2709
|
!row.workspace && React.createElement(ActionButton, { type: 'button', disabled, 'aria-label': `${t('connection.removeDirectory')}: ${row.path}`,
|
|
2658
|
-
onClick: () => {
|
|
2710
|
+
onClick: () => { setCatalog(value => ({ ...value, items: value.items.filter(item => item.path !== row.path) })); change({ knownDirectories: draft.knownDirectories.filter(path => path !== row.path), allowedDirectories: draft.allowedDirectories.filter(path => path !== row.path) }) } }, t('preset.remove')))),
|
|
2659
2711
|
!rows.length && React.createElement('p', null, t('connection.noDirectories'))),
|
|
2660
2712
|
React.createElement('div', { className: 'dsh-super-code-settings-actions' },
|
|
2661
2713
|
React.createElement(ActionButton, { type: 'button', disabled: disabled || catalog.picker === 'unavailable', onClick: addDirectory }, t('connection.addDirectory'))),
|
|
@@ -2672,7 +2724,10 @@ function ConnectionSettings({ api, t, active, openSession, onSaved = () => {} })
|
|
|
2672
2724
|
active && token && React.createElement('input', { className: 'dsh-super-code-connection-token', 'aria-label': t('connection.token'), value: token, readOnly: true, autoComplete: 'off', spellCheck: false }),
|
|
2673
2725
|
React.createElement('small', null, t('connection.tokenHint'))),
|
|
2674
2726
|
notice && React.createElement('p', { role: 'status' }, t(`connection.${notice}`)),
|
|
2675
|
-
(error || editing.error) && React.createElement('
|
|
2727
|
+
(error || editing.error) && React.createElement('div', { className: 'dsh-super-code-settings-actions' },
|
|
2728
|
+
React.createElement('p', { role: 'alert' }, t(`connection.error.${error || editing.error}`)),
|
|
2729
|
+
!error && editing.error === 'save-failed' && React.createElement(ActionButton, { type: 'button', disabled: disabled || saving,
|
|
2730
|
+
onClick: () => { if (!disabled && !editor.getSnapshot().saving) void editor.retry() } }, t('save.retry'))),
|
|
2676
2731
|
browser && React.createElement(DirectoryBrowser, { api, t, onSelect: choose, onClose: () => setBrowser(false) }))
|
|
2677
2732
|
}
|
|
2678
2733
|
|
|
@@ -2697,7 +2752,7 @@ function SegmentedControl({ label, value, choices, onChange, disabled = false, b
|
|
|
2697
2752
|
}
|
|
2698
2753
|
function SettingsHome({ budgetApi, connectionApi, t, active, revision, navigate, children }) {
|
|
2699
2754
|
const [budget, setBudget] = useState(null), [connection, setConnection] = useState(null), [overview, setOverview] = useState({ connections: [], sessions: [] })
|
|
2700
|
-
//
|
|
2755
|
+
// Keep the choice visible until the save is acknowledged.
|
|
2701
2756
|
const [saving, setSaving] = useState(null), [failure, setFailure] = useState('')
|
|
2702
2757
|
const alive = useRef(false), request = useRef(0), loading = useRef(false), writing = useRef(false)
|
|
2703
2758
|
const load = async (force = false) => {
|
|
@@ -2726,6 +2781,10 @@ function SettingsHome({ budgetApi, connectionApi, t, active, revision, navigate,
|
|
|
2726
2781
|
const configuration = kind === 'protection' ? { ...current.configuration, deletionProtection: value } : { ...current.configuration, enabled: value }
|
|
2727
2782
|
const response = await (kind === 'protection' ? budgetApi : connectionApi).saveConfig(JSON.stringify(configuration), String(current.revision))
|
|
2728
2783
|
saved = Boolean(response.ok && response.value.ok)
|
|
2784
|
+
if (saved && alive.current) {
|
|
2785
|
+
if (kind === 'protection') setBudget(response.value.snapshot)
|
|
2786
|
+
else setConnection(response.value.snapshot)
|
|
2787
|
+
}
|
|
2729
2788
|
} catch { /* Reported on the row below. */ }
|
|
2730
2789
|
if (saved && alive.current) await load(true)
|
|
2731
2790
|
writing.current = false
|
|
@@ -3363,7 +3422,7 @@ function apply(ctx) {
|
|
|
3363
3422
|
.dsh-super-code-feedback-step[data-step-state=completed]{color:var(--sc-muted)}
|
|
3364
3423
|
.dsh-super-code-feedback-step[data-step-state=completed]>span:last-child{text-decoration:line-through;text-decoration-color:color-mix(in srgb,var(--sc-muted) 40%,transparent)}
|
|
3365
3424
|
.dsh-super-code-feedback-step[data-step-state=pending]{color:var(--sc-muted)}
|
|
3366
|
-
.dsh-super-code-feedback-step[data-step-state=in_progress]{background:color-mix(in srgb,var(--sc-accent) 7%,transparent);box-shadow:inset 2px 0 color-mix(in srgb,var(--sc-accent) 55%,transparent);color:var(--sc-text)}
|
|
3425
|
+
.dsh-super-code-feedback-step[data-step-state=in_progress]:not([data-step-history]){background:color-mix(in srgb,var(--sc-accent) 7%,transparent);box-shadow:inset 2px 0 color-mix(in srgb,var(--sc-accent) 55%,transparent);color:var(--sc-text)}
|
|
3367
3426
|
.dsh-super-code-feedback-mark{position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;width:14px;height:14px;margin-top:3px;color:var(--sc-muted);font-size:11px;line-height:14px}
|
|
3368
3427
|
.dsh-super-code-feedback-mark>svg{width:14px;height:14px}
|
|
3369
3428
|
.dsh-super-code-feedback-mark.pending:before,.dsh-super-code-feedback-mark.idle:before,.dsh-super-code-feedback-mark.unavailable:before{content:"";width:7px;height:7px;border:1px solid var(--sc-faint);border-radius:50%}
|
|
@@ -3640,8 +3699,8 @@ function apply(ctx) {
|
|
|
3640
3699
|
.dsh-super-code-detail-entry-label>span{min-width:0;overflow-wrap:anywhere}
|
|
3641
3700
|
.dsh-super-code-detail-entry.user .dsh-super-code-detail-entry-label{color:var(--sc-accent)}
|
|
3642
3701
|
.dsh-super-code-detail-entry time{flex:none;font-family:var(--sc-mono);font-size:11px;font-weight:400;color:var(--sc-faint)}
|
|
3643
|
-
.dsh-super-code-detail-
|
|
3644
|
-
.dsh-super-code-detail-
|
|
3702
|
+
.dsh-super-code-detail-content{min-width:0;margin-top:6px}
|
|
3703
|
+
.dsh-super-code-detail-plain{min-width:0;font:inherit;font-size:14px;line-height:1.75;white-space:pre-wrap;overflow-wrap:anywhere;margin:0}
|
|
3645
3704
|
.dsh-super-code-detail-message>details{min-width:0;color:var(--sc-muted)}
|
|
3646
3705
|
.dsh-super-code-detail-message>details[open]{color:var(--sc-text)}
|
|
3647
3706
|
.dsh-super-code-detail-message summary{display:flex;align-items:center;gap:6px;cursor:pointer;overflow-wrap:anywhere;list-style:none}
|
|
@@ -3649,8 +3708,8 @@ function apply(ctx) {
|
|
|
3649
3708
|
.dsh-super-code-detail-message summary .dsh-super-code-detail-entry-label{flex:1;min-width:0;font-size:12px}
|
|
3650
3709
|
.dsh-super-code-detail-message summary>.dsh-super-code-glyph{width:14px;height:14px;transition:transform .12s}
|
|
3651
3710
|
.dsh-super-code-detail-message details[open] summary>.dsh-super-code-glyph{transform:rotate(180deg)}
|
|
3652
|
-
.dsh-super-code-detail-message details
|
|
3653
|
-
.dsh-super-code-detail-
|
|
3711
|
+
.dsh-super-code-detail-message details .dsh-super-code-detail-content{margin-top:10px}
|
|
3712
|
+
.dsh-super-code-detail-message>button,.dsh-super-code-detail-message>details>button{margin:8px 0 0}
|
|
3654
3713
|
.dsh-super-code-new-content{flex:none;align-self:center;margin:8px 16px 12px;border:1px solid var(--sc-line);border-radius:8px;padding:6px 12px;background:var(--sc-bg);font-size:13px}
|
|
3655
3714
|
@media(hover:none) and (pointer:coarse){:where(.dsh-super-code-workspace,.dsh-super-code-settings,.dsh-super-code-memory,.dsh-super-code-tree) input{font-size:16px}}
|
|
3656
3715
|
@media(prefers-reduced-motion:reduce){:where(.dsh-super-code-workspace,.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm,.dsh-super-code-select) *{transition:none!important;animation:none!important}.dsh-super-code-graph-node>.dsh-super-code-circle:after{animation:none!important}}
|
package/cordis.patch.yml
CHANGED
package/docs/Changelog.md
CHANGED
|
@@ -4,6 +4,49 @@
|
|
|
4
4
|
|
|
5
5
|
版本号格式为「主版本.效果版本.维护版本」。第二位变化表示编码效果或效率有提升;第三位表示修复、界面和兼容性更新。各版本的验证范围见[兼容性](Compatibility.md)。
|
|
6
6
|
|
|
7
|
+
## 0.3.11 · 2026-11-06
|
|
8
|
+
|
|
9
|
+
**卸载恢复与预设管理**
|
|
10
|
+
|
|
11
|
+
- 修复卸载插件后 Super Code 历史会话无法续聊的问题:已登记且归属匹配的会话改用官方标准预设继续,并显示一次切换提示;保留原会话与子任务历史、模型、目录和权限。
|
|
12
|
+
- 修复官方 minimal 在关闭删除保护、取消官方适用范围或停用、卸载插件后仍沿用旧规则的问题;切换保护等级不再重复叠加规则。旧摘要保留原文,并在后面补充明确的撤销说明。
|
|
13
|
+
- 修复预设恢复在异步读取、用户改选、插件重新启用及模块换代时使用旧状态的问题;旧实例不再迟到覆盖新记录或重复接管服务。
|
|
14
|
+
- 修复安装、重装失败回滚及语言同步可能覆盖外部变更、丢失归属记录的问题;保留用户修改及符号链接,拒绝无效记录,冲突时停止写入。
|
|
15
|
+
|
|
16
|
+
**任务侧栏、执行记录与用量**
|
|
17
|
+
|
|
18
|
+
- 修复任务侧栏只显示本轮要求的问题,保留最近 20 条历史要求及对应的已记录步骤;超过显示上限时明确提示。
|
|
19
|
+
- 修复执行详情缺少渲染的问题,复用宿主 Markdown 和代码组件,保留用户与工具输出原文,支持展开长内容。
|
|
20
|
+
- 补齐 PTC 子工具的调用、结果、失败及回合终止错误记录,崩溃恢复时正确显示中断状态;慢工具超出最近活动窗口后,成功的文件变更证据仍能保留。
|
|
21
|
+
- 修复执行记录分页与断线重连之间的重复读取、边界变化和阅读位置丢失;历史读取失败后可重试,关闭页面后不再回填。
|
|
22
|
+
- 修复 fork 继承历史被重复计入子 Agent 和执行树用量,以及模型标识含特殊分隔符时统计合并错误的问题;旧缓存会重建。
|
|
23
|
+
- 修复侧栏可全部收起的问题,任务、协作执行和记忆始终只展开一项,默认任务;切换保留阅读位置和草稿。
|
|
24
|
+
|
|
25
|
+
**设置、预算与记忆**
|
|
26
|
+
|
|
27
|
+
- 修复首页保存成功但随后刷新失败时显示旧设置的问题;修复自动保存尚未结束时可重复确认“恢复默认”、造成重复提交和版本冲突的问题。
|
|
28
|
+
- 修复自动压缩等待模型信息期间取消,之后仍裁剪工具记录或忽略取消的问题;保留原有压缩策略和预算默认值。
|
|
29
|
+
- 修复旧版记忆草稿在接口重连后继续使用旧接口的问题;保留草稿,主动重试使用当前接口,不自动重发进行中的写入。
|
|
30
|
+
- 修复删除最后一条记忆后,空主题仍占满 200 个主题额度的问题;额度按非空主题计算,同时保留并发修改检查,不增加内容版本记录。
|
|
31
|
+
|
|
32
|
+
**MCP 连接**
|
|
33
|
+
|
|
34
|
+
- 修复异步准备后仍使用已撤销目录授权或已关闭开关的问题;创建会话、选择模型和发送请求前重新核对当前授权与取消状态。
|
|
35
|
+
- 修复 `newConversation: false` 未指定 `taskId` 时仍创建对话的问题;现在要求先选择具体会话。
|
|
36
|
+
- 修复新建、续聊或取消的保存失败后,内存状态仍提前变更、错误占用额度或迟到取消的问题;准备期间保留上一轮跟踪,重启和重连不自动重发已保存请求。
|
|
37
|
+
- 修复审批等待取消后仍接受迟到批准的问题;单次审批重新核对取消、目录与开关状态,未决定的请求可交回 DSH 处理。
|
|
38
|
+
- 修复目录申请在路径被替换、校验期间过期或撤回后仍可批准的问题;已撤销的旧授权不会因复用申请而重新生效。
|
|
39
|
+
- 修复符号链接别名造成允许目录重复、移除后再次出现的问题;同一实际目录只保留一项,不可用目录仍可移除。
|
|
40
|
+
- 补齐 `dsh_read` 的 PTC 子调用公开记录;子工具活动计入进度观察,不再被误判为长时间没有进展。
|
|
41
|
+
- 修复初始化、凭据轮换、关闭和卸载竞态导致连接额度、端口或锁残留的问题;保存已成功时返回实际设置,清理失败明确提示并允许重试,不重新发送任务。
|
|
42
|
+
|
|
43
|
+
**命令与运行时**
|
|
44
|
+
|
|
45
|
+
- 修复部分 Shell 包装命令、`find`、`xargs` 及 PowerShell 启动参数的删除识别漏报和误报;仍由现有保护等级和宿主审批决定是否执行。
|
|
46
|
+
- 修复 Windows Shell 过滤、官方预算和 PTC 包装在卸载后残留或覆盖其他包装的问题;异步初始化落定后释放本插件资源,保留宿主与其他插件的状态。
|
|
47
|
+
|
|
48
|
+
各项修复按对应范围完成回归,版本契约、前端检查和完整宿主验收分别记录,不代表所有版本、所有平台均完成完整进程测试。本版未重新运行 100 题效果评测。
|
|
49
|
+
|
|
7
50
|
## 0.3.10 · 2026-11-03
|
|
8
51
|
|
|
9
52
|
**Windows 命令环境**
|
package/docs/Compatibility.md
CHANGED
|
@@ -6,6 +6,8 @@ Web 已验证 Harness `0.1.5-alpha.1` ~ `0.2.1-rc.4`,其中 `rc.4` 为下述
|
|
|
6
6
|
|
|
7
7
|
0.3.10 的内置 Windows Bash 另在官方 Desktop `0.2.1-rc.5` 和 NEXT `2.0.21-next`(内置 `0.2.1-rc.4`)完成 Windows 完整进程专项验收,范围见下文。
|
|
8
8
|
|
|
9
|
+
0.3.11 的修复按阶段补充了至 `0.2.2-alpha.3` 的版本契约和官方前端验证,完整宿主范围单独记录,见下方 0.3.11 记录。
|
|
10
|
+
|
|
9
11
|
## 已验证的宿主
|
|
10
12
|
|
|
11
13
|
以下 26 个目标在 0.3.6、0.3.7、0.3.8 中均完成整组验证。
|
|
@@ -53,6 +55,17 @@ Web 已验证 Harness `0.1.5-alpha.1` ~ `0.2.1-rc.4`,其中 `rc.4` 为下述
|
|
|
53
55
|
|
|
54
56
|
`zod`、`js-yaml`、`@modelcontextprotocol/sdk` 为运行依赖,不打包进插件。Windows Shell 另随包携带独立进程运行的第三方程序,其来源、许可证和对应源码见[运行时说明](../runtime/windows/README.md)。
|
|
55
57
|
|
|
58
|
+
## 0.3.11 · 2026-11-06
|
|
59
|
+
|
|
60
|
+
本版包含 11 月 4–6 日多轮修复。以下结果对应各轮实际测试的代码,不将早期开发包的完整宿主结果视为最终发布包的全部平台复验。
|
|
61
|
+
|
|
62
|
+
- **发布候选**:560 项全量测试、类型检查、构建及客户端语法检查通过;包、锁文件、目录预设和声明式预设版本统一为 0.3.11。
|
|
63
|
+
- **逐版契约与前端**:26 个精确发布的 Harness 版本,从 `0.1.5-alpha.1` 至 `0.2.2-alpha.3`,涵盖 0.1.5、0.1.6、0.1.7、0.2.0、0.2.1 各已列 alpha/rc,以及 `0.2.2-alpha.2`、`0.2.2-rc.1`、`0.2.2-alpha.3`。按变更分别验证 Session/LLM 恢复、任务投影、用量、压缩取消及旧记忆;官方前端使用实际 React 和插件组件,Remote 等外部边界使用夹具,不等同于 26 个完整宿主。
|
|
64
|
+
- **最近变更的定向证据**:PTC 历史读取为 26 版契约与前端检查;fork 用量为 26 版 157 项契约检查;压缩取消为 26 版 170 项检查;目录别名为 26 版 156 项前端检查;旧记忆额度为 26 版 156 项存储契约检查及最早/最新两版前端交互;设置重置为 26 版 182 项前端检查,均通过。不同批次数量不合计为独立宿主数。
|
|
65
|
+
- **Web 与 macOS 完整宿主**:卸载恢复、MCP 生命周期等修复阶段验收了 Web `0.1.5-alpha.1`、`0.2.1-rc.5`、`0.2.2-rc.1`、`0.2.2-alpha.3`,官方 macOS Desktop `0.2.1-rc.5` 和 NEXT `2.0.19-next`(内置 `0.2.1-rc.2`)。后续任务历史和渲染修复另在最低/最新两版 Web、官方 macOS rc.5 检查了真实工具、三轮记录与冷启动;较晚的用量、压缩、目录、记忆额度和重置修复未再次跑完整桌面矩阵。
|
|
66
|
+
- **Windows 与 Linux**:本批较早阶段在 Windows 11 ARM64 VM 运行官方 x64 Desktop rc.5 和 NEXT `2.0.21-next`(内置 rc.4),覆盖 MCP、Bash、PowerShell、删除保护、物理卸载、冷启及历史续聊,两款各 37 组通过;118 项 Windows 回归通过,3 项 POSIX 专有场景跳过,另有 22 项 PowerShell 5/7 对照。Linux ARM64 非 root 的阶段性全量 527 项通过。后续修复未重新执行上述操作系统完整套件。
|
|
67
|
+
- **保留与限制**:已验收范围内,原主/子会话历史保留,Super Code 卸载后使用官方标准续聊并显示一次说明;minimal 撤销旧插件规则。公开记忆仍为旧版 CRUD。所有宿主模型来自确定性适配器,无外部模型调用;没有新增 100 题效果评测、Safari 专项或历史原生 Windows 桌面逐版验收。
|
|
68
|
+
|
|
56
69
|
## 0.3.10 · 2026-11-03
|
|
57
70
|
|
|
58
71
|
以下为 2026-11-02 ~ 03 各阶段的 Windows Bash 验证,保留各批次的代码基线与验收范围,不改变下方历史版本记录。
|