@flowingspring/dsh-workspace-memory 0.1.0 → 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/DESIGN.md CHANGED
@@ -104,6 +104,20 @@ rebuilt from active entries. A bounded history is kept before replacement.
104
104
  - `memory_search` remains the Agentic second-search seam: an Agent can issue
105
105
  alternate queries when the automatic first recall is insufficient.
106
106
 
107
+ ### Settings memory browser
108
+
109
+ The Web client contributes a top-level `settings.section` named `记忆`. It reads
110
+ the same store through two loopback, read-only Host routes:
111
+
112
+ - `GET /workspace-memory/api/v1/scopes` lists the global scope and persisted
113
+ workspace descriptors.
114
+ - `GET /workspace-memory/api/v1/scope?cwd=...` returns a redacted summary,
115
+ active entries, and checkpoint counters for one scope.
116
+
117
+ The browser never opens checkpoint Markdown or writes the JSON files directly.
118
+ Mutations continue to go through the memory engine so its per-scope locks,
119
+ deduplication, secret checks, and atomic writes remain authoritative.
120
+
107
121
  ## Voco integration
108
122
 
109
123
  - Before frontend routing, Voco optionally calls `workspaceMemory.recall`.
package/README.md CHANGED
@@ -17,6 +17,7 @@ Session 共享一份稳定摘要和长期原子记忆,并通过可选 Cordis
17
17
  - Agent turn 结束只进入 checkpoint 缓冲,不会每轮强制调用记忆蒸馏模型。
18
18
  - LLM 只蒸馏长期有效事实;重复/近重复事实会更新原条目。
19
19
  - 提供 `memory_search`、`memory_remember`、`memory_forget` 工具。
20
+ - Web profile 设置中提供“记忆”页面,可查看全局记忆和不同项目的脱敏摘要、结构化条目。
20
21
  - 凭据形态内容默认拒绝持久化,并在模型输入前脱敏。
21
22
  - 没有安装本插件时,`dsh-voco` 保持原有行为。
22
23
 
@@ -89,6 +90,10 @@ workspace-memory/
89
90
  `memory_entries.json` 是事实来源;`memory_summary.md` 是自动注入的短摘要;
90
91
  `checkpoints/` 保留每次阶段性蒸馏的可审计 Markdown 记录。
91
92
 
93
+ 设置中的“记忆”页面是只读浏览器:前端通过 Host 的内部读取接口访问同一套
94
+ Store,按照 `scope.json` 显示项目目录。它不会直接读写 JSON 文件,也不会展示
95
+ 包含完整对话的 checkpoint 原文。
96
+
92
97
  ## 开发验证
93
98
 
94
99
  源码与测试均使用 TypeScript;`pnpm build` 将 ESM JavaScript 和类型声明生成到
@@ -0,0 +1,170 @@
1
+ import { useEffect, useMemo, useState, useSyncExternalStore } from 'react';
2
+ import { createElement as h } from 'react';
3
+ const NS = 'workspace-memory';
4
+ const zh = {
5
+ nav: '记忆',
6
+ title: '记忆',
7
+ refresh: '刷新',
8
+ global: '全局记忆',
9
+ workspace: '项目记忆',
10
+ current: '当前项目',
11
+ emptyScopes: '还没有已记录的项目记忆',
12
+ summary: '摘要记忆',
13
+ entries: '结构化记忆',
14
+ search: '筛选记忆',
15
+ searchPlaceholder: '搜索标题、内容或标签',
16
+ noSummary: '暂无摘要',
17
+ noEntries: '暂无结构化记忆',
18
+ loading: '正在读取…',
19
+ failed: '读取记忆失败',
20
+ retry: '重试',
21
+ pending: '待整理',
22
+ checkpoints: '整理次数',
23
+ updated: '最近更新',
24
+ all: '全部',
25
+ count: '条',
26
+ };
27
+ const en = {
28
+ nav: 'Memory',
29
+ title: 'Memory',
30
+ refresh: 'Refresh',
31
+ global: 'Global memory',
32
+ workspace: 'Project memory',
33
+ current: 'Current project',
34
+ emptyScopes: 'No project memories recorded yet',
35
+ summary: 'Summary memory',
36
+ entries: 'Structured memory',
37
+ search: 'Filter memory',
38
+ searchPlaceholder: 'Search title, content, or tags',
39
+ noSummary: 'No summary yet',
40
+ noEntries: 'No structured memories yet',
41
+ loading: 'Loading…',
42
+ failed: 'Unable to read memory',
43
+ retry: 'Retry',
44
+ pending: 'Pending',
45
+ checkpoints: 'Checkpoints',
46
+ updated: 'Last updated',
47
+ all: 'All',
48
+ count: '',
49
+ };
50
+ function useSnapshot(source) {
51
+ return useSyncExternalStore(source.subscribe, source.getSnapshot, source.getSnapshot);
52
+ }
53
+ function workspaceName(cwd, fallback) {
54
+ const normalized = cwd.replaceAll('\\', '/').replace(/\/+$/u, '');
55
+ const name = normalized.split('/').filter(Boolean).at(-1);
56
+ return name ?? fallback;
57
+ }
58
+ function formatDate(value) {
59
+ if (value === undefined || value === '')
60
+ return '';
61
+ const date = new Date(value);
62
+ return Number.isFinite(date.getTime()) ? date.toLocaleString() : value;
63
+ }
64
+ function iconRefresh() {
65
+ return h('svg', { width: 16, height: 16, viewBox: '0 0 16 16', 'aria-hidden': true }, h('path', { d: 'M13 4.8A5.5 5.5 0 1 0 13.5 9', fill: 'none', stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round' }), h('path', { d: 'M10.8 2.8h2.8v2.8', fill: 'none', stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round', strokeLinejoin: 'round' }));
66
+ }
67
+ function MemorySection({ t, sessions }) {
68
+ const sessionList = useSnapshot(sessions.list);
69
+ const currentCwd = sessionList.current === undefined ? '' : sessionList.byId[sessionList.current]?.cwd ?? '';
70
+ const [scopes, setScopes] = useState([]);
71
+ const [selectedCwd, setSelectedCwd] = useState('');
72
+ const [payload, setPayload] = useState();
73
+ const [query, setQuery] = useState('');
74
+ const [loading, setLoading] = useState(true);
75
+ const [error, setError] = useState(false);
76
+ const loadScopes = async () => {
77
+ const response = await fetch('/workspace-memory/api/v1/scopes');
78
+ if (!response.ok)
79
+ throw new Error(`scope list failed (${response.status})`);
80
+ const result = await response.json();
81
+ return Array.isArray(result.scopes) ? result.scopes : [];
82
+ };
83
+ const loadScope = async (cwd) => {
84
+ const response = await fetch(`/workspace-memory/api/v1/scope?cwd=${encodeURIComponent(cwd)}`);
85
+ if (!response.ok)
86
+ throw new Error(`scope read failed (${response.status})`);
87
+ return await response.json();
88
+ };
89
+ const reload = async (cwd = selectedCwd) => {
90
+ setLoading(true);
91
+ setError(false);
92
+ try {
93
+ const nextScopes = await loadScopes();
94
+ setScopes(nextScopes);
95
+ const next = await loadScope(cwd);
96
+ setPayload(next);
97
+ setSelectedCwd(next.scope.cwd);
98
+ }
99
+ catch {
100
+ setError(true);
101
+ }
102
+ finally {
103
+ setLoading(false);
104
+ }
105
+ };
106
+ useEffect(() => {
107
+ void reload(currentCwd);
108
+ // The initial project follows the current session; later changes are user-selected.
109
+ // eslint-disable-next-line react-hooks/exhaustive-deps
110
+ }, []);
111
+ const options = useMemo(() => {
112
+ const known = new Map(scopes.map(scope => [scope.cwd, scope]));
113
+ if (currentCwd !== '' && !known.has(currentCwd)) {
114
+ known.set(currentCwd, {
115
+ key: `current:${currentCwd}`,
116
+ cwd: currentCwd,
117
+ kind: 'workspace',
118
+ entryCount: 0,
119
+ hasSummary: false,
120
+ pending: 0,
121
+ checkpointCount: 0,
122
+ });
123
+ }
124
+ return [...known.values()];
125
+ }, [scopes, currentCwd]);
126
+ const filteredEntries = useMemo(() => {
127
+ const normalized = query.trim().toLocaleLowerCase();
128
+ if (normalized === '')
129
+ return payload?.entries ?? [];
130
+ return (payload?.entries ?? []).filter(entry => [entry.title, entry.description, entry.content, ...entry.tags]
131
+ .join(' ').toLocaleLowerCase().includes(normalized));
132
+ }, [payload, query]);
133
+ const onSelect = (cwd) => {
134
+ setSelectedCwd(cwd);
135
+ void reload(cwd);
136
+ };
137
+ const colors = {
138
+ text: 'var(--ds-color-text-primary, #f1f1f1)',
139
+ secondary: 'var(--ds-color-text-secondary, #a7a7ad)',
140
+ border: 'var(--ds-color-border, rgba(255,255,255,.12))',
141
+ surface: 'var(--ds-color-bg-secondary, rgba(255,255,255,.045))',
142
+ accent: 'var(--ds-color-primary, #8ab4ff)',
143
+ };
144
+ return h('section', { style: { color: colors.text, maxWidth: 820, paddingBottom: 24 } }, h('header', { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, marginBottom: 18 } }, h('div', null, h('h2', { style: { margin: 0, fontSize: 20, fontWeight: 650 } }, t('title')), h('p', { style: { margin: '6px 0 0', color: colors.secondary, fontSize: 12, wordBreak: 'break-all' } }, payload?.scope.cwd || t('global'))), h('button', {
145
+ type: 'button', title: t('refresh'), 'aria-label': t('refresh'), onClick: () => { void reload(); },
146
+ style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 34, height: 34, border: `1px solid ${colors.border}`, borderRadius: 6, background: 'transparent', color: colors.text, cursor: 'pointer' },
147
+ }, iconRefresh())), h('div', { style: { display: 'grid', gap: 8, marginBottom: 18 } }, h('label', { style: { color: colors.secondary, fontSize: 12 } }, t('current')), h('select', {
148
+ value: selectedCwd, onChange: (event) => { onSelect(event.target.value); },
149
+ style: { minHeight: 38, padding: '0 10px', color: colors.text, background: colors.surface, border: `1px solid ${colors.border}`, borderRadius: 6 },
150
+ }, options.length === 0
151
+ ? h('option', { value: '' }, t('emptyScopes'))
152
+ : options.map(scope => h('option', { key: scope.cwd, value: scope.cwd }, scope.kind === 'global' ? t('global') : workspaceName(scope.cwd, t('workspace')))))), error && h('div', { role: 'alert', style: { padding: 12, border: `1px solid ${colors.border}`, borderRadius: 6, color: colors.secondary, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 } }, h('span', null, t('failed')), h('button', { type: 'button', onClick: () => { void reload(); }, style: { color: colors.accent, background: 'transparent', border: 0, cursor: 'pointer' } }, t('retry'))), loading && h('p', { style: { color: colors.secondary } }, t('loading')), !loading && !error && h('div', { style: { display: 'grid', gap: 16 } }, h('div', { style: { display: 'flex', gap: 16, color: colors.secondary, fontSize: 12, flexWrap: 'wrap' } }, h('span', null, `${payload?.entries.length ?? 0}${t('count')}`), h('span', null, `${t('pending')}: ${payload?.state.pending ?? 0}`), h('span', null, `${t('checkpoints')}: ${payload?.state.checkpointCount ?? 0}`)), h('article', { style: { border: `1px solid ${colors.border}`, borderRadius: 6, padding: 14, background: colors.surface } }, h('h3', { style: { margin: '0 0 10px', fontSize: 14 } }, t('summary')), h('pre', { style: { margin: 0, color: colors.secondary, whiteSpace: 'pre-wrap', wordBreak: 'break-word', font: 'inherit', lineHeight: 1.55 } }, payload?.summary.trim() || t('noSummary'))), h('div', { style: { display: 'grid', gap: 10 } }, h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 } }, h('h3', { style: { margin: 0, fontSize: 14 } }, `${t('entries')} (${filteredEntries.length})`), h('input', { type: 'search', value: query, placeholder: t('searchPlaceholder'), 'aria-label': t('search'), onChange: (event) => { setQuery(event.target.value); }, style: { minHeight: 32, width: 230, maxWidth: '48%', padding: '0 9px', color: colors.text, background: 'transparent', border: `1px solid ${colors.border}`, borderRadius: 6 } })), filteredEntries.length === 0 && h('p', { style: { color: colors.secondary, margin: 0 } }, t('noEntries')), filteredEntries.map(entry => h('details', { key: entry.id, style: { border: `1px solid ${colors.border}`, borderRadius: 6, padding: '10px 12px', background: colors.surface } }, h('summary', { style: { cursor: 'pointer', display: 'flex', gap: 8, alignItems: 'baseline' } }, h('strong', { style: { fontSize: 13 } }, entry.title), h('span', { style: { color: colors.secondary, fontSize: 11 } }, entry.type)), h('p', { style: { margin: '10px 0 0', color: colors.secondary, lineHeight: 1.5, whiteSpace: 'pre-wrap', wordBreak: 'break-word' } }, entry.content), entry.tags.length > 0 && h('div', { style: { marginTop: 10, color: colors.accent, fontSize: 11 } }, entry.tags.join(' · ')), entry.updatedAt !== undefined && h('div', { style: { marginTop: 8, color: colors.secondary, fontSize: 11 } }, `${t('updated')}: ${formatDate(entry.updatedAt)}`))))));
153
+ }
154
+ export const inject = ['slots', 'locale', 'sessions'];
155
+ export function apply(ctx) {
156
+ ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'workspace-memory: dictionaries');
157
+ const translate = ctx.locale.bind(NS);
158
+ const t = (key) => {
159
+ const translated = translate(key);
160
+ return translated || zh[key];
161
+ };
162
+ ctx.slots.inject('settings.section', () => ctx.slots.register({
163
+ name: 'settings.section',
164
+ id: 'workspace-memory',
165
+ order: 50,
166
+ label: () => t('nav'),
167
+ locale: NS,
168
+ }, () => h(MemorySection, { t, sessions: ctx.sessions })));
169
+ }
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
package/lib/client.js ADDED
@@ -0,0 +1,364 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@flowingspring/dsh-workspace-memory",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let react = require("react");
8
+ //#region src/client/index.tsx
9
+ const NS = "workspace-memory";
10
+ const zh = {
11
+ nav: "记忆",
12
+ title: "记忆",
13
+ refresh: "刷新",
14
+ global: "全局记忆",
15
+ workspace: "项目记忆",
16
+ current: "当前项目",
17
+ emptyScopes: "还没有已记录的项目记忆",
18
+ summary: "摘要记忆",
19
+ entries: "结构化记忆",
20
+ search: "筛选记忆",
21
+ searchPlaceholder: "搜索标题、内容或标签",
22
+ noSummary: "暂无摘要",
23
+ noEntries: "暂无结构化记忆",
24
+ loading: "正在读取…",
25
+ failed: "读取记忆失败",
26
+ retry: "重试",
27
+ pending: "待整理",
28
+ checkpoints: "整理次数",
29
+ updated: "最近更新",
30
+ all: "全部",
31
+ count: "条"
32
+ };
33
+ const en = {
34
+ nav: "Memory",
35
+ title: "Memory",
36
+ refresh: "Refresh",
37
+ global: "Global memory",
38
+ workspace: "Project memory",
39
+ current: "Current project",
40
+ emptyScopes: "No project memories recorded yet",
41
+ summary: "Summary memory",
42
+ entries: "Structured memory",
43
+ search: "Filter memory",
44
+ searchPlaceholder: "Search title, content, or tags",
45
+ noSummary: "No summary yet",
46
+ noEntries: "No structured memories yet",
47
+ loading: "Loading…",
48
+ failed: "Unable to read memory",
49
+ retry: "Retry",
50
+ pending: "Pending",
51
+ checkpoints: "Checkpoints",
52
+ updated: "Last updated",
53
+ all: "All",
54
+ count: ""
55
+ };
56
+ function useSnapshot(source) {
57
+ return (0, react.useSyncExternalStore)(source.subscribe, source.getSnapshot, source.getSnapshot);
58
+ }
59
+ function workspaceName(cwd, fallback) {
60
+ return cwd.replaceAll("\\", "/").replace(/\/+$/u, "").split("/").filter(Boolean).at(-1) ?? fallback;
61
+ }
62
+ function formatDate(value) {
63
+ if (value === void 0 || value === "") return "";
64
+ const date = new Date(value);
65
+ return Number.isFinite(date.getTime()) ? date.toLocaleString() : value;
66
+ }
67
+ function iconRefresh() {
68
+ return (0, react.createElement)("svg", {
69
+ width: 16,
70
+ height: 16,
71
+ viewBox: "0 0 16 16",
72
+ "aria-hidden": true
73
+ }, (0, react.createElement)("path", {
74
+ d: "M13 4.8A5.5 5.5 0 1 0 13.5 9",
75
+ fill: "none",
76
+ stroke: "currentColor",
77
+ strokeWidth: 1.4,
78
+ strokeLinecap: "round"
79
+ }), (0, react.createElement)("path", {
80
+ d: "M10.8 2.8h2.8v2.8",
81
+ fill: "none",
82
+ stroke: "currentColor",
83
+ strokeWidth: 1.4,
84
+ strokeLinecap: "round",
85
+ strokeLinejoin: "round"
86
+ }));
87
+ }
88
+ function MemorySection({ t, sessions }) {
89
+ const sessionList = useSnapshot(sessions.list);
90
+ const currentCwd = sessionList.current === void 0 ? "" : sessionList.byId[sessionList.current]?.cwd ?? "";
91
+ const [scopes, setScopes] = (0, react.useState)([]);
92
+ const [selectedCwd, setSelectedCwd] = (0, react.useState)("");
93
+ const [payload, setPayload] = (0, react.useState)();
94
+ const [query, setQuery] = (0, react.useState)("");
95
+ const [loading, setLoading] = (0, react.useState)(true);
96
+ const [error, setError] = (0, react.useState)(false);
97
+ const loadScopes = async () => {
98
+ const response = await fetch("/workspace-memory/api/v1/scopes");
99
+ if (!response.ok) throw new Error(`scope list failed (${response.status})`);
100
+ const result = await response.json();
101
+ return Array.isArray(result.scopes) ? result.scopes : [];
102
+ };
103
+ const loadScope = async (cwd) => {
104
+ const response = await fetch(`/workspace-memory/api/v1/scope?cwd=${encodeURIComponent(cwd)}`);
105
+ if (!response.ok) throw new Error(`scope read failed (${response.status})`);
106
+ return await response.json();
107
+ };
108
+ const reload = async (cwd = selectedCwd) => {
109
+ setLoading(true);
110
+ setError(false);
111
+ try {
112
+ const nextScopes = await loadScopes();
113
+ setScopes(nextScopes);
114
+ const next = await loadScope(cwd);
115
+ setPayload(next);
116
+ setSelectedCwd(next.scope.cwd);
117
+ } catch {
118
+ setError(true);
119
+ } finally {
120
+ setLoading(false);
121
+ }
122
+ };
123
+ (0, react.useEffect)(() => {
124
+ reload(currentCwd);
125
+ }, []);
126
+ const options = (0, react.useMemo)(() => {
127
+ const known = new Map(scopes.map((scope) => [scope.cwd, scope]));
128
+ if (currentCwd !== "" && !known.has(currentCwd)) known.set(currentCwd, {
129
+ key: `current:${currentCwd}`,
130
+ cwd: currentCwd,
131
+ kind: "workspace",
132
+ entryCount: 0,
133
+ hasSummary: false,
134
+ pending: 0,
135
+ checkpointCount: 0
136
+ });
137
+ return [...known.values()];
138
+ }, [scopes, currentCwd]);
139
+ const filteredEntries = (0, react.useMemo)(() => {
140
+ const normalized = query.trim().toLocaleLowerCase();
141
+ if (normalized === "") return payload?.entries ?? [];
142
+ return (payload?.entries ?? []).filter((entry) => [
143
+ entry.title,
144
+ entry.description,
145
+ entry.content,
146
+ ...entry.tags
147
+ ].join(" ").toLocaleLowerCase().includes(normalized));
148
+ }, [payload, query]);
149
+ const onSelect = (cwd) => {
150
+ setSelectedCwd(cwd);
151
+ reload(cwd);
152
+ };
153
+ const colors = {
154
+ text: "var(--ds-color-text-primary, #f1f1f1)",
155
+ secondary: "var(--ds-color-text-secondary, #a7a7ad)",
156
+ border: "var(--ds-color-border, rgba(255,255,255,.12))",
157
+ surface: "var(--ds-color-bg-secondary, rgba(255,255,255,.045))",
158
+ accent: "var(--ds-color-primary, #8ab4ff)"
159
+ };
160
+ return (0, react.createElement)("section", { style: {
161
+ color: colors.text,
162
+ maxWidth: 820,
163
+ paddingBottom: 24
164
+ } }, (0, react.createElement)("header", { style: {
165
+ display: "flex",
166
+ alignItems: "flex-start",
167
+ justifyContent: "space-between",
168
+ gap: 16,
169
+ marginBottom: 18
170
+ } }, (0, react.createElement)("div", null, (0, react.createElement)("h2", { style: {
171
+ margin: 0,
172
+ fontSize: 20,
173
+ fontWeight: 650
174
+ } }, t("title")), (0, react.createElement)("p", { style: {
175
+ margin: "6px 0 0",
176
+ color: colors.secondary,
177
+ fontSize: 12,
178
+ wordBreak: "break-all"
179
+ } }, payload?.scope.cwd || t("global"))), (0, react.createElement)("button", {
180
+ type: "button",
181
+ title: t("refresh"),
182
+ "aria-label": t("refresh"),
183
+ onClick: () => {
184
+ reload();
185
+ },
186
+ style: {
187
+ display: "inline-flex",
188
+ alignItems: "center",
189
+ justifyContent: "center",
190
+ width: 34,
191
+ height: 34,
192
+ border: `1px solid ${colors.border}`,
193
+ borderRadius: 6,
194
+ background: "transparent",
195
+ color: colors.text,
196
+ cursor: "pointer"
197
+ }
198
+ }, iconRefresh())), (0, react.createElement)("div", { style: {
199
+ display: "grid",
200
+ gap: 8,
201
+ marginBottom: 18
202
+ } }, (0, react.createElement)("label", { style: {
203
+ color: colors.secondary,
204
+ fontSize: 12
205
+ } }, t("current")), (0, react.createElement)("select", {
206
+ value: selectedCwd,
207
+ onChange: (event) => {
208
+ onSelect(event.target.value);
209
+ },
210
+ style: {
211
+ minHeight: 38,
212
+ padding: "0 10px",
213
+ color: colors.text,
214
+ background: colors.surface,
215
+ border: `1px solid ${colors.border}`,
216
+ borderRadius: 6
217
+ }
218
+ }, options.length === 0 ? (0, react.createElement)("option", { value: "" }, t("emptyScopes")) : options.map((scope) => (0, react.createElement)("option", {
219
+ key: scope.cwd,
220
+ value: scope.cwd
221
+ }, scope.kind === "global" ? t("global") : workspaceName(scope.cwd, t("workspace")))))), error && (0, react.createElement)("div", {
222
+ role: "alert",
223
+ style: {
224
+ padding: 12,
225
+ border: `1px solid ${colors.border}`,
226
+ borderRadius: 6,
227
+ color: colors.secondary,
228
+ display: "flex",
229
+ justifyContent: "space-between",
230
+ alignItems: "center",
231
+ gap: 12
232
+ }
233
+ }, (0, react.createElement)("span", null, t("failed")), (0, react.createElement)("button", {
234
+ type: "button",
235
+ onClick: () => {
236
+ reload();
237
+ },
238
+ style: {
239
+ color: colors.accent,
240
+ background: "transparent",
241
+ border: 0,
242
+ cursor: "pointer"
243
+ }
244
+ }, t("retry"))), loading && (0, react.createElement)("p", { style: { color: colors.secondary } }, t("loading")), !loading && !error && (0, react.createElement)("div", { style: {
245
+ display: "grid",
246
+ gap: 16
247
+ } }, (0, react.createElement)("div", { style: {
248
+ display: "flex",
249
+ gap: 16,
250
+ color: colors.secondary,
251
+ fontSize: 12,
252
+ flexWrap: "wrap"
253
+ } }, (0, react.createElement)("span", null, `${payload?.entries.length ?? 0}${t("count")}`), (0, react.createElement)("span", null, `${t("pending")}: ${payload?.state.pending ?? 0}`), (0, react.createElement)("span", null, `${t("checkpoints")}: ${payload?.state.checkpointCount ?? 0}`)), (0, react.createElement)("article", { style: {
254
+ border: `1px solid ${colors.border}`,
255
+ borderRadius: 6,
256
+ padding: 14,
257
+ background: colors.surface
258
+ } }, (0, react.createElement)("h3", { style: {
259
+ margin: "0 0 10px",
260
+ fontSize: 14
261
+ } }, t("summary")), (0, react.createElement)("pre", { style: {
262
+ margin: 0,
263
+ color: colors.secondary,
264
+ whiteSpace: "pre-wrap",
265
+ wordBreak: "break-word",
266
+ font: "inherit",
267
+ lineHeight: 1.55
268
+ } }, payload?.summary.trim() || t("noSummary"))), (0, react.createElement)("div", { style: {
269
+ display: "grid",
270
+ gap: 10
271
+ } }, (0, react.createElement)("div", { style: {
272
+ display: "flex",
273
+ alignItems: "center",
274
+ justifyContent: "space-between",
275
+ gap: 12
276
+ } }, (0, react.createElement)("h3", { style: {
277
+ margin: 0,
278
+ fontSize: 14
279
+ } }, `${t("entries")} (${filteredEntries.length})`), (0, react.createElement)("input", {
280
+ type: "search",
281
+ value: query,
282
+ placeholder: t("searchPlaceholder"),
283
+ "aria-label": t("search"),
284
+ onChange: (event) => {
285
+ setQuery(event.target.value);
286
+ },
287
+ style: {
288
+ minHeight: 32,
289
+ width: 230,
290
+ maxWidth: "48%",
291
+ padding: "0 9px",
292
+ color: colors.text,
293
+ background: "transparent",
294
+ border: `1px solid ${colors.border}`,
295
+ borderRadius: 6
296
+ }
297
+ })), filteredEntries.length === 0 && (0, react.createElement)("p", { style: {
298
+ color: colors.secondary,
299
+ margin: 0
300
+ } }, t("noEntries")), filteredEntries.map((entry) => (0, react.createElement)("details", {
301
+ key: entry.id,
302
+ style: {
303
+ border: `1px solid ${colors.border}`,
304
+ borderRadius: 6,
305
+ padding: "10px 12px",
306
+ background: colors.surface
307
+ }
308
+ }, (0, react.createElement)("summary", { style: {
309
+ cursor: "pointer",
310
+ display: "flex",
311
+ gap: 8,
312
+ alignItems: "baseline"
313
+ } }, (0, react.createElement)("strong", { style: { fontSize: 13 } }, entry.title), (0, react.createElement)("span", { style: {
314
+ color: colors.secondary,
315
+ fontSize: 11
316
+ } }, entry.type)), (0, react.createElement)("p", { style: {
317
+ margin: "10px 0 0",
318
+ color: colors.secondary,
319
+ lineHeight: 1.5,
320
+ whiteSpace: "pre-wrap",
321
+ wordBreak: "break-word"
322
+ } }, entry.content), entry.tags.length > 0 && (0, react.createElement)("div", { style: {
323
+ marginTop: 10,
324
+ color: colors.accent,
325
+ fontSize: 11
326
+ } }, entry.tags.join(" · ")), entry.updatedAt !== void 0 && (0, react.createElement)("div", { style: {
327
+ marginTop: 8,
328
+ color: colors.secondary,
329
+ fontSize: 11
330
+ } }, `${t("updated")}: ${formatDate(entry.updatedAt)}`))))));
331
+ }
332
+ const inject = [
333
+ "slots",
334
+ "locale",
335
+ "sessions"
336
+ ];
337
+ function apply(ctx) {
338
+ ctx.effect(() => ctx.locale.register(NS, {
339
+ zh,
340
+ en
341
+ }), "workspace-memory: dictionaries");
342
+ const translate = ctx.locale.bind(NS);
343
+ const t = (key) => {
344
+ return translate(key) || zh[key];
345
+ };
346
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
347
+ name: "settings.section",
348
+ id: "workspace-memory",
349
+ order: 50,
350
+ label: () => t("nav"),
351
+ locale: NS
352
+ }, () => (0, react.createElement)(MemorySection, {
353
+ t,
354
+ sessions: ctx.sessions
355
+ })));
356
+ }
357
+ //#endregion
358
+ exports.apply = apply;
359
+ exports.inject = inject;
360
+ return module.exports;
361
+ }
362
+ });
363
+
364
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["useSyncExternalStore","h","useState","useMemo"],"sources":["../src/client/index.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport { createElement as h } from 'react'\nimport type { SettingsSectionOwnerProps } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { SessionListState } from '@deepseek-ai/dsh-client-runtime/client'\n\nconst NS = 'workspace-memory'\n\nconst zh = {\n nav: '记忆',\n title: '记忆',\n refresh: '刷新',\n global: '全局记忆',\n workspace: '项目记忆',\n current: '当前项目',\n emptyScopes: '还没有已记录的项目记忆',\n summary: '摘要记忆',\n entries: '结构化记忆',\n search: '筛选记忆',\n searchPlaceholder: '搜索标题、内容或标签',\n noSummary: '暂无摘要',\n noEntries: '暂无结构化记忆',\n loading: '正在读取…',\n failed: '读取记忆失败',\n retry: '重试',\n pending: '待整理',\n checkpoints: '整理次数',\n updated: '最近更新',\n all: '全部',\n count: '条',\n}\n\nconst en = {\n nav: 'Memory',\n title: 'Memory',\n refresh: 'Refresh',\n global: 'Global memory',\n workspace: 'Project memory',\n current: 'Current project',\n emptyScopes: 'No project memories recorded yet',\n summary: 'Summary memory',\n entries: 'Structured memory',\n search: 'Filter memory',\n searchPlaceholder: 'Search title, content, or tags',\n noSummary: 'No summary yet',\n noEntries: 'No structured memories yet',\n loading: 'Loading…',\n failed: 'Unable to read memory',\n retry: 'Retry',\n pending: 'Pending',\n checkpoints: 'Checkpoints',\n updated: 'Last updated',\n all: 'All',\n count: '',\n}\n\ntype Translate = (key: keyof typeof zh) => string\n\ninterface ScopeInfo {\n key: string\n cwd: string\n kind: 'global' | 'workspace'\n entryCount: number\n hasSummary: boolean\n pending: number\n checkpointCount: number\n updatedAt?: string\n}\n\ninterface MemoryEntry {\n id: string\n scope: string\n type: string\n title: string\n description: string\n content: string\n tags: string[]\n importance: number\n createdAt?: string\n updatedAt?: string\n}\n\ninterface ScopePayload {\n scope: { key: string; cwd: string; kind: 'global' | 'workspace' }\n summary: string\n entries: MemoryEntry[]\n state: { pending: number; checkpointCount: number; lastCheckpointAt: number }\n}\n\ninterface Snapshot<T> {\n getSnapshot(): T\n subscribe(listener: () => void): () => void\n}\n\ninterface SessionsLike {\n list: Snapshot<SessionListState>\n}\n\ninterface SlotsLike {\n inject(slot: string, register: () => unknown): void\n register(options: Record<string, unknown>, component: () => unknown): unknown\n}\n\ninterface LocaleLike {\n register(namespace: string, dictionaries: { zh: Record<string, string>; en: Record<string, string> }): unknown\n bind(namespace: string): (key: string) => string\n}\n\ninterface MemoryClientContext {\n effect(callback: () => unknown, label?: string): void\n slots: SlotsLike\n locale: LocaleLike\n sessions: SessionsLike\n}\n\nfunction useSnapshot<T>(source: Snapshot<T>): T {\n return useSyncExternalStore(source.subscribe, source.getSnapshot, source.getSnapshot)\n}\n\nfunction workspaceName(cwd: string, fallback: string): string {\n const normalized = cwd.replaceAll('\\\\', '/').replace(/\\/+$/u, '')\n const name = normalized.split('/').filter(Boolean).at(-1)\n return name ?? fallback\n}\n\nfunction formatDate(value: string | undefined): string {\n if (value === undefined || value === '') return ''\n const date = new Date(value)\n return Number.isFinite(date.getTime()) ? date.toLocaleString() : value\n}\n\nfunction iconRefresh(): ReturnType<typeof h> {\n return h('svg', { width: 16, height: 16, viewBox: '0 0 16 16', 'aria-hidden': true },\n h('path', { d: 'M13 4.8A5.5 5.5 0 1 0 13.5 9', fill: 'none', stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round' }),\n h('path', { d: 'M10.8 2.8h2.8v2.8', fill: 'none', stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round', strokeLinejoin: 'round' }),\n )\n}\n\nfunction MemorySection({ t, sessions }: { t: Translate; sessions: SessionsLike } & Partial<SettingsSectionOwnerProps>) {\n const sessionList = useSnapshot(sessions.list)\n const currentCwd = sessionList.current === undefined ? '' : sessionList.byId[sessionList.current]?.cwd ?? ''\n const [scopes, setScopes] = useState<ScopeInfo[]>([])\n const [selectedCwd, setSelectedCwd] = useState('')\n const [payload, setPayload] = useState<ScopePayload | undefined>()\n const [query, setQuery] = useState('')\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState(false)\n\n const loadScopes = async (): Promise<ScopeInfo[]> => {\n const response = await fetch('/workspace-memory/api/v1/scopes')\n if (!response.ok) throw new Error(`scope list failed (${response.status})`)\n const result = await response.json() as { scopes?: ScopeInfo[] }\n return Array.isArray(result.scopes) ? result.scopes : []\n }\n\n const loadScope = async (cwd: string): Promise<ScopePayload> => {\n const response = await fetch(`/workspace-memory/api/v1/scope?cwd=${encodeURIComponent(cwd)}`)\n if (!response.ok) throw new Error(`scope read failed (${response.status})`)\n return await response.json() as ScopePayload\n }\n\n const reload = async (cwd = selectedCwd): Promise<void> => {\n setLoading(true)\n setError(false)\n try {\n const nextScopes = await loadScopes()\n setScopes(nextScopes)\n const next = await loadScope(cwd)\n setPayload(next)\n setSelectedCwd(next.scope.cwd)\n } catch {\n setError(true)\n } finally {\n setLoading(false)\n }\n }\n\n useEffect(() => {\n void reload(currentCwd)\n // The initial project follows the current session; later changes are user-selected.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const options = useMemo(() => {\n const known = new Map(scopes.map(scope => [scope.cwd, scope]))\n if (currentCwd !== '' && !known.has(currentCwd)) {\n known.set(currentCwd, {\n key: `current:${currentCwd}`,\n cwd: currentCwd,\n kind: 'workspace',\n entryCount: 0,\n hasSummary: false,\n pending: 0,\n checkpointCount: 0,\n })\n }\n return [...known.values()]\n }, [scopes, currentCwd])\n\n const filteredEntries = useMemo(() => {\n const normalized = query.trim().toLocaleLowerCase()\n if (normalized === '') return payload?.entries ?? []\n return (payload?.entries ?? []).filter(entry => [entry.title, entry.description, entry.content, ...entry.tags]\n .join(' ').toLocaleLowerCase().includes(normalized))\n }, [payload, query])\n\n const onSelect = (cwd: string): void => {\n setSelectedCwd(cwd)\n void reload(cwd)\n }\n\n const colors = {\n text: 'var(--ds-color-text-primary, #f1f1f1)',\n secondary: 'var(--ds-color-text-secondary, #a7a7ad)',\n border: 'var(--ds-color-border, rgba(255,255,255,.12))',\n surface: 'var(--ds-color-bg-secondary, rgba(255,255,255,.045))',\n accent: 'var(--ds-color-primary, #8ab4ff)',\n }\n\n return h('section', { style: { color: colors.text, maxWidth: 820, paddingBottom: 24 } },\n h('header', { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, marginBottom: 18 } },\n h('div', null,\n h('h2', { style: { margin: 0, fontSize: 20, fontWeight: 650 } }, t('title')),\n h('p', { style: { margin: '6px 0 0', color: colors.secondary, fontSize: 12, wordBreak: 'break-all' } }, payload?.scope.cwd || t('global')),\n ),\n h('button', {\n type: 'button', title: t('refresh'), 'aria-label': t('refresh'), onClick: () => { void reload() },\n style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 34, height: 34, border: `1px solid ${colors.border}`, borderRadius: 6, background: 'transparent', color: colors.text, cursor: 'pointer' },\n }, iconRefresh()),\n ),\n h('div', { style: { display: 'grid', gap: 8, marginBottom: 18 } },\n h('label', { style: { color: colors.secondary, fontSize: 12 } }, t('current')),\n h('select', {\n value: selectedCwd, onChange: (event: Event) => { onSelect((event.target as unknown as { value: string }).value) },\n style: { minHeight: 38, padding: '0 10px', color: colors.text, background: colors.surface, border: `1px solid ${colors.border}`, borderRadius: 6 },\n }, options.length === 0\n ? h('option', { value: '' }, t('emptyScopes'))\n : options.map(scope => h('option', { key: scope.cwd, value: scope.cwd }, scope.kind === 'global' ? t('global') : workspaceName(scope.cwd, t('workspace')))),\n ),\n ),\n error && h('div', { role: 'alert', style: { padding: 12, border: `1px solid ${colors.border}`, borderRadius: 6, color: colors.secondary, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 } },\n h('span', null, t('failed')),\n h('button', { type: 'button', onClick: () => { void reload() }, style: { color: colors.accent, background: 'transparent', border: 0, cursor: 'pointer' } }, t('retry')),\n ),\n loading && h('p', { style: { color: colors.secondary } }, t('loading')),\n !loading && !error && h('div', { style: { display: 'grid', gap: 16 } },\n h('div', { style: { display: 'flex', gap: 16, color: colors.secondary, fontSize: 12, flexWrap: 'wrap' } },\n h('span', null, `${payload?.entries.length ?? 0}${t('count')}`),\n h('span', null, `${t('pending')}: ${payload?.state.pending ?? 0}`),\n h('span', null, `${t('checkpoints')}: ${payload?.state.checkpointCount ?? 0}`),\n ),\n h('article', { style: { border: `1px solid ${colors.border}`, borderRadius: 6, padding: 14, background: colors.surface } },\n h('h3', { style: { margin: '0 0 10px', fontSize: 14 } }, t('summary')),\n h('pre', { style: { margin: 0, color: colors.secondary, whiteSpace: 'pre-wrap', wordBreak: 'break-word', font: 'inherit', lineHeight: 1.55 } }, payload?.summary.trim() || t('noSummary')),\n ),\n h('div', { style: { display: 'grid', gap: 10 } },\n h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 } },\n h('h3', { style: { margin: 0, fontSize: 14 } }, `${t('entries')} (${filteredEntries.length})`),\n h('input', { type: 'search', value: query, placeholder: t('searchPlaceholder'), 'aria-label': t('search'), onChange: (event: Event) => { setQuery((event.target as unknown as { value: string }).value) }, style: { minHeight: 32, width: 230, maxWidth: '48%', padding: '0 9px', color: colors.text, background: 'transparent', border: `1px solid ${colors.border}`, borderRadius: 6 } }),\n ),\n filteredEntries.length === 0 && h('p', { style: { color: colors.secondary, margin: 0 } }, t('noEntries')),\n filteredEntries.map(entry => h('details', { key: entry.id, style: { border: `1px solid ${colors.border}`, borderRadius: 6, padding: '10px 12px', background: colors.surface } },\n h('summary', { style: { cursor: 'pointer', display: 'flex', gap: 8, alignItems: 'baseline' } },\n h('strong', { style: { fontSize: 13 } }, entry.title),\n h('span', { style: { color: colors.secondary, fontSize: 11 } }, entry.type),\n ),\n h('p', { style: { margin: '10px 0 0', color: colors.secondary, lineHeight: 1.5, whiteSpace: 'pre-wrap', wordBreak: 'break-word' } }, entry.content),\n entry.tags.length > 0 && h('div', { style: { marginTop: 10, color: colors.accent, fontSize: 11 } }, entry.tags.join(' · ')),\n entry.updatedAt !== undefined && h('div', { style: { marginTop: 8, color: colors.secondary, fontSize: 11 } }, `${t('updated')}: ${formatDate(entry.updatedAt)}`),\n )),\n ),\n ),\n )\n}\n\nexport const inject = ['slots', 'locale', 'sessions']\n\nexport function apply(ctx: MemoryClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'workspace-memory: dictionaries')\n const translate = ctx.locale.bind(NS)\n const t = (key: keyof typeof zh): string => {\n const translated = translate(key)\n return translated || zh[key]\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'workspace-memory',\n order: 50,\n label: () => t('nav'),\n locale: NS,\n }, () => h(MemorySection, { t, sessions: ctx.sessions })))\n}\n"],"mappings":"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"}