@moxxy/plugin-memory 0.37.0 → 0.37.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.
@@ -1 +1 @@
1
- {"version":3,"file":"user-model.d.ts","sourceRoot":"","sources":["../src/user-model.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;;;GAaG;AAGH,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAC9C,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,mDAAmD;AACnD,eAAO,MAAM,cAAc,8DAA+D,CAAC;AAE3F,gEAAgE;AAChE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAK9D,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,SAAS,CAAC;AACvF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAkBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAsBtD;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAQ3D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAE,MAA2B,GAAG,MAAM,CAkB9F;AAMD,oFAAoF;AACpF,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,MAAM,CAAsD;IAEpE,uEAAuE;gBAC3D,GAAG,CAAC,EAAE,MAAM;IAIxB;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAiBvC,sEAAsE;IAChE,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASvC;;;;;OAKG;IACG,MAAM,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAkB1G,uDAAuD;YACzC,QAAQ;IAKtB;;;;;;OAMG;IACG,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;CAgBxE;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CA2B5D"}
1
+ {"version":3,"file":"user-model.d.ts","sourceRoot":"","sources":["../src/user-model.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;;;GAaG;AAGH,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAC9C,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,mDAAmD;AACnD,eAAO,MAAM,cAAc,8DAA+D,CAAC;AAE3F,gEAAgE;AAChE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAK9D,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,SAAS,CAAC;AACvF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAgBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAoBtD;AAUD,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAQ3D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAE,MAA2B,GAAG,MAAM,CAkB9F;AAMD,oFAAoF;AACpF,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,MAAM,CAAsD;IAEpE,uEAAuE;gBAC3D,GAAG,CAAC,EAAE,MAAM;IAIxB;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAsBvC,sEAAsE;IAChE,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASvC;;;;;OAKG;IACG,MAAM,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAkB1G,uDAAuD;YACzC,QAAQ;IAKtB;;;;;;OAMG;IACG,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;CAgBxE;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CA2B5D"}
@@ -1,6 +1,6 @@
1
1
  import { promises as fs } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { z, assertDefined, defineTool, createMutex, } from '@moxxy/sdk';
3
+ import { z, defineTool, createMutex, } from '@moxxy/sdk';
4
4
  import { moxxyPath, writeFileAtomic } from '@moxxy/sdk/server';
5
5
  /**
6
6
  * The persistent USER MODEL — `~/.moxxy/memory/user-model.md`.
@@ -46,7 +46,6 @@ function templateModel() {
46
46
  };
47
47
  }
48
48
  // ── parse / serialize (round-trips unknown sections) ─────────────────────────
49
- const HEADING_RE = /^##\s+(.+?)\s*$/;
50
49
  /**
51
50
  * Parse the user-model Markdown into a preamble + ordered H2 sections. Any
52
51
  * section title is preserved (not just the fixed four), so a user's hand-added
@@ -58,14 +57,12 @@ export function parseUserModel(text) {
58
57
  let current = null;
59
58
  let seenHeading = false;
60
59
  for (const line of text.split('\n')) {
61
- const m = HEADING_RE.exec(line);
62
- if (m) {
60
+ const title = parseHeading(line);
61
+ if (title !== null) {
63
62
  seenHeading = true;
64
63
  if (current)
65
64
  sections.push({ title: current.title, content: current.body.join('\n').trim() });
66
- const title = m[1];
67
- assertDefined(title, 'HEADING_RE capture group 1 is present on any match');
68
- current = { title: title.trim(), body: [] };
65
+ current = { title, body: [] };
69
66
  }
70
67
  else if (!seenHeading) {
71
68
  preambleLines.push(line);
@@ -78,6 +75,15 @@ export function parseUserModel(text) {
78
75
  sections.push({ title: current.title, content: current.body.join('\n').trim() });
79
76
  return { preamble: preambleLines.join('\n').trim(), sections };
80
77
  }
78
+ function parseHeading(line) {
79
+ if (!line.startsWith('##') || !/\s/u.test(line[2] ?? ''))
80
+ return null;
81
+ let titleStart = 2;
82
+ while (titleStart < line.length && /\s/u.test(line[titleStart] ?? ''))
83
+ titleStart += 1;
84
+ const title = line.slice(titleStart).trim();
85
+ return title.length > 0 ? title : null;
86
+ }
81
87
  /** Serialize back to Markdown, preserving the preamble and every section. */
82
88
  export function serializeUserModel(model) {
83
89
  const parts = [];
@@ -144,9 +150,9 @@ export class UserModelStore {
144
150
  * provider request.
145
151
  */
146
152
  async load() {
147
- let mtimeMs;
153
+ let handle;
148
154
  try {
149
- mtimeMs = (await fs.stat(this.path)).mtimeMs;
155
+ handle = await fs.open(this.path, 'r');
150
156
  }
151
157
  catch (err) {
152
158
  if (isEnoent(err)) {
@@ -155,11 +161,17 @@ export class UserModelStore {
155
161
  }
156
162
  throw err;
157
163
  }
158
- if (this.cached && this.cached.mtimeMs === mtimeMs)
159
- return this.cached.model;
160
- const model = parseUserModel(await fs.readFile(this.path, 'utf8'));
161
- this.cached = { mtimeMs, model };
162
- return model;
164
+ try {
165
+ const mtimeMs = (await handle.stat()).mtimeMs;
166
+ if (this.cached && this.cached.mtimeMs === mtimeMs)
167
+ return this.cached.model;
168
+ const model = parseUserModel(await handle.readFile({ encoding: 'utf8' }));
169
+ this.cached = { mtimeMs, model };
170
+ return model;
171
+ }
172
+ finally {
173
+ await handle.close();
174
+ }
163
175
  }
164
176
  /** Raw file text (or `null` when absent) — used by the CLI viewer. */
165
177
  async readRaw() {
@@ -1 +1 @@
1
- {"version":3,"file":"user-model.js","sourceRoot":"","sources":["../src/user-model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user-model.js","sourceRoot":"","sources":["../src/user-model.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/plugin-memory",
3
- "version": "0.37.0",
3
+ "version": "0.37.1",
4
4
  "description": "Journal-based long-term memory for moxxy. Markdown files at ~/.moxxy/memory/ with type/description frontmatter + an index. Plus STM selectors over the event log.",
5
5
  "keywords": [
6
6
  "moxxy",
@@ -43,15 +43,15 @@
43
43
  }
44
44
  },
45
45
  "dependencies": {
46
- "zod": "^3.24.0",
47
- "@moxxy/sdk": "0.37.0"
46
+ "zod": "^3.25.76",
47
+ "@moxxy/sdk": "0.37.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "^22.10.0",
51
51
  "typescript": "^5.7.3",
52
- "vitest": "^2.1.8",
53
- "@moxxy/tsconfig": "0.0.0",
54
- "@moxxy/vitest-preset": "0.0.0"
52
+ "vitest": "^3.2.6",
53
+ "@moxxy/vitest-preset": "0.0.0",
54
+ "@moxxy/tsconfig": "0.0.0"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "tsc -p tsconfig.json",
@@ -19,6 +19,18 @@ let tmp: string;
19
19
  const newStore = () => new UserModelStore(tmp);
20
20
  const modelPath = () => path.join(tmp, 'user-model.md');
21
21
 
22
+ async function fileHandlePrototype(): Promise<
23
+ Pick<Awaited<ReturnType<typeof fs.open>>, 'readFile'>
24
+ > {
25
+ const handle = await fs.open(modelPath(), 'r');
26
+ const prototype = Object.getPrototypeOf(handle) as Pick<
27
+ Awaited<ReturnType<typeof fs.open>>,
28
+ 'readFile'
29
+ >;
30
+ await handle.close();
31
+ return prototype;
32
+ }
33
+
22
34
  beforeEach(async () => {
23
35
  tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'mox-um-'));
24
36
  });
@@ -123,7 +135,7 @@ describe('UserModelStore.load (mtime cache)', () => {
123
135
  it('reads the file once, then serves an unchanged file from cache (no re-read)', async () => {
124
136
  const store = newStore();
125
137
  await store.update('identity', 'first', 'replace');
126
- const spy = vi.spyOn(fs, 'readFile');
138
+ const spy = vi.spyOn(await fileHandlePrototype(), 'readFile');
127
139
  await store.load();
128
140
  await store.load();
129
141
  await store.load();
@@ -264,7 +276,7 @@ describe('UserModelStore.injectInto', () => {
264
276
  it('returns the request unchanged when parsing/reading throws', async () => {
265
277
  const store = newStore();
266
278
  await store.update('identity', 'A', 'replace');
267
- vi.spyOn(fs, 'readFile').mockRejectedValueOnce(new Error('disk on fire'));
279
+ vi.spyOn(await fileHandlePrototype(), 'readFile').mockRejectedValueOnce(new Error('disk on fire'));
268
280
  expect(await store.injectInto(req('BASE'))).toBeUndefined();
269
281
  });
270
282
  });
package/src/user-model.ts CHANGED
@@ -2,7 +2,6 @@ import { promises as fs } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import {
4
4
  z,
5
- assertDefined,
6
5
  defineTool,
7
6
  createMutex,
8
7
  type Mutex,
@@ -77,8 +76,6 @@ function templateModel(): UserModel {
77
76
 
78
77
  // ── parse / serialize (round-trips unknown sections) ─────────────────────────
79
78
 
80
- const HEADING_RE = /^##\s+(.+?)\s*$/;
81
-
82
79
  /**
83
80
  * Parse the user-model Markdown into a preamble + ordered H2 sections. Any
84
81
  * section title is preserved (not just the fixed four), so a user's hand-added
@@ -91,13 +88,11 @@ export function parseUserModel(text: string): UserModel {
91
88
  let seenHeading = false;
92
89
 
93
90
  for (const line of text.split('\n')) {
94
- const m = HEADING_RE.exec(line);
95
- if (m) {
91
+ const title = parseHeading(line);
92
+ if (title !== null) {
96
93
  seenHeading = true;
97
94
  if (current) sections.push({ title: current.title, content: current.body.join('\n').trim() });
98
- const title = m[1];
99
- assertDefined(title, 'HEADING_RE capture group 1 is present on any match');
100
- current = { title: title.trim(), body: [] };
95
+ current = { title, body: [] };
101
96
  } else if (!seenHeading) {
102
97
  preambleLines.push(line);
103
98
  } else if (current) {
@@ -108,6 +103,14 @@ export function parseUserModel(text: string): UserModel {
108
103
  return { preamble: preambleLines.join('\n').trim(), sections };
109
104
  }
110
105
 
106
+ function parseHeading(line: string): string | null {
107
+ if (!line.startsWith('##') || !/\s/u.test(line[2] ?? '')) return null;
108
+ let titleStart = 2;
109
+ while (titleStart < line.length && /\s/u.test(line[titleStart] ?? '')) titleStart += 1;
110
+ const title = line.slice(titleStart).trim();
111
+ return title.length > 0 ? title : null;
112
+ }
113
+
111
114
  /** Serialize back to Markdown, preserving the preamble and every section. */
112
115
  export function serializeUserModel(model: UserModel): string {
113
116
  const parts: string[] = [];
@@ -177,9 +180,9 @@ export class UserModelStore {
177
180
  * provider request.
178
181
  */
179
182
  async load(): Promise<UserModel | null> {
180
- let mtimeMs: number;
183
+ let handle: import('node:fs/promises').FileHandle;
181
184
  try {
182
- mtimeMs = (await fs.stat(this.path)).mtimeMs;
185
+ handle = await fs.open(this.path, 'r');
183
186
  } catch (err) {
184
187
  if (isEnoent(err)) {
185
188
  this.cached = null;
@@ -187,10 +190,15 @@ export class UserModelStore {
187
190
  }
188
191
  throw err;
189
192
  }
190
- if (this.cached && this.cached.mtimeMs === mtimeMs) return this.cached.model;
191
- const model = parseUserModel(await fs.readFile(this.path, 'utf8'));
192
- this.cached = { mtimeMs, model };
193
- return model;
193
+ try {
194
+ const mtimeMs = (await handle.stat()).mtimeMs;
195
+ if (this.cached && this.cached.mtimeMs === mtimeMs) return this.cached.model;
196
+ const model = parseUserModel(await handle.readFile({ encoding: 'utf8' }));
197
+ this.cached = { mtimeMs, model };
198
+ return model;
199
+ } finally {
200
+ await handle.close();
201
+ }
194
202
  }
195
203
 
196
204
  /** Raw file text (or `null` when absent) — used by the CLI viewer. */