dsh-super-code 0.1.3 → 0.2.0
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 +43 -31
- package/client/index.js +253 -20
- package/cordis.patch.yml +63 -16
- package/docs/Changelog.md +38 -0
- package/docs/Compatibility.md +57 -0
- package/docs/EvaluationResults.md +66 -0
- package/docs/UsageGuide.md +110 -0
- package/docs/images/agent-tree-preview.png +0 -0
- package/docs/images/agent-tree.png +0 -0
- package/docs/images/preset-settings-preview.png +0 -0
- package/docs/images/preset-settings.png +0 -0
- package/lib/core/host-messages.d.ts +11 -0
- package/lib/core/host-messages.d.ts.map +1 -0
- package/lib/core/host-messages.js +13 -0
- package/lib/core/host-messages.js.map +1 -0
- package/lib/core/task-memory.d.ts +6 -0
- package/lib/core/task-memory.d.ts.map +1 -1
- package/lib/core/task-memory.js +13 -4
- package/lib/core/task-memory.js.map +1 -1
- package/lib/core/tool-evidence.d.ts.map +1 -1
- package/lib/core/tool-evidence.js +9 -9
- package/lib/core/tool-evidence.js.map +1 -1
- package/lib/dsh/index.d.ts +1 -1
- package/lib/dsh/index.d.ts.map +1 -1
- package/lib/dsh/index.js +23 -1
- package/lib/dsh/index.js.map +1 -1
- package/lib/dsh/memory-library.d.ts +45 -0
- package/lib/dsh/memory-library.d.ts.map +1 -0
- package/lib/dsh/memory-library.js +106 -0
- package/lib/dsh/memory-library.js.map +1 -0
- package/lib/dsh/preset-files.d.ts +26 -0
- package/lib/dsh/preset-files.d.ts.map +1 -0
- package/lib/dsh/preset-files.js +44 -0
- package/lib/dsh/preset-files.js.map +1 -0
- package/lib/dsh/preset-installation.d.ts +28 -3
- package/lib/dsh/preset-installation.d.ts.map +1 -1
- package/lib/dsh/preset-installation.js +28 -7
- package/lib/dsh/preset-installation.js.map +1 -1
- package/lib/dsh/preset-metadata.js +1 -1
- package/lib/dsh/preset-metadata.js.map +1 -1
- package/lib/dsh/super-code.d.ts.map +1 -1
- package/lib/dsh/super-code.js +159 -3
- package/lib/dsh/super-code.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/long-memory.d.ts +75 -0
- package/lib/long-memory.d.ts.map +1 -0
- package/lib/long-memory.js +126 -0
- package/lib/long-memory.js.map +1 -0
- package/lib/memory-usage-projection.d.ts +46 -0
- package/lib/memory-usage-projection.d.ts.map +1 -0
- package/lib/memory-usage-projection.js +111 -0
- package/lib/memory-usage-projection.js.map +1 -0
- package/lib/task-memory-projection.d.ts +7 -0
- package/lib/task-memory-projection.d.ts.map +1 -1
- package/lib/task-memory-projection.js +4 -2
- package/lib/task-memory-projection.js.map +1 -1
- package/lib/task-memory-store.js +1 -1
- package/lib/task-memory-store.js.map +1 -1
- package/package.json +26 -12
package/README.md
CHANGED
|
@@ -1,66 +1,78 @@
|
|
|
1
1
|
# dsh-super-code
|
|
2
2
|
|
|
3
|
-
一个更快、更节省、更聪明的 DeepSeek Harness
|
|
3
|
+
一个更快、更节省、更聪明的 DeepSeek Harness 编码插件。简单任务直接做,复杂任务按需组织专业 Agent;任务状态和有来源的经验可以留到后续对话,不必反复交代。
|
|
4
4
|
|
|
5
|
-
A faster, more efficient
|
|
5
|
+
A faster, more efficient coding plugin for DeepSeek Harness. It handles straightforward tasks directly, brings in specialist Agents when useful, and keeps sourced knowledge available for later conversations.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
在同一组 SWE-bench Pro hard-100 的校正结果中,0.2.0 分层记忆候选相比官方 minimal,平均回答耗时减少 **41%**、每题总 token 减少 **20%**,通过率从 **44% 提高到 52%**。[完整结果与限制](docs/EvaluationResults.md)
|
|
8
8
|
|
|
9
|
-
On the
|
|
9
|
+
On the same SWE-bench Pro hard-100 set, the corrected results for the 0.2.0 memory-hierarchy candidate show **41% less response time**, **20% fewer total tokens**, and a pass rate of **52% versus 44%** for official minimal. [Full results and limitations](docs/EvaluationResults.md)
|
|
10
|
+
|
|
11
|
+
## 0.2.0 候选 · What's New
|
|
12
|
+
|
|
13
|
+
- **分层记忆:** 区分本次任务、当前项目和全局偏好;只自动带入少量相关摘要,需要时再读详情。
|
|
14
|
+
**Layered memory:** Separates task state, project knowledge, and global preferences. Only a few relevant summaries enter context; details are read when needed.
|
|
15
|
+
- **记忆库:** 在右侧新标签查看和搜索记忆;Agent 详情中能看到带入上下文、读取、保存和删除记录。
|
|
16
|
+
**Memory library:** Browse and search memories in a sidebar tab, and see each Agent's recorded context, reads, saves, and removals in its details.
|
|
17
|
+
- **宿主兼容:** 保留旧版目录预设,并适配新版声明式预设及消息格式。具体版本和验收范围见[兼容矩阵](docs/Compatibility.md)。
|
|
18
|
+
**Host compatibility:** Keeps directory presets on older hosts and supports newer declarative presets and message formats. See the [verified versions and scope](docs/Compatibility.md).
|
|
19
|
+
|
|
20
|
+
0.2.0 当前为候选,尚未发布到 npm;发布前请使用候选安装包。效果数据来自已冻结的分层记忆实验,不是新增 UI 和兼容改动后的又一轮 100 题评测。
|
|
21
|
+
|
|
22
|
+
Version 0.2.0 is a candidate, not yet published to npm; use the candidate package before release. Its quality results belong to the frozen memory-hierarchy experiment, not a new 100-task run of the integrated UI and compatibility changes.
|
|
10
23
|
|
|
11
24
|
## 开始使用 · Get Started
|
|
12
25
|
|
|
13
|
-
需要
|
|
26
|
+
需要 Node.js 22 或更高版本,以及[已验证的 Harness 版本](docs/Compatibility.md)。
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
Use Node.js 22 or later and a [verified Harness version](docs/Compatibility.md).
|
|
16
29
|
|
|
17
|
-
1.
|
|
30
|
+
1. **安装:** 在插件市场搜索 `dsh-super-code`,或运行以下命令安装 npm 已发布版。
|
|
18
31
|
|
|
19
|
-
**Install
|
|
32
|
+
**Install:** Search for `dsh-super-code` in the plugin marketplace, or install the published npm version:
|
|
20
33
|
|
|
21
34
|
```bash
|
|
22
35
|
dsh plugin --profile web add dsh-super-code
|
|
23
36
|
```
|
|
24
37
|
|
|
25
|
-
|
|
38
|
+
候选包可用 `dsh plugin --profile web add ./dsh-super-code-0.2.0.tgz` 安装。
|
|
39
|
+
For the candidate, use `dsh plugin --profile web add ./dsh-super-code-0.2.0.tgz`.
|
|
26
40
|
|
|
27
|
-
|
|
41
|
+
2. **选中预设:** 打开“设置”→“Agent 预设”,选择 `super-code`。
|
|
28
42
|
|
|
29
|
-
|
|
43
|
+
**Select the preset:** Open “Settings” → “Agent Presets” and choose `super-code`.
|
|
30
44
|
|
|
31
|
-
|
|
45
|
+
3. **开始对话:** 新建会话,描述你要完成的编码任务。模型、推理等级、权限和工具沿用 Harness 的设置;子 Agent 默认继承父 Agent 的模型,不用另配模型池。
|
|
32
46
|
|
|
33
|
-
|
|
47
|
+
**Start a conversation:** Open a new session and describe the task. Models, reasoning effort, permissions, and tools come from Harness; child Agents inherit the parent's model by default.
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
没看到预设?在“设置”→ **Super Code** 查看状态;旧插件版本的入口在“插件配置”中。[安装与排查](docs/UsageGuide.md)
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
模型、推理等级、权限和工具沿用 Harness 的设置;子 Agent 默认继承父 Agent 的模型选择,不用再配置一套。
|
|
51
|
+
Can't find the preset? Open “Settings” → **Super Code**. Older plugin versions place this under “Plugin configuration”. [Setup and troubleshooting](docs/UsageGuide.md)
|
|
40
52
|
|
|
41
|
-
|
|
53
|
+
[](docs/images/preset-settings.png)
|
|
42
54
|
|
|
43
|
-
|
|
55
|
+
右侧执行树显示各 Agent 的状态、用量和缓存率。拖动平移、滚轮缩放;点节点查看详情,不切换主对话。右侧新标签页中的“记忆库”可以查看当前项目和全局偏好。[界面与记忆说明](docs/UsageGuide.md)
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
The Agent tree shows status, usage, and cache hit rate. Drag to pan, scroll to zoom, and click a node for details without leaving the main conversation. Open “Memory library” from the sidebar's new-tab page to view project knowledge and global preferences. [Interface and memory guide](docs/UsageGuide.md)
|
|
46
58
|
|
|
47
59
|
[](docs/images/agent-tree.png)
|
|
48
60
|
|
|
49
61
|
## 效果 · Results
|
|
50
62
|
|
|
51
|
-
|
|
63
|
+
同一组 100 题,均完成官方评分;评分环境异常已使用原补丁复核。时间不含官方评分,token 包含缓存输入,并不等于费用。
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
All four versions received official scores for the same 100 tasks. Grading anomalies were rechecked with the original patches. Time excludes grading; tokens include cache reads and are not a monetary cost estimate.
|
|
54
66
|
|
|
55
|
-
| 指标 / Metric |
|
|
56
|
-
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
67
|
+
| 指标 / Metric | 官方 minimal | 0.0.9 | 0.1.2 | 0.2.0 分层记忆 |
|
|
68
|
+
|---|---:|---:|---:|---:|
|
|
69
|
+
| 通过 / Passed | 44/100 | 48/100 | 52/100 | **52/100** |
|
|
70
|
+
| 平均耗时 / Minutes per task | 25.69 | 16.46 | 16.01 | **15.15** |
|
|
71
|
+
| 平均总 token / Tokens per task | 11,578,047 | 9,623,217 | 9,938,176 | **9,299,094** |
|
|
72
|
+
| 模型调用/题 / Model calls | 124.85 | 92.78 | 99.78 | 93.83 |
|
|
61
73
|
|
|
62
|
-
|
|
74
|
+
0.2.0 与 0.1.2 通过数相同,但有 6 题改善、6 题回退,不代表每道题都更好。这是已用于诊断的历史题集,各轮宿主版本也不同,不能把全部差异归因于插件或记忆功能。[多维指标、逐题证据与统计口径](docs/EvaluationResults.md)
|
|
63
75
|
|
|
64
|
-
|
|
76
|
+
Version 0.2.0 ties 0.1.2 overall, with six gains and six regressions—not an improvement on every task. This is a historically exposed diagnostic set, and host revisions differ between runs; the results do not isolate the effect of the plugin or memory alone. [Detailed metrics, per-task evidence, and methodology](docs/EvaluationResults.md)
|
|
65
77
|
|
|
66
|
-
[使用说明 · Usage
|
|
78
|
+
[使用说明 · Usage](docs/UsageGuide.md) · [兼容性 · Compatibility](docs/Compatibility.md) · [版本记录 · Changelog](docs/Changelog.md)
|
package/client/index.js
CHANGED
|
@@ -9,11 +9,24 @@
|
|
|
9
9
|
;(globalThis.window || globalThis).__ModuleLoader__.load({ id: 'dsh-super-code', factory: (require) => {
|
|
10
10
|
const React = require('react')
|
|
11
11
|
const { useEffect, useLayoutEffect, useRef, useMemo, useState, useSyncExternalStore } = React
|
|
12
|
-
const
|
|
12
|
+
const icons = require('@deepseek-ai/dsh-client-ui-primitives')
|
|
13
|
+
// Harness 0.2 names shared artwork by weight instead of its nominal size.
|
|
14
|
+
const IconChevronDownOutline14 = icons.IconChevronDownOutlineRegular ?? icons.IconChevronDownOutline14
|
|
15
|
+
const IconRefreshOutline16 = icons.IconRefreshOutlineRegular ?? icons.IconRefreshOutline16
|
|
13
16
|
const { SessionEventStream } = require('@deepseek-ai/dsh-api-session-controller')
|
|
14
17
|
|
|
15
18
|
const LOCALE_NS = 'dshSuperCode'
|
|
16
19
|
const zh = {
|
|
20
|
+
'memory.title': '记忆库', 'memory.project': '当前项目', 'memory.global': '全局偏好', 'memory.search': '搜索主题或记忆',
|
|
21
|
+
'memory.description': '跨对话保留的经验与偏好。按需读取,不会整库塞进上下文。',
|
|
22
|
+
'memory.empty': '还没有保存的记忆。需要长期保留时,直接告诉 Agent 即可。', 'memory.noMatches': '没有匹配的记忆',
|
|
23
|
+
'memory.selectSession': '先打开一个对话,查看它所在项目的记忆。', 'memory.error': '暂时无法读取记忆,请刷新重试。',
|
|
24
|
+
'memory.refresh': '刷新记忆库', 'memory.count': '{count} 条记忆', 'memory.back': '返回列表', 'memory.missing': '这条记忆已删除或更新,请刷新列表。',
|
|
25
|
+
'memory.historical': '历史记录,不代表当前代码仍然如此;以本次需求和实际验证为准。',
|
|
26
|
+
'memory.constraint': '用户约定', 'memory.fact': '项目事实', 'memory.experience': '实践经验', 'memory.source': '来源', 'memory.version': '记录时版本',
|
|
27
|
+
'memory.user': '用户消息', 'memory.tool': '工具结果', 'memory.agentUsage': '记忆使用记录', 'memory.usageHint': '只展示已记录的上下文与工具动作,不代表模型已理解或遵守。',
|
|
28
|
+
'memory.usageEmpty': '尚无记忆读取记录', 'memory.context': '带入上下文', 'memory.read': '读取详情', 'memory.summary': '读取摘要',
|
|
29
|
+
'memory.remember': '保存', 'memory.forget': '删除', 'memory.omitted': '仅展示最近 100 条不同动作,完整记录保留在会话中。', 'memory.open': '查看记忆库',
|
|
17
30
|
'preset.title': 'Super Code 模式', 'usage.cacheUnknown': '缓存 —',
|
|
18
31
|
'preset.description': '更快、更省、更聪明的编码模式。', 'preset.refresh': '刷新状态', 'preset.expand': '展开设置', 'preset.collapse': '收起设置',
|
|
19
32
|
'preset.state.available': '预设可用', 'preset.state.installed': '用户预设已安装', 'preset.state.conflict': '已有同名预设',
|
|
@@ -49,6 +62,16 @@ const zh = {
|
|
|
49
62
|
'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': '[图片]'
|
|
50
63
|
}
|
|
51
64
|
const en = {
|
|
65
|
+
'memory.title': 'Memory library', 'memory.project': 'This project', 'memory.global': 'Global preferences', 'memory.search': 'Search topics or memories',
|
|
66
|
+
'memory.description': 'Experience and preferences kept across conversations. Details are read on demand, never injected in bulk.',
|
|
67
|
+
'memory.empty': 'No saved memories yet. Tell the agent when something is worth keeping.', 'memory.noMatches': 'No matching memories',
|
|
68
|
+
'memory.selectSession': 'Open a conversation to view memory for its project.', 'memory.error': 'Memory is unavailable. Refresh to try again.',
|
|
69
|
+
'memory.refresh': 'Refresh memory', 'memory.count': '{count} memories', 'memory.back': 'Back to list', 'memory.missing': 'This memory was removed or changed. Refresh the list.',
|
|
70
|
+
'memory.historical': 'A historical record, not proof of the current code. Follow the current request and verify changing facts.',
|
|
71
|
+
'memory.constraint': 'User agreement', 'memory.fact': 'Project fact', 'memory.experience': 'Experience', 'memory.source': 'Source', 'memory.version': 'Recorded version',
|
|
72
|
+
'memory.user': 'User message', 'memory.tool': 'Tool result', 'memory.agentUsage': 'Memory activity', 'memory.usageHint': 'Recorded context and tool actions only; not proof the model understood or followed them.',
|
|
73
|
+
'memory.usageEmpty': 'No memory reads recorded yet', 'memory.context': 'Added to context', 'memory.read': 'Read details', 'memory.summary': 'Read summary',
|
|
74
|
+
'memory.remember': 'Saved', 'memory.forget': 'Removed', 'memory.omitted': 'Showing the latest 100 distinct actions. Full records remain in the conversation.', 'memory.open': 'Open memory library',
|
|
52
75
|
'preset.title': 'Super Code', 'usage.cacheUnknown': 'Cache —',
|
|
53
76
|
'preset.description': 'A faster, more efficient, smarter coding mode.', 'preset.refresh': 'Refresh status', 'preset.expand': 'Show settings', 'preset.collapse': 'Hide settings',
|
|
54
77
|
'preset.state.available': 'Preset available', 'preset.state.installed': 'User preset installed', 'preset.state.conflict': 'Preset name already exists',
|
|
@@ -80,6 +103,21 @@ function formatText(template, values = {}) { return template.replace(/\{(\w+)\}/
|
|
|
80
103
|
function text(t, key, values) { return formatText(t(key), values) }
|
|
81
104
|
function localeCode(t) { return text(t, 'status.active') === en['status.active'] ? 'en-US' : 'zh-CN' }
|
|
82
105
|
|
|
106
|
+
// The registry captures a fallback title when a tab opens. Title slots receive
|
|
107
|
+
// live locale updates, including for tabs whose bodies are not currently shown.
|
|
108
|
+
function LocalizedTabTitle({ titleKey, t }) { return t(titleKey) }
|
|
109
|
+
|
|
110
|
+
function agentTabTitle(state, address, t) {
|
|
111
|
+
const target = agentDetailTarget(address), id = target.childSessionId || target.sessionId
|
|
112
|
+
const node = buildAgentView(agentSessionState(state, id)).nodes.get(id)
|
|
113
|
+
return node?.title || node?.displayTitle || t('detail.title')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function AgentDetailTitle({ useTabInfo, useSessions, t }) {
|
|
117
|
+
const { tab } = useTabInfo(), state = useSessions(value => value)
|
|
118
|
+
return agentTabTitle(state, tab.contentId, t)
|
|
119
|
+
}
|
|
120
|
+
|
|
83
121
|
function TaskMemoryPanel({ state, t = key => zh[key] || key }) {
|
|
84
122
|
const tasks = state?.tasks || []
|
|
85
123
|
if (!tasks.length) return null
|
|
@@ -98,6 +136,29 @@ function TaskMemoryPanel({ state, t = key => zh[key] || key }) {
|
|
|
98
136
|
)
|
|
99
137
|
}
|
|
100
138
|
|
|
139
|
+
/** Normalize the two published host catalog shapes, without opening Agents. */
|
|
140
|
+
function agentSessionState(state, sessionId, statuses) {
|
|
141
|
+
const current = sessionId || state.current
|
|
142
|
+
if (state.subagentsByParent) return { ...state, current }
|
|
143
|
+
const snapshots = state.projectionsBySession || {}, byId = { ...state.byId }, catalogs = {}
|
|
144
|
+
for (const [id, snapshot] of Object.entries(snapshots)) {
|
|
145
|
+
byId[id] = { ...byId[id], id, projectionValues: snapshot.values,
|
|
146
|
+
running: statuses?.get(id)?.running ?? byId[id]?.running }
|
|
147
|
+
}
|
|
148
|
+
for (const [parentId, snapshot] of Object.entries(snapshots)) {
|
|
149
|
+
const entries = snapshot.values.subagentCatalog || []
|
|
150
|
+
catalogs[parentId] = { state: snapshot.state === 'idle' ? snapshot.values.subagentCatalog === undefined ? 'loading' : 'ready' : snapshot.state,
|
|
151
|
+
entries: entries.map(entry => {
|
|
152
|
+
const child = byId[entry.id], children = snapshots[entry.id]?.values.subagentCatalog
|
|
153
|
+
const running = statuses?.get(entry.id)?.running ?? child?.running
|
|
154
|
+
return { ...entry, hasChildren: children === undefined || children.length > 0,
|
|
155
|
+
kind: entry.mode === 'unknown' ? 'diagnostic' : 'child',
|
|
156
|
+
...(typeof running === 'boolean' ? { activity: running ? 'running' : 'inactive' } : {}) }
|
|
157
|
+
}) }
|
|
158
|
+
}
|
|
159
|
+
return { ...state, current, byId, subagentsByParent: catalogs }
|
|
160
|
+
}
|
|
161
|
+
|
|
101
162
|
/** Join host catalogs without leaking agents from unrelated conversations. */
|
|
102
163
|
function buildAgentView(state) {
|
|
103
164
|
const nodes = new Map(Object.values(state.byId || {}).map(node => [node.id, { ...node }]))
|
|
@@ -109,7 +170,7 @@ function buildAgentView(state) {
|
|
|
109
170
|
nodes.set(entry.id, { ...summary, id: entry.id, parentId,
|
|
110
171
|
title: entry.label || summary?.title || summary?.displayTitle || entry.id,
|
|
111
172
|
mode: entry.mode, hasChildren: entry.hasChildren, createdAt: created.get(entry.id),
|
|
112
|
-
running: summary?.running ?? entry.activity === 'running',
|
|
173
|
+
running: summary?.running ?? (entry.activity === undefined ? undefined : entry.activity === 'running'),
|
|
113
174
|
unavailable: entry.kind === 'diagnostic',
|
|
114
175
|
})
|
|
115
176
|
}
|
|
@@ -344,8 +405,10 @@ function AgentHistory({ view, hidden, totals, open, t = key => zh[key] || key })
|
|
|
344
405
|
!records.length && React.createElement('p', { className: 'dsh-super-code-history-empty' }, text(t, 'history.empty'))))
|
|
345
406
|
}
|
|
346
407
|
|
|
347
|
-
function AgentTree({ useSessions, useTabInfo, treeStates, openDetail, refresh, watchCatalog, t = key => zh[key] || key }) {
|
|
348
|
-
const
|
|
408
|
+
function AgentTree({ useSessions, useSessionStatus, sessionId, useTabInfo, treeStates, openDetail, refresh, watchCatalog, t = key => zh[key] || key }) {
|
|
409
|
+
const catalog = useSessions(s => s)
|
|
410
|
+
const statuses = useSessionStatus ? useSessionStatus(s => s) : undefined
|
|
411
|
+
const state = useMemo(() => agentSessionState(catalog, sessionId, statuses), [catalog, sessionId, statuses])
|
|
349
412
|
const { tab } = useTabInfo()
|
|
350
413
|
const view = useMemo(() => buildAgentView(state), [state.byId, state.subagentsByParent, state.current, state.currentAddress])
|
|
351
414
|
const saved = useMemo(() => {
|
|
@@ -710,9 +773,130 @@ function DetailText({ text: value, t = key => zh[key] || key }) {
|
|
|
710
773
|
!full && value.length > 12000 && React.createElement('button', { type: 'button', onClick: () => setFull(true) }, text(t, 'detail.open')))
|
|
711
774
|
}
|
|
712
775
|
|
|
713
|
-
function
|
|
776
|
+
function MemoryActivity({ usage, openMemory, sessionId, t }) {
|
|
777
|
+
const rows = [...(usage?.rows || [])].reverse()
|
|
778
|
+
return React.createElement('details', { className: 'dsh-super-code-memory-activity' },
|
|
779
|
+
React.createElement('summary', null, text(t, 'memory.agentUsage'), rows.length ? ` · ${rows.length}` : ''),
|
|
780
|
+
React.createElement('p', { className: 'dsh-super-code-memory-muted' }, text(t, 'memory.usageHint')),
|
|
781
|
+
!rows.length && React.createElement('p', null, text(t, 'memory.usageEmpty')),
|
|
782
|
+
React.createElement('div', { className: 'dsh-super-code-memory-activity-list' }, rows.map(row =>
|
|
783
|
+
React.createElement('button', { key: `${row.scope}/${row.topic}/${row.id}/${row.action}`, type: 'button',
|
|
784
|
+
onClick: () => openMemory(sessionId, row), title: text(t, 'memory.open') },
|
|
785
|
+
React.createElement('span', { className: 'dsh-super-code-memory-action', 'data-action': row.action }, text(t, `memory.${row.action}`)),
|
|
786
|
+
React.createElement('span', null, row.summary || row.id),
|
|
787
|
+
React.createElement('small', null, `${text(t, `memory.${row.scope}`)} · ${row.topic} · r${row.revision}`)))),
|
|
788
|
+
usage?.omitted > 0 && React.createElement('p', { className: 'dsh-super-code-memory-muted' }, text(t, 'memory.omitted')))
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function memoryLibraryAddress(sessionId, row = {}) {
|
|
792
|
+
const url = new URL(`dsh-resource://super-code-memory/${encodeURIComponent(sessionId)}`)
|
|
793
|
+
for (const key of ['scope', 'topic', 'id']) if (row[key]) url.searchParams.set(key, row[key])
|
|
794
|
+
return url.href
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function memoryLibraryTarget(address, current) {
|
|
798
|
+
try {
|
|
799
|
+
const url = new URL(address)
|
|
800
|
+
if (url.protocol === 'dsh-resource:' && url.host === 'super-code-memory') return {
|
|
801
|
+
sessionId: decodeURIComponent(url.pathname.slice(1)) || current, scope: url.searchParams.get('scope') === 'global' ? 'global' : 'project',
|
|
802
|
+
topic: url.searchParams.get('topic') || '', id: url.searchParams.get('id') || '',
|
|
803
|
+
}
|
|
804
|
+
} catch {}
|
|
805
|
+
return { sessionId: current, scope: 'project', topic: '', id: '' }
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/** A fixed-height index keeps large libraries cheap; entry bodies load on click. */
|
|
809
|
+
function memoryLibraryWindow(items, query, top, height) {
|
|
810
|
+
const search = query.trim().toLocaleLowerCase()
|
|
811
|
+
const matches = items.filter(item => !search || `${item.topic} ${item.id} ${item.summary}`.toLocaleLowerCase().includes(search))
|
|
812
|
+
const start = Math.min(Math.max(0, Math.floor(top / 76) - 3), Math.max(0, matches.length - 1))
|
|
813
|
+
const end = Math.min(matches.length, start + Math.ceil(height / 76) + 7)
|
|
814
|
+
return { rows: matches.slice(start, end), count: matches.length, before: start * 76, after: (matches.length - end) * 76 }
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
function MemoryLibrary({ useTabInfo, useSessions, sessionId: scopeSessionId, api, memoryStates, t = key => zh[key] || key }) {
|
|
818
|
+
const { tab } = useTabInfo(), current = useSessions(state => scopeSessionId || state.current)
|
|
819
|
+
const target = memoryLibraryTarget(tab.contentId, current)
|
|
820
|
+
const saved = useMemo(() => {
|
|
821
|
+
if (!memoryStates.has(tab.signal)) memoryStates.set(tab.signal, {})
|
|
822
|
+
return memoryStates.get(tab.signal)
|
|
823
|
+
}, [memoryStates, tab.signal])
|
|
824
|
+
const [scope, setScope] = useState(saved.scope || target.scope)
|
|
825
|
+
const [query, setQuery] = useState(saved.query || '')
|
|
826
|
+
const [selected, setSelected] = useState(saved.selected || (target.id ? { topic: target.topic, id: target.id } : null))
|
|
827
|
+
const [state, setState] = useState({ key: '', items: [], loading: true, error: false })
|
|
828
|
+
const [detail, setDetail] = useState(null), [revision, setRevision] = useState(0)
|
|
829
|
+
const [viewport, setViewport] = useState({ top: saved.top || 0, height: 600 })
|
|
830
|
+
const list = useRef(null), sessionId = target.sessionId
|
|
831
|
+
const key = `${sessionId}/${scope}`, selectionKey = selected ? `${key}/${selected.topic}/${selected.id}` : ''
|
|
832
|
+
const visibleState = state.key === key ? state : { items: [], loading: true, error: false }
|
|
833
|
+
useEffect(() => {
|
|
834
|
+
if (!tab.visible || !sessionId) return
|
|
835
|
+
let cancelled = false
|
|
836
|
+
setState(previous => ({ ...previous, loading: true, error: false }))
|
|
837
|
+
api.list(sessionId, scope).then(result => {
|
|
838
|
+
if (!cancelled) setState({ key, items: result.ok ? result.value.items : [], loading: false, error: !result.ok })
|
|
839
|
+
}).catch(() => { if (!cancelled) setState({ key, items: [], loading: false, error: true }) })
|
|
840
|
+
return () => { cancelled = true }
|
|
841
|
+
}, [api, tab.visible, sessionId, scope, revision])
|
|
842
|
+
useEffect(() => {
|
|
843
|
+
if (!tab.visible || !sessionId || !selected) return
|
|
844
|
+
let cancelled = false
|
|
845
|
+
setDetail(null)
|
|
846
|
+
api.read(sessionId, scope, selected.topic, selected.id).then(result => {
|
|
847
|
+
if (!cancelled) setDetail({ key: selectionKey, ...(result.ok ? result.value : { kind: 'error' }) })
|
|
848
|
+
}).catch(() => { if (!cancelled) setDetail({ key: selectionKey, kind: 'error' }) })
|
|
849
|
+
return () => { cancelled = true }
|
|
850
|
+
}, [api, tab.visible, sessionId, scope, selectionKey, revision])
|
|
851
|
+
useLayoutEffect(() => {
|
|
852
|
+
const element = list.current
|
|
853
|
+
if (!element) return
|
|
854
|
+
element.scrollTop = saved.top || 0
|
|
855
|
+
const resize = () => setViewport({ top: element.scrollTop, height: element.clientHeight || 600 })
|
|
856
|
+
resize()
|
|
857
|
+
const observer = new ResizeObserver(resize); observer.observe(element)
|
|
858
|
+
return () => observer.disconnect()
|
|
859
|
+
}, [selected, key, tab.visible])
|
|
860
|
+
const resetScroll = () => { saved.top = 0; if (list.current) list.current.scrollTop = 0; setViewport(value => ({ ...value, top: 0 })) }
|
|
861
|
+
const choose = value => { saved.selected = value; setSelected(value) }
|
|
862
|
+
const page = useMemo(() => memoryLibraryWindow(visibleState.items, query, viewport.top, viewport.height), [visibleState.items, query, viewport])
|
|
863
|
+
const currentDetail = detail?.key === selectionKey ? detail : null
|
|
864
|
+
const entry = currentDetail?.kind === 'found' ? currentDetail.entry : null
|
|
865
|
+
return React.createElement('section', { className: 'dsh-super-code-memory', 'aria-label': text(t, 'memory.title') },
|
|
866
|
+
React.createElement('header', null,
|
|
867
|
+
React.createElement('div', { className: 'dsh-super-code-memory-heading' }, React.createElement('h2', null, text(t, 'memory.title')),
|
|
868
|
+
React.createElement('button', { type: 'button', className: 'dsh-super-code-icon-button', title: text(t, 'memory.refresh'), 'aria-label': text(t, 'memory.refresh'), onClick: () => setRevision(value => value + 1) }, React.createElement(IconRefreshOutline16))),
|
|
869
|
+
React.createElement('p', { className: 'dsh-super-code-memory-muted' }, text(t, 'memory.description')),
|
|
870
|
+
React.createElement('div', { className: 'dsh-super-code-memory-scopes', role: 'group', 'aria-label': text(t, 'memory.title') },
|
|
871
|
+
['project', 'global'].map(value => React.createElement('button', { key: value, type: 'button', 'aria-pressed': scope === value, onClick: () => { saved.scope = value; setScope(value); choose(null); resetScroll() } }, text(t, `memory.${value}`)))),
|
|
872
|
+
!selected && React.createElement('input', { type: 'search', 'aria-label': text(t, 'memory.search'), placeholder: text(t, 'memory.search'), value: query, onChange: event => { saved.query = event.target.value; setQuery(event.target.value); resetScroll() } }),
|
|
873
|
+
!selected && React.createElement('small', null, text(t, 'memory.count', { count: page.count }))),
|
|
874
|
+
!sessionId ? React.createElement('p', { className: 'dsh-super-code-memory-empty' }, text(t, 'memory.selectSession')) : selected
|
|
875
|
+
? React.createElement('div', { className: 'dsh-super-code-memory-body', 'aria-busy': !currentDetail },
|
|
876
|
+
React.createElement('button', { type: 'button', className: 'dsh-super-code-view-button', onClick: () => choose(null) }, `← ${text(t, 'memory.back')}`),
|
|
877
|
+
currentDetail?.kind === 'error' && React.createElement('p', { role: 'alert' }, text(t, 'memory.error')),
|
|
878
|
+
currentDetail?.kind === 'missing' && React.createElement('p', null, text(t, 'memory.missing')),
|
|
879
|
+
entry && React.createElement('article', null, React.createElement('small', null, `${entry.topic} · r${entry.revision} · ${text(t, `memory.${entry.kind}`)}`),
|
|
880
|
+
React.createElement('h3', null, entry.summary), React.createElement('p', { className: 'dsh-super-code-memory-detail' }, entry.detail),
|
|
881
|
+
React.createElement('p', { className: 'dsh-super-code-memory-hint' }, text(t, 'memory.historical')),
|
|
882
|
+
React.createElement('dl', null, React.createElement('dt', null, text(t, 'memory.source')),
|
|
883
|
+
React.createElement('dd', null, `${text(t, `memory.${entry.source.kind}`)} · #${entry.source.eventSeq}`, React.createElement('br'), entry.source.sessionId),
|
|
884
|
+
entry.sourceVersion && React.createElement(React.Fragment, null, React.createElement('dt', null, text(t, 'memory.version')), React.createElement('dd', null, entry.sourceVersion)))))
|
|
885
|
+
: React.createElement('div', { ref: list, className: 'dsh-super-code-memory-list', role: 'list', 'aria-busy': visibleState.loading, onScroll: event => { saved.top = event.currentTarget.scrollTop; setViewport(value => ({ ...value, top: saved.top })) } },
|
|
886
|
+
visibleState.error && React.createElement('p', { role: 'alert' }, text(t, 'memory.error')),
|
|
887
|
+
!visibleState.error && !visibleState.loading && !page.count && React.createElement('p', { className: 'dsh-super-code-memory-empty' }, text(t, query ? 'memory.noMatches' : 'memory.empty')),
|
|
888
|
+
React.createElement('div', { 'aria-hidden': true, style: { height: page.before } }),
|
|
889
|
+
page.rows.map(item => React.createElement('div', { role: 'listitem', key: `${item.topic}/${item.id}` },
|
|
890
|
+
React.createElement('button', { type: 'button', className: 'dsh-super-code-memory-row', onClick: () => choose({ topic: item.topic, id: item.id }) },
|
|
891
|
+
React.createElement('strong', null, item.summary), React.createElement('span', null, `${item.topic} · ${text(t, `memory.${item.kind}`)}`)))),
|
|
892
|
+
React.createElement('div', { 'aria-hidden': true, style: { height: page.after } })))
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
function AgentDetail({ useTabInfo, useSessions, useSessionStatus, sessionId, createInspector, detailStates, openMemory, t = key => zh[key] || key }) {
|
|
714
896
|
const { tab } = useTabInfo()
|
|
715
|
-
const
|
|
897
|
+
const catalog = useSessions(s => s)
|
|
898
|
+
const statuses = useSessionStatus ? useSessionStatus(s => s) : undefined
|
|
899
|
+
const state = useMemo(() => agentSessionState(catalog, sessionId, statuses), [catalog, sessionId, statuses])
|
|
716
900
|
const saved = useMemo(() => {
|
|
717
901
|
if (!detailStates.has(tab.signal)) detailStates.set(tab.signal, { top: 0, following: true, open: new Set(), snapshot: undefined })
|
|
718
902
|
return detailStates.get(tab.signal)
|
|
@@ -753,7 +937,7 @@ function AgentDetail({ useTabInfo, useSessions, createInspector, detailStates, t
|
|
|
753
937
|
const target = agentDetailTarget(tab.contentId), id = target.childSessionId || target.sessionId
|
|
754
938
|
const view = buildAgentView(state), node = view.nodes.get(id)
|
|
755
939
|
const path = agentPath(view, id)
|
|
756
|
-
const projections = state.byId[id]?.projectionValues
|
|
940
|
+
const projections = { ...snapshot.projections, ...state.byId[id]?.projectionValues }
|
|
757
941
|
const totals = projections.superAgentUsage?.totals || projections.tokenUsage
|
|
758
942
|
const input = totals ? (totals.uncachedInputTokens || 0) + (totals.cacheReadTokens || 0) + (totals.cacheWriteTokens || 0) : 0
|
|
759
943
|
const format = value => value === undefined ? text(t, 'detail.unavailable') : value.toLocaleString(localeCode(t))
|
|
@@ -774,6 +958,7 @@ function AgentDetail({ useTabInfo, useSessions, createInspector, detailStates, t
|
|
|
774
958
|
React.createElement('button', { type: 'button', className: 'dsh-super-code-icon-button', title: text(t, 'detail.refresh'), 'aria-label': text(t, 'detail.refresh'), onClick: latest }, React.createElement(IconRefreshOutline16))),
|
|
775
959
|
id !== view.root && task?.goal && task.goal !== title && React.createElement('p', { className: 'dsh-super-code-detail-task' }, task.goal),
|
|
776
960
|
id === view.root && React.createElement(TaskMemoryPanel, { state: tasks, t }),
|
|
961
|
+
React.createElement(MemoryActivity, { usage: projections.superCodeMemoryUsage, sessionId: id, openMemory, t }),
|
|
777
962
|
React.createElement('dl', { className: 'dsh-super-code-detail-metrics' },
|
|
778
963
|
React.createElement('div', null, React.createElement('dt', null, text(t, 'detail.total')), React.createElement('dd', null, format(totals ? input + (totals.outputTokens || 0) : undefined))),
|
|
779
964
|
React.createElement('div', null, React.createElement('dt', null, text(t, 'detail.hitRate')), React.createElement('dd', null, totals ? (input ? Math.round((totals.cacheReadTokens || 0) / input * 100) : 0) + '%' : text(t, 'detail.unavailable')))),
|
|
@@ -808,12 +993,13 @@ function AgentDetail({ useTabInfo, useSessions, createInspector, detailStates, t
|
|
|
808
993
|
}
|
|
809
994
|
|
|
810
995
|
// Explicit public Remote contribution; no model tools or private transport hooks.
|
|
811
|
-
const
|
|
996
|
+
const remoteStringSchema = {
|
|
812
997
|
parse(value) {
|
|
813
998
|
if (typeof value !== 'string') throw new TypeError('Expected a string')
|
|
814
999
|
return value
|
|
815
1000
|
},
|
|
816
|
-
}
|
|
1001
|
+
}
|
|
1002
|
+
const remoteStringCodec = { mode: 'strict', typeSymbol: 'string', schema: remoteStringSchema, create: () => remoteStringSchema }
|
|
817
1003
|
const presetRemoteContribution = {
|
|
818
1004
|
package: 'dsh-super-code',
|
|
819
1005
|
descriptors: ['status', 'installPreset', 'reinstallPreset', 'synchronize'].map(method => ({
|
|
@@ -825,6 +1011,12 @@ const presetRemoteContribution = {
|
|
|
825
1011
|
result: { mode: 'src-json' },
|
|
826
1012
|
})),
|
|
827
1013
|
}
|
|
1014
|
+
const memoryRemoteContribution = {
|
|
1015
|
+
package: 'dsh-super-code', descriptors: ['list', 'read'].map(method => ({
|
|
1016
|
+
id: `dsh-super-code:superCodeMemory/${method}`, service: 'superCodeMemory', namespace: 'superCodeMemory', method, invocation: { kind: 'direct' },
|
|
1017
|
+
parameters: (method === 'list' ? ['sessionId', 'scope'] : ['sessionId', 'scope', 'topic', 'id']).map(name => ({ name, wire: name, source: 'json', codec: remoteStringCodec })), result: { mode: 'src-json' },
|
|
1018
|
+
})),
|
|
1019
|
+
}
|
|
828
1020
|
|
|
829
1021
|
// Old hosts render file metadata. Synchronize through our own Remote, then
|
|
830
1022
|
// reload their cached roster only when a managed field actually changed.
|
|
@@ -903,7 +1095,7 @@ function PresetSettings({ api, t }) {
|
|
|
903
1095
|
} else run(true)
|
|
904
1096
|
}
|
|
905
1097
|
const available = status && ['available', 'installed'].includes(status.state)
|
|
906
|
-
return React.createElement('
|
|
1098
|
+
return React.createElement('section', { className: `dsh-super-code-settings${open ? ' dsh-super-code-settings-open' : ''}` },
|
|
907
1099
|
React.createElement('button', { type: 'button', className: 'dsh-super-code-settings-header', 'aria-expanded': open,
|
|
908
1100
|
'aria-label': `${t(open ? 'preset.collapse' : 'preset.expand')}: ${t('preset.title')}`, onClick: () => setOpen(!open) },
|
|
909
1101
|
React.createElement('span', { className: 'dsh-super-code-settings-head-text' },
|
|
@@ -965,12 +1157,21 @@ function apply(ctx) {
|
|
|
965
1157
|
const t = locale.bind(LOCALE_NS)
|
|
966
1158
|
// $mount creates a lifecycle effect on this same fiber; awaiting it from
|
|
967
1159
|
// another effect would stall the namespace and the settings contribution.
|
|
968
|
-
void ctx.remote.$mount(
|
|
1160
|
+
void ctx.remote.$mount({ package: 'dsh-super-code', descriptors: [
|
|
1161
|
+
...presetRemoteContribution.descriptors, ...memoryRemoteContribution.descriptors,
|
|
1162
|
+
] }).catch(error => console.warn('Super Code Remote:', error))
|
|
1163
|
+
const memoryStates = new WeakMap()
|
|
1164
|
+
ctx.inject(['remote.superCodeMemory'], ready => {
|
|
1165
|
+
ready.slots.inject('sidebar.right.pane.tab', () => ready.slots.register({
|
|
1166
|
+
name: 'sidebar.right.pane.tab', key: 'dsh-super-code-memory', locale: LOCALE_NS,
|
|
1167
|
+
inject: () => ({ api: ready.remote.superCodeMemory, memoryStates }),
|
|
1168
|
+
}, MemoryLibrary))
|
|
1169
|
+
})
|
|
969
1170
|
ctx.inject(['remote.superCodePresets'], ready => {
|
|
970
1171
|
ready.effect(() => synchronizePresetDisplay(ready.remote.superCodePresets, locale,
|
|
971
1172
|
() => window.location.reload(), error => console.warn('Super Code preset display:', error)), 'super-code: preset display')
|
|
972
|
-
|
|
973
|
-
name: 'settings.
|
|
1173
|
+
ready.slots.inject('settings.section', () => ready.slots.register({
|
|
1174
|
+
name: 'settings.section', id: 'super-code', order: 120, label: () => t('preset.title'), locale: LOCALE_NS,
|
|
974
1175
|
inject: () => ({ api: ready.remote.superCodePresets }),
|
|
975
1176
|
}, PresetSettings))
|
|
976
1177
|
})
|
|
@@ -978,6 +1179,23 @@ function apply(ctx) {
|
|
|
978
1179
|
const style = document.createElement('style')
|
|
979
1180
|
style.dataset.dshSuperCode = 'true'
|
|
980
1181
|
style.textContent = `
|
|
1182
|
+
.dsh-super-code-memory{height:100%;min-height:0;display:flex;flex-direction:column;font-size:13px;--agent-muted:var(--dsw-alias-label-secondary,#70757d);--agent-line:var(--dsw-alias-border-l1,#dedfe3)}
|
|
1183
|
+
.dsh-super-code-memory>header{padding:18px 18px 12px;border-bottom:1px solid var(--agent-line)}
|
|
1184
|
+
.dsh-super-code-memory-heading{display:flex;align-items:center;justify-content:space-between;gap:12px}.dsh-super-code-memory h2{margin:0;font-size:16px;font-weight:600}
|
|
1185
|
+
.dsh-super-code-memory-muted{color:var(--agent-muted);font-size:12px;line-height:1.65;margin:10px 0}
|
|
1186
|
+
.dsh-super-code-memory-scopes{display:flex;gap:4px;padding:3px;margin:14px 0;border-radius:8px;background:color-mix(in srgb,currentColor 5%,transparent)}
|
|
1187
|
+
.dsh-super-code-memory-scopes button{flex:1;border:0;border-radius:6px;padding:7px;background:transparent;color:var(--agent-muted);font:inherit;cursor:pointer}
|
|
1188
|
+
.dsh-super-code-memory-scopes button[aria-pressed=true]{background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-color-primary,#3276dc);box-shadow:0 1px 4px #0001}
|
|
1189
|
+
.dsh-super-code-memory input{width:100%;box-sizing:border-box;border:1px solid var(--agent-line);border-radius:7px;background:transparent;color:inherit;font:inherit;padding:9px 10px;margin-bottom:10px}
|
|
1190
|
+
.dsh-super-code-memory small{font-size:11px;color:var(--agent-muted);overflow-wrap:anywhere}
|
|
1191
|
+
.dsh-super-code-memory-list{flex:1;min-height:0;overflow:auto;padding:0 12px}.dsh-super-code-memory-row{display:flex;flex-direction:column;justify-content:center;gap:7px;width:100%;height:76px;box-sizing:border-box;border:0;border-bottom:1px solid var(--agent-line);background:transparent;text-align:left;color:inherit;padding:12px 8px;cursor:pointer;font:inherit}
|
|
1192
|
+
.dsh-super-code-memory-row:hover{background:color-mix(in srgb,var(--dsw-color-primary,#3276dc) 5%,transparent)}.dsh-super-code-memory-row strong,.dsh-super-code-memory-row span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-super-code-memory-row strong{font-weight:500}.dsh-super-code-memory-row span{font-size:11px;color:var(--agent-muted)}
|
|
1193
|
+
.dsh-super-code-memory-body{overflow:auto;flex:1;min-height:0;padding:14px 18px 28px}.dsh-super-code-memory-body article{padding-top:18px}.dsh-super-code-memory-body h3{font-size:15px;line-height:1.6;margin:8px 0 14px;overflow-wrap:anywhere}
|
|
1194
|
+
.dsh-super-code-memory-detail{white-space:pre-wrap;line-height:1.8;overflow-wrap:anywhere}.dsh-super-code-memory-hint{border-left:2px solid #b8ac82;padding:8px 12px;background:color-mix(in srgb,#b8ac82 8%,transparent);color:var(--agent-muted);font-size:12px;line-height:1.6;margin:22px 0}
|
|
1195
|
+
.dsh-super-code-memory-body dt{font-size:11px;color:var(--agent-muted);margin-top:18px}.dsh-super-code-memory-body dd{margin:6px 0;line-height:1.6;overflow-wrap:anywhere;font-size:12px}.dsh-super-code-memory-empty{padding:20px 6px;line-height:1.8;color:var(--agent-muted)}
|
|
1196
|
+
.dsh-super-code-memory-activity{margin-top:14px;font-size:12px}.dsh-super-code-memory-activity summary{cursor:pointer}.dsh-super-code-memory-activity-list{max-height:200px;overflow:auto}.dsh-super-code-memory-activity-list button{display:grid;grid-template-columns:auto 1fr;gap:5px 8px;width:100%;text-align:left;background:transparent;border:0;border-bottom:1px solid var(--agent-line);padding:10px 2px;color:inherit;font:inherit;cursor:pointer}.dsh-super-code-memory-activity-list small{grid-column:2;color:var(--agent-muted);overflow-wrap:anywhere}.dsh-super-code-memory-activity-list span{overflow-wrap:anywhere}
|
|
1197
|
+
.dsh-super-code-memory-action{font-size:10px;color:#4d779f}.dsh-super-code-memory-action[data-action=read]{color:#14867b}.dsh-super-code-memory-action[data-action=remember]{color:#927247}.dsh-super-code-memory-action[data-action=forget]{color:var(--agent-muted)}
|
|
1198
|
+
.dsh-super-code-memory button:focus-visible,.dsh-super-code-memory input:focus-visible{outline:2px solid var(--dsw-color-primary,#3276dc);outline-offset:2px}
|
|
981
1199
|
.dsh-super-code-settings{list-style:none;border:.5px solid var(--dsw-alias-border-l4,#dedfe3);border-radius:16px;background:var(--dsw-alias-bg-layer-3,transparent);line-height:1.6;font-size:13px;transition:border-color .16s,background .16s}
|
|
982
1200
|
.dsh-super-code-settings:hover{border-color:var(--dsw-alias-label-dimmed,#a8abb2)}.dsh-super-code-settings-open{background:var(--dsw-alias-bg-layer-2,transparent);border-color:var(--dsw-alias-label-dimmed,#a8abb2)}
|
|
983
1201
|
.dsh-super-code-settings-header{width:100%;appearance:none;border:0;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer;display:flex;align-items:center;gap:12px;padding:14px 16px;border-radius:12px}
|
|
@@ -1134,22 +1352,36 @@ function apply(ctx) {
|
|
|
1134
1352
|
title: () => t('tree.aria'),
|
|
1135
1353
|
guide: [{ order: 40, title: () => t('tree.aria'), description: () => t('tree.canvas') }],
|
|
1136
1354
|
})
|
|
1355
|
+
const disposeMemoryType = ctx.sidebarRightTabs.register({ id: 'dsh-super-code-memory', kind: 'super-code-memory',
|
|
1356
|
+
patterns: ['dsh-resource://super-code-memory/**'], title: () => t('memory.title'),
|
|
1357
|
+
guide: [{ order: 41, title: () => t('memory.title'), description: () => t('memory.description') }],
|
|
1358
|
+
})
|
|
1359
|
+
const openMemory = (sessionId, row) => ctx.sidebarRight.openResource(memoryLibraryAddress(sessionId, row), { kind: 'super-code-memory' })
|
|
1137
1360
|
const treeActions = {
|
|
1138
1361
|
// The host unmounts hidden bodies; tab signals live until close/unload.
|
|
1139
1362
|
treeStates: new WeakMap(),
|
|
1140
|
-
refresh: id => ctx.sessions.refreshSubagents(id),
|
|
1141
|
-
watchCatalog: (id, open) =>
|
|
1363
|
+
refresh: id => ctx.sessions.refreshSubagents ? ctx.sessions.refreshSubagents(id) : ctx.sessions.refreshProjections(id),
|
|
1364
|
+
watchCatalog: (id, open) => {
|
|
1365
|
+
if (ctx.sessions.setSubagentCatalogOpen) ctx.sessions.setSubagentCatalogOpen(id, open)
|
|
1366
|
+
else if (open) void ctx.sessions.refreshProjections(id).catch(error => console.warn('Super Code projections:', error))
|
|
1367
|
+
},
|
|
1142
1368
|
openDetail: child => ctx.sidebarRight.openResource(agentDetailAddress(child), { kind: 'super-agent-detail' }),
|
|
1143
1369
|
}
|
|
1144
1370
|
const disposeDetailType = ctx.sidebarRightTabs.register({
|
|
1145
1371
|
id: 'dsh-super-code-detail', kind: 'super-agent-detail', patterns: ['dsh-resource://super-agent/**'],
|
|
1146
1372
|
title: address => {
|
|
1147
|
-
|
|
1148
|
-
const node = buildAgentView(state).nodes.get(target.childSessionId || target.sessionId)
|
|
1149
|
-
return node?.title || node?.displayTitle || t('detail.title')
|
|
1373
|
+
return agentTabTitle(ctx.sessions.list.getSnapshot(), address, t)
|
|
1150
1374
|
},
|
|
1151
1375
|
})
|
|
1152
|
-
|
|
1376
|
+
ctx.slots.inject('sidebar.right.pane.tab.title', function* () {
|
|
1377
|
+
for (const [key, titleKey] of [[treeId, 'tree.aria'], ['dsh-super-code-memory', 'memory.title']]) {
|
|
1378
|
+
yield ctx.slots.register({ name: 'sidebar.right.pane.tab.title', key, locale: LOCALE_NS,
|
|
1379
|
+
inject: () => ({ titleKey }),
|
|
1380
|
+
}, LocalizedTabTitle)
|
|
1381
|
+
}
|
|
1382
|
+
yield ctx.slots.register({ name: 'sidebar.right.pane.tab.title', key: 'dsh-super-code-detail', locale: LOCALE_NS }, AgentDetailTitle)
|
|
1383
|
+
})
|
|
1384
|
+
const detailActions = { openMemory, detailStates: new WeakMap(), createInspector: (address, initial) => createAgentInspector(
|
|
1153
1385
|
(target, options) => new SessionEventStream(ctx.remote, target, options), address,
|
|
1154
1386
|
(request, signal) => ctx.remote.session.page(request, signal), initial, t) }
|
|
1155
1387
|
ctx.slots.inject('sidebar.right.pane.tab', () => ctx.slots.register({
|
|
@@ -1163,7 +1395,8 @@ function apply(ctx) {
|
|
|
1163
1395
|
}, AgentTree))
|
|
1164
1396
|
ctx.effect(() => disposeTreeType, 'super-code: Agent tree tab')
|
|
1165
1397
|
ctx.effect(() => disposeDetailType, 'super-code: Agent detail tab')
|
|
1398
|
+
ctx.effect(() => disposeMemoryType, 'super-code: memory library tab')
|
|
1166
1399
|
}
|
|
1167
1400
|
|
|
1168
|
-
return { inject, apply, synchronizePresetDisplay, buildAgentView, visibleAgentRows, agentTreeDisplay, agentTreeTotals, agentTreeLayout, agentExecutionStatus, agentDetailAddress, agentDetailTarget, agentPath, detailRecord, createAgentInspector, agentHistoryRange, agentHistoryRows, agentHistoryWindow }
|
|
1401
|
+
return { inject, apply, synchronizePresetDisplay, agentSessionState, buildAgentView, visibleAgentRows, agentTreeDisplay, agentTreeTotals, agentTreeLayout, agentExecutionStatus, agentDetailAddress, agentDetailTarget, agentPath, detailRecord, createAgentInspector, agentHistoryRange, agentHistoryRows, agentHistoryWindow, memoryLibraryAddress, memoryLibraryTarget, memoryLibraryWindow }
|
|
1169
1402
|
} })
|