@max-null/dsh-memory 0.2.0 → 0.2.1

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
@@ -56,6 +56,12 @@ memory_forget → 随时删除
56
56
 
57
57
  明文还有一层**跟随仓库分享**的好处:`project` 命名空间的记忆落在项目文件夹内(`<cwd>/.dsh/storages/memory_project.json`),随 `git` 提交、分享给所有协作者;`global` 命名空间的记忆留在本地 `$DSH_HOME`。团队的共识("本项目统一用 Vue3 `<script setup>`")能沉淀进仓库,而不是散落在每个人的本地。FTS5 的 SQLite 二进制、向量的数字串,都无法这样"跟着仓库走"。
58
58
 
59
+ ## SSID 系列
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`。
62
+
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
+
59
65
  ## 开发
60
66
 
61
67
  ```bash
package/dist/engine.d.ts CHANGED
@@ -74,8 +74,17 @@ export declare class MemoryEngine extends Service {
74
74
  static inject: string[];
75
75
  private globalTable?;
76
76
  private projectTable?;
77
+ private facility?;
77
78
  constructor(ctx: import('@deepseek-ai/cordis').Context, config?: MemoryConfig);
78
79
  protected [Service.init](): Promise<void>;
80
+ /** 打开两个存储域(init 与 reload 共用)。 */
81
+ private openDomains;
82
+ /**
83
+ * 强制重载存储:关闭两域后重开,放弃内存缓存重读文件。
84
+ * 供外部编辑记忆文件后刷新(JsonStorageBackend 打开时加载一次,
85
+ * 无 watch——2026-08-19 用户实测面板不感知外部编辑)。
86
+ */
87
+ reload(): Promise<void>;
79
88
  /** Create one record in `suggested` status — never self-promoting. */
80
89
  remember(input: MemoryWrite): Promise<MemoryRecord>;
81
90
  list(filter?: MemoryFilter): MemoryRecord[];
package/dist/engine.js CHANGED
@@ -52,11 +52,17 @@ export class MemoryEngine extends Service {
52
52
  static inject = ['storage'];
53
53
  globalTable;
54
54
  projectTable;
55
+ facility;
55
56
  constructor(ctx, config = {}) {
56
57
  super(ctx, 'memory');
57
58
  this.config = config;
58
59
  }
59
60
  async [Service.init]() {
61
+ await this.openDomains();
62
+ this.ctx.effect(() => () => { void this.facility?.closeAll(); }, 'memory.domainsClose');
63
+ }
64
+ /** 打开两个存储域(init 与 reload 共用)。 */
65
+ async openDomains() {
60
66
  const globalBackend = new JsonStorageBackend(this.config.globalRoot ?? globalRoot());
61
67
  const projectBackend = new JsonStorageBackend(this.config.projectRoot ?? projectRoot());
62
68
  this.ctx.storage.backend.register('memory-global', globalBackend);
@@ -67,10 +73,19 @@ export class MemoryEngine extends Service {
67
73
  });
68
74
  const globalDomain = await facility.open(memorySpec('memory'));
69
75
  const projectDomain = await facility.open(memorySpec('memory_project'));
70
- this.ctx.effect(() => () => { void facility.closeAll(); }, 'memory.domainsClose');
76
+ this.facility = facility;
71
77
  this.globalTable = globalDomain.table('blocks');
72
78
  this.projectTable = projectDomain.table('blocks');
73
79
  }
80
+ /**
81
+ * 强制重载存储:关闭两域后重开,放弃内存缓存重读文件。
82
+ * 供外部编辑记忆文件后刷新(JsonStorageBackend 打开时加载一次,
83
+ * 无 watch——2026-08-19 用户实测面板不感知外部编辑)。
84
+ */
85
+ async reload() {
86
+ await this.facility?.closeAll();
87
+ await this.openDomains();
88
+ }
74
89
  /** Create one record in `suggested` status — never self-promoting. */
75
90
  async remember(input) {
76
91
  const namespace = input.namespace ?? 'global';
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { defineTool } from '@deepseek-ai/dsh-tools';
8
8
  import { MemoryEngine } from "./engine.js";
9
+ import { MemoryGateway } from "./remote.js";
9
10
  export { MemoryEngine } from "./engine.js";
10
11
  export { MemoryId } from "./engine.js";
11
12
  export { bm25Scores, tokenize } from "./bm25.js";
@@ -65,6 +66,7 @@ function present(title, kind, rawInput) {
65
66
  }
66
67
  export async function apply(ctx, config) {
67
68
  await ctx.plugin(MemoryEngine, config);
69
+ await ctx.plugin(MemoryGateway);
68
70
  const memory = ctx.get('memory');
69
71
  if (memory === undefined)
70
72
  throw new Error('memory engine failed to register');
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `MemoryGateway` — Typert Remote projection of the memory service, so a Web
3
+ * client can browse, search, confirm, and forget memories through `remote.memory`.
4
+ *
5
+ * Read-only except for the two human-owned mutations (`confirm` promotes a
6
+ * `suggested` record to `auto`; `forget` deletes one). It owns no storage or
7
+ * state — every call delegates to the process-local `ctx.memory` engine.
8
+ */
9
+ import type { Context } from '@deepseek-ai/cordis';
10
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
11
+ import type { MemoryFilter, MemoryHit, MemoryRecord } from './engine.ts';
12
+ /** Client-callable memory surface; registered as the `memory` Typert namespace. */
13
+ export declare class MemoryGateway extends TypertRemoteService {
14
+ static inject: string[];
15
+ constructor(ctx: Context);
16
+ /** List every stored memory, optionally filtered by namespace or status. */
17
+ list(filter?: MemoryFilter): MemoryRecord[];
18
+ /** Recall memories by keyword; deterministic literal matching. */
19
+ search(query: string, filter?: MemoryFilter): MemoryHit[];
20
+ /** Confirm a suggested memory so it becomes effective (`auto`). */
21
+ confirm(id: string): Promise<MemoryRecord>;
22
+ /** Delete one stored memory by id. */
23
+ forget(id: string): Promise<boolean>;
24
+ }
25
+ export default MemoryGateway;
package/dist/remote.js ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * `MemoryGateway` — Typert Remote projection of the memory service, so a Web
3
+ * client can browse, search, confirm, and forget memories through `remote.memory`.
4
+ *
5
+ * Read-only except for the two human-owned mutations (`confirm` promotes a
6
+ * `suggested` record to `auto`; `forget` deletes one). It owns no storage or
7
+ * state — every call delegates to the process-local `ctx.memory` engine.
8
+ */
9
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
10
+ var useValue = arguments.length > 2;
11
+ for (var i = 0; i < initializers.length; i++) {
12
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
13
+ }
14
+ return useValue ? value : void 0;
15
+ };
16
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
17
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
18
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
19
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
20
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
21
+ var _, done = false;
22
+ for (var i = decorators.length - 1; i >= 0; i--) {
23
+ var context = {};
24
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
25
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
26
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
27
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
28
+ if (kind === "accessor") {
29
+ if (result === void 0) continue;
30
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
31
+ if (_ = accept(result.get)) descriptor.get = _;
32
+ if (_ = accept(result.set)) descriptor.set = _;
33
+ if (_ = accept(result.init)) initializers.unshift(_);
34
+ }
35
+ else if (_ = accept(result)) {
36
+ if (kind === "field") initializers.unshift(_);
37
+ else descriptor[key] = _;
38
+ }
39
+ }
40
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
41
+ done = true;
42
+ };
43
+ import { TypertRemoteService, Remote } from '@deepseek-ai/dsh-typert-protocol';
44
+ import { MemoryId } from "./engine.js";
45
+ /** Client-callable memory surface; registered as the `memory` Typert namespace. */
46
+ let MemoryGateway = (() => {
47
+ let _classSuper = TypertRemoteService;
48
+ let _instanceExtraInitializers = [];
49
+ let _list_decorators;
50
+ let _search_decorators;
51
+ let _confirm_decorators;
52
+ let _forget_decorators;
53
+ return class MemoryGateway extends _classSuper {
54
+ static {
55
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
56
+ _list_decorators = [Remote('list')];
57
+ _search_decorators = [Remote('search')];
58
+ _confirm_decorators = [Remote('confirm')];
59
+ _forget_decorators = [Remote('forget')];
60
+ __esDecorate(this, null, _list_decorators, { kind: "method", name: "list", static: false, private: false, access: { has: obj => "list" in obj, get: obj => obj.list }, metadata: _metadata }, null, _instanceExtraInitializers);
61
+ __esDecorate(this, null, _search_decorators, { kind: "method", name: "search", static: false, private: false, access: { has: obj => "search" in obj, get: obj => obj.search }, metadata: _metadata }, null, _instanceExtraInitializers);
62
+ __esDecorate(this, null, _confirm_decorators, { kind: "method", name: "confirm", static: false, private: false, access: { has: obj => "confirm" in obj, get: obj => obj.confirm }, metadata: _metadata }, null, _instanceExtraInitializers);
63
+ __esDecorate(this, null, _forget_decorators, { kind: "method", name: "forget", static: false, private: false, access: { has: obj => "forget" in obj, get: obj => obj.forget }, metadata: _metadata }, null, _instanceExtraInitializers);
64
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
65
+ }
66
+ static inject = ['memory'];
67
+ constructor(ctx) {
68
+ // Service key 'memoryRemote' avoids colliding with MemoryEngine's 'memory';
69
+ // the wire namespace stays 'memory' so clients call `remote.memory.*`.
70
+ super(ctx, 'memoryRemote', { namespace: 'memory' });
71
+ __runInitializers(this, _instanceExtraInitializers);
72
+ }
73
+ /** List every stored memory, optionally filtered by namespace or status. */
74
+ list(filter) {
75
+ return this.ctx.memory.list(filter);
76
+ }
77
+ /** Recall memories by keyword; deterministic literal matching. */
78
+ search(query, filter) {
79
+ return this.ctx.memory.search(query, filter);
80
+ }
81
+ /** Confirm a suggested memory so it becomes effective (`auto`). */
82
+ confirm(id) {
83
+ return this.ctx.memory.setStatus(MemoryId(id), 'auto');
84
+ }
85
+ /** Delete one stored memory by id. */
86
+ forget(id) {
87
+ return this.ctx.memory.forget(MemoryId(id));
88
+ }
89
+ };
90
+ })();
91
+ export { MemoryGateway };
92
+ export default MemoryGateway;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@max-null/dsh-memory",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
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": {
@@ -53,7 +53,8 @@
53
53
  "@deepseek-ai/dsh-storage-domain": ">=0.0.1-rc.1",
54
54
  "@deepseek-ai/dsh-storage-json": ">=0.0.1-rc.1",
55
55
  "@deepseek-ai/dsh-system-prompt": ">=0.0.1-rc.1",
56
- "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1"
56
+ "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1",
57
+ "@deepseek-ai/dsh-typert-protocol": ">=0.0.1-rc.5"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@deepseek-ai/cordis": "^4.0.1",
@@ -63,6 +64,7 @@
63
64
  "@deepseek-ai/dsh-storage-json": ">=0.0.1-rc.1",
64
65
  "@deepseek-ai/dsh-system-prompt": ">=0.0.1-rc.1",
65
66
  "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1",
67
+ "@deepseek-ai/dsh-typert-protocol": ">=0.0.1-rc.5",
66
68
  "@types/node": "^26.2.0",
67
69
  "tsx": "^4.0.0",
68
70
  "typescript": "^5.5.0",