dsh-continual-evolve 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,7 @@ Reusable experience gathered in one session (user preferences, pitfalls, project
23
23
  1. **Session-start injection** — the plugin registers a single system-prompt section: the `MEMORY.md` index content (whole-line truncated over budget, with a read-the-directory hint), the absolute store path, and the when_to_save guide. The section is computed once per session and reused byte-for-byte, keeping the system prompt stable and the prompt cache warm; an empty store costs zero tokens.
24
24
  2. **Native read/write** — DSH fully permits file access inside the workspace (reads are never fenced; the write fence only covers paths outside the workspace, see [`docs/FAQ.md`](docs/FAQ.md) #6). The model reads, writes, and edits memory files and maintains the index directly; the store is bootstrapped on first use.
25
25
  3. **Governance is the file** — no versions, no snapshots, no approvals, no background extraction: a bad memory is a visible file in the workspace, and deleting it is the retirement path. Memories are personal context — on bootstrap in a git workspace the store appends `.evolve/` to the workspace `.gitignore` (non-git workspaces are left untouched).
26
- 4. **Read-only card** — the plugin mounts a read-only memory card on its own page in the official plugin manager (the `plugins.bundle.config` slot; hosts without it silently degrade to no card): recently served workspaces, per-workspace entry and index counts, and index-drift warnings (unindexed files, index rows whose file is gone). The card is a request-time projection of the files on disk — the single source of truth remains `.evolve/memory/`; the card has no edit path, edit the files directly.
26
+ 4. **Read-only card** — the plugin mounts a read-only memory card on its own page in the official plugin manager (the `plugins.bundle.config` slot; hosts without it silently degrade to no card): recently served workspaces, per-workspace entry and index counts, and index-drift warnings (unindexed files, index rows whose file is gone). The card follows the market's look — host theme tokens, the `Button` primitive for refresh, and zh/en copy that tracks the DSH language (plain themed elements on old hosts). The card is a request-time projection of the files on disk — the single source of truth remains `.evolve/memory/`; the card has no edit path, edit the files directly.
27
27
 
28
28
  Memory file format (same as ZCode): frontmatter with `name` / `description` (the hook that decides whether a future session recalls it) / `metadata.type` (`user | feedback | project | reference`); `feedback` bodies must carry **Why:** and **How to apply:** lines.
29
29
 
@@ -66,7 +66,7 @@ Profile patch example:
66
66
 
67
67
  ```bash
68
68
  pnpm install && pnpm build # deps + tsc -> lib/
69
- pnpm test # vitest (62 tests)
69
+ pnpm test # vitest (66 tests)
70
70
  pnpm test:coverage # v8 coverage, CI-enforced thresholds
71
71
  pnpm lint # oxlint src test
72
72
  ```
package/README.zh.md CHANGED
@@ -23,7 +23,7 @@ Agent 每个会话积累的可复用经验(用户偏好、踩坑教训、项
23
23
  1. **开局注入** —— 插件只注册一个 system-prompt section:注入 `MEMORY.md` 索引正文(超预算按整行截断并提示读目录)、记忆目录绝对路径、when_to_save 指南。该 section 每会话只算一次并逐字节复用,system prompt 稳定、prompt cache 持续命中;空 store 零 token。
24
24
  2. **原生读写** —— DSH 对工作区内文件读写全放行(读路径从不设防,写围栏只围工作区外,见 [`docs/FAQ.md`](docs/FAQ.md) #6)。模型直接 Read/Write/Edit 记忆文件并维护索引;store 不存在时自动 bootstrap。
25
25
  3. **治理即文件** —— 无版本、无快照、无审批、无后台提取:一条坏记忆就是工作区里一个可见的文件,删掉它就是退役。记忆是个人上下文——bootstrap 时若工作区是 git 仓库会自动把 `.evolve/` 追加进 `.gitignore`(非 git 工作区不碰任何文件)。
26
- 4. **只读卡片** —— 插件在官方插件管理的本 bundle 页面挂一张只读记忆卡片(`plugins.bundle.config` slot,老宿主自动降级为无卡片):最近服务过的工作区、各自记忆库的条目数/索引行数、索引漂移警告(未索引文件与索引失联文件)。卡片是磁盘文件的请求时投影——单一事实源永远是 `.evolve/memory/` 里的文件,卡片没有编辑路径,编辑请直接改文件。
26
+ 4. **只读卡片** —— 插件在官方插件管理的本 bundle 页面挂一张只读记忆卡片(`plugins.bundle.config` slot,老宿主自动降级为无卡片):最近服务过的工作区、各自记忆库的条目数/索引行数、索引漂移警告(未索引文件与索引失联文件)。卡片与市场同款——宿主主题 token、`Button` 原语刷新按钮、中英文案跟随 DSH 语言(老宿主降级为同主题裸元素)。卡片是磁盘文件的请求时投影——单一事实源永远是 `.evolve/memory/` 里的文件,卡片没有编辑路径,编辑请直接改文件。
27
27
 
28
28
  记忆文件格式(与 ZCode 一致):frontmatter 带 `name` / `description`(决定未来会话会不会想起它)/ `metadata.type`(`user | feedback | project | reference`);`feedback` 正文必带 **Why:** 与 **How to apply:**。
29
29
 
@@ -66,7 +66,7 @@ profile patch 示例:
66
66
 
67
67
  ```bash
68
68
  pnpm install && pnpm build # 依赖 + tsc -> lib/
69
- pnpm test # vitest(62 例)
69
+ pnpm test # vitest(66 例)
70
70
  pnpm test:coverage # v8 覆盖率,CI 强制阈值
71
71
  pnpm lint # oxlint src test
72
72
  ```
package/client/client.js CHANGED
@@ -4,9 +4,10 @@
4
4
  * Hand-written (no bundler: docs/coding-standard.md forbids a second one) in
5
5
  * the host loader's factory shape, verified against dshmarket's built
6
6
  * bundle: `window.__ModuleLoader__.load({ id, factory })`, where the factory
7
- * resolves host-provided modules through the passed `require` (here: only
8
- * react) and returns its `module.exports`. The host mounts the bundle via
9
- * package.json `dsh.client` + the `./client` export.
7
+ * resolves host-provided modules through the passed `require` (here: react
8
+ * plus, optionally, the UI primitives) and returns its `module.exports`.
9
+ * The host mounts the bundle via package.json `dsh.client` + the `./client`
10
+ * export.
10
11
  *
11
12
  * The card registers one slot, `plugins.bundle.config` — the seat the 0.1.7+
12
13
  * plugin manager declares for a bundle's own page. Slot detection is the
@@ -16,9 +17,13 @@
16
17
  * call with null (the bundle list row shows the package description; the
17
18
  * card is the page).
18
19
  *
19
- * The card is a read-only projection of the workspace memory store, fetched
20
- * at render time from this plugin's host routes (same-origin). No editor, no
21
- * write path, no cached state — refresh refetches everything.
20
+ * Market parity (v0.13): locale/theme/primitives wiring copied from
21
+ * dshmarket's client — `ctx.locale.register(NS, { zh, en })` + `bind`,
22
+ * `var(--dsw-alias-*)` theme tokens, `Button` primitive for the refresh
23
+ * control. Missing primitives/locale degrade to themed plain elements, so an
24
+ * old host never blanks the settings dialog. The card stays a read-only
25
+ * projection: fetched at render time from this plugin's host routes
26
+ * (same-origin). No editor, no write path, no cached state.
22
27
  */
23
28
  window.__ModuleLoader__.load({
24
29
  id: "dsh-continual-evolve",
@@ -44,6 +49,15 @@ window.__ModuleLoader__.load({
44
49
  return module.exports;
45
50
  }
46
51
 
52
+ var primitives = undefined;
53
+ try {
54
+ primitives = require("@deepseek-ai/dsh-client-ui-primitives");
55
+ } catch (error) {
56
+ // Old host without the primitives package: themed plain elements below.
57
+ void error;
58
+ primitives = undefined;
59
+ }
60
+
47
61
  var createElement = react.createElement;
48
62
  var useState = react.useState;
49
63
  var useEffect = react.useEffect;
@@ -52,6 +66,42 @@ window.__ModuleLoader__.load({
52
66
  var SLOT = "plugins.bundle.config";
53
67
  var API_ROOT = "/dsh-continual-evolve/api/v1";
54
68
 
69
+ var zh = {
70
+ title: "工作区记忆(只读投影)",
71
+ refresh: "刷新",
72
+ hint: "事实源是各工作区 .evolve/memory/ 下的 markdown 文件——模型原生读写;本卡片只展示,编辑请直接改文件。",
73
+ loading: "读取中…",
74
+ loadFailed: "卡片数据加载失败:",
75
+ empty: "本进程还没有服务过任何工作区会话——在某个工作区开一次会话后回来刷新。",
76
+ absent: "该工作区尚无记忆库(开一次会话自动创建)。",
77
+ readFailed: "记忆库读取失败:",
78
+ stats: "{files} 条记忆 · 索引 {index} 行",
79
+ missing: "索引失联(索引引用但文件已删):",
80
+ unindexed: "未入索引(文件存在但索引没有行):",
81
+ readError: "读取失败:",
82
+ };
83
+ var en = {
84
+ title: "Workspace memory (read-only)",
85
+ refresh: "Refresh",
86
+ hint: "The source of truth is the markdown files under each workspace's .evolve/memory/ — read and written by the model; this card only displays them, edit the files directly.",
87
+ loading: "Loading…",
88
+ loadFailed: "Failed to load card data: ",
89
+ empty: "This process has not served any workspace session yet — open a session in a workspace, then come back and refresh.",
90
+ absent: "No memory store in this workspace yet (one is created when you open a session).",
91
+ readFailed: "Failed to read the memory store: ",
92
+ stats: "{files} memories · {index} index rows",
93
+ missing: "Dangling index (indexed but deleted): ",
94
+ unindexed: "Unindexed (on disk, missing from the index): ",
95
+ readError: "Read failed: ",
96
+ };
97
+
98
+ function format(template, params) {
99
+ return String(template).replace(/\{(\w+)\}/g, function (match, key) {
100
+ var value = params[key];
101
+ return value === undefined || value === null ? match : String(value);
102
+ });
103
+ }
104
+
55
105
  /**
56
106
  * Assemble the card's view model: the workspace allowlist, then one
57
107
  * snapshot per workspace. Network or API failure per workspace degrades
@@ -64,7 +114,7 @@ window.__ModuleLoader__.load({
64
114
  async function loadCardModel(fetchImpl) {
65
115
  var listResponse = await fetchImpl(API_ROOT + "/workspaces");
66
116
  if (!listResponse.ok) {
67
- throw new Error("workspaces API answered HTTP " + listResponse.status);
117
+ throw new Error("HTTP " + listResponse.status);
68
118
  }
69
119
  var listBody = await listResponse.json();
70
120
  var workspaces = Array.isArray(listBody.workspaces) ? listBody.workspaces : [];
@@ -91,69 +141,152 @@ window.__ModuleLoader__.load({
91
141
  return { workspaces: entries };
92
142
  }
93
143
 
144
+ var CARD_STYLE = {
145
+ background: "var(--dsw-alias-bg-layer-1,#fff)",
146
+ border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
147
+ borderRadius: "12px",
148
+ padding: "12px 14px",
149
+ display: "flex",
150
+ flexDirection: "column",
151
+ gap: "12px",
152
+ };
153
+ var TITLE_STYLE = {
154
+ color: "var(--dsw-alias-label-primary,#1f2328)",
155
+ fontSize: "15px",
156
+ fontWeight: 600,
157
+ lineHeight: "22px",
158
+ };
159
+ var HINT_STYLE = {
160
+ color: "var(--dsw-alias-label-tertiary,#8b93a1)",
161
+ fontSize: "12px",
162
+ lineHeight: "18px",
163
+ };
164
+ var SECTION_STYLE = {
165
+ borderTop: "1px solid var(--dsw-alias-border-l2,#f0f1f3)",
166
+ paddingTop: "8px",
167
+ display: "flex",
168
+ flexDirection: "column",
169
+ gap: "6px",
170
+ };
171
+ var ROOT_STYLE = {
172
+ fontFamily: "ui-monospace,Menlo,monospace",
173
+ fontSize: "11px",
174
+ color: "var(--dsw-alias-label-secondary,#6b7280)",
175
+ wordBreak: "break-all",
176
+ };
177
+ var STATS_STYLE = {
178
+ fontSize: "12px",
179
+ lineHeight: "18px",
180
+ color: "var(--dsw-alias-label-secondary,#6b7280)",
181
+ };
182
+ var WARN_STYLE = {
183
+ fontSize: "12px",
184
+ lineHeight: "18px",
185
+ color: "var(--dsw-alias-state-warn-primary,#b45309)",
186
+ };
187
+ var ERROR_STYLE = {
188
+ fontSize: "12px",
189
+ lineHeight: "18px",
190
+ color: "var(--dsw-alias-state-error-primary,#dc2626)",
191
+ };
192
+ var LIST_STYLE = { margin: "4px 0 0", paddingLeft: "18px", fontSize: "12px", lineHeight: "18px" };
193
+ var FALLBACK_BUTTON_STYLE = {
194
+ background: "var(--dsw-alias-bg-layer-2,#f3f4f6)",
195
+ color: "var(--dsw-alias-label-primary,#1f2328)",
196
+ border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
197
+ borderRadius: "6px",
198
+ padding: "3px 10px",
199
+ fontSize: "12px",
200
+ lineHeight: "18px",
201
+ cursor: "pointer",
202
+ };
203
+
204
+ function RefreshButton(props) {
205
+ var UI = props.UI;
206
+ var t = props.t;
207
+ var onClick = props.onClick;
208
+ if (UI !== null && UI !== undefined && typeof UI.Button !== "undefined" && UI.Button !== null) {
209
+ return createElement(
210
+ UI.Button,
211
+ { variant: "outline", size: "sm", onClick: onClick },
212
+ t("refresh"),
213
+ );
214
+ }
215
+ return createElement("button", { type: "button", style: FALLBACK_BUTTON_STYLE, onClick: onClick }, t("refresh"));
216
+ }
217
+
94
218
  /** One workspace block: root, stats, drift warnings, per-file lines. */
95
219
  function WorkspaceBlock(props) {
96
220
  var entry = props.entry;
97
- var snapshot = entry.snapshot;
98
- var children = [
99
- createElement("div", { key: "root", style: { fontFamily: "monospace", wordBreak: "break-all" } }, entry.root),
100
- ];
101
- if (entry.error !== null) {
102
- children.push(createElement("div", { key: "error" }, "读取失败:" + entry.error));
103
- return createElement("div", { style: { marginBottom: "12px" } }, children);
221
+ var t = props.t;
222
+ if (entry.error !== null && entry.error !== undefined) {
223
+ return createElement(
224
+ "div",
225
+ { style: SECTION_STYLE },
226
+ createElement("div", { style: ROOT_STYLE }, entry.root),
227
+ createElement("div", { style: ERROR_STYLE }, t("readError") + entry.error),
228
+ );
104
229
  }
105
- if (snapshot === null || !snapshot.exists) {
106
- children.push(createElement("div", { key: "absent" }, "该工作区尚无记忆库(开一次会话自动创建)。"));
107
- return createElement("div", { style: { marginBottom: "12px" } }, children);
230
+ var snapshot = entry.snapshot;
231
+ if (snapshot === null || snapshot === undefined || !snapshot.exists) {
232
+ return createElement(
233
+ "div",
234
+ { style: SECTION_STYLE },
235
+ createElement("div", { style: ROOT_STYLE }, entry.root),
236
+ createElement("div", { style: HINT_STYLE }, t("absent")),
237
+ );
108
238
  }
109
- if (snapshot.readError !== null) {
110
- children.push(createElement("div", { key: "readError" }, "记忆库读取失败:" + snapshot.readError));
111
- return createElement("div", { style: { marginBottom: "12px" } }, children);
239
+ if (snapshot.readError !== null && snapshot.readError !== undefined) {
240
+ return createElement(
241
+ "div",
242
+ { style: SECTION_STYLE },
243
+ createElement("div", { style: ROOT_STYLE }, entry.root),
244
+ createElement("div", { style: ERROR_STYLE }, t("readFailed") + snapshot.readError),
245
+ );
112
246
  }
113
- children.push(
247
+ var children = [
248
+ createElement("div", { key: "root", style: ROOT_STYLE }, entry.root),
114
249
  createElement(
115
250
  "div",
116
- { key: "stats" },
117
- snapshot.fileCount + " 条记忆 · 索引 " + snapshot.indexEntryCount + " 行",
251
+ { key: "stats", style: STATS_STYLE },
252
+ t("stats", { files: snapshot.fileCount, index: snapshot.indexEntryCount }),
118
253
  ),
119
- );
254
+ ];
120
255
  if (snapshot.missingFiles.length > 0) {
121
256
  children.push(
122
- createElement(
123
- "div",
124
- { key: "missing" },
125
- "索引失联(索引引用但文件已删):" + snapshot.missingFiles.join("、"),
126
- ),
257
+ createElement("div", { key: "missing", style: WARN_STYLE }, t("missing") + snapshot.missingFiles.join("、")),
127
258
  );
128
259
  }
129
260
  if (snapshot.unindexedFiles.length > 0) {
130
261
  children.push(
131
262
  createElement(
132
263
  "div",
133
- { key: "unindexed" },
134
- "未入索引(文件存在但索引没有行):" + snapshot.unindexedFiles.join("、"),
264
+ { key: "unindexed", style: WARN_STYLE },
265
+ t("unindexed") + snapshot.unindexedFiles.join("、"),
135
266
  ),
136
267
  );
137
268
  }
138
269
  children.push(
139
270
  createElement(
140
271
  "ul",
141
- { key: "files", style: { margin: "4px 0 0", paddingLeft: "18px" } },
272
+ { key: "files", style: LIST_STYLE },
142
273
  snapshot.files.map(function (file) {
143
274
  return createElement(
144
275
  "li",
145
276
  { key: file.file },
146
- createElement("strong", null, file.file) +
147
- (file.description !== "" ? " — " + file.description : ""),
277
+ createElement("strong", null, file.file),
278
+ file.description !== "" ? " — " + file.description : "",
148
279
  );
149
280
  }),
150
281
  ),
151
282
  );
152
- return createElement("div", { style: { marginBottom: "12px" } }, children);
283
+ return createElement("div", { style: SECTION_STYLE }, children);
153
284
  }
154
285
 
155
286
  /** The card page: refresh control + one block per known workspace. */
156
- function MemoryCard() {
287
+ function MemoryCard(props) {
288
+ var t = props.t;
289
+ var UI = props.UI;
157
290
  var state = useState({ status: "loading", model: null, message: "" });
158
291
  var model = state[0];
159
292
  var setModel = state[1];
@@ -178,72 +311,111 @@ window.__ModuleLoader__.load({
178
311
  },
179
312
  [reloadState[0]],
180
313
  );
181
- var children = [
182
- createElement(
183
- "div",
184
- { key: "head", style: { display: "flex", alignItems: "baseline", gap: "12px" } },
185
- createElement("strong", null, "工作区记忆(只读投影)"),
186
- createElement(
187
- "button",
188
- {
189
- type: "button",
190
- onClick: function () {
191
- setModel({ status: "loading", model: null, message: "" });
192
- reload(function (n) {
193
- return n + 1;
194
- });
195
- },
196
- },
197
- "刷新",
198
- ),
199
- ),
200
- createElement(
201
- "div",
202
- { key: "hint" },
203
- "事实源是各工作区 .evolve/memory/ 下的 markdown 文件——模型原生读写;本卡片只展示,编辑请直接改文件。",
204
- ),
205
- ];
314
+ var body = null;
206
315
  if (model.status === "loading") {
207
- children.push(createElement("div", { key: "body" }, "读取中…"));
316
+ body = createElement("div", { key: "body", style: HINT_STYLE }, t("loading"));
208
317
  } else if (model.status === "error") {
209
- children.push(createElement("div", { key: "body" }, "卡片数据加载失败:" + model.message));
318
+ body = createElement("div", { key: "body", style: ERROR_STYLE }, t("loadFailed") + model.message);
210
319
  } else if (model.model.workspaces.length === 0) {
211
- children.push(
212
- createElement(
213
- "div",
214
- { key: "body" },
215
- "本进程还没有服务过任何工作区会话——在某个工作区开一次会话后回来刷新。",
216
- ),
217
- );
320
+ body = createElement("div", { key: "body", style: HINT_STYLE }, t("empty"));
218
321
  } else {
219
- children.push(
220
- createElement(
221
- "div",
222
- { key: "body" },
223
- model.model.workspaces.map(function (entry) {
224
- return createElement(WorkspaceBlock, { key: entry.root, entry: entry });
225
- }),
226
- ),
322
+ body = createElement(
323
+ "div",
324
+ { key: "body" },
325
+ model.model.workspaces.map(function (entry) {
326
+ return createElement(WorkspaceBlock, { key: entry.root, entry: entry, t: t, UI: UI });
327
+ }),
227
328
  );
228
329
  }
229
- return createElement("div", null, children);
330
+ return createElement(
331
+ "div",
332
+ { style: CARD_STYLE },
333
+ createElement(
334
+ "div",
335
+ { style: { display: "flex", alignItems: "center", gap: "12px" } },
336
+ createElement("div", { style: TITLE_STYLE }, t("title")),
337
+ createElement("span", { style: { flex: 1 } }),
338
+ createElement(RefreshButton, {
339
+ UI: UI,
340
+ t: t,
341
+ onClick: function () {
342
+ setModel({ status: "loading", model: null, message: "" });
343
+ reload(function (n) {
344
+ return n + 1;
345
+ });
346
+ },
347
+ }),
348
+ ),
349
+ createElement("div", { style: HINT_STYLE }, t("hint")),
350
+ body,
351
+ );
230
352
  }
231
353
 
232
354
  exports.name = NS;
233
- exports.inject = ["slots"];
355
+ exports.inject = ["slots", "locale", "theme"];
234
356
  exports.loadCardModel = loadCardModel;
235
357
  exports.apply = function apply(ctx) {
358
+ var tRaw = null;
359
+ try {
360
+ if (ctx.locale !== undefined && ctx.locale !== null) {
361
+ var register = function () {
362
+ return ctx.locale.register(NS, { zh: zh, en: en });
363
+ };
364
+ if (typeof ctx.effect === "function") {
365
+ ctx.effect(register, "dsh-continual-evolve: dictionaries");
366
+ } else if (typeof ctx.locale.register === "function") {
367
+ register();
368
+ }
369
+ if (typeof ctx.locale.bind === "function") {
370
+ tRaw = ctx.locale.bind(NS);
371
+ }
372
+ }
373
+ } catch (error) {
374
+ void error;
375
+ tRaw = null;
376
+ }
377
+ var fallbackT = function (key, params) {
378
+ var template = Object.prototype.hasOwnProperty.call(zh, key) ? zh[key] : key;
379
+ if (params !== undefined) {
380
+ return format(template, params);
381
+ }
382
+ return template;
383
+ };
384
+ var t = fallbackT;
385
+ if (typeof tRaw === "function") {
386
+ t = function (key, params) {
387
+ var rendered = null;
388
+ try {
389
+ rendered = tRaw(key);
390
+ } catch (error) {
391
+ void error;
392
+ rendered = null;
393
+ }
394
+ if (typeof rendered !== "string") {
395
+ return fallbackT(key, params);
396
+ }
397
+ if (params !== undefined) {
398
+ return format(rendered, params);
399
+ }
400
+ return rendered;
401
+ };
402
+ }
403
+ var UI = null;
404
+ if (primitives !== undefined && primitives !== null && typeof primitives.Button !== "undefined") {
405
+ UI = { Button: primitives.Button };
406
+ }
236
407
  ctx.slots.inject(SLOT, function () {
237
408
  return ctx.slots.register(
238
409
  {
239
410
  name: SLOT,
240
411
  key: NS,
412
+ locale: NS,
241
413
  inject: function () {
242
- return {};
414
+ return { t: typeof tRaw === "function" ? tRaw : fallbackT };
243
415
  },
244
416
  },
245
417
  function (ownerProps) {
246
- return ownerProps && ownerProps.view === "summary" ? null : createElement(MemoryCard);
418
+ return ownerProps && ownerProps.view === "summary" ? null : createElement(MemoryCard, { t: t, UI: UI });
247
419
  },
248
420
  );
249
421
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-continual-evolve",
3
- "version": "0.12.1",
4
- "description": "ZCode-style workspace memory for DeepSeek Harness: a per-workspace markdown store (<workspace>/.evolve/memory/) with session-start index injection — the model reads and writes the files with its native tools.",
3
+ "version": "0.13.0",
4
+ "description": "DSH 工作区记忆:每个工作区一个 markdown 记忆库,会话开局注入索引,模型原生读写 / ZCode-style workspace memory for DeepSeek Harness: a per-workspace markdown store with session-start index injection.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -35,7 +35,11 @@
35
35
  "patch": "./cordis.patch.yml"
36
36
  },
37
37
  "client": {
38
- "inject": [],
38
+ "inject": [
39
+ "@deepseek-ai/dsh-client-locale",
40
+ "@deepseek-ai/dsh-client-ui-settings",
41
+ "@deepseek-ai/dsh-client-ui-theme"
42
+ ],
39
43
  "platform": "web"
40
44
  }
41
45
  },