sage-mem 0.6.4 → 0.7.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * sage-mem — 手写 strict typert host manifest(对齐官方生成文件格式)。
2
+ * sage-mem — 手写 strict typert host manifest。
3
3
  * typert-loader 在插件挂载时读 package.json 的 exports["./typert"],
4
4
  * import 本文件并把 TYPERT 注册进 ctx.typert.local(strict 定义)。
5
5
  * schema 必须是 zod v4 实例(typert-loader 校验 "_zod" in schema)。
@@ -9,10 +9,15 @@ import { z } from 'zod'
9
9
  // 文件名:与 host 侧 safeName 同一套底线 —— 非空、无路径分隔符与 Windows 非法字符、
10
10
  // 以 .md 结尾、长度有界。(真正的目录逃逸防护仍在 host 侧 safeName。)
11
11
  const fileNameSchema = z.string().min(1).max(255).regex(/^[^\\/:*?"<>|\u0000-\u001f]+\.md$/)
12
- // 正文:512 KB 上限。理由是「记忆要塞进 system prompt」——现行 memory 目录最大一条 19 KB,
12
+ // 正文:512 KB 上限。理由是「记忆要塞进 system prompt」——单条正常量级在几十 KB,
13
13
  // 到半兆量级基本是写错了目标(贴了日志/代码进来)。与 lib/index.js 的 MAX_FILE_BYTES 一致。
14
14
  const fileContentSchema = z.string().max(512 * 1024)
15
15
 
16
+ // autodream 报告引用:比 fileNameSchema 宽——旧版报告列表里的条目带 `dream/` 前缀
17
+ // (新版 `autodream/` 不加前缀只给裸文件名)。这里放行斜杠,真正的目录逃逸防护
18
+ // 在 host 侧 AutodreamEngine.readReport 里(先剥已知前缀、再对 basename 走 safeName)。
19
+ const reportRefSchema = z.string().min(1).max(320)
20
+
16
21
  const starmapStarSchema = z.object({
17
22
  'file': z.string().readonly(),
18
23
  'kind': z.string().readonly(),
@@ -58,11 +63,11 @@ const deleteResultSchema = z.object({
58
63
  'error': z.string().readonly().optional(),
59
64
  }).readonly()
60
65
 
61
- // ── dream(夜间记忆整理)───────────────────────────────────────────────
66
+ // ── autodream(夜间记忆整理)───────────────────────────────────────────────
62
67
  // 配置的每一项都可写;lastResult 是一个「成功/失败两条分支共用」的结构,
63
68
  // 所以除了三个必有字段外全是 optional —— 用 strict 校验两种形态的并集,
64
69
  // 比给成功与失败各来一套 schema 少一半维护面。
65
- const dreamConfigSchema = z.object({
70
+ const autodreamConfigSchema = z.object({
66
71
  'enabled': z.boolean().readonly(),
67
72
  'trigger': z.string().readonly(),
68
73
  'apply': z.boolean().readonly(),
@@ -73,21 +78,25 @@ const dreamConfigSchema = z.object({
73
78
  'model': z.string().readonly(),
74
79
  'maxSteps': z.number().readonly(),
75
80
  'maxSnapshotKeep': z.number().readonly(),
81
+ 'rollbackScope': z.string().readonly(),
76
82
  }).readonly()
77
83
 
78
- const dreamPathsSchema = z.object({
84
+ const autodreamPathsSchema = z.object({
79
85
  'memoryDir': z.string().readonly(),
80
86
  'configPath': z.string().readonly(),
81
87
  'stateRoot': z.string().readonly(),
88
+ 'home': z.string().readonly(),
82
89
  }).readonly()
83
90
 
84
- const dreamRouteSchema = z.object({
91
+ const autodreamRouteSchema = z.object({
85
92
  'provider': z.string().readonly(),
86
93
  'model': z.string().readonly(),
87
94
  'fromDefault': z.boolean().readonly(),
95
+ 'source': z.string().readonly(),
96
+ 'error': z.string().readonly().nullable(),
88
97
  }).readonly()
89
98
 
90
- const dreamLastResultSchema = z.object({
99
+ const autodreamLastResultSchema = z.object({
91
100
  'at': z.number().readonly(),
92
101
  'atHuman': z.string().readonly(),
93
102
  'ok': z.boolean().readonly(),
@@ -98,50 +107,58 @@ const dreamLastResultSchema = z.object({
98
107
  'problemsAfter': z.number().readonly().optional(),
99
108
  'tokensIn': z.number().readonly().optional(),
100
109
  'tokensOut': z.number().readonly().optional(),
110
+ 'runId': z.string().readonly().optional(),
111
+ 'changeCount': z.number().readonly().optional(),
112
+ 'preflight': z.boolean().readonly().optional(),
113
+ 'snapshotId': z.string().readonly().nullable().optional(),
101
114
  'report': z.string().readonly().optional(),
102
115
  }).readonly()
103
116
 
104
- const dreamConfigResultSchema = z.object({
105
- 'config': dreamConfigSchema,
106
- 'route': dreamRouteSchema.nullable(),
117
+ const autodreamConfigResultSchema = z.object({
118
+ 'config': autodreamConfigSchema,
119
+ 'route': autodreamRouteSchema.nullable(),
107
120
  'lastRunAt': z.number().readonly(),
108
- 'lastResult': dreamLastResultSchema.nullable(),
109
- 'paths': dreamPathsSchema,
110
- 'defaults': dreamConfigSchema,
121
+ 'lastResult': autodreamLastResultSchema.nullable(),
122
+ 'paths': autodreamPathsSchema,
123
+ 'defaults': autodreamConfigSchema,
111
124
  }).readonly()
112
125
 
113
- const dreamStepSchema = z.object({
126
+ const autodreamStepSchema = z.object({
114
127
  'step': z.number().readonly(),
115
128
  'tools': z.array(z.string()).readonly(),
116
129
  'chars': z.number().readonly(),
117
130
  'at': z.number().readonly(),
118
131
  }).readonly()
119
132
 
120
- const dreamStatusSchema = z.object({
133
+ const autodreamStatusSchema = z.object({
121
134
  'running': z.boolean().readonly(),
122
135
  'phase': z.string().readonly(),
123
136
  'startedAt': z.number().readonly(),
124
- 'steps': z.array(dreamStepSchema).readonly(),
125
- 'config': dreamConfigSchema,
126
- 'route': dreamRouteSchema.nullable(),
137
+ 'runId': z.string().readonly(),
138
+ 'steps': z.array(autodreamStepSchema).readonly(),
139
+ 'config': autodreamConfigSchema,
140
+ 'route': autodreamRouteSchema.nullable(),
127
141
  'lastRunAt': z.number().readonly(),
128
142
  'hoursSince': z.number().readonly().nullable(),
129
- 'lastResult': dreamLastResultSchema.nullable(),
143
+ 'lastResult': autodreamLastResultSchema.nullable(),
130
144
  'retryAfter': z.number().readonly(),
131
145
  'gate': z.object({ 'minHours': z.number().readonly(), 'minSessions': z.number().readonly() }).readonly().nullable(),
132
- 'paths': dreamPathsSchema,
146
+ 'paths': autodreamPathsSchema,
133
147
  }).readonly()
134
148
 
135
- const dreamRunResultSchema = z.object({
149
+ const autodreamRunResultSchema = z.object({
136
150
  'ok': z.boolean().readonly(),
137
151
  'error': z.string().readonly().optional(),
138
152
  'report': z.string().readonly().optional(),
139
153
  'touched': z.array(z.string()).readonly().optional(),
154
+ 'runId': z.string().readonly().optional(),
155
+ 'changeCount': z.number().readonly().optional(),
156
+ 'snapshotId': z.string().readonly().nullable().optional(),
140
157
  }).readonly()
141
158
 
142
159
  // setConfig 的补丁:全部 optional —— 设置面板每次只改动一项,传整个对象反而
143
160
  // 容易把没碰过的字段用旧值覆盖回去。
144
- const dreamPatchSchema = z.object({
161
+ const autodreamPatchSchema = z.object({
145
162
  'enabled': z.boolean().optional(),
146
163
  'trigger': z.string().optional(),
147
164
  'apply': z.boolean().optional(),
@@ -152,6 +169,7 @@ const dreamPatchSchema = z.object({
152
169
  'model': z.string().optional(),
153
170
  'maxSteps': z.number().optional(),
154
171
  'maxSnapshotKeep': z.number().optional(),
172
+ 'rollbackScope': z.string().optional(),
155
173
  }).readonly()
156
174
 
157
175
  const reportListSchema = z.array(z.object({
@@ -159,6 +177,7 @@ const reportListSchema = z.array(z.object({
159
177
  'bytes': z.number().readonly(),
160
178
  'at': z.number().readonly(),
161
179
  'atHuman': z.string().readonly(),
180
+ 'legacy': z.boolean().readonly(),
162
181
  }).readonly()).readonly()
163
182
 
164
183
  const snapshotListSchema = z.array(z.object({
@@ -167,8 +186,71 @@ const snapshotListSchema = z.array(z.object({
167
186
  'atHuman': z.string().readonly(),
168
187
  'files': z.number().readonly(),
169
188
  'path': z.string().readonly(),
189
+ 'runId': z.string().readonly().nullable(),
190
+ 'kind': z.string().readonly(),
191
+ 'legacy': z.boolean().readonly(),
170
192
  }).readonly()).readonly()
171
193
 
194
+ // ── autodream 回滚点 / 整理声明 / 模型目录(2026-10-01 新增)──
195
+ // 「运行」是这四样东西的共同线索:runId 同时是快照目录名、运行记录目录名与报告文件名,
196
+ // 所以 listRuns 的一条记录能把「改了哪些文件、为什么、能不能退」一次串起来。
197
+ const runListSchema = z.array(z.object({
198
+ 'runId': z.string().readonly(),
199
+ 'at': z.number().readonly(),
200
+ 'atHuman': z.string().readonly(),
201
+ 'mode': z.string().readonly(),
202
+ 'reason': z.string().readonly(),
203
+ 'changeCount': z.number().readonly(),
204
+ 'report': z.string().readonly().nullable(),
205
+ 'snapshotId': z.string().readonly().nullable(),
206
+ 'snapshotAvailable': z.boolean().readonly(),
207
+ 'rolledBackAt': z.number().readonly(),
208
+ 'rolledBackAtHuman': z.string().readonly(),
209
+ }).readonly()).readonly()
210
+
211
+ // manifest 是机读记录,字段面宽且在演进;这里用宽松对象接住,
212
+ // 前端的「整理声明」区只读 markdown,manifest 留给后续工具消费。
213
+ const declarationSchema = z.object({
214
+ 'runId': z.string().readonly(),
215
+ 'markdown': z.string().readonly(),
216
+ 'manifest': z.unknown(),
217
+ }).readonly()
218
+
219
+ const rollbackResultSchema = z.object({
220
+ 'ok': z.boolean().readonly(),
221
+ 'error': z.string().readonly().optional(),
222
+ 'restored': z.number().readonly().optional(),
223
+ 'parked': z.number().readonly().optional(),
224
+ 'skipped': z.number().readonly().optional(),
225
+ 'protection': z.string().readonly().optional(),
226
+ 'report': z.string().readonly().optional(),
227
+ }).readonly()
228
+
229
+ const modelListSchema = z.object({
230
+ 'routes': z.array(z.object({
231
+ 'provider': z.string().readonly(),
232
+ 'model': z.string().readonly(),
233
+ 'label': z.string().readonly(),
234
+ 'isDefault': z.boolean().readonly(),
235
+ }).readonly()).readonly(),
236
+ 'defaultRoute': z.object({
237
+ 'provider': z.string().readonly(),
238
+ 'model': z.string().readonly(),
239
+ }).readonly().nullable(),
240
+ 'catalogAvailable': z.boolean().readonly(),
241
+ 'note': z.string().readonly(),
242
+ }).readonly()
243
+
244
+ // 四个新方法的入参形状不同,但都是「一个对象参数」;合并成一个全 optional 的 schema,
245
+ // 免得为每个方法各写一份。注意 zod 默认会**丢掉未声明的键**,所以用到的字段必须在这里列全。
246
+ const autodreamOptsSchema = z.object({
247
+ 'reason': z.string().optional(),
248
+ 'limit': z.number().optional(),
249
+ 'runId': z.string().optional(),
250
+ 'snapshotId': z.string().optional(),
251
+ 'scope': z.string().optional(),
252
+ }).readonly()
253
+
172
254
  export const TYPERT = {
173
255
  package: 'sage-mem',
174
256
  face: 'host',
@@ -243,85 +325,131 @@ export const TYPERT = {
243
325
  result: { mode: 'strict', typeSymbol: 'sage-mem/types#StarmapRead', schema: starmapReadSchema, create: () => starmapReadSchema },
244
326
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
245
327
  },
246
- // ── dream 的七个方法 ──
328
+ // ── autodream 的七个方法 ──
247
329
  // 全部挂在 package `sage-mem` 下(和 memory 同一份 manifest),
248
- // 所以前端直接 ctx.get('remote.dream') 就能用,不需要像 starmap 那样
330
+ // 所以前端直接 ctx.get('remote.autodream') 就能用,不需要像 starmap 那样
249
331
  // 在 client 侧再 $mount 一次 —— 那个 mount 是因为 starmap 当年是独立包
250
332
  // (package: 'sage-starmap'),合并进 sage-mem 后一直没改回来。
251
333
  {
252
- id: 'sage-mem#dream/getConfig',
253
- service: 'dream',
254
- namespace: 'dream',
334
+ id: 'sage-mem#autodream/getConfig',
335
+ service: 'autodream',
336
+ namespace: 'autodream',
255
337
  method: 'getConfig',
256
338
  invocation: { kind: 'direct' },
257
339
  parameters: [],
258
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamConfigResult', schema: dreamConfigResultSchema, create: () => dreamConfigResultSchema },
340
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamConfigResult', schema: autodreamConfigResultSchema, create: () => autodreamConfigResultSchema },
259
341
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
260
342
  },
261
343
  {
262
- id: 'sage-mem#dream/setConfig',
263
- service: 'dream',
264
- namespace: 'dream',
344
+ id: 'sage-mem#autodream/setConfig',
345
+ service: 'autodream',
346
+ namespace: 'autodream',
265
347
  method: 'setConfig',
266
348
  invocation: { kind: 'direct' },
267
349
  parameters: [
268
- { name: 'patch', wire: 'patch', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamPatch', schema: dreamPatchSchema, create: () => dreamPatchSchema } },
350
+ { name: 'patch', wire: 'patch', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamPatch', schema: autodreamPatchSchema, create: () => autodreamPatchSchema } },
269
351
  ],
270
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamConfigResult', schema: dreamConfigResultSchema, create: () => dreamConfigResultSchema },
352
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamConfigResult', schema: autodreamConfigResultSchema, create: () => autodreamConfigResultSchema },
271
353
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
272
354
  },
273
355
  {
274
- id: 'sage-mem#dream/status',
275
- service: 'dream',
276
- namespace: 'dream',
356
+ id: 'sage-mem#autodream/status',
357
+ service: 'autodream',
358
+ namespace: 'autodream',
277
359
  method: 'status',
278
360
  invocation: { kind: 'direct' },
279
361
  parameters: [],
280
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamStatus', schema: dreamStatusSchema, create: () => dreamStatusSchema },
362
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamStatus', schema: autodreamStatusSchema, create: () => autodreamStatusSchema },
281
363
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
282
364
  },
283
365
  {
284
- id: 'sage-mem#dream/runNow',
285
- service: 'dream',
286
- namespace: 'dream',
366
+ id: 'sage-mem#autodream/runNow',
367
+ service: 'autodream',
368
+ namespace: 'autodream',
287
369
  method: 'runNow',
288
370
  invocation: { kind: 'direct' },
289
371
  parameters: [
290
- { name: 'force', wire: 'force', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#Boolean', schema: z.boolean(), create: () => z.boolean() } },
372
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
291
373
  ],
292
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamRunResult', schema: dreamRunResultSchema, create: () => dreamRunResultSchema },
374
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRunResult', schema: autodreamRunResultSchema, create: () => autodreamRunResultSchema },
293
375
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
294
376
  },
295
377
  {
296
- id: 'sage-mem#dream/listReports',
297
- service: 'dream',
298
- namespace: 'dream',
378
+ id: 'sage-mem#autodream/listReports',
379
+ service: 'autodream',
380
+ namespace: 'autodream',
299
381
  method: 'listReports',
300
382
  invocation: { kind: 'direct' },
301
383
  parameters: [],
302
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamReportList', schema: reportListSchema, create: () => reportListSchema },
384
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamReportList', schema: reportListSchema, create: () => reportListSchema },
303
385
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
304
386
  },
305
387
  {
306
- id: 'sage-mem#dream/readReport',
307
- service: 'dream',
308
- namespace: 'dream',
388
+ id: 'sage-mem#autodream/readReport',
389
+ service: 'autodream',
390
+ namespace: 'autodream',
309
391
  method: 'readReport',
310
392
  invocation: { kind: 'direct' },
311
393
  parameters: [
312
- { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
394
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamReportRef', schema: reportRefSchema, create: () => reportRefSchema } },
313
395
  ],
314
396
  result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: readResultSchema, create: () => readResultSchema },
315
397
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
316
398
  },
317
399
  {
318
- id: 'sage-mem#dream/listSnapshots',
319
- service: 'dream',
320
- namespace: 'dream',
400
+ id: 'sage-mem#autodream/listSnapshots',
401
+ service: 'autodream',
402
+ namespace: 'autodream',
321
403
  method: 'listSnapshots',
322
404
  invocation: { kind: 'direct' },
323
405
  parameters: [],
324
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DreamSnapshotList', schema: snapshotListSchema, create: () => snapshotListSchema },
406
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamSnapshotList', schema: snapshotListSchema, create: () => snapshotListSchema },
407
+ sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
408
+ },
409
+ {
410
+ id: 'sage-mem#autodream/listRuns',
411
+ service: 'autodream',
412
+ namespace: 'autodream',
413
+ method: 'listRuns',
414
+ invocation: { kind: 'direct' },
415
+ parameters: [
416
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
417
+ ],
418
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRunList', schema: runListSchema, create: () => runListSchema },
419
+ sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
420
+ },
421
+ {
422
+ id: 'sage-mem#autodream/readDeclaration',
423
+ service: 'autodream',
424
+ namespace: 'autodream',
425
+ method: 'readDeclaration',
426
+ invocation: { kind: 'direct' },
427
+ parameters: [
428
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
429
+ ],
430
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamDeclaration', schema: declarationSchema, create: () => declarationSchema },
431
+ sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
432
+ },
433
+ {
434
+ id: 'sage-mem#autodream/rollback',
435
+ service: 'autodream',
436
+ namespace: 'autodream',
437
+ method: 'rollback',
438
+ invocation: { kind: 'direct' },
439
+ parameters: [
440
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
441
+ ],
442
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRollbackResult', schema: rollbackResultSchema, create: () => rollbackResultSchema },
443
+ sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
444
+ },
445
+ {
446
+ id: 'sage-mem#autodream/listModels',
447
+ service: 'autodream',
448
+ namespace: 'autodream',
449
+ method: 'listModels',
450
+ invocation: { kind: 'direct' },
451
+ parameters: [],
452
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamModelList', schema: modelListSchema, create: () => modelListSchema },
325
453
  sourceLocation: { "file": "workspace/sage-mem/lib/index.js", "line": 1, "column": 1 },
326
454
  },
327
455
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sage-mem",
3
- "description": "File-based memory plugin for DeepSeek Harness (DSH) — cross-session memory in transparent markdown files, with a memory star-map view, type/tag filtering, and an optional dream pass that consolidates memories on demand or on a schedule",
4
- "version": "0.6.4",
3
+ "description": "File-based memory plugin for DeepSeek Harness (DSH) — cross-session memory in plain markdown files, with a memory star-map view, type/tag filtering, retrieval aliases, and an optional autodream pass that consolidates memories on demand or on a schedule — with per-run rollback points, a per-file change declaration (what changed and why), and a separately selectable model for the consolidation pass",
4
+ "version": "0.7.0",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -86,4 +86,4 @@
86
86
  "agent",
87
87
  "claude-code"
88
88
  ]
89
- }
89
+ }