dsh-super-code 0.3.2 → 0.3.3
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 +79 -40
- package/client/index.js +309 -78
- package/cordis.patch.yml +14 -1
- package/docs/Changelog.md +3 -0
- package/docs/Compatibility.md +28 -0
- package/docs/EvaluationResults.md +2 -2
- package/docs/UsageGuide.md +24 -10
- package/lib/dsh/memory-library.d.ts +9 -4
- package/lib/dsh/memory-library.d.ts.map +1 -1
- package/lib/dsh/memory-library.js +29 -3
- package/lib/dsh/memory-library.js.map +1 -1
- package/lib/dsh/super-code.js +2 -2
- package/lib/dsh/super-code.js.map +1 -1
- package/lib/long-memory.d.ts +18 -0
- package/lib/long-memory.d.ts.map +1 -1
- package/lib/long-memory.js +42 -2
- package/lib/long-memory.js.map +1 -1
- package/package.json +1 -1
- package/presets/super-code/agent.cordis.yml +10 -1
- package/presets/super-code/skills/super-code-frontend/SKILL.md +33 -0
- package/presets/super-code/skills/super-code-frontend/references/browser-validation.md +59 -0
- package/presets/super-code/skills/super-code-frontend/references/interaction-states.md +51 -0
- package/presets/super-code/skills/super-code-frontend/references/visual-design.md +43 -0
package/client/index.js
CHANGED
|
@@ -256,6 +256,13 @@ const ActionButton = React.forwardRef(function ActionButton({ children, title, .
|
|
|
256
256
|
|
|
257
257
|
const LOCALE_NS = 'dshSuperCode'
|
|
258
258
|
const zh = {
|
|
259
|
+
'memory.add': '新增记忆', 'memory.edit': '编辑', 'memory.cancel': '取消', 'memory.save': '保存', 'memory.delete': '删除', 'memory.deleting': '正在删除…', 'memory.saving': '正在保存…',
|
|
260
|
+
'memory.topic': '主题', 'memory.kind': '类型', 'memory.summaryLabel': '标题', 'memory.detailLabel': '内容', 'memory.manual': '手动维护',
|
|
261
|
+
'memory.topicHint': '字母、数字、点、下划线或短横线,最多 96 个字符。',
|
|
262
|
+
'memory.deleteTitle': '删除记忆', 'memory.deleteHint': '确定删除“{summary}”吗?删除后无法恢复。',
|
|
263
|
+
'memory.writeError': '操作失败,内容已保留,请重试。', 'memory.conflict': '这条记忆已在别处更改,请取消后刷新再编辑。',
|
|
264
|
+
'memory.missingEdit': '这条记忆已被删除,输入内容已保留。', 'memory.full': '该主题或记忆库已满,请删除不再需要的条目。',
|
|
265
|
+
'workspace.title': 'Super Code', 'workspace.description': 'Agent 执行树与记忆库', 'workspace.resize': '调整执行树与记忆库高度',
|
|
259
266
|
'tree.collapsedLabel': '已收起', 'tree.organizeLabel': '自动整理',
|
|
260
267
|
'detail.toolCall': '工具调用', 'detail.toolResult': '工具结果', 'detail.toolError': '工具失败',
|
|
261
268
|
'detail.cache': '缓存', 'detail.info': '详情', 'tree.countCompact': '{shown}/{total} · 运行 {running}',
|
|
@@ -319,6 +326,13 @@ const zh = {
|
|
|
319
326
|
'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': '[图片]'
|
|
320
327
|
}
|
|
321
328
|
const en = {
|
|
329
|
+
'memory.add': 'Add memory', 'memory.edit': 'Edit', 'memory.cancel': 'Cancel', 'memory.save': 'Save', 'memory.delete': 'Delete', 'memory.deleting': 'Deleting…', 'memory.saving': 'Saving…',
|
|
330
|
+
'memory.topic': 'Topic', 'memory.kind': 'Type', 'memory.summaryLabel': 'Title', 'memory.detailLabel': 'Content', 'memory.manual': 'Manually maintained',
|
|
331
|
+
'memory.topicHint': 'Letters, digits, dots, underscores or hyphens; up to 96 characters.',
|
|
332
|
+
'memory.deleteTitle': 'Delete memory', 'memory.deleteHint': 'Delete “{summary}”? This cannot be undone.',
|
|
333
|
+
'memory.writeError': 'The operation failed. Your input is retained; try again.', 'memory.conflict': 'This memory changed elsewhere. Cancel and refresh before editing again.',
|
|
334
|
+
'memory.missingEdit': 'This memory was deleted. Your input is retained.', 'memory.full': 'This topic or library is full. Remove entries you no longer need.',
|
|
335
|
+
'workspace.title': 'Super Code', 'workspace.description': 'Agent tree and memory library', 'workspace.resize': 'Resize agent tree and memory library',
|
|
322
336
|
'tree.collapsedLabel': 'Collapsed', 'tree.organizeLabel': 'Organize',
|
|
323
337
|
'detail.toolCall': 'Tool call', 'detail.toolResult': 'Tool result', 'detail.toolError': 'Tool failed',
|
|
324
338
|
'detail.cache': 'Cache', 'detail.info': 'Details', 'tree.countCompact': '{shown}/{total} · Running {running}',
|
|
@@ -611,9 +625,10 @@ function agentHistoryWindow(count, scrollTop, height) {
|
|
|
611
625
|
}
|
|
612
626
|
|
|
613
627
|
/** Local scroll state keeps the graph out of the scrolling render path. */
|
|
614
|
-
function AgentHistory({ view, hidden, totals, open, t = key => zh[key] || key }) {
|
|
615
|
-
const [filters, setFilters] = useState({ query: '', range: 'all', from: '', to: '', sort: 'time-desc' })
|
|
616
|
-
const [scroll, setScroll] = useState({ top: 0, height: 168 })
|
|
628
|
+
function AgentHistory({ view, hidden, totals, open, saved, t = key => zh[key] || key }) {
|
|
629
|
+
const [filters, setFilters] = useState(saved.historyFilters || { query: '', range: 'all', from: '', to: '', sort: 'time-desc' })
|
|
630
|
+
const [scroll, setScroll] = useState({ top: saved.historyTop || 0, height: 168 })
|
|
631
|
+
const previousFilters = useRef(filters)
|
|
617
632
|
const viewport = useRef(null), focusTarget = useRef('')
|
|
618
633
|
const records = useMemo(() => agentHistoryRows(view, hidden, totals, { ...filters, t }), [view, hidden, totals, filters, t])
|
|
619
634
|
const language = localeCode(t)
|
|
@@ -622,20 +637,25 @@ function AgentHistory({ view, hidden, totals, open, t = key => zh[key] || key })
|
|
|
622
637
|
const range = agentHistoryRange(filters.range, filters.from, filters.to)
|
|
623
638
|
const change = (key, value) => setFilters(previous => ({ ...previous, [key]: value }))
|
|
624
639
|
useLayoutEffect(() => {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
640
|
+
saved.historyFilters = filters
|
|
641
|
+
if (previousFilters.current !== filters) {
|
|
642
|
+
viewport.current.scrollTop = 0; saved.historyTop = 0
|
|
643
|
+
setScroll(previous => ({ ...previous, top: 0 }))
|
|
644
|
+
}
|
|
645
|
+
previousFilters.current = filters
|
|
646
|
+
}, [filters, saved])
|
|
628
647
|
useLayoutEffect(() => {
|
|
629
648
|
const element = viewport.current
|
|
630
649
|
const measure = () => setScroll(previous => previous.top === element.scrollTop && previous.height === element.clientHeight
|
|
631
650
|
? previous : { top: element.scrollTop, height: element.clientHeight })
|
|
651
|
+
element.scrollTop = saved.historyTop || 0
|
|
632
652
|
measure()
|
|
633
653
|
const observer = new ResizeObserver(measure)
|
|
634
654
|
observer.observe(element)
|
|
635
655
|
return () => observer.disconnect()
|
|
636
656
|
}, [])
|
|
637
657
|
useLayoutEffect(() => {
|
|
638
|
-
viewport.current.scrollTop = window.top
|
|
658
|
+
viewport.current.scrollTop = window.top; saved.historyTop = window.top
|
|
639
659
|
if (focusTarget.current) {
|
|
640
660
|
const target = Array.from(viewport.current.querySelectorAll('button')).find(button => button.dataset.historyId === focusTarget.current)
|
|
641
661
|
if (target) { target.focus({ preventScroll: true }); focusTarget.current = '' }
|
|
@@ -680,7 +700,7 @@ function AgentHistory({ view, hidden, totals, open, t = key => zh[key] || key })
|
|
|
680
700
|
!records.length && React.createElement('p', { className: 'dsh-super-code-history-empty' }, text(t, 'history.empty'))))
|
|
681
701
|
}
|
|
682
702
|
|
|
683
|
-
function AgentTree({ useSessions, useSessionStatus, sessionId, useTabInfo, treeStates, openDetail, refresh, watchCatalog, t = key => zh[key] || key }) {
|
|
703
|
+
function AgentTree({ useSessions, useSessionStatus, sessionId, useTabInfo, treeStates, openDetail, refresh, watchCatalog, onToggle, t = key => zh[key] || key }) {
|
|
684
704
|
const catalog = useSessions(s => s)
|
|
685
705
|
const statuses = useSessionStatus ? useSessionStatus(s => s) : undefined
|
|
686
706
|
const state = useMemo(() => agentSessionState(catalog, sessionId, statuses), [catalog, sessionId, statuses])
|
|
@@ -694,7 +714,59 @@ function AgentTree({ useSessions, useSessionStatus, sessionId, useTabInfo, treeS
|
|
|
694
714
|
}
|
|
695
715
|
return value
|
|
696
716
|
}, [treeStates, tab.signal, view.root])
|
|
697
|
-
return React.createElement(AgentTreeBody, { key: view.root, state, view, saved, openDetail, refresh, watchCatalog, t })
|
|
717
|
+
return React.createElement(AgentTreeBody, { key: view.root, state, view, saved, openDetail, refresh, watchCatalog, onToggle, t })
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function WorkspaceSectionToggle({ section, expanded, onToggle, children, t }) {
|
|
721
|
+
const label = text(t, section === 'tree' ? 'tree.title' : 'memory.title')
|
|
722
|
+
return React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-section-toggle',
|
|
723
|
+
'data-workspace-section': section, 'aria-label': label, 'aria-expanded': expanded, onClick: onToggle },
|
|
724
|
+
React.createElement(Glyph, { type: 'chevron' }),
|
|
725
|
+
React.createElement(Glyph, { type: section === 'tree' ? 'branch' : 'memory' }),
|
|
726
|
+
React.createElement('strong', null, label), children)
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/** One active section guarantees exactly one open view; tab state retains drafts. */
|
|
730
|
+
function SuperCodeWorkspace(props) {
|
|
731
|
+
const { tab } = props.useTabInfo()
|
|
732
|
+
const address = typeof tab.navigation?.params?.memory === 'string' ? tab.navigation.params.memory : tab.contentId
|
|
733
|
+
const navigationKey = `${address}/${tab.navigation?.revision || 0}`
|
|
734
|
+
const memoryTarget = memoryLibraryTarget(address, '')
|
|
735
|
+
const saved = useMemo(() => {
|
|
736
|
+
const value = props.workspaceStates.get(tab.signal) || { active: 'tree' }
|
|
737
|
+
if (value.navigationKey !== navigationKey) {
|
|
738
|
+
value.navigationKey = navigationKey
|
|
739
|
+
if (memoryTarget.id) value.active = 'memory'
|
|
740
|
+
}
|
|
741
|
+
props.workspaceStates.set(tab.signal, value)
|
|
742
|
+
return value
|
|
743
|
+
}, [props.workspaceStates, tab.signal])
|
|
744
|
+
const [active, setActive] = useState(saved.active === 'memory' ? 'memory' : 'tree')
|
|
745
|
+
const layout = useRef(null), focusSection = useRef('')
|
|
746
|
+
const toggle = () => {
|
|
747
|
+
const next = active === 'tree' ? 'memory' : 'tree'
|
|
748
|
+
saved.active = next; focusSection.current = next; setActive(next)
|
|
749
|
+
}
|
|
750
|
+
useLayoutEffect(() => {
|
|
751
|
+
if (saved.navigationKey === navigationKey) return
|
|
752
|
+
saved.navigationKey = navigationKey
|
|
753
|
+
if (memoryTarget.id) { saved.active = 'memory'; setActive('memory') }
|
|
754
|
+
}, [saved, navigationKey])
|
|
755
|
+
useLayoutEffect(() => {
|
|
756
|
+
if (!focusSection.current) return
|
|
757
|
+
layout.current.querySelector(`[data-workspace-section="${focusSection.current}"]`)?.focus({ preventScroll: true })
|
|
758
|
+
focusSection.current = ''
|
|
759
|
+
}, [active])
|
|
760
|
+
return React.createElement('section', { className: 'dsh-super-code-workspace', 'aria-label': text(props.t, 'workspace.title') },
|
|
761
|
+
React.createElement('div', { ref: layout, className: 'dsh-super-code-workspace-layout', 'data-active-section': active, style: {
|
|
762
|
+
gridTemplateRows: active === 'tree' ? 'minmax(280px, 1fr) 44px' : '44px minmax(280px, 1fr)',
|
|
763
|
+
} },
|
|
764
|
+
active === 'tree' ? React.createElement(AgentTree, { ...props, key: 'tree', onToggle: toggle })
|
|
765
|
+
: React.createElement('header', { key: 'tree-collapsed', className: 'dsh-super-code-workspace-collapsed' },
|
|
766
|
+
React.createElement(WorkspaceSectionToggle, { section: 'tree', expanded: false, onToggle: toggle, t: props.t })),
|
|
767
|
+
active === 'memory' ? React.createElement(MemoryLibrary, { ...props, key: 'memory', onToggle: toggle })
|
|
768
|
+
: React.createElement('header', { key: 'memory-collapsed', className: 'dsh-super-code-workspace-collapsed' },
|
|
769
|
+
React.createElement(WorkspaceSectionToggle, { section: 'memory', expanded: false, onToggle: toggle, t: props.t }))))
|
|
698
770
|
}
|
|
699
771
|
|
|
700
772
|
function AgentCatalogWatch({ id, watchCatalog }) {
|
|
@@ -705,6 +777,8 @@ function AgentCatalogWatch({ id, watchCatalog }) {
|
|
|
705
777
|
return null
|
|
706
778
|
}
|
|
707
779
|
|
|
780
|
+
// Keep connector anchors and canvas bounds in step with the node's text stack.
|
|
781
|
+
const agentTreeNodeHeight = 120, agentTreeLevelSpacing = 152
|
|
708
782
|
function agentTreeLayout(view, limit) {
|
|
709
783
|
const { rows, more } = visibleAgentRows(view, () => true, limit)
|
|
710
784
|
const positions = new Map(), edges = []
|
|
@@ -713,14 +787,14 @@ function agentTreeLayout(view, limit) {
|
|
|
713
787
|
const row = rows[i]
|
|
714
788
|
const children = (view.children.get(row.id) || []).filter(id => positions.has(id) && positions.get(id).level === row.level + 1)
|
|
715
789
|
const x = children.length ? children.reduce((sum, id) => sum + positions.get(id).x, 0) / children.length : 70 + leaves++ * 140
|
|
716
|
-
positions.set(row.id, { ...row, x, y: 18 + (row.level - 1) *
|
|
790
|
+
positions.set(row.id, { ...row, x, y: 18 + (row.level - 1) * agentTreeLevelSpacing })
|
|
717
791
|
for (const child of children) edges.push({ parent: row.id, child })
|
|
718
792
|
}
|
|
719
793
|
const width = Math.max(140, leaves * 140)
|
|
720
794
|
// Reverse the postorder leaf allocation to preserve catalog order.
|
|
721
795
|
for (const position of positions.values()) position.x = width - position.x
|
|
722
796
|
return { rows: rows.map(row => positions.get(row.id)), edges, positions, more, width,
|
|
723
|
-
height: Math.max(140, ...rows.map(row => row.level *
|
|
797
|
+
height: Math.max(140, ...rows.map(row => row.level * agentTreeLevelSpacing)) }
|
|
724
798
|
}
|
|
725
799
|
|
|
726
800
|
function agentExecutionStatus(node, isRoot, t = key => zh[key] || key) {
|
|
@@ -729,7 +803,7 @@ function agentExecutionStatus(node, isRoot, t = key => zh[key] || key) {
|
|
|
729
803
|
return isRoot || node.mode === 'continuable' ? { tone: 'idle', label: text(t, 'tree.legend.idle') } : { tone: 'stopped', label: text(t, 'tree.legend.stopped') }
|
|
730
804
|
}
|
|
731
805
|
|
|
732
|
-
function AgentTreeBody({ state, view, saved, openDetail, refresh, watchCatalog, t = key => zh[key] || key }) {
|
|
806
|
+
function AgentTreeBody({ state, view, saved, openDetail, refresh, watchCatalog, onToggle, t = key => zh[key] || key }) {
|
|
733
807
|
const [pan, setPan] = useState(saved.pan || { x: 0, y: 0 })
|
|
734
808
|
const [zoom, setZoom] = useState(saved.zoom || 1)
|
|
735
809
|
const viewport = useRef(null), graph = useRef(null)
|
|
@@ -768,9 +842,9 @@ function AgentTreeBody({ state, view, saved, openDetail, refresh, watchCatalog,
|
|
|
768
842
|
const [focused, setFocused] = useState(saved.focused)
|
|
769
843
|
const [expanded, setExpanded] = useState(saved.expanded || new Set())
|
|
770
844
|
const [collapsed, setCollapsed] = useState(saved.collapsed || new Set())
|
|
771
|
-
const [historyOpen, setHistoryOpen] = useState(false)
|
|
845
|
+
const [historyOpen, setHistoryOpen] = useState(saved.historyOpen || false)
|
|
772
846
|
const [compact, setCompact] = useState(false)
|
|
773
|
-
useEffect(() => { Object.assign(saved, { limit, focused, expanded, collapsed }) }, [saved, limit, focused, expanded, collapsed])
|
|
847
|
+
useEffect(() => { Object.assign(saved, { limit, focused, expanded, collapsed, historyOpen }) }, [saved, limit, focused, expanded, collapsed, historyOpen])
|
|
774
848
|
const catalogs = state.subagentsByParent || {}
|
|
775
849
|
const display = useMemo(() => agentTreeDisplay(view, catalogs, { expanded, collapsed, focused, compact }), [view, catalogs, expanded, collapsed, focused, compact])
|
|
776
850
|
const { rows, more, edges, positions, width, height } = useMemo(() => agentTreeLayout(display.view, limit), [display, limit])
|
|
@@ -845,8 +919,11 @@ function AgentTreeBody({ state, view, saved, openDetail, refresh, watchCatalog,
|
|
|
845
919
|
watched.map(id => React.createElement(AgentCatalogWatch, { key: id, id, watchCatalog })),
|
|
846
920
|
React.createElement('header', { className: 'dsh-super-code-tree-header' },
|
|
847
921
|
React.createElement('div', { className: 'dsh-super-code-tree-heading' },
|
|
848
|
-
React.createElement(
|
|
849
|
-
|
|
922
|
+
onToggle ? React.createElement(WorkspaceSectionToggle, { section: 'tree', expanded: true, onToggle, t },
|
|
923
|
+
React.createElement('span', { className: 'dsh-super-code-tree-count' }, text(t, 'tree.countCompact', { shown: rows.length, total: view.nodes.size, running })))
|
|
924
|
+
: React.createElement(React.Fragment, null,
|
|
925
|
+
React.createElement('div', { className: 'dsh-super-code-title-line' }, React.createElement(Glyph, { type: 'branch' }), React.createElement('strong', null, text(t, 'tree.title'))),
|
|
926
|
+
React.createElement('span', { className: 'dsh-super-code-tree-count', title: text(t, 'tree.count', { shown: rows.length, total: view.nodes.size, running }) }, text(t, 'tree.countCompact', { shown: rows.length, total: view.nodes.size, running })))),
|
|
850
927
|
React.createElement('div', { className: 'dsh-super-code-tree-toolbar' },
|
|
851
928
|
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-icon-button', disabled: busy || !view.root, onClick: reload, title: text(t, 'tree.refresh'), 'aria-label': text(t, 'tree.refresh') }, React.createElement(IconRefreshOutline16)),
|
|
852
929
|
React.createElement('div', { className: 'dsh-super-code-graph-controls', 'aria-label': text(t, 'tree.canvas') },
|
|
@@ -856,13 +933,13 @@ function AgentTreeBody({ state, view, saved, openDetail, refresh, watchCatalog,
|
|
|
856
933
|
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-icon-button', title: text(t, 'tree.fit'), 'aria-label': text(t, 'tree.fit'), onClick: fit }, React.createElement(Glyph, { type: 'fit' })),
|
|
857
934
|
(display.hidden.length > 0 || expanded.size > 0 || collapsed.size > 0) && React.createElement('div', { className: 'dsh-super-code-history-controls' },
|
|
858
935
|
React.createElement(ActionButton, { type: 'button', title: text(t, 'tree.collapsed', { count: display.hidden.length }), 'aria-label': text(t, 'tree.collapsed', { count: display.hidden.length }), 'aria-expanded': historyOpen, onClick: () => setHistoryOpen(!historyOpen) }, React.createElement(Glyph, { type: 'history' }), React.createElement('span', { className: 'dsh-super-code-action-label' }, text(t, 'tree.collapsedLabel')), React.createElement('span', { className: 'dsh-super-code-action-count' }, display.hidden.length)),
|
|
859
|
-
(expanded.size > 0 || collapsed.size > 0) && React.createElement(ActionButton, { type: 'button', title: text(t, 'tree.organize'), 'aria-label': text(t, 'tree.organize'), onClick: () => { autoFit.current = true; setExpanded(new Set()); setCollapsed(new Set()); setFocused(state.current) } }, React.createElement(Glyph, { type: 'organize' }), React.createElement('span', { className: 'dsh-super-code-action-label' }, text(t, 'tree.organizeLabel'))))),
|
|
936
|
+
(expanded.size > 0 || collapsed.size > 0) && React.createElement(ActionButton, { type: 'button', title: text(t, 'tree.organize'), 'aria-label': text(t, 'tree.organize'), onClick: () => { autoFit.current = true; setExpanded(new Set()); setCollapsed(new Set()); setHistoryOpen(false); setFocused(state.current) } }, React.createElement(Glyph, { type: 'organize' }), React.createElement('span', { className: 'dsh-super-code-action-label' }, text(t, 'tree.organizeLabel'))))),
|
|
860
937
|
React.createElement('div', { className: 'dsh-super-code-graph-legend', 'aria-label': text(t, 'tree.status') },
|
|
861
938
|
['tree.legend.active', 'tree.legend.idle', 'tree.legend.stopped', 'tree.legend.unavailable'].map((key, index) => React.createElement('span', { key },
|
|
862
939
|
React.createElement('i', { className: 'dsh-super-code-circle ' + ['active', 'idle', 'stopped', 'unavailable'][index], 'aria-hidden': true }), text(t, key))))),
|
|
863
940
|
(error || catalogError) && React.createElement('p', { role: 'alert', className: 'dsh-super-code-tree-error' }, text(t, error || 'tree.loadError')),
|
|
864
941
|
!view.root && React.createElement('p', { className: 'dsh-super-code-tree-empty' }, text(t, 'tree.empty')),
|
|
865
|
-
historyOpen && React.createElement(AgentHistory, { view, hidden: display.hidden, totals, open, t }),
|
|
942
|
+
historyOpen && React.createElement(AgentHistory, { view, hidden: display.hidden, totals, open, saved, t }),
|
|
866
943
|
React.createElement('div', { ref: viewport, className: 'dsh-super-code-graph-scroll',
|
|
867
944
|
onPointerDown: event => {
|
|
868
945
|
if (!event.isPrimary || event.button !== 0) return
|
|
@@ -887,7 +964,7 @@ function AgentTreeBody({ state, view, saved, openDetail, refresh, watchCatalog,
|
|
|
887
964
|
React.createElement('div', { ref: graph, role: 'tree', 'aria-label': text(t, 'tree.aria'), className: 'dsh-super-code-graph', style: { width, height, transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})` } },
|
|
888
965
|
React.createElement('svg', { width, height, className: 'dsh-super-code-graph-edges', 'aria-hidden': true }, edges.map(edge => {
|
|
889
966
|
const parent = positions.get(edge.parent), child = positions.get(edge.child)
|
|
890
|
-
return React.createElement('path', { key: edge.child, d: `M ${parent.x} ${parent.y +
|
|
967
|
+
return React.createElement('path', { key: edge.child, d: `M ${parent.x} ${parent.y + agentTreeNodeHeight} V ${child.y - 16} H ${child.x} V ${child.y - 10}`, fill: 'none' })
|
|
891
968
|
})),
|
|
892
969
|
rows.map(row => {
|
|
893
970
|
const node = view.nodes.get(row.id)
|
|
@@ -1077,7 +1154,7 @@ function MemoryActivity({ usage, openMemory, sessionId, t }) {
|
|
|
1077
1154
|
onClick: () => openMemory(sessionId, row), title: text(t, 'memory.open') },
|
|
1078
1155
|
React.createElement('span', { className: 'dsh-super-code-memory-action', 'data-action': row.action }, text(t, `memory.${row.action}`)),
|
|
1079
1156
|
React.createElement('span', null, row.summary || row.id),
|
|
1080
|
-
React.createElement('small', null, `${text(t, `memory.${row.scope}`)} · ${row.topic}
|
|
1157
|
+
React.createElement('small', null, `${text(t, `memory.${row.scope}`)} · ${row.topic}`)))),
|
|
1081
1158
|
usage?.omitted > 0 && React.createElement('p', { className: 'dsh-super-code-memory-muted' }, text(t, 'memory.omitted')))
|
|
1082
1159
|
}
|
|
1083
1160
|
|
|
@@ -1098,6 +1175,18 @@ function memoryLibraryTarget(address, current) {
|
|
|
1098
1175
|
return { sessionId: current, scope: 'project', topic: '', id: '' }
|
|
1099
1176
|
}
|
|
1100
1177
|
|
|
1178
|
+
/** A repeated explicit navigation reopens its entry; ordinary remounts retain reading state. */
|
|
1179
|
+
function memoryLibraryNavigation(saved, tab, current) {
|
|
1180
|
+
const address = typeof tab.navigation?.params?.memory === 'string' ? tab.navigation.params.memory : tab.contentId
|
|
1181
|
+
const navigationKey = `${address}/${tab.navigation?.revision || 0}`
|
|
1182
|
+
if (saved.navigationKey === navigationKey) return saved
|
|
1183
|
+
const target = memoryLibraryTarget(address, current)
|
|
1184
|
+
return { ...saved, navigationKey, ...(target.id ? {
|
|
1185
|
+
scope: target.scope, selected: { topic: target.topic, id: target.id }, detailTop: 0,
|
|
1186
|
+
...(saved.scope && saved.scope !== target.scope ? { topicFilter: '', top: 0 } : {}),
|
|
1187
|
+
} : {}) }
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1101
1190
|
/** A fixed-height index keeps large libraries cheap; entry bodies load on click. */
|
|
1102
1191
|
function memoryLibraryWindow(items, query, top, height) {
|
|
1103
1192
|
const search = query.trim().toLocaleLowerCase()
|
|
@@ -1107,23 +1196,119 @@ function memoryLibraryWindow(items, query, top, height) {
|
|
|
1107
1196
|
return { rows: matches.slice(start, end), count: matches.length, before: start * 76, after: (matches.length - end) * 76 }
|
|
1108
1197
|
}
|
|
1109
1198
|
|
|
1110
|
-
|
|
1199
|
+
/** Drafts and in-flight operations survive the host unmounting a hidden tab. */
|
|
1200
|
+
function createMemoryEditor(saved, api) {
|
|
1201
|
+
if (saved.editorStore) return saved.editorStore
|
|
1202
|
+
let snapshot = { draft: null, confirmation: null, busy: false, error: '', refresh: 0 }
|
|
1203
|
+
const listeners = new Set()
|
|
1204
|
+
const update = patch => { snapshot = { ...snapshot, ...patch }; for (const listener of listeners) listener() }
|
|
1205
|
+
const run = async (method, target) => {
|
|
1206
|
+
if (snapshot.busy) return { kind: 'busy' }
|
|
1207
|
+
update({ busy: true, error: '' })
|
|
1208
|
+
try {
|
|
1209
|
+
const response = method === 'save' ? await api.saveEntry(target.sessionId, target.scope, target.topic, target.id, JSON.stringify({
|
|
1210
|
+
expected: target.expected, kind: target.kind, summary: target.summary.trim(), detail: target.detail.trim(),
|
|
1211
|
+
})) : await api.deleteEntry(target.sessionId, target.scope, target.topic, target.id, target.expected)
|
|
1212
|
+
if (!response.ok) throw new Error('Remote unavailable')
|
|
1213
|
+
const result = response.value
|
|
1214
|
+
if (!['saved', 'removed'].includes(result.kind)) {
|
|
1215
|
+
update({ busy: false, error: { conflict: 'memory.conflict', missing: 'memory.missingEdit', full: 'memory.full' }[result.kind] || 'memory.writeError' })
|
|
1216
|
+
return result
|
|
1217
|
+
}
|
|
1218
|
+
saved.scope = target.scope
|
|
1219
|
+
saved.selected = result.kind === 'saved' ? { topic: target.topic, id: target.id } : null
|
|
1220
|
+
saved.detailTop = 0
|
|
1221
|
+
update({ draft: null, confirmation: null, busy: false, error: '', refresh: snapshot.refresh + 1 })
|
|
1222
|
+
return result
|
|
1223
|
+
} catch {
|
|
1224
|
+
update({ busy: false, error: 'memory.writeError' })
|
|
1225
|
+
return { kind: 'error' }
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
saved.editorStore = { getSnapshot: () => snapshot, subscribe: listener => { listeners.add(listener); return () => listeners.delete(listener) },
|
|
1229
|
+
update, save: () => run('save', snapshot.draft), remove: () => run('remove', snapshot.confirmation) }
|
|
1230
|
+
return saved.editorStore
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
function MemoryEditor({ store, state, t }) {
|
|
1234
|
+
const draft = state.draft
|
|
1235
|
+
const set = (key, value) => store.update({ draft: { ...draft, [key]: value }, error: '' })
|
|
1236
|
+
return React.createElement('form', { className: 'dsh-super-code-memory-editor', 'aria-label': text(t, draft.expected ? 'memory.edit' : 'memory.add'),
|
|
1237
|
+
onSubmit: event => { event.preventDefault(); void store.save() } },
|
|
1238
|
+
React.createElement('div', { className: 'dsh-super-code-memory-editor-heading' },
|
|
1239
|
+
React.createElement('strong', null, text(t, draft.expected ? 'memory.edit' : 'memory.add')),
|
|
1240
|
+
React.createElement('small', null, text(t, `memory.${draft.scope}`))),
|
|
1241
|
+
React.createElement('label', null, text(t, 'memory.topic'),
|
|
1242
|
+
React.createElement('input', { value: draft.topic, 'aria-label': text(t, 'memory.topic'), required: true, maxLength: 96,
|
|
1243
|
+
disabled: state.busy || Boolean(draft.expected) || draft.scope === 'global', onChange: event => set('topic', event.target.value) }),
|
|
1244
|
+
!draft.expected && draft.scope !== 'global' && React.createElement('small', null, text(t, 'memory.topicHint'))),
|
|
1245
|
+
React.createElement(SelectControl, { label: text(t, 'memory.kind'), value: draft.kind, disabled: state.busy || draft.scope === 'global',
|
|
1246
|
+
choices: ['constraint', 'fact', 'experience'].map(kind => [kind, text(t, `memory.${kind}`)]), onChange: kind => set('kind', kind) }),
|
|
1247
|
+
React.createElement('label', null, text(t, 'memory.summaryLabel'), React.createElement('small', null, `${Array.from(draft.summary).length}/30`),
|
|
1248
|
+
React.createElement('input', { value: draft.summary, 'aria-label': text(t, 'memory.summaryLabel'), required: true, disabled: state.busy, onChange: event => set('summary', event.target.value) })),
|
|
1249
|
+
React.createElement('label', null, text(t, 'memory.detailLabel'), React.createElement('small', null, `${draft.detail.length}/1000`),
|
|
1250
|
+
React.createElement('textarea', { value: draft.detail, 'aria-label': text(t, 'memory.detailLabel'), required: true, maxLength: 1000, rows: 5, disabled: state.busy, onChange: event => set('detail', event.target.value) })),
|
|
1251
|
+
state.error && React.createElement('p', { role: 'alert' }, text(t, state.error)),
|
|
1252
|
+
React.createElement('div', { className: 'dsh-super-code-memory-actions' },
|
|
1253
|
+
React.createElement(ActionButton, { type: 'button', disabled: state.busy, onClick: () => store.update({ draft: null, error: '' }) }, text(t, 'memory.cancel')),
|
|
1254
|
+
React.createElement(ActionButton, { type: 'submit', className: 'dsh-super-code-memory-primary', disabled: state.busy || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}$/.test(draft.topic) || !draft.summary.trim() || Array.from(draft.summary.trim()).length > 30 || !draft.detail.trim() }, text(t, state.busy ? 'memory.saving' : 'memory.save'))))
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
function MemoryDeleteConfirmation({ store, state, t }) {
|
|
1258
|
+
const dialog = useRef(null), target = state.confirmation
|
|
1259
|
+
useLayoutEffect(() => {
|
|
1260
|
+
dialog.current.showModal()
|
|
1261
|
+
return () => { if (dialog.current?.open) dialog.current.close() }
|
|
1262
|
+
}, [])
|
|
1263
|
+
const cancel = () => { if (!store.getSnapshot().busy) store.update({ confirmation: null, error: '' }) }
|
|
1264
|
+
return React.createElement('dialog', { ref: dialog, className: 'dsh-super-code-confirm', 'aria-label': text(t, 'memory.deleteTitle'),
|
|
1265
|
+
onCancel: event => { event.preventDefault(); cancel() }, onKeyDown: event => {
|
|
1266
|
+
if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); cancel() }
|
|
1267
|
+
} },
|
|
1268
|
+
React.createElement('h3', null, text(t, 'memory.deleteTitle')),
|
|
1269
|
+
React.createElement('p', null, text(t, 'memory.deleteHint', { summary: target.summary })),
|
|
1270
|
+
state.error && React.createElement('p', { role: 'alert' }, text(t, state.error)),
|
|
1271
|
+
React.createElement('div', { className: 'dsh-super-code-confirm-actions' },
|
|
1272
|
+
React.createElement(ActionButton, { type: 'button', disabled: state.busy, onClick: cancel }, text(t, 'memory.cancel')),
|
|
1273
|
+
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-memory-danger', disabled: state.busy, onClick: () => { void store.remove() } }, text(t, state.busy ? 'memory.deleting' : 'memory.delete'))))
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
function MemoryLibrary({ useTabInfo, useSessions, sessionId: scopeSessionId, api, memoryStates, onToggle, t = key => zh[key] || key }) {
|
|
1111
1277
|
const { tab } = useTabInfo(), current = useSessions(state => scopeSessionId || state.current)
|
|
1112
|
-
const
|
|
1278
|
+
const address = typeof tab.navigation?.params?.memory === 'string' ? tab.navigation.params.memory : tab.contentId
|
|
1279
|
+
const target = memoryLibraryTarget(address, current)
|
|
1113
1280
|
const saved = useMemo(() => {
|
|
1114
|
-
|
|
1115
|
-
|
|
1281
|
+
const value = memoryStates.get(tab.signal) || {}
|
|
1282
|
+
Object.assign(value, memoryLibraryNavigation(value, tab, current))
|
|
1283
|
+
memoryStates.set(tab.signal, value)
|
|
1284
|
+
return value
|
|
1116
1285
|
}, [memoryStates, tab.signal])
|
|
1286
|
+
const editor = useMemo(() => createMemoryEditor(saved, api), [saved, api])
|
|
1287
|
+
const editing = useSyncExternalStore(editor.subscribe, editor.getSnapshot, editor.getSnapshot)
|
|
1117
1288
|
const [scope, setScope] = useState(saved.scope || target.scope)
|
|
1118
1289
|
const [query, setQuery] = useState(saved.query || '')
|
|
1119
1290
|
const [topicFilter, setTopicFilter] = useState(saved.topicFilter || '')
|
|
1120
|
-
const [selected, setSelected] = useState(saved.selected ||
|
|
1291
|
+
const [selected, setSelected] = useState(saved.selected || null)
|
|
1121
1292
|
const [state, setState] = useState({ key: '', items: [], loading: true, error: false })
|
|
1122
1293
|
const [detail, setDetail] = useState(null), [revision, setRevision] = useState(0)
|
|
1123
1294
|
const [viewport, setViewport] = useState({ top: saved.top || 0, height: 600 })
|
|
1124
|
-
const list = useRef(null), detailBody = useRef(null), sessionId = target.sessionId
|
|
1295
|
+
const list = useRef(null), detailBody = useRef(null), sessionId = editing.draft?.sessionId || editing.confirmation?.sessionId || target.sessionId
|
|
1125
1296
|
const key = `${sessionId}/${scope}`, selectionKey = selected ? `${key}/${selected.topic}/${selected.id}` : ''
|
|
1126
1297
|
const visibleState = state.key === key ? state : { items: [], loading: true, error: false }
|
|
1298
|
+
useLayoutEffect(() => {
|
|
1299
|
+
if (editing.draft || editing.confirmation || editing.busy) return
|
|
1300
|
+
const next = memoryLibraryNavigation(saved, tab, current)
|
|
1301
|
+
if (next === saved) return
|
|
1302
|
+
Object.assign(saved, next)
|
|
1303
|
+
setScope(saved.scope || target.scope); setSelected(saved.selected || null)
|
|
1304
|
+
setTopicFilter(saved.topicFilter || '')
|
|
1305
|
+
setViewport(value => ({ ...value, top: saved.top || 0 }))
|
|
1306
|
+
if (detailBody.current) detailBody.current.scrollTop = 0
|
|
1307
|
+
}, [saved, address, tab.navigation?.revision, editing.draft, editing.confirmation, editing.busy])
|
|
1308
|
+
useLayoutEffect(() => {
|
|
1309
|
+
if (!editing.refresh) return
|
|
1310
|
+
setScope(saved.scope); setSelected(saved.selected); setRevision(value => value + 1)
|
|
1311
|
+
}, [editing.refresh])
|
|
1127
1312
|
useEffect(() => {
|
|
1128
1313
|
if (!tab.visible || !sessionId) return
|
|
1129
1314
|
let cancelled = false
|
|
@@ -1150,9 +1335,12 @@ function MemoryLibrary({ useTabInfo, useSessions, sessionId: scopeSessionId, api
|
|
|
1150
1335
|
resize()
|
|
1151
1336
|
const observer = new ResizeObserver(resize); observer.observe(element)
|
|
1152
1337
|
return () => observer.disconnect()
|
|
1153
|
-
}, [selected, key, tab.visible])
|
|
1338
|
+
}, [selected, key, tab.visible, Boolean(editing.draft)])
|
|
1339
|
+
useLayoutEffect(() => {
|
|
1340
|
+
if (detailBody.current) detailBody.current.scrollTop = saved.detailTop || 0
|
|
1341
|
+
}, [selectionKey, detail?.key, tab.visible, Boolean(editing.draft)])
|
|
1154
1342
|
const resetScroll = () => { saved.top = 0; if (list.current) list.current.scrollTop = 0; setViewport(value => ({ ...value, top: 0 })) }
|
|
1155
|
-
const choose = value => { if (detailBody.current) detailBody.current.scrollTop = 0; saved.selected = value; setSelected(value) }
|
|
1343
|
+
const choose = value => { saved.detailTop = 0; if (detailBody.current) detailBody.current.scrollTop = 0; saved.selected = value; setSelected(value) }
|
|
1156
1344
|
const changeTopic = value => { saved.topicFilter = value; setTopicFilter(value); resetScroll() }
|
|
1157
1345
|
const topics = useMemo(() => {
|
|
1158
1346
|
const counts = new Map()
|
|
@@ -1167,28 +1355,36 @@ function MemoryLibrary({ useTabInfo, useSessions, sessionId: scopeSessionId, api
|
|
|
1167
1355
|
return React.createElement('section', { className: 'dsh-super-code-memory', 'aria-label': text(t, 'memory.title') },
|
|
1168
1356
|
React.createElement('header', null,
|
|
1169
1357
|
React.createElement('div', { className: 'dsh-super-code-memory-heading' },
|
|
1170
|
-
|
|
1171
|
-
|
|
1358
|
+
onToggle ? React.createElement(WorkspaceSectionToggle, { section: 'memory', expanded: true, onToggle, t })
|
|
1359
|
+
: React.createElement('div', { className: 'dsh-super-code-title-line' }, React.createElement(Glyph, { type: 'memory' }), React.createElement('h2', null, text(t, 'memory.title'))),
|
|
1360
|
+
React.createElement('div', { className: 'dsh-super-code-memory-header-actions' },
|
|
1361
|
+
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-view-button', 'aria-label': text(t, 'memory.add'), disabled: !sessionId || editing.busy || Boolean(editing.draft), onClick: () => editor.update({ error: '', draft: {
|
|
1362
|
+
sessionId, scope, topic: scope === 'global' ? 'preferences' : topicFilter || 'notes', id: window.crypto.randomUUID(), expected: '', kind: 'constraint', summary: '', detail: '',
|
|
1363
|
+
} }) }, `+ ${text(t, 'memory.add')}`),
|
|
1364
|
+
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-icon-button', title: text(t, 'memory.refresh'), 'aria-label': text(t, 'memory.refresh'), disabled: editing.busy || Boolean(editing.draft), onClick: () => { editor.update({ error: '' }); setRevision(value => value + 1) } }, React.createElement(IconRefreshOutline16)))),
|
|
1172
1365
|
React.createElement('div', { className: 'dsh-super-code-memory-scopes', role: 'group', 'aria-label': text(t, 'memory.title') },
|
|
1173
|
-
['project', 'global'].map(value => React.createElement(ActionButton, { key: value, type: 'button', 'aria-pressed': scope === value, onClick: () => {
|
|
1366
|
+
['project', 'global'].map(value => React.createElement(ActionButton, { key: value, type: 'button', 'aria-pressed': scope === value, disabled: editing.busy || Boolean(editing.draft), onClick: () => {
|
|
1174
1367
|
saved.scope = value; setScope(value); changeTopic(''); choose(null)
|
|
1175
1368
|
} }, text(t, `memory.${value}`)))),
|
|
1176
|
-
!selected && React.createElement('div', { className: 'dsh-super-code-memory-search' }, React.createElement(Glyph, { type: 'search' }),
|
|
1369
|
+
!selected && !editing.draft && React.createElement('div', { className: 'dsh-super-code-memory-search' }, React.createElement(Glyph, { type: 'search' }),
|
|
1177
1370
|
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() } }))),
|
|
1178
|
-
!sessionId ? React.createElement('p', { className: 'dsh-super-code-memory-empty' }, text(t, 'memory.selectSession')) : selected
|
|
1179
|
-
? React.createElement('div', { ref: detailBody, className: 'dsh-super-code-memory-body', 'aria-busy': !currentDetail },
|
|
1180
|
-
React.createElement(
|
|
1371
|
+
!sessionId ? React.createElement('p', { className: 'dsh-super-code-memory-empty' }, text(t, 'memory.selectSession')) : editing.draft ? React.createElement(MemoryEditor, { store: editor, state: editing, t }) : selected
|
|
1372
|
+
? React.createElement('div', { ref: detailBody, className: 'dsh-super-code-memory-body', 'aria-busy': !currentDetail, onScroll: event => { saved.detailTop = event.currentTarget.scrollTop } },
|
|
1373
|
+
React.createElement('div', { className: 'dsh-super-code-memory-actions' },
|
|
1374
|
+
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-view-button', onClick: () => choose(null) }, `← ${text(t, 'memory.back')}`),
|
|
1375
|
+
entry && React.createElement(React.Fragment, null,
|
|
1376
|
+
React.createElement(ActionButton, { type: 'button', onClick: () => editor.update({ error: '', draft: { sessionId, scope, topic: entry.topic, id: entry.id, expected: entry.token, kind: entry.kind, summary: entry.summary, detail: entry.detail } }) }, text(t, 'memory.edit')),
|
|
1377
|
+
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-memory-danger', onClick: () => editor.update({ error: '', confirmation: { sessionId, scope, topic: entry.topic, id: entry.id, expected: entry.token, summary: entry.summary } }) }, text(t, 'memory.delete')))),
|
|
1181
1378
|
!currentDetail && React.createElement('p', { role: 'status', className: 'dsh-super-code-memory-empty' }, text(t, 'memory.loading')),
|
|
1182
1379
|
currentDetail?.kind === 'error' && React.createElement('p', { role: 'alert' }, text(t, 'memory.error')),
|
|
1183
1380
|
currentDetail?.kind === 'missing' && React.createElement('p', null, text(t, 'memory.missing')),
|
|
1184
1381
|
entry && React.createElement('article', { 'data-kind': entry.kind },
|
|
1185
1382
|
React.createElement('div', { className: 'dsh-super-code-memory-detail-meta' },
|
|
1186
1383
|
React.createElement('span', null, React.createElement(Glyph, { type: 'folder' }), entry.topic),
|
|
1187
|
-
React.createElement('span', null, text(t, `memory.${entry.kind}`))
|
|
1384
|
+
React.createElement('span', null, text(t, `memory.${entry.kind}`))),
|
|
1188
1385
|
React.createElement('h3', null, entry.summary), React.createElement('p', { className: 'dsh-super-code-memory-detail' }, entry.detail),
|
|
1189
1386
|
React.createElement('dl', null, React.createElement('dt', null, text(t, 'memory.source')),
|
|
1190
|
-
React.createElement('dd', null, `${text(t, `memory.${entry.source.kind}`)} · #${entry.source.eventSeq}`, React.createElement('br'), entry.source.sessionId),
|
|
1191
|
-
entry.sourceVersion && React.createElement(React.Fragment, null, React.createElement('dt', null, text(t, 'memory.version')), React.createElement('dd', null, entry.sourceVersion))),
|
|
1387
|
+
React.createElement('dd', null, `${text(t, `memory.${entry.source.kind}`)}${entry.source.eventSeq === undefined ? '' : ` · #${entry.source.eventSeq}`}`, React.createElement('br'), entry.source.sessionId)),
|
|
1192
1388
|
related.length > 0 && React.createElement('section', { className: 'dsh-super-code-memory-related' },
|
|
1193
1389
|
React.createElement('h4', null, text(t, 'memory.related')),
|
|
1194
1390
|
related.map(item => React.createElement(ActionButton, { key: item.id, type: 'button', onClick: () => choose({ topic: item.topic, id: item.id }) },
|
|
@@ -1210,8 +1406,9 @@ function MemoryLibrary({ useTabInfo, useSessions, sessionId: scopeSessionId, api
|
|
|
1210
1406
|
React.createElement(ActionButton, { type: 'button', className: 'dsh-super-code-memory-row', 'data-topic': item.topic, 'data-kind': item.kind, onClick: () => choose({ topic: item.topic, id: item.id }) },
|
|
1211
1407
|
React.createElement('span', { className: 'dsh-super-code-memory-row-heading' }, React.createElement(Glyph, { type: 'folder' }), React.createElement('span', { className: 'dsh-super-code-memory-row-topic' }, item.topic)),
|
|
1212
1408
|
React.createElement('strong', null, item.summary),
|
|
1213
|
-
React.createElement('span', { className: 'dsh-super-code-memory-row-meta' }, React.createElement('span', { className: 'dsh-super-code-memory-row-kind' }, text(t, `memory.${item.kind}`))
|
|
1214
|
-
React.createElement('div', { 'aria-hidden': true, style: { height: page.after } }))))
|
|
1409
|
+
React.createElement('span', { className: 'dsh-super-code-memory-row-meta' }, React.createElement('span', { className: 'dsh-super-code-memory-row-kind' }, text(t, `memory.${item.kind}`)))))),
|
|
1410
|
+
React.createElement('div', { 'aria-hidden': true, style: { height: page.after } })))),
|
|
1411
|
+
editing.confirmation && React.createElement(MemoryDeleteConfirmation, { store: editor, state: editing, t }))
|
|
1215
1412
|
}
|
|
1216
1413
|
|
|
1217
1414
|
function AgentDetail({ useTabInfo, useSessions, useSessionStatus, sessionId, createInspector, detailStates, openMemory, t = key => zh[key] || key }) {
|
|
@@ -1330,9 +1527,9 @@ const presetRemoteContribution = {
|
|
|
1330
1527
|
})),
|
|
1331
1528
|
}
|
|
1332
1529
|
const memoryRemoteContribution = {
|
|
1333
|
-
package: 'dsh-super-code', descriptors: ['list', 'read'].map(method => ({
|
|
1530
|
+
package: 'dsh-super-code', descriptors: ['list', 'read', 'saveEntry', 'deleteEntry'].map(method => ({
|
|
1334
1531
|
id: `dsh-super-code:superCodeMemory/${method}`, service: 'superCodeMemory', namespace: 'superCodeMemory', method, invocation: { kind: 'direct' },
|
|
1335
|
-
parameters: (method === 'list' ? ['sessionId', 'scope'] : ['sessionId', 'scope', 'topic', 'id']).map(name => ({ name, wire: name, source: 'json', codec: remoteStringCodec })), result: { mode: 'src-json' },
|
|
1532
|
+
parameters: (method === 'list' ? ['sessionId', 'scope'] : method === 'saveEntry' ? ['sessionId', 'scope', 'topic', 'id', 'content'] : method === 'deleteEntry' ? ['sessionId', 'scope', 'topic', 'id', 'expected'] : ['sessionId', 'scope', 'topic', 'id']).map(name => ({ name, wire: name, source: 'json', codec: remoteStringCodec })), result: { mode: 'src-json' },
|
|
1336
1533
|
})),
|
|
1337
1534
|
}
|
|
1338
1535
|
|
|
@@ -1514,13 +1711,7 @@ function apply(ctx) {
|
|
|
1514
1711
|
void ctx.remote.$mount({ package: 'dsh-super-code', descriptors: [
|
|
1515
1712
|
...presetRemoteContribution.descriptors, ...memoryRemoteContribution.descriptors,
|
|
1516
1713
|
] }).catch(error => console.warn('Super Code Remote:', error))
|
|
1517
|
-
const memoryStates = new WeakMap()
|
|
1518
|
-
ctx.inject(['remote.superCodeMemory'], ready => {
|
|
1519
|
-
ready.slots.inject('sidebar.right.pane.tab', () => ready.slots.register({
|
|
1520
|
-
name: 'sidebar.right.pane.tab', key: 'dsh-super-code-memory', locale: LOCALE_NS,
|
|
1521
|
-
inject: () => ({ api: ready.remote.superCodeMemory, memoryStates }),
|
|
1522
|
-
}, MemoryLibrary))
|
|
1523
|
-
})
|
|
1714
|
+
const memoryStates = new WeakMap(), workspaceStates = new WeakMap()
|
|
1524
1715
|
// Locale already requires its host's preference service. Declare that same
|
|
1525
1716
|
// service here: Cordis rejects even optional reads without an injection.
|
|
1526
1717
|
const preferenceService = 'configForms' in ctx ? 'configForms' : 'settingsScope'
|
|
@@ -1539,7 +1730,7 @@ function apply(ctx) {
|
|
|
1539
1730
|
style.dataset.dshSuperCode = 'true'
|
|
1540
1731
|
style.textContent = `
|
|
1541
1732
|
/* Host aliases remain the source of theme colors. */
|
|
1542
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm,.dsh-super-code-select,.dsh-super-code-tooltip){
|
|
1733
|
+
: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,.dsh-super-code-tooltip){
|
|
1543
1734
|
--sc-text:var(--dsw-alias-label-primary,#242831);
|
|
1544
1735
|
--sc-muted:var(--dsw-alias-label-secondary,#6a707a);
|
|
1545
1736
|
--sc-faint:var(--dsw-alias-label-tertiary,#818793);
|
|
@@ -1557,14 +1748,14 @@ function apply(ctx) {
|
|
|
1557
1748
|
color:var(--sc-text);font-size:14px;line-height:1.55;letter-spacing:0;
|
|
1558
1749
|
box-sizing:border-box;min-width:0;
|
|
1559
1750
|
}
|
|
1560
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm) *{box-sizing:border-box}
|
|
1561
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm) :is(button,input,select){font:inherit;color:inherit;min-width:0}
|
|
1562
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm) button{cursor:pointer;transition:background-color .12s,border-color .12s;color:inherit}
|
|
1563
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm) button:disabled{opacity:.45;cursor:default}
|
|
1564
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory,.dsh-super-code-confirm) :is(button,input,select,summary):focus-visible{outline:2px solid var(--sc-accent);outline-offset:2px}
|
|
1565
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory) :is(input,select){width:100%;height:36px;padding:7px 12px;border:1px solid var(--sc-line);border-radius:8px;background:var(--sc-bg);transition:border-color .12s;outline-offset:2px}
|
|
1566
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-memory) input::placeholder{color:var(--sc-faint)}
|
|
1567
|
-
:where(.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-memory) :is(input,select):hover{border-color:color-mix(in srgb,var(--sc-text) 25%,var(--sc-line))}
|
|
1751
|
+
: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) *{box-sizing:border-box}
|
|
1752
|
+
: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) :is(button,input,select){font:inherit;color:inherit;min-width:0}
|
|
1753
|
+
: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) button{cursor:pointer;transition:background-color .12s,border-color .12s;color:inherit}
|
|
1754
|
+
: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) button:disabled{opacity:.45;cursor:default}
|
|
1755
|
+
: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) :is(button,input,select,summary):focus-visible{outline:2px solid var(--sc-accent);outline-offset:2px}
|
|
1756
|
+
:where(.dsh-super-code-workspace,.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-detail,.dsh-super-code-memory) :is(input,select){width:100%;height:36px;padding:7px 12px;border:1px solid var(--sc-line);border-radius:8px;background:var(--sc-bg);transition:border-color .12s;outline-offset:2px}
|
|
1757
|
+
:where(.dsh-super-code-workspace,.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-memory) input::placeholder{color:var(--sc-faint)}
|
|
1758
|
+
:where(.dsh-super-code-workspace,.dsh-super-code-settings,.dsh-super-code-tree,.dsh-super-code-memory) :is(input,select):hover{border-color:color-mix(in srgb,var(--sc-text) 25%,var(--sc-line))}
|
|
1568
1759
|
.dsh-super-code-technical,.dsh-super-code-confirm code,.dsh-super-code-preset-status code{font-family:var(--sc-mono);font-size:12px}
|
|
1569
1760
|
.dsh-super-code-title-line{display:flex;align-items:center;gap:8px;min-width:0}
|
|
1570
1761
|
.dsh-super-code-glyph{width:18px;height:18px;flex:none;color:var(--sc-muted)}
|
|
@@ -1630,6 +1821,19 @@ function apply(ctx) {
|
|
|
1630
1821
|
.dsh-super-code-confirm-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}
|
|
1631
1822
|
.dsh-super-code-confirm .dsh-super-code-confirm-empty{padding:20px 16px;background:var(--sc-surface);border-radius:12px}
|
|
1632
1823
|
|
|
1824
|
+
/* Exactly one section fills the pane; the other keeps its clickable heading. */
|
|
1825
|
+
.dsh-super-code-workspace{height:100%;min-height:0;overflow:auto;background:var(--sc-bg)}
|
|
1826
|
+
.dsh-super-code-workspace-layout{display:grid;height:100%;min-height:324px;min-width:0}
|
|
1827
|
+
.dsh-super-code-workspace-collapsed{display:flex;align-items:center;border-block:1px solid var(--sc-line);background:var(--sc-bg);padding:0 12px}
|
|
1828
|
+
.dsh-super-code-section-toggle{display:flex;align-items:center;gap:6px;flex:1;min-width:0;width:100%;min-height:36px;border:0;border-radius:6px;background:transparent;padding:6px 8px;text-align:left}
|
|
1829
|
+
.dsh-super-code-section-toggle>.dsh-super-code-tree-count{margin-left:auto}
|
|
1830
|
+
.dsh-super-code-section-toggle strong{font-size:14px;font-weight:600;white-space:nowrap}
|
|
1831
|
+
.dsh-super-code-section-toggle>.dsh-super-code-glyph{width:16px;height:16px}
|
|
1832
|
+
.dsh-super-code-section-toggle>.dsh-super-code-glyph:first-child{width:12px;height:12px;transition:transform .12s}
|
|
1833
|
+
.dsh-super-code-section-toggle[aria-expanded=false]>.dsh-super-code-glyph:first-child{transform:rotate(-90deg)}
|
|
1834
|
+
.dsh-super-code-section-toggle:hover{background:var(--sc-hover)}
|
|
1835
|
+
.dsh-super-code-workspace-collapsed>.dsh-super-code-section-toggle{width:100%;height:100%}
|
|
1836
|
+
|
|
1633
1837
|
/* Memory library: geometry stays at 76px per row. */
|
|
1634
1838
|
.dsh-super-code-memory{height:100%;min-height:0;display:flex;flex-direction:column;container-type:inline-size}
|
|
1635
1839
|
.dsh-super-code-memory>header{padding:16px;border-bottom:1px solid var(--sc-line);flex:none}
|
|
@@ -1709,7 +1913,32 @@ function apply(ctx) {
|
|
|
1709
1913
|
.dsh-super-code-memory-action[data-action=read]{color:var(--sc-accent)}
|
|
1710
1914
|
.dsh-super-code-memory-action[data-action=remember]{color:var(--sc-success)}
|
|
1711
1915
|
|
|
1712
|
-
/*
|
|
1916
|
+
/* Direct memory editing keeps one current copy, with no version UI. */
|
|
1917
|
+
.dsh-super-code-memory-editor{display:grid;align-content:start;gap:12px;flex:1;min-height:0;overflow:auto;padding:12px 16px}
|
|
1918
|
+
.dsh-super-code-memory-editor-heading{display:flex;align-items:center;justify-content:space-between;gap:8px}
|
|
1919
|
+
.dsh-super-code-memory-editor label{display:grid;grid-template-columns:1fr auto;gap:6px;font-size:12px}
|
|
1920
|
+
.dsh-super-code-memory-editor label>:is(input,textarea),.dsh-super-code-memory-editor label>small:last-child{grid-column:1/-1}
|
|
1921
|
+
.dsh-super-code-memory-editor textarea{font:inherit;color:inherit;resize:vertical;min-height:100px;width:100%;padding:8px 12px;border:1px solid var(--sc-line);border-radius:8px;background:var(--sc-bg)}
|
|
1922
|
+
.dsh-super-code-memory-editor [role=alert]{margin:0;font-size:12px;color:var(--sc-error)}
|
|
1923
|
+
.dsh-super-code-memory-actions{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex-wrap:wrap}
|
|
1924
|
+
.dsh-super-code-memory-actions>button{padding:5px 10px;font-size:12px;border:1px solid var(--sc-line);border-radius:7px;background:var(--sc-bg)}
|
|
1925
|
+
.dsh-super-code-memory-actions>.dsh-super-code-view-button{margin-right:auto;border:0;padding-left:0}
|
|
1926
|
+
.dsh-super-code-memory-actions>.dsh-super-code-memory-primary{background:var(--sc-text);color:var(--sc-bg);border-color:var(--sc-text)}
|
|
1927
|
+
.dsh-super-code-memory-danger{color:var(--sc-error)!important}
|
|
1928
|
+
.dsh-super-code-memory-editor textarea:focus-visible{outline:2px solid var(--sc-accent);outline-offset:2px}
|
|
1929
|
+
|
|
1930
|
+
/* Compact library header leaves room for entries in the shared pane. */
|
|
1931
|
+
.dsh-super-code-workspace .dsh-super-code-memory>header{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;padding:10px 12px}
|
|
1932
|
+
.dsh-super-code-workspace .dsh-super-code-memory-heading{display:contents}
|
|
1933
|
+
.dsh-super-code-workspace .dsh-super-code-memory h2{font-size:14px}
|
|
1934
|
+
.dsh-super-code-workspace .dsh-super-code-memory-header-actions{display:flex;align-items:center;gap:4px;grid-column:2;grid-row:1}
|
|
1935
|
+
.dsh-super-code-memory-header-actions>.dsh-super-code-view-button{font-size:12px;white-space:nowrap}
|
|
1936
|
+
.dsh-super-code-workspace .dsh-super-code-memory-scopes{grid-column:1/-1;margin:0;padding:2px}
|
|
1937
|
+
.dsh-super-code-workspace .dsh-super-code-memory-search{grid-column:1/-1;margin:0}
|
|
1938
|
+
.dsh-super-code-workspace .dsh-super-code-memory-topic-index{padding:8px 12px;gap:6px}
|
|
1939
|
+
.dsh-super-code-workspace .dsh-super-code-memory-list-heading{padding:8px 12px 6px}
|
|
1940
|
+
|
|
1941
|
+
/* Graph: reserve space for animated/selected rings before the text stack. */
|
|
1713
1942
|
.dsh-super-code-tree{height:100%;min-height:0;display:flex;flex-direction:column;overflow:auto;container-type:inline-size}
|
|
1714
1943
|
.dsh-super-code-tree>header,.dsh-super-code-graph-legend,.dsh-super-code-graph-controls,.dsh-super-code-history-controls{flex:none}
|
|
1715
1944
|
.dsh-super-code-tree-header{display:flex;flex-direction:column;gap:8px;padding:12px}
|
|
@@ -1750,12 +1979,12 @@ function apply(ctx) {
|
|
|
1750
1979
|
.dsh-super-code-graph-scroll.dragging,.dsh-super-code-graph-scroll.dragging *{cursor:grabbing!important}
|
|
1751
1980
|
.dsh-super-code-graph{position:relative;transform-origin:0 0}
|
|
1752
1981
|
.dsh-super-code-graph-edges{position:absolute;inset:0;pointer-events:none;stroke:color-mix(in srgb,var(--sc-muted) 35%,var(--sc-surface));stroke-width:1.25}
|
|
1753
|
-
.dsh-super-code-graph-node{position:absolute;display:flex;align-items:center;flex-direction:column;width:128px;height
|
|
1982
|
+
.dsh-super-code-graph-node{position:absolute;display:flex;align-items:center;flex-direction:column;width:128px;height:${agentTreeNodeHeight}px;gap:16px;padding:0 4px;border:0;border-radius:12px;background:transparent;cursor:pointer}
|
|
1754
1983
|
.dsh-super-code-graph-node[aria-disabled]{cursor:default;opacity:.65}
|
|
1755
1984
|
.dsh-super-code-graph-node>.dsh-super-code-circle{position:relative;display:grid;place-items:center;flex:none;width:40px;height:40px;border-radius:50%!important;corner-shape:round!important;background:linear-gradient(145deg,color-mix(in srgb,var(--state-color) 83%,white),var(--state-color));box-shadow:inset 0 1px 1px #ffffff40,0 2px 6px #00000012;color:#fff;font-size:13px;font-weight:600}
|
|
1756
1985
|
.dsh-super-code-graph-node>.dsh-super-code-circle:after{content:"";position:absolute;inset:-5px;border:1px solid color-mix(in srgb,var(--state-color) 22%,transparent);border-radius:50%;corner-shape:round;pointer-events:none}
|
|
1757
1986
|
.dsh-super-code-graph-node>.dsh-super-code-circle.idle:after{animation:super-agent-breathe 3s ease-in-out infinite}
|
|
1758
|
-
.dsh-super-code-graph-node>.dsh-super-code-circle.active:after{border-width:
|
|
1987
|
+
.dsh-super-code-graph-node>.dsh-super-code-circle.active:after{inset:-6px;border-width:3px;border-color:color-mix(in srgb,var(--state-color) 14%,transparent);border-top-color:var(--state-color);border-right-color:color-mix(in srgb,var(--state-color) 60%,transparent);animation:super-agent-process 1.2s linear infinite}
|
|
1759
1988
|
.dsh-super-code-graph-node>.dsh-super-code-circle.stopped{background:linear-gradient(145deg,#9297a0,#747a84);box-shadow:inset 0 1px 1px #ffffff30}
|
|
1760
1989
|
.dsh-super-code-graph-node>.dsh-super-code-circle.stopped:after{border-color:color-mix(in srgb,var(--state-color) 14%,transparent)}
|
|
1761
1990
|
.dsh-super-code-graph-node>.dsh-super-code-circle.unavailable:after{border-style:dashed;border-color:var(--state-color)}
|
|
@@ -1856,8 +2085,8 @@ function apply(ctx) {
|
|
|
1856
2085
|
.dsh-super-code-detail-message details pre{margin-top:10px;padding:8px 10px;border:1px solid var(--sc-line);border-radius:7px;background:var(--sc-bg)}
|
|
1857
2086
|
.dsh-super-code-detail-entry button{margin:8px 0 0}
|
|
1858
2087
|
.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}
|
|
1859
|
-
@media(hover:none) and (pointer:coarse){:where(.dsh-super-code-settings,.dsh-super-code-memory,.dsh-super-code-tree) input{font-size:16px}}
|
|
1860
|
-
@media(prefers-reduced-motion:reduce){:where(.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}}
|
|
2088
|
+
@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}}
|
|
2089
|
+
@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}}
|
|
1861
2090
|
|
|
1862
2091
|
/* Same custom trigger and option list for all six dropdowns. Fixed placement
|
|
1863
2092
|
* keeps history menus visible outside the clipped graph/sidebar viewport. */
|
|
@@ -1888,19 +2117,18 @@ function apply(ctx) {
|
|
|
1888
2117
|
document.head.appendChild(style)
|
|
1889
2118
|
return () => { style.remove() }
|
|
1890
2119
|
}, 'super-code: browser styles')
|
|
1891
|
-
//
|
|
2120
|
+
// Keep the original tree kind so restored tabs become the unified workspace.
|
|
1892
2121
|
const treeId = 'dsh-super-code'
|
|
1893
2122
|
const treeKind = 'super-agent-agents'
|
|
1894
2123
|
const disposeTreeType = ctx.sidebarRightTabs.register({
|
|
1895
2124
|
id: treeId, kind: treeKind,
|
|
1896
|
-
title: () => t('
|
|
1897
|
-
guide: [{ order: 40, title: () => t('
|
|
2125
|
+
title: () => t('workspace.title'),
|
|
2126
|
+
guide: [{ order: 40, title: () => t('workspace.title'), description: () => t('workspace.description') }],
|
|
1898
2127
|
})
|
|
1899
2128
|
const disposeMemoryType = ctx.sidebarRightTabs.register({ id: 'dsh-super-code-memory', kind: 'super-code-memory',
|
|
1900
|
-
patterns: ['dsh-resource://super-code-memory/**'], title: () => t('
|
|
1901
|
-
guide: [{ order: 41, title: () => t('memory.title'), description: () => t('memory.description') }],
|
|
2129
|
+
patterns: ['dsh-resource://super-code-memory/**'], title: () => t('workspace.title'),
|
|
1902
2130
|
})
|
|
1903
|
-
const openMemory = (sessionId, row) => ctx.sidebarRight.
|
|
2131
|
+
const openMemory = (sessionId, row) => ctx.sidebarRight.openTab(treeKind, { params: { memory: memoryLibraryAddress(sessionId, row) } })
|
|
1904
2132
|
const treeActions = {
|
|
1905
2133
|
// The host unmounts hidden bodies; tab signals live until close/unload.
|
|
1906
2134
|
treeStates: new WeakMap(),
|
|
@@ -1918,7 +2146,7 @@ function apply(ctx) {
|
|
|
1918
2146
|
},
|
|
1919
2147
|
})
|
|
1920
2148
|
ctx.slots.inject('sidebar.right.pane.tab.title', function* () {
|
|
1921
|
-
for (const [key, titleKey] of [[treeId, '
|
|
2149
|
+
for (const [key, titleKey] of [[treeId, 'workspace.title'], ['dsh-super-code-memory', 'workspace.title']]) {
|
|
1922
2150
|
yield ctx.slots.register({ name: 'sidebar.right.pane.tab.title', key, locale: LOCALE_NS,
|
|
1923
2151
|
inject: () => ({ titleKey }),
|
|
1924
2152
|
}, LocalizedTabTitle)
|
|
@@ -1931,16 +2159,19 @@ function apply(ctx) {
|
|
|
1931
2159
|
ctx.slots.inject('sidebar.right.pane.tab', () => ctx.slots.register({
|
|
1932
2160
|
name: 'sidebar.right.pane.tab', key: 'dsh-super-code-detail', locale: LOCALE_NS, inject: () => ({ ...detailActions }),
|
|
1933
2161
|
}, AgentDetail))
|
|
1934
|
-
ctx.
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
2162
|
+
ctx.inject(['remote.superCodeMemory'], ready => {
|
|
2163
|
+
ready.slots.inject('sidebar.right.pane.tab', function* () {
|
|
2164
|
+
// The hidden legacy key restores old memory tabs and resource URLs.
|
|
2165
|
+
for (const key of [treeId, 'dsh-super-code-memory']) yield ready.slots.register({
|
|
2166
|
+
name: 'sidebar.right.pane.tab', key, locale: LOCALE_NS,
|
|
2167
|
+
inject: () => ({ ...treeActions, api: ready.remote.superCodeMemory, memoryStates, workspaceStates }),
|
|
2168
|
+
}, SuperCodeWorkspace)
|
|
2169
|
+
})
|
|
2170
|
+
})
|
|
2171
|
+
ctx.effect(() => disposeTreeType, 'super-code: workspace tab')
|
|
1941
2172
|
ctx.effect(() => disposeDetailType, 'super-code: Agent detail tab')
|
|
1942
2173
|
ctx.effect(() => disposeMemoryType, 'super-code: memory library tab')
|
|
1943
2174
|
}
|
|
1944
2175
|
|
|
1945
|
-
return { inject, apply, synchronizePresetDisplay, agentSessionState, buildAgentView, visibleAgentRows, agentTreeDisplay, agentTreeTotals, agentTreeLayout, agentExecutionStatus, agentDetailAddress, agentDetailTarget, agentPath, detailRecord, createAgentInspector, agentHistoryRange, agentHistoryRows, agentHistoryWindow, memoryLibraryAddress, memoryLibraryTarget, memoryLibraryWindow }
|
|
2176
|
+
return { inject, apply, synchronizePresetDisplay, agentSessionState, buildAgentView, visibleAgentRows, agentTreeDisplay, agentTreeTotals, agentTreeLayout, agentExecutionStatus, agentDetailAddress, agentDetailTarget, agentPath, detailRecord, createAgentInspector, agentHistoryRange, agentHistoryRows, agentHistoryWindow, memoryLibraryAddress, memoryLibraryTarget, memoryLibraryNavigation, memoryLibraryWindow, createMemoryEditor }
|
|
1946
2177
|
} })
|