@max-null/dsh-memory 0.3.8 → 0.5.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/client.js +243 -145
  3. package/package.json +13 -13
package/README.md CHANGED
@@ -58,7 +58,7 @@ memory_forget → 随时删除
58
58
 
59
59
  ## SSID 系列
60
60
 
61
- 本插件属于 **`@max-null/*` 插件系列**——这一系列共同构成 **[SSID(思灵 · Seek Soul in Darkness)](https://github.com/Max-Null/seek-soul-in-darkness)** 桌面体验。SSID 是整合它们的盒:`dsh-plugin-center` · `dsh-memory` · `dsh-chinese-thinking` · `dsh-guardian` · `dsh-habit`。
61
+ 本插件属于 **`@max-null/*` 插件系列**——这一系列共同构成 **[SSID(思灵 · Seek Soul in Darkness)](https://github.com/Max-Null/seek-soul-in-darkness)** 桌面体验。SSID 是整合它们的盒:`dsh-chat-rail` · `dsh-chinese-thinking` · `dsh-draft-polish` · `dsh-guardian` · `dsh-habit` · `dsh-header-unify` · `dsh-memory` · `dsh-node-appearance` · `dsh-plugin-center` · `dsh-skill-mcp-center` · `dsh-ssid-panels` · `dsh-ssid-zh-ui`。
62
62
 
63
63
  This plugin belongs to the **`@max-null/*` family** — a set of plugins that together form the **[SSID (思灵 · Seek Soul in Darkness)](https://github.com/Max-Null/seek-soul-in-darkness)** desktop experience.
64
64
 
package/client.js CHANGED
@@ -32,6 +32,62 @@ __export(index_exports, {
32
32
  module.exports = __toCommonJS(index_exports);
33
33
  var import_react = require("react");
34
34
  var inject = ["slots", "locale"];
35
+ var FILE_REF_RE = /@("([^"]+)"|([^\s"@]+))/g;
36
+ function looksLikePath(path) {
37
+ if (path.includes("\\")) return true;
38
+ if (path.startsWith("./") || path.startsWith("../") || path.startsWith("/") || path.startsWith("~/")) return true;
39
+ if (path.includes("/")) {
40
+ return path.includes(".");
41
+ }
42
+ const m = /\.([A-Za-z0-9]{1,6})$/.exec(path);
43
+ if (m === null) return false;
44
+ const ext = m[1].toLowerCase();
45
+ const COMMON_EXTS = /* @__PURE__ */ new Set(["md", "txt", "ts", "tsx", "js", "mjs", "cjs", "json", "yml", "yaml", "toml", "png", "jpg", "jpeg", "gif", "webp", "svg", "ico", "css", "scss", "html", "py", "rs", "go", "java", "c", "h", "cpp", "sh", "ps1", "bat", "exe", "zip", "tar", "gz", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "log", "env", "lock", "csv", "xml", "sql", "db", "wasm"]);
46
+ return COMMON_EXTS.has(ext);
47
+ }
48
+ function splitFileRefs(text) {
49
+ const parts = [];
50
+ let last = 0;
51
+ let m;
52
+ FILE_REF_RE.lastIndex = 0;
53
+ while ((m = FILE_REF_RE.exec(text)) !== null) {
54
+ if (m.index > last) parts.push({ kind: "text", text: text.slice(last, m.index) });
55
+ const path = m[2] ?? m[3];
56
+ if (m[2] !== void 0 || looksLikePath(path)) {
57
+ parts.push({ kind: "ref", ref: { raw: m[0], path } });
58
+ } else {
59
+ parts.push({ kind: "text", text: m[0] });
60
+ }
61
+ last = m.index + m[0].length;
62
+ }
63
+ if (last < text.length) parts.push({ kind: "text", text: text.slice(last) });
64
+ return parts;
65
+ }
66
+ var openFileRef = null;
67
+ function ContentWithRefs({ text, style }) {
68
+ const parts = splitFileRefs(text);
69
+ if (parts.every((p) => p.kind === "text")) return text;
70
+ return (0, import_react.createElement)(
71
+ "span",
72
+ { style: { whiteSpace: "pre-wrap", wordBreak: "break-all" } },
73
+ parts.map((p, i) => p.kind === "text" ? (0, import_react.createElement)("span", { key: i, style }, p.text) : (0, import_react.createElement)("span", {
74
+ key: i,
75
+ title: "open file",
76
+ onClick: () => {
77
+ openFileRef?.(p.ref.path, p.ref.path);
78
+ },
79
+ style: {
80
+ ...style,
81
+ cursor: "pointer",
82
+ borderRadius: 4,
83
+ padding: "0 3px",
84
+ background: "var(--dsw-alias-state-business-tertiary, rgba(79,195,247,.16))",
85
+ color: "var(--dsw-alias-state-business-primary, #4FC3F7)",
86
+ textDecoration: "underline dotted"
87
+ }
88
+ }, p.ref.raw))
89
+ );
90
+ }
35
91
  var BRAIN_PATHS = [
36
92
  "M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z",
37
93
  "M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z"
@@ -170,7 +226,26 @@ function useT() {
170
226
  }
171
227
  var ssid = {
172
228
  accent: "#4FC3F7",
173
- wrap: { display: "flex", flexDirection: "column", gap: 8, padding: "10px 12px", overflowY: "auto", height: "100%", boxSizing: "border-box" },
229
+ // Root column: toolbar + namespace tabs stay pinned at the top (flex:none);
230
+ // only the content area below scrolls (2026-08-22 用户: tab 与功能不应随滚动)。
231
+ wrap: { display: "flex", flexDirection: "column", gap: 8, padding: "10px 12px", height: "100%", boxSizing: "border-box" },
232
+ header: { display: "flex", flexDirection: "column", gap: 8, flex: "none" },
233
+ content: { flex: 1, minHeight: 0, overflowY: "auto", display: "flex", flexDirection: "column", gap: 8, marginRight: -4, paddingRight: 4 },
234
+ // 计数徽标(醒目:accent 底 + 白色数字)。
235
+ count: {
236
+ display: "inline-flex",
237
+ alignItems: "center",
238
+ justifyContent: "center",
239
+ minWidth: 18,
240
+ height: 18,
241
+ padding: "0 6px",
242
+ borderRadius: 9,
243
+ background: "var(--dsw-alias-state-business-primary, #4FC3F7)",
244
+ color: "#fff",
245
+ fontSize: 11,
246
+ fontWeight: 600,
247
+ lineHeight: 1
248
+ },
174
249
  card: {
175
250
  background: "var(--dsw-alias-bg-layer-1, #131a26)",
176
251
  border: "1px solid var(--dsw-alias-border-l2, #1e2836)",
@@ -313,6 +388,11 @@ function MemoryView(props) {
313
388
  const q = query.trim().toLowerCase();
314
389
  const byNs = namespace === null ? records : namespace === "workspace" ? records.filter((record) => record.namespace === "project") : records.filter((record) => record.namespace === "global");
315
390
  const filtered = byNs.filter((record) => q === "" || record.content.toLowerCase().includes(q));
391
+ const nsCounts = {
392
+ all: records.length,
393
+ global: records.filter((record) => record.namespace === "global").length,
394
+ workspace: records.filter((record) => record.namespace === "project").length
395
+ };
316
396
  const groups = [
317
397
  { key: "pending", label: t("groupPending"), items: filtered.filter((record) => record.status === "suggested") },
318
398
  { key: "ondemand", label: t("groupOnDemand"), items: filtered.filter((record) => record.status === "approved" && !record.injected) },
@@ -323,164 +403,177 @@ function MemoryView(props) {
323
403
  { style: ssid.wrap },
324
404
  (0, import_react.createElement)(
325
405
  "div",
326
- { style: { display: "flex", gap: 6 } },
327
- (0, import_react.createElement)("button", {
328
- type: "button",
329
- title: t("organizeMemory"),
330
- onClick: () => {
331
- void organize();
332
- },
333
- disabled: organizing,
334
- style: { ...ssid.btn, color: ssid.accent, borderColor: ssid.accent }
335
- }, organizing ? "\u2026" : t("organizeMemory")),
336
- (0, import_react.createElement)("button", {
337
- type: "button",
338
- title: t("injectPreview"),
339
- onClick: () => {
340
- void togglePreview();
341
- },
342
- style: { ...ssid.btn, ...previewOpen ? { color: ssid.accent, borderColor: ssid.accent } : {} }
343
- }, t("injectPreview")),
344
- (0, import_react.createElement)("input", {
345
- value: query,
346
- onChange: (event) => {
347
- setQuery(event.target.value);
348
- },
349
- placeholder: t("memorySearch"),
350
- style: {
351
- flex: 1,
352
- padding: "6px 10px",
353
- fontSize: 12.5,
354
- boxSizing: "border-box",
355
- background: "var(--dsw-alias-bg-layer-1, #0f141d)",
356
- border: "1px solid var(--dsw-alias-border-l2, #1e2836)",
357
- borderRadius: 8,
358
- color: "var(--dsw-alias-label-primary, #d8e0ea)",
359
- outline: "none"
360
- }
361
- }),
362
- (0, import_react.createElement)("button", {
363
- type: "button",
364
- title: t("refresh"),
365
- onClick: () => {
366
- void refreshFromDisk();
367
- },
368
- disabled: refreshing,
369
- style: ssid.btn
370
- }, refreshing ? "\u2026" : "\u21BB")
371
- ),
372
- (0, import_react.createElement)(
373
- "div",
374
- { style: { display: "flex", gap: 4 } },
375
- [null, "global", "workspace"].map((ns) => (0, import_react.createElement)("button", {
376
- key: ns ?? "all",
377
- onClick: () => {
378
- setNamespace(ns);
379
- },
380
- style: { flex: 1, ...ssid.btn, ...namespace === ns ? { color: ssid.accent, borderColor: ssid.accent } : {} }
381
- }, ns === null ? t("allNamespaces") : ns === "global" ? t("nsGlobal") : t("nsWorkspace")))
382
- ),
383
- // 注入预览(开发者):self 自述 + 当前注入的记忆 + 上下文占用统计
384
- previewOpen && preview !== null ? (0, import_react.createElement)(
385
- "div",
386
- { style: { ...ssid.card, display: "flex", flexDirection: "column", gap: 6 } },
406
+ { style: ssid.header },
387
407
  (0, import_react.createElement)(
388
408
  "div",
389
- { style: { ...ssid.muted, fontSize: 10.5, display: "flex", justifyContent: "space-between", alignItems: "center" } },
390
- (0, import_react.createElement)("span", null, t("contextUsage")),
391
- (0, import_react.createElement)("span", null, (() => {
392
- const selfChars = preview.self.length;
393
- const injectedChars = preview.injected.reduce((sum, record) => sum + record.content.length + record.keywords.join("").length, 0);
394
- const total = selfChars + injectedChars;
395
- const tokens = Math.ceil(total / 2);
396
- return `${selfChars}+${injectedChars} \u5B57\u7B26 \u2248 ${tokens} token`;
397
- })())
409
+ { style: { display: "flex", gap: 6 } },
410
+ (0, import_react.createElement)("button", {
411
+ type: "button",
412
+ title: t("organizeMemory"),
413
+ onClick: () => {
414
+ void organize();
415
+ },
416
+ disabled: organizing,
417
+ style: { ...ssid.btn, color: ssid.accent, borderColor: ssid.accent }
418
+ }, organizing ? "\u2026" : t("organizeMemory")),
419
+ (0, import_react.createElement)("button", {
420
+ type: "button",
421
+ title: t("injectPreview"),
422
+ onClick: () => {
423
+ void togglePreview();
424
+ },
425
+ style: { ...ssid.btn, ...previewOpen ? { color: ssid.accent, borderColor: ssid.accent } : {} }
426
+ }, t("injectPreview")),
427
+ (0, import_react.createElement)("input", {
428
+ value: query,
429
+ onChange: (event) => {
430
+ setQuery(event.target.value);
431
+ },
432
+ placeholder: t("memorySearch"),
433
+ style: {
434
+ flex: 1,
435
+ padding: "6px 10px",
436
+ fontSize: 12.5,
437
+ boxSizing: "border-box",
438
+ background: "var(--dsw-alias-bg-layer-1, #0f141d)",
439
+ border: "1px solid var(--dsw-alias-border-l2, #1e2836)",
440
+ borderRadius: 8,
441
+ color: "var(--dsw-alias-label-primary, #d8e0ea)",
442
+ outline: "none"
443
+ }
444
+ }),
445
+ (0, import_react.createElement)("button", {
446
+ type: "button",
447
+ title: t("refresh"),
448
+ onClick: () => {
449
+ void refreshFromDisk();
450
+ },
451
+ disabled: refreshing,
452
+ style: ssid.btn
453
+ }, refreshing ? "\u2026" : "\u21BB")
398
454
  ),
399
- (0, import_react.createElement)("div", { style: { ...ssid.text, fontSize: 11, whiteSpace: "pre-wrap", wordBreak: "break-all" } }, preview.self),
400
- preview.injected.length === 0 ? (0, import_react.createElement)("div", { style: ssid.muted }, t("empty")) : preview.injected.map((record) => (0, import_react.createElement)(
401
- "div",
402
- { key: record.id, style: { ...ssid.muted, fontSize: 11 } },
403
- `- [memory:${record.id.slice(0, 8)}] ${record.content}`
404
- ))
405
- ) : null,
406
- // 未选择工作区:工作区视图显示占位(0.3.4 工作区路由语义)
407
- namespace === "workspace" && (props.cwd === void 0 || props.cwd === "") ? (0, import_react.createElement)("div", { style: ssid.empty }, t("noWorkspace")) : groups.length === 0 ? (0, import_react.createElement)("div", { style: ssid.empty }, t("empty")) : groups.map((group) => (0, import_react.createElement)(
408
- "div",
409
- { key: group.key, style: { display: "flex", flexDirection: "column", gap: 6 } },
410
455
  (0, import_react.createElement)(
411
456
  "div",
412
- { style: ssid.title },
413
- (0, import_react.createElement)("span", null, group.label),
414
- (0, import_react.createElement)(
415
- "div",
416
- { style: { display: "flex", alignItems: "center", gap: 6 } },
417
- group.key === "pending" && group.items.length > 0 ? (0, import_react.createElement)("button", {
418
- type: "button",
419
- title: t("confirmAll"),
457
+ { style: { display: "flex", gap: 4 } },
458
+ [null, "global", "workspace"].map((ns) => {
459
+ const label = ns === null ? t("allNamespaces") : ns === "global" ? t("nsGlobal") : t("nsWorkspace");
460
+ const count = ns === null ? nsCounts.all : ns === "global" ? nsCounts.global : nsCounts.workspace;
461
+ return (0, import_react.createElement)("button", {
462
+ key: ns ?? "all",
420
463
  onClick: () => {
421
- void confirmAll();
464
+ setNamespace(ns);
422
465
  },
423
- style: { ...ssid.btn, padding: "1px 8px", fontSize: 10.5 }
424
- }, t("confirmAll")) : null,
425
- (0, import_react.createElement)("span", null, `${group.items.length}`)
426
- )
427
- ),
428
- group.items.map((record) => (0, import_react.createElement)(
466
+ style: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, ...ssid.btn, ...namespace === ns ? { color: ssid.accent, borderColor: ssid.accent } : {} }
467
+ }, (0, import_react.createElement)("span", null, label), (0, import_react.createElement)("span", { style: ssid.count }, String(count)));
468
+ })
469
+ )
470
+ ),
471
+ // 内容区独立滚动:预览 + 分组列表。
472
+ (0, import_react.createElement)(
473
+ "div",
474
+ { style: ssid.content },
475
+ // 注入预览(开发者):self 自述 + 当前注入的记忆 + 上下文占用统计
476
+ previewOpen && preview !== null ? (0, import_react.createElement)(
429
477
  "div",
430
- { key: record.id, style: ssid.card },
431
- (0, import_react.createElement)("div", { style: ssid.text }, record.content),
432
- // keywords 展示(0.3.5:设计约定 UI 显示 keywords)
433
- record.keywords !== void 0 && record.keywords.length > 0 ? (0, import_react.createElement)(
434
- "div",
435
- { style: { display: "flex", flexWrap: "wrap", gap: 4, marginTop: 6 } },
436
- record.keywords.map((keyword) => (0, import_react.createElement)("span", {
437
- key: keyword,
438
- style: {
439
- fontSize: 10,
440
- padding: "1px 7px",
441
- borderRadius: 8,
442
- background: "var(--dsw-alias-bg-module-platform, rgba(128,148,168,.14))",
443
- color: "var(--dsw-alias-label-secondary, #67748a)"
444
- }
445
- }, keyword))
446
- ) : null,
478
+ { style: { ...ssid.card, display: "flex", flexDirection: "column", gap: 6 } },
447
479
  (0, import_react.createElement)(
448
480
  "div",
449
- { style: { ...ssid.muted, marginTop: 6 } },
450
- `${record.namespace} \xB7 ${record.status === "approved" ? t("approved") : t("suggested")}${record.injected ? ` \xB7 ${t("groupInjected")}` : ""}`
481
+ { style: { ...ssid.muted, fontSize: 10.5, display: "flex", justifyContent: "space-between", alignItems: "center" } },
482
+ (0, import_react.createElement)("span", null, t("contextUsage")),
483
+ (0, import_react.createElement)("span", null, (() => {
484
+ const selfChars = preview.self.length;
485
+ const injectedChars = preview.injected.reduce((sum, record) => sum + record.content.length + record.keywords.join("").length, 0);
486
+ const total = selfChars + injectedChars;
487
+ const tokens = Math.ceil(total / 2);
488
+ return `${selfChars}+${injectedChars} \u5B57\u7B26 \u2248 ${tokens} token`;
489
+ })())
451
490
  ),
491
+ (0, import_react.createElement)("div", { style: { ...ssid.text, fontSize: 11, whiteSpace: "pre-wrap", wordBreak: "break-all" } }, preview.self),
492
+ preview.injected.length === 0 ? (0, import_react.createElement)("div", { style: ssid.muted }, t("empty")) : preview.injected.map((record) => (0, import_react.createElement)(
493
+ "div",
494
+ { key: record.id, style: { ...ssid.muted, fontSize: 11 } },
495
+ `- [memory:${record.id.slice(0, 8)}] ${record.content}`
496
+ ))
497
+ ) : null,
498
+ // 未选择工作区:工作区视图显示占位(0.3.4 工作区路由语义)
499
+ namespace === "workspace" && (props.cwd === void 0 || props.cwd === "") ? (0, import_react.createElement)("div", { style: ssid.empty }, t("noWorkspace")) : groups.length === 0 ? (0, import_react.createElement)("div", { style: ssid.empty }, t("empty")) : groups.map((group) => (0, import_react.createElement)(
500
+ "div",
501
+ { key: group.key, style: { display: "flex", flexDirection: "column", gap: 6 } },
452
502
  (0, import_react.createElement)(
453
503
  "div",
454
- { style: { display: "flex", gap: 6, marginTop: 8, alignItems: "center" } },
455
- (0, import_react.createElement)("button", {
456
- type: "button",
457
- title: record.status === "approved" ? t("injectSwitch") : t("approveFirst"),
458
- disabled: record.status !== "approved",
459
- onClick: () => {
460
- void toggleInjected(record);
461
- },
462
- style: {
463
- ...ssid.btn,
464
- ...record.injected ? { color: ssid.accent, borderColor: ssid.accent } : {},
465
- opacity: record.status !== "approved" ? 0.4 : 1,
466
- cursor: record.status !== "approved" ? "not-allowed" : "pointer"
467
- }
468
- }, record.injected ? `\u2713 ${t("injectSwitch")}` : t("injectSwitch")),
469
- record.status === "suggested" ? (0, import_react.createElement)("button", {
470
- style: ssid.btn,
471
- onClick: () => {
472
- void memoryApi.confirm(record.id, props.cwd).then(() => reload());
473
- }
474
- }, t("confirm")) : null,
475
- (0, import_react.createElement)("button", {
476
- style: ssid.btn,
477
- onClick: () => {
478
- void memoryApi.forget(record.id, props.cwd).then(() => reload());
479
- }
480
- }, t("forget"))
481
- )
504
+ { style: ssid.title },
505
+ (0, import_react.createElement)("span", null, group.label),
506
+ (0, import_react.createElement)(
507
+ "div",
508
+ { style: { display: "flex", alignItems: "center", gap: 6 } },
509
+ group.key === "pending" && group.items.length > 0 ? (0, import_react.createElement)("button", {
510
+ type: "button",
511
+ title: t("confirmAll"),
512
+ onClick: () => {
513
+ void confirmAll();
514
+ },
515
+ style: { ...ssid.btn, padding: "1px 8px", fontSize: 10.5 }
516
+ }, t("confirmAll")) : null,
517
+ (0, import_react.createElement)("span", { style: ssid.count }, String(group.items.length))
518
+ )
519
+ ),
520
+ group.items.map((record) => (0, import_react.createElement)(
521
+ "div",
522
+ { key: record.id, style: ssid.card },
523
+ (0, import_react.createElement)("div", { style: ssid.text }, ContentWithRefs({ text: record.content })),
524
+ // keywords 展示(0.3.5:设计约定 UI 显示 keywords)
525
+ record.keywords !== void 0 && record.keywords.length > 0 ? (0, import_react.createElement)(
526
+ "div",
527
+ { style: { display: "flex", flexWrap: "wrap", gap: 4, marginTop: 6 } },
528
+ record.keywords.map((keyword) => (0, import_react.createElement)("span", {
529
+ key: keyword,
530
+ style: {
531
+ fontSize: 10,
532
+ padding: "1px 7px",
533
+ borderRadius: 8,
534
+ background: "var(--dsw-alias-bg-module-platform, rgba(128,148,168,.14))",
535
+ color: "var(--dsw-alias-label-secondary, #67748a)"
536
+ }
537
+ }, keyword))
538
+ ) : null,
539
+ (0, import_react.createElement)(
540
+ "div",
541
+ { style: { ...ssid.muted, marginTop: 6 } },
542
+ `${record.namespace} \xB7 ${record.status === "approved" ? t("approved") : t("suggested")}${record.injected ? ` \xB7 ${t("groupInjected")}` : ""}`
543
+ ),
544
+ (0, import_react.createElement)(
545
+ "div",
546
+ { style: { display: "flex", gap: 6, marginTop: 8, alignItems: "center" } },
547
+ (0, import_react.createElement)("button", {
548
+ type: "button",
549
+ title: record.status === "approved" ? t("injectSwitch") : t("approveFirst"),
550
+ disabled: record.status !== "approved",
551
+ onClick: () => {
552
+ void toggleInjected(record);
553
+ },
554
+ style: {
555
+ ...ssid.btn,
556
+ ...record.injected ? { color: ssid.accent, borderColor: ssid.accent } : {},
557
+ opacity: record.status !== "approved" ? 0.4 : 1,
558
+ cursor: record.status !== "approved" ? "not-allowed" : "pointer"
559
+ }
560
+ }, record.injected ? `\u2713 ${t("injectSwitch")}` : t("injectSwitch")),
561
+ record.status === "suggested" ? (0, import_react.createElement)("button", {
562
+ style: ssid.btn,
563
+ onClick: () => {
564
+ void memoryApi.confirm(record.id, props.cwd).then(() => reload());
565
+ }
566
+ }, t("confirm")) : null,
567
+ (0, import_react.createElement)("button", {
568
+ style: ssid.btn,
569
+ onClick: () => {
570
+ void memoryApi.forget(record.id, props.cwd).then(() => reload());
571
+ }
572
+ }, t("forget"))
573
+ )
574
+ ))
482
575
  ))
483
- ))
576
+ )
484
577
  );
485
578
  }
486
579
  function currentSessionCwd(ctx) {
@@ -527,6 +620,11 @@ function apply(ctx) {
527
620
  root.inject(["betterSidebar"], (sidebarCtx) => {
528
621
  const service = sidebarCtx.betterSidebar;
529
622
  if (service?.registerTab === void 0) return;
623
+ if (typeof service.openFile === "function") {
624
+ openFileRef = (path, title) => {
625
+ service.openFile?.({}, path, title);
626
+ };
627
+ }
530
628
  const tabCtx = ctx;
531
629
  service.registerTab({
532
630
  id: "@max-null/dsh-memory:memory",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@max-null/dsh-memory",
3
- "version": "0.3.8",
3
+ "version": "0.5.0",
4
4
  "description": "Cross-session plaintext memory plugin for the DeepSeek Harness — deterministic BM25 recall, human-owned, no embeddings",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -61,22 +61,22 @@
61
61
  },
62
62
  "peerDependencies": {
63
63
  "@deepseek-ai/cordis": "^4.0.1",
64
- "@deepseek-ai/dsh-storage": ">=0.0.1-rc.1",
65
- "@deepseek-ai/dsh-storage-domain": ">=0.0.1-rc.1",
66
- "@deepseek-ai/dsh-storage-json": ">=0.0.1-rc.1",
67
- "@deepseek-ai/dsh-system-prompt": ">=0.0.1-rc.1",
68
- "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1",
69
- "@deepseek-ai/dsh-typert-protocol": ">=0.0.1-rc.5"
64
+ "@deepseek-ai/dsh-storage": "^0.1.1-rc.1",
65
+ "@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.1",
66
+ "@deepseek-ai/dsh-storage-json": "^0.1.1-rc.1",
67
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.1",
68
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.1",
69
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.1"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@deepseek-ai/cordis": "^4.0.1",
73
73
  "@deepseek-ai/cordis-plugin-loader": "^1.0.2",
74
- "@deepseek-ai/dsh-storage": ">=0.0.1-rc.1",
75
- "@deepseek-ai/dsh-storage-domain": ">=0.0.1-rc.1",
76
- "@deepseek-ai/dsh-storage-json": ">=0.0.1-rc.1",
77
- "@deepseek-ai/dsh-system-prompt": ">=0.0.1-rc.1",
78
- "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1",
79
- "@deepseek-ai/dsh-typert-protocol": ">=0.0.1-rc.5",
74
+ "@deepseek-ai/dsh-storage": "^0.1.1-rc.1",
75
+ "@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.1",
76
+ "@deepseek-ai/dsh-storage-json": "^0.1.1-rc.1",
77
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.1",
78
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.1",
79
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.1",
80
80
  "@types/node": "^26.2.0",
81
81
  "tsx": "^4.0.0",
82
82
  "typescript": "^5.5.0",