sage-mem 0.7.2 → 0.9.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,461 +1,747 @@
1
- /**
2
- * sage-mem — 手写 strict typert host manifest。
3
- * typert-loader 在插件挂载时读 package.json 的 exports["./typert"],
4
- * import 本文件并把 TYPERT 注册进 ctx.typert.local(strict 定义)。
5
- * schema 必须是 zod v4 实例(typert-loader 校验 "_zod" in schema)。
6
- */
7
- import { z } from 'zod'
8
-
9
- // 文件名:与 host 侧 safeName 同一套底线 —— 非空、无路径分隔符与 Windows 非法字符、
10
- // 以 .md 结尾、长度有界。(真正的目录逃逸防护仍在 host 侧 safeName。)
11
- const fileNameSchema = z.string().min(1).max(255).regex(/^[^\\/:*?"<>|\u0000-\u001f]+\.md$/)
12
- // 正文:512 KB 上限。理由是「记忆要塞进 system prompt」——单条正常量级在几十 KB,
13
- // 到半兆量级基本是写错了目标(贴了日志/代码进来)。与 lib/index.js 的 MAX_FILE_BYTES 一致。
14
- const fileContentSchema = z.string().max(512 * 1024)
15
-
16
- // autodream 报告引用:比 fileNameSchema 宽——旧版报告列表里的条目带 `dream/` 前缀
17
- // (新版 `autodream/` 不加前缀只给裸文件名)。这里放行斜杠,真正的目录逃逸防护
18
- // 在 host 侧 AutodreamEngine.readReport 里(先剥已知前缀、再对 basename 走 safeName)。
19
- const reportRefSchema = z.string().min(1).max(320)
20
-
21
- const starmapStarSchema = z.object({
22
- 'file': z.string().readonly(),
23
- 'kind': z.string().readonly(),
24
- 'title': z.string().readonly(),
25
- 'desc': z.string().readonly(),
26
- 'bytes': z.number().readonly(),
27
- 'mtimeMs': z.number().readonly(),
28
- }).readonly()
29
- const starmapListSchema = z.object({
30
- 'count': z.number().readonly(),
31
- 'stars': z.array(starmapStarSchema).readonly(),
32
- }).readonly()
33
- const starmapReadSchema = z.object({
34
- 'name': z.string().readonly(),
35
- 'content': z.string().readonly(),
36
- }).readonly()
37
-
38
- const fileSchema = z.object({
39
- 'file': z.string().readonly(),
40
- 'type': z.string().readonly(),
41
- 'description': z.string().readonly(),
42
- 'size': z.number().readonly(),
43
- // 自定义标签:来自 frontmatter 的 tags(flow / block / 逗号三种写法都收)。
44
- // strict 模式下 host 多返回的字段会被剥掉,所以「列表页要能按标签筛」这件事
45
- // 必须在这里显式声明,否则前端永远拿到 undefined。
46
- 'tags': z.array(z.string()).readonly(),
47
- }).readonly()
48
-
49
- const listResultSchema = z.array(fileSchema)
50
- const readResultSchema = z.object({
51
- 'name': z.string().readonly(),
52
- 'content': z.string().readonly(),
53
- }).readonly()
54
- // 写/删失败不再抛异常,走 { ok: false, error } 分支:error 必须声明,否则 strict
55
- // 校验会把它当未知字段剥掉,设置页只能看到一个没有原因的 ok:false。
56
- const writeResultSchema = z.object({
57
- 'ok': z.boolean().readonly(),
58
- 'file': z.string().readonly(),
59
- 'error': z.string().readonly().optional(),
60
- }).readonly()
61
- const deleteResultSchema = z.object({
62
- 'ok': z.boolean().readonly(),
63
- 'error': z.string().readonly().optional(),
64
- }).readonly()
65
-
66
- // ── autodream(夜间记忆整理)───────────────────────────────────────────────
67
- // 配置的每一项都可写;lastResult 是一个「成功/失败两条分支共用」的结构,
68
- // 所以除了三个必有字段外全是 optional —— 用 strict 校验两种形态的并集,
69
- // 比给成功与失败各来一套 schema 少一半维护面。
70
- const autodreamConfigSchema = z.object({
71
- 'enabled': z.boolean().readonly(),
72
- 'trigger': z.string().readonly(),
73
- 'apply': z.boolean().readonly(),
74
- 'source': z.string().readonly(),
75
- 'minHours': z.number().readonly(),
76
- 'minSessions': z.number().readonly(),
77
- 'provider': z.string().readonly(),
78
- 'model': z.string().readonly(),
79
- 'maxSteps': z.number().readonly(),
80
- 'maxSnapshotKeep': z.number().readonly(),
81
- 'rollbackScope': z.string().readonly(),
82
- }).readonly()
83
-
84
- const autodreamPathsSchema = z.object({
85
- 'memoryDir': z.string().readonly(),
86
- 'configPath': z.string().readonly(),
87
- 'stateRoot': z.string().readonly(),
88
- 'home': z.string().readonly(),
89
- }).readonly()
90
-
91
- const autodreamRouteSchema = z.object({
92
- 'provider': z.string().readonly(),
93
- 'model': z.string().readonly(),
94
- 'fromDefault': z.boolean().readonly(),
95
- 'source': z.string().readonly(),
96
- 'error': z.string().readonly().nullable(),
97
- }).readonly()
98
-
99
- const autodreamLastResultSchema = z.object({
100
- 'at': z.number().readonly(),
101
- 'atHuman': z.string().readonly(),
102
- 'ok': z.boolean().readonly(),
103
- 'apply': z.boolean().readonly().optional(),
104
- 'error': z.string().readonly().optional(),
105
- 'touched': z.array(z.string()).readonly().optional(),
106
- 'problemsBefore': z.number().readonly().optional(),
107
- 'problemsAfter': z.number().readonly().optional(),
108
- 'tokensIn': z.number().readonly().optional(),
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(),
114
- 'report': z.string().readonly().optional(),
115
- }).readonly()
116
-
117
- const autodreamConfigResultSchema = z.object({
118
- 'config': autodreamConfigSchema,
119
- 'route': autodreamRouteSchema.nullable(),
120
- 'lastRunAt': z.number().readonly(),
121
- 'lastResult': autodreamLastResultSchema.nullable(),
122
- 'paths': autodreamPathsSchema,
123
- 'defaults': autodreamConfigSchema,
124
- }).readonly()
125
-
126
- const autodreamStepSchema = z.object({
127
- 'step': z.number().readonly(),
128
- 'tools': z.array(z.string()).readonly(),
129
- 'chars': z.number().readonly(),
130
- 'at': z.number().readonly(),
131
- }).readonly()
132
-
133
- const autodreamStatusSchema = z.object({
134
- 'running': z.boolean().readonly(),
135
- 'phase': z.string().readonly(),
136
- 'startedAt': z.number().readonly(),
137
- 'runId': z.string().readonly(),
138
- 'steps': z.array(autodreamStepSchema).readonly(),
139
- 'config': autodreamConfigSchema,
140
- 'route': autodreamRouteSchema.nullable(),
141
- 'lastRunAt': z.number().readonly(),
142
- 'hoursSince': z.number().readonly().nullable(),
143
- 'lastResult': autodreamLastResultSchema.nullable(),
144
- 'retryAfter': z.number().readonly(),
145
- 'gate': z.object({ 'minHours': z.number().readonly(), 'minSessions': z.number().readonly() }).readonly().nullable(),
146
- 'paths': autodreamPathsSchema,
147
- }).readonly()
148
-
149
- const autodreamRunResultSchema = z.object({
150
- 'ok': z.boolean().readonly(),
151
- 'error': z.string().readonly().optional(),
152
- 'report': z.string().readonly().optional(),
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(),
157
- }).readonly()
158
-
159
- // setConfig 的补丁:全部 optional —— 设置面板每次只改动一项,传整个对象反而
160
- // 容易把没碰过的字段用旧值覆盖回去。
161
- const autodreamPatchSchema = z.object({
162
- 'enabled': z.boolean().optional(),
163
- 'trigger': z.string().optional(),
164
- 'apply': z.boolean().optional(),
165
- 'source': z.string().optional(),
166
- 'minHours': z.number().optional(),
167
- 'minSessions': z.number().optional(),
168
- 'provider': z.string().optional(),
169
- 'model': z.string().optional(),
170
- 'maxSteps': z.number().optional(),
171
- 'maxSnapshotKeep': z.number().optional(),
172
- 'rollbackScope': z.string().optional(),
173
- }).readonly()
174
-
175
- const reportListSchema = z.array(z.object({
176
- 'name': z.string().readonly(),
177
- 'bytes': z.number().readonly(),
178
- 'at': z.number().readonly(),
179
- 'atHuman': z.string().readonly(),
180
- 'legacy': z.boolean().readonly(),
181
- }).readonly()).readonly()
182
-
183
- const snapshotListSchema = z.array(z.object({
184
- 'name': z.string().readonly(),
185
- 'at': z.number().readonly(),
186
- 'atHuman': z.string().readonly(),
187
- 'files': z.number().readonly(),
188
- 'path': z.string().readonly(),
189
- 'runId': z.string().readonly().nullable(),
190
- 'kind': z.string().readonly(),
191
- 'legacy': z.boolean().readonly(),
192
- }).readonly()).readonly()
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
-
254
- export const TYPERT = {
255
- package: 'sage-mem',
256
- face: 'host',
257
- schemas: [],
258
- invocations: [
259
- {
260
- id: 'sage-mem#memory/listFiles',
261
- service: 'memory',
262
- namespace: 'memory',
263
- method: 'listFiles',
264
- invocation: { kind: 'direct' },
265
- parameters: [],
266
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileList', schema: listResultSchema, create: () => listResultSchema },
267
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
268
- },
269
- {
270
- id: 'sage-mem#memory/readFile',
271
- service: 'memory',
272
- namespace: 'memory',
273
- method: 'readFile',
274
- invocation: { kind: 'direct' },
275
- parameters: [
276
- { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
277
- ],
278
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: readResultSchema, create: () => readResultSchema },
279
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
280
- },
281
- {
282
- id: 'sage-mem#memory/writeFile',
283
- service: 'memory',
284
- namespace: 'memory',
285
- method: 'writeFile',
286
- invocation: { kind: 'direct' },
287
- parameters: [
288
- { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
289
- { name: 'content', wire: 'content', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: fileContentSchema, create: () => fileContentSchema } },
290
- ],
291
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#WriteResult', schema: writeResultSchema, create: () => writeResultSchema },
292
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
293
- },
294
- {
295
- id: 'sage-mem#memory/deleteFile',
296
- service: 'memory',
297
- namespace: 'memory',
298
- method: 'deleteFile',
299
- invocation: { kind: 'direct' },
300
- parameters: [
301
- { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
302
- ],
303
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#DeleteResult', schema: deleteResultSchema, create: () => deleteResultSchema },
304
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
305
- },
306
- {
307
- id: 'sage-mem#starmap/listStars',
308
- service: 'starmap',
309
- namespace: 'starmap',
310
- method: 'listStars',
311
- invocation: { kind: 'direct' },
312
- parameters: [],
313
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#StarmapList', schema: starmapListSchema, create: () => starmapListSchema },
314
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
315
- },
316
- {
317
- id: 'sage-mem#starmap/readFile',
318
- service: 'starmap',
319
- namespace: 'starmap',
320
- method: 'readFile',
321
- invocation: { kind: 'direct' },
322
- parameters: [
323
- { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
324
- ],
325
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#StarmapRead', schema: starmapReadSchema, create: () => starmapReadSchema },
326
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
327
- },
328
- // ── autodream 的七个方法 ──
329
- // 全部挂在 package `sage-mem` 下(和 memory 同一份 manifest),
330
- // 所以前端直接 ctx.get('remote.autodream') 就能用,不需要像 starmap 那样
331
- // 在 client 侧再 $mount 一次 —— 那个 mount 是因为 starmap 当年是独立包
332
- // (package: 'sage-starmap'),合并进 sage-mem 后一直没改回来。
333
- {
334
- id: 'sage-mem#autodream/getConfig',
335
- service: 'autodream',
336
- namespace: 'autodream',
337
- method: 'getConfig',
338
- invocation: { kind: 'direct' },
339
- parameters: [],
340
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamConfigResult', schema: autodreamConfigResultSchema, create: () => autodreamConfigResultSchema },
341
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
342
- },
343
- {
344
- id: 'sage-mem#autodream/setConfig',
345
- service: 'autodream',
346
- namespace: 'autodream',
347
- method: 'setConfig',
348
- invocation: { kind: 'direct' },
349
- parameters: [
350
- { name: 'patch', wire: 'patch', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamPatch', schema: autodreamPatchSchema, create: () => autodreamPatchSchema } },
351
- ],
352
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamConfigResult', schema: autodreamConfigResultSchema, create: () => autodreamConfigResultSchema },
353
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
354
- },
355
- {
356
- id: 'sage-mem#autodream/status',
357
- service: 'autodream',
358
- namespace: 'autodream',
359
- method: 'status',
360
- invocation: { kind: 'direct' },
361
- parameters: [],
362
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamStatus', schema: autodreamStatusSchema, create: () => autodreamStatusSchema },
363
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
364
- },
365
- {
366
- id: 'sage-mem#autodream/runNow',
367
- service: 'autodream',
368
- namespace: 'autodream',
369
- method: 'runNow',
370
- invocation: { kind: 'direct' },
371
- parameters: [
372
- { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
373
- ],
374
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRunResult', schema: autodreamRunResultSchema, create: () => autodreamRunResultSchema },
375
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
376
- },
377
- {
378
- id: 'sage-mem#autodream/listReports',
379
- service: 'autodream',
380
- namespace: 'autodream',
381
- method: 'listReports',
382
- invocation: { kind: 'direct' },
383
- parameters: [],
384
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamReportList', schema: reportListSchema, create: () => reportListSchema },
385
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
386
- },
387
- {
388
- id: 'sage-mem#autodream/readReport',
389
- service: 'autodream',
390
- namespace: 'autodream',
391
- method: 'readReport',
392
- invocation: { kind: 'direct' },
393
- parameters: [
394
- { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamReportRef', schema: reportRefSchema, create: () => reportRefSchema } },
395
- ],
396
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: readResultSchema, create: () => readResultSchema },
397
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
398
- },
399
- {
400
- id: 'sage-mem#autodream/listSnapshots',
401
- service: 'autodream',
402
- namespace: 'autodream',
403
- method: 'listSnapshots',
404
- invocation: { kind: 'direct' },
405
- parameters: [],
406
- result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamSnapshotList', schema: snapshotListSchema, create: () => snapshotListSchema },
407
- sourceLocation: { "file": "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": "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": "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": "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 },
453
- sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
454
- },
455
- ],
456
- model: {
457
- "services": [],
458
- "events": [],
459
- "objects": [],
460
- },
461
- }
1
+ /**
2
+ * sage-mem — 手写 strict typert host manifest。
3
+ * typert-loader 在插件挂载时读 package.json 的 exports["./typert"],
4
+ * import 本文件并把 TYPERT 注册进 ctx.typert.local(strict 定义)。
5
+ * schema 必须是 zod v4 实例(typert-loader 校验 "_zod" in schema)。
6
+ */
7
+ import { z } from 'zod'
8
+
9
+ // 文件名:与 host 侧 safeName 同一套底线 —— 非空、无路径分隔符与 Windows 非法字符、
10
+ // 以 .md 结尾、长度有界。(真正的目录逃逸防护仍在 host 侧 safeName。)
11
+ const fileNameSchema = z.string().min(1).max(255).regex(/^[^\\/:*?"<>|\u0000-\u001f]+\.md$/)
12
+ // 正文:512 KB 上限。理由是「记忆要塞进 system prompt」——单条正常量级在几十 KB,
13
+ // 到半兆量级基本是写错了目标(贴了日志/代码进来)。与 lib/index.js 的 MAX_FILE_BYTES 一致。
14
+ const fileContentSchema = z.string().max(512 * 1024)
15
+
16
+ // autodream 报告引用:比 fileNameSchema 宽——旧版报告列表里的条目带 `dream/` 前缀
17
+ // (新版 `autodream/` 不加前缀只给裸文件名)。这里放行斜杠,真正的目录逃逸防护
18
+ // 在 host 侧 AutodreamEngine.readReport 里(先剥已知前缀、再对 basename 走 safeName)。
19
+ const reportRefSchema = z.string().min(1).max(320)
20
+
21
+ const starmapStarSchema = z.object({
22
+ 'file': z.string().readonly(),
23
+ 'kind': z.string().readonly(),
24
+ 'title': z.string().readonly(),
25
+ 'desc': z.string().readonly(),
26
+ 'bytes': z.number().readonly(),
27
+ 'mtimeMs': z.number().readonly(),
28
+ // 归档星:`archived` 每颗星都有(活动星是 false);两个留痕字段只对归档星出现,
29
+ // 且旧版 autodream 工具归档的文件没有它们 —— 所以 optional,不是 nullable。
30
+ 'archived': z.boolean().readonly(),
31
+ 'archivedAt': z.string().readonly().optional(),
32
+ 'archivedReason': z.string().readonly().optional(),
33
+ }).readonly()
34
+ const starmapListSchema = z.object({
35
+ 'count': z.number().readonly(),
36
+ 'stars': z.array(starmapStarSchema).readonly(),
37
+ }).readonly()
38
+ const starmapReadSchema = z.object({
39
+ 'name': z.string().readonly(),
40
+ 'content': z.string().readonly(),
41
+ }).readonly()
42
+
43
+ const fileSchema = z.object({
44
+ 'file': z.string().readonly(),
45
+ 'type': z.string().readonly(),
46
+ 'description': z.string().readonly(),
47
+ 'size': z.number().readonly(),
48
+ // 自定义标签:来自 frontmatter 的 tags(flow / block / 逗号三种写法都收)。
49
+ // strict 模式下 host 多返回的字段会被剥掉,所以「列表页要能按标签筛」这件事
50
+ // 必须在这里显式声明,否则前端永远拿到 undefined。
51
+ 'tags': z.array(z.string()).readonly(),
52
+ }).readonly()
53
+
54
+ const listResultSchema = z.array(fileSchema)
55
+ const readResultSchema = z.object({
56
+ 'name': z.string().readonly(),
57
+ 'content': z.string().readonly(),
58
+ }).readonly()
59
+ // 写/删失败不再抛异常,走 { ok: false, error } 分支:error 必须声明,否则 strict
60
+ // 校验会把它当未知字段剥掉,设置页只能看到一个没有原因的 ok:false。
61
+ const writeResultSchema = z.object({
62
+ 'ok': z.boolean().readonly(),
63
+ 'file': z.string().readonly(),
64
+ 'error': z.string().readonly().optional(),
65
+ }).readonly()
66
+ const deleteResultSchema = z.object({
67
+ 'ok': z.boolean().readonly(),
68
+ 'error': z.string().readonly().optional(),
69
+ }).readonly()
70
+
71
+ // ── 归档区(v0.9.0 档案馆)─────────────────────────────────────────────────
72
+ // 归档条目的形状 = fileSchema + 两个留痕字段。留痕可能为空串(旧版 autodream 工具
73
+ // 直接移文件、不写留痕),所以是 string 而不是 optional —— 面板永远能拿到一个值。
74
+ const archivedFileSchema = z.object({
75
+ 'file': z.string().readonly(),
76
+ 'type': z.string().readonly(),
77
+ 'description': z.string().readonly(),
78
+ 'size': z.number().readonly(),
79
+ 'tags': z.array(z.string()).readonly(),
80
+ 'archivedAt': z.string().readonly(),
81
+ 'archivedReason': z.string().readonly(),
82
+ }).readonly()
83
+ const archivedListSchema = z.object({
84
+ 'count': z.number().readonly(),
85
+ 'files': z.array(archivedFileSchema).readonly(),
86
+ }).readonly()
87
+
88
+ // 归档缘由:用户输入的一句话。真正的 YAML 转义在 host 侧 yamlScalar(值里的「: 」「 #」),
89
+ // 这里只兜长度 —— 缘由不该长到把 frontmatter 变成正文。
90
+ const archiveReasonSchema = z.string().max(1000).optional()
91
+ // starmap.listStars 的可选开关:不看归档星时行为与从前完全一致。
92
+ const includeArchivedSchema = z.boolean().optional()
93
+
94
+ // 归档 / 恢复的结果:成功 `{ ok: true, file }`,失败 `{ ok: false, error }` —— 失败分支
95
+ // **没有 file**(名字本身可能就是非法的)。所以不能复用 writeResultSchema:那边 `file`
96
+ // 是必填(writeFile 连失败都带着归一后的文件名),strict 校验会把失败分支判成坏结果。
97
+ const archiveResultSchema = z.object({
98
+ 'ok': z.boolean().readonly(),
99
+ 'file': z.string().readonly().optional(),
100
+ 'error': z.string().readonly().optional(),
101
+ }).readonly()
102
+
103
+ // 归档文件的读 / 写(v0.9.0 B1b):归档不是删除,正文要能看能改。三个类型名与活跃记忆
104
+ // 那套(FileName / FileContent / WriteResult)对称,只是作用目录换成 `memory/archive/`。
105
+ // 名字仍受 safeName 约束 —— 调用方不许自己拼路径。
106
+ const archivedReadResultSchema = z.object({
107
+ 'name': z.string().readonly(),
108
+ 'content': z.string().readonly(),
109
+ }).readonly()
110
+ // 写归档的结果与 writeResultSchema 同形,但**另立一个类型名**:strict 层要能区分
111
+ // 「写活跃记忆」与「写归档记忆」两条路径,将来两者形状分叉时也不必回头改协议。
112
+ const archivedWriteResultSchema = z.object({
113
+ 'ok': z.boolean().readonly(),
114
+ 'file': z.string().readonly(),
115
+ 'error': z.string().readonly().optional(),
116
+ }).readonly()
117
+
118
+ // ── 面板 API(v0.9.0 D1):体检 / 归档候选 / 设置 / 保留名原样读写 ──────────────
119
+ // 审计报告:字段面就是 `auditMemoryDir()` 的返回,逐项在这里钉住 —— strict 会把没声明的
120
+ // 字段剥掉,面板看到的清单必须与模型看到的一致。
121
+ const auditItemSchema = z.object({ 'file': z.string().readonly() }).readonly()
122
+ const auditLinkSchema = z.object({ 'file': z.string().readonly(), 'target': z.string().readonly() }).readonly()
123
+ const auditTypeMismatchSchema = z.object({
124
+ 'file': z.string().readonly(),
125
+ 'type': z.string().readonly(),
126
+ 'prefix': z.string().readonly(),
127
+ 'effective': z.string().readonly(),
128
+ }).readonly()
129
+ const auditHazardSchema = z.object({ 'file': z.string().readonly(), 'line': z.string().readonly() }).readonly()
130
+ const auditReportSchema = z.object({
131
+ 'dir': z.string().readonly(),
132
+ 'fileCount': z.number().readonly(),
133
+ 'skipped': z.number().readonly(),
134
+ 'archivedCount': z.number().readonly(),
135
+ 'indexEntries': z.number().readonly(),
136
+ 'dangling': z.array(auditItemSchema).readonly(),
137
+ 'unlisted': z.array(auditItemSchema).readonly(),
138
+ 'typeMismatch': z.array(auditTypeMismatchSchema).readonly(),
139
+ 'crlf': z.array(auditItemSchema).readonly(),
140
+ 'brokenLinks': z.array(auditLinkSchema).readonly(),
141
+ 'archivedLinks': z.array(auditLinkSchema).readonly(),
142
+ 'hashHazards': z.array(auditHazardSchema).readonly(),
143
+ 'noFrontmatter': z.array(auditItemSchema).readonly(),
144
+ 'unreadable': z.array(auditItemSchema).readonly(),
145
+ 'problems': z.number().readonly(),
146
+ }).readonly()
147
+
148
+ const archiveCandidateSchema = z.object({
149
+ 'file': z.string().readonly(),
150
+ 'type': z.string().readonly(),
151
+ 'days': z.number().readonly(),
152
+ 'limit': z.number().readonly(),
153
+ 'reason': z.string().readonly(),
154
+ }).readonly()
155
+ const archiveCandidatesResultSchema = z.object({
156
+ 'count': z.number().readonly(),
157
+ 'candidates': z.array(archiveCandidateSchema).readonly(),
158
+ 'autoArchive': z.string().readonly(),
159
+ 'thresholds': z.object({
160
+ 'project': z.number().readonly(),
161
+ 'reference': z.number().readonly(),
162
+ 'user': z.number().readonly(),
163
+ }).readonly(),
164
+ }).readonly()
165
+
166
+ // 设置:limits = 当前**已生效**的值(模块加载时读的),pendingLimits = 待生效值
167
+ // (settings.json > 环境变量 > 默认)。两个都给,界面才说得清「改了要重启」。
168
+ const settingsLimitsSchema = z.object({
169
+ 'maxResults': z.number().readonly(),
170
+ 'maxChars': z.number().readonly(),
171
+ 'maxBaseline': z.number().readonly(),
172
+ 'maxSessionBytes': z.number().readonly(),
173
+ 'staleDays': z.number().readonly(),
174
+ }).readonly()
175
+ const settingsSchema = z.object({
176
+ 'limits': settingsLimitsSchema,
177
+ 'pendingLimits': settingsLimitsSchema,
178
+ 'restartRequired': z.boolean().readonly(),
179
+ 'reserved': z.array(z.string()).readonly(),
180
+ 'reservedExtra': z.array(z.string()).readonly(),
181
+ }).readonly()
182
+ const settingsPatchSchema = z.object({
183
+ 'limits': z.object({
184
+ 'maxResults': z.number().optional(),
185
+ 'maxChars': z.number().optional(),
186
+ 'maxBaseline': z.number().optional(),
187
+ 'maxSessionBytes': z.number().optional(),
188
+ 'staleDays': z.number().optional(),
189
+ }).readonly().optional(),
190
+ 'reserved': z.array(z.string()).optional(),
191
+ }).readonly()
192
+ // 成功回 { ok, settings, restartRequired },失败回 { ok:false, error } —— 两条分支并集。
193
+ const settingsResultSchema = z.object({
194
+ 'ok': z.boolean().readonly(),
195
+ 'error': z.string().readonly().optional(),
196
+ 'settings': settingsSchema.optional(),
197
+ 'restartRequired': z.boolean().readonly().optional(),
198
+ }).readonly()
199
+
200
+ // 保留名原样读写。读的两条分支(成功 {name,content} / 拒绝 {ok:false,error})用可选字段
201
+ // 的并集接住;写的失败分支可能没有 file,所以 file 也是 optional。
202
+ const rawReadResultSchema = z.object({
203
+ 'name': z.string().readonly().optional(),
204
+ 'content': z.string().readonly().optional(),
205
+ 'ok': z.boolean().readonly().optional(),
206
+ 'error': z.string().readonly().optional(),
207
+ }).readonly()
208
+ const rawWriteResultSchema = z.object({
209
+ 'ok': z.boolean().readonly(),
210
+ 'file': z.string().readonly().optional(),
211
+ 'error': z.string().readonly().optional(),
212
+ }).readonly()
213
+ // 保留名的体积上限比单条记忆大得多(session-log.md 天然 > 512 KB)—— 4 MB,独立于
214
+ // fileContentSchema,别把两者混用。
215
+ const rawFileContentSchema = z.string().max(4 * 1024 * 1024)
216
+
217
+ // ── autodream(夜间记忆整理)───────────────────────────────────────────────
218
+ // 配置的每一项都可写;lastResult 是一个「成功/失败两条分支共用」的结构,
219
+ // 所以除了三个必有字段外全是 optional —— 用 strict 校验两种形态的并集,
220
+ // 比给成功与失败各来一套 schema 少一半维护面。
221
+ const autodreamConfigSchema = z.object({
222
+ 'enabled': z.boolean().readonly(),
223
+ 'trigger': z.string().readonly(),
224
+ 'apply': z.boolean().readonly(),
225
+ 'source': z.string().readonly(),
226
+ 'minHours': z.number().readonly(),
227
+ 'minSessions': z.number().readonly(),
228
+ 'provider': z.string().readonly(),
229
+ 'model': z.string().readonly(),
230
+ 'maxSteps': z.number().readonly(),
231
+ 'maxSnapshotKeep': z.number().readonly(),
232
+ 'rollbackScope': z.string().readonly(),
233
+ }).readonly()
234
+
235
+ const autodreamPathsSchema = z.object({
236
+ 'memoryDir': z.string().readonly(),
237
+ 'configPath': z.string().readonly(),
238
+ 'stateRoot': z.string().readonly(),
239
+ 'home': z.string().readonly(),
240
+ }).readonly()
241
+
242
+ const autodreamRouteSchema = z.object({
243
+ 'provider': z.string().readonly(),
244
+ 'model': z.string().readonly(),
245
+ 'fromDefault': z.boolean().readonly(),
246
+ 'source': z.string().readonly(),
247
+ 'error': z.string().readonly().nullable(),
248
+ }).readonly()
249
+
250
+ const autodreamLastResultSchema = z.object({
251
+ 'at': z.number().readonly(),
252
+ 'atHuman': z.string().readonly(),
253
+ 'ok': z.boolean().readonly(),
254
+ 'apply': z.boolean().readonly().optional(),
255
+ 'error': z.string().readonly().optional(),
256
+ 'touched': z.array(z.string()).readonly().optional(),
257
+ 'problemsBefore': z.number().readonly().optional(),
258
+ 'problemsAfter': z.number().readonly().optional(),
259
+ 'tokensIn': z.number().readonly().optional(),
260
+ 'tokensOut': z.number().readonly().optional(),
261
+ 'runId': z.string().readonly().optional(),
262
+ 'changeCount': z.number().readonly().optional(),
263
+ 'preflight': z.boolean().readonly().optional(),
264
+ 'snapshotId': z.string().readonly().nullable().optional(),
265
+ 'report': z.string().readonly().optional(),
266
+ }).readonly()
267
+
268
+ const autodreamConfigResultSchema = z.object({
269
+ 'config': autodreamConfigSchema,
270
+ 'route': autodreamRouteSchema.nullable(),
271
+ 'lastRunAt': z.number().readonly(),
272
+ 'lastResult': autodreamLastResultSchema.nullable(),
273
+ 'paths': autodreamPathsSchema,
274
+ 'defaults': autodreamConfigSchema,
275
+ }).readonly()
276
+
277
+ const autodreamStepSchema = z.object({
278
+ 'step': z.number().readonly(),
279
+ 'tools': z.array(z.string()).readonly(),
280
+ 'chars': z.number().readonly(),
281
+ 'at': z.number().readonly(),
282
+ }).readonly()
283
+
284
+ const autodreamStatusSchema = z.object({
285
+ 'running': z.boolean().readonly(),
286
+ 'phase': z.string().readonly(),
287
+ 'startedAt': z.number().readonly(),
288
+ 'runId': z.string().readonly(),
289
+ 'steps': z.array(autodreamStepSchema).readonly(),
290
+ 'config': autodreamConfigSchema,
291
+ 'route': autodreamRouteSchema.nullable(),
292
+ 'lastRunAt': z.number().readonly(),
293
+ 'hoursSince': z.number().readonly().nullable(),
294
+ 'lastResult': autodreamLastResultSchema.nullable(),
295
+ 'retryAfter': z.number().readonly(),
296
+ 'gate': z.object({ 'minHours': z.number().readonly(), 'minSessions': z.number().readonly() }).readonly().nullable(),
297
+ 'paths': autodreamPathsSchema,
298
+ }).readonly()
299
+
300
+ const autodreamRunResultSchema = z.object({
301
+ 'ok': z.boolean().readonly(),
302
+ 'error': z.string().readonly().optional(),
303
+ 'report': z.string().readonly().optional(),
304
+ 'touched': z.array(z.string()).readonly().optional(),
305
+ 'runId': z.string().readonly().optional(),
306
+ 'changeCount': z.number().readonly().optional(),
307
+ 'snapshotId': z.string().readonly().nullable().optional(),
308
+ }).readonly()
309
+
310
+ // setConfig 的补丁:全部 optional —— 设置面板每次只改动一项,传整个对象反而
311
+ // 容易把没碰过的字段用旧值覆盖回去。
312
+ const autodreamPatchSchema = z.object({
313
+ 'enabled': z.boolean().optional(),
314
+ 'trigger': z.string().optional(),
315
+ 'apply': z.boolean().optional(),
316
+ 'source': z.string().optional(),
317
+ 'minHours': z.number().optional(),
318
+ 'minSessions': z.number().optional(),
319
+ 'provider': z.string().optional(),
320
+ 'model': z.string().optional(),
321
+ 'maxSteps': z.number().optional(),
322
+ 'maxSnapshotKeep': z.number().optional(),
323
+ 'rollbackScope': z.string().optional(),
324
+ }).readonly()
325
+
326
+ const reportListSchema = z.array(z.object({
327
+ 'name': z.string().readonly(),
328
+ 'bytes': z.number().readonly(),
329
+ 'at': z.number().readonly(),
330
+ 'atHuman': z.string().readonly(),
331
+ 'legacy': z.boolean().readonly(),
332
+ }).readonly()).readonly()
333
+
334
+ const snapshotListSchema = z.array(z.object({
335
+ 'name': z.string().readonly(),
336
+ 'at': z.number().readonly(),
337
+ 'atHuman': z.string().readonly(),
338
+ 'files': z.number().readonly(),
339
+ 'path': z.string().readonly(),
340
+ 'runId': z.string().readonly().nullable(),
341
+ 'kind': z.string().readonly(),
342
+ 'legacy': z.boolean().readonly(),
343
+ }).readonly()).readonly()
344
+
345
+ // ── autodream 回滚点 / 整理声明 / 模型目录(新增)──
346
+ // 「运行」是这四样东西的共同线索:runId 同时是快照目录名、运行记录目录名与报告文件名,
347
+ // 所以 listRuns 的一条记录能把「改了哪些文件、为什么、能不能退」一次串起来。
348
+ const runListSchema = z.array(z.object({
349
+ 'runId': z.string().readonly(),
350
+ 'at': z.number().readonly(),
351
+ 'atHuman': z.string().readonly(),
352
+ 'mode': z.string().readonly(),
353
+ 'reason': z.string().readonly(),
354
+ 'changeCount': z.number().readonly(),
355
+ 'report': z.string().readonly().nullable(),
356
+ 'snapshotId': z.string().readonly().nullable(),
357
+ 'snapshotAvailable': z.boolean().readonly(),
358
+ 'rolledBackAt': z.number().readonly(),
359
+ 'rolledBackAtHuman': z.string().readonly(),
360
+ }).readonly()).readonly()
361
+
362
+ // manifest 是机读记录,字段面宽且在演进;这里用宽松对象接住,
363
+ // 前端的「整理声明」区只读 markdown,manifest 留给后续工具消费。
364
+ const declarationSchema = z.object({
365
+ 'runId': z.string().readonly(),
366
+ 'markdown': z.string().readonly(),
367
+ 'manifest': z.unknown(),
368
+ }).readonly()
369
+
370
+ const rollbackResultSchema = z.object({
371
+ 'ok': z.boolean().readonly(),
372
+ 'error': z.string().readonly().optional(),
373
+ 'restored': z.number().readonly().optional(),
374
+ 'parked': z.number().readonly().optional(),
375
+ 'skipped': z.number().readonly().optional(),
376
+ 'protection': z.string().readonly().optional(),
377
+ 'report': z.string().readonly().optional(),
378
+ }).readonly()
379
+
380
+ const modelListSchema = z.object({
381
+ 'routes': z.array(z.object({
382
+ 'provider': z.string().readonly(),
383
+ 'model': z.string().readonly(),
384
+ 'label': z.string().readonly(),
385
+ 'isDefault': z.boolean().readonly(),
386
+ }).readonly()).readonly(),
387
+ 'defaultRoute': z.object({
388
+ 'provider': z.string().readonly(),
389
+ 'model': z.string().readonly(),
390
+ }).readonly().nullable(),
391
+ 'catalogAvailable': z.boolean().readonly(),
392
+ 'note': z.string().readonly(),
393
+ }).readonly()
394
+
395
+ // 四个新方法的入参形状不同,但都是「一个对象参数」;合并成一个全 optional 的 schema,
396
+ // 免得为每个方法各写一份。注意 zod 默认会**丢掉未声明的键**,所以用到的字段必须在这里列全。
397
+ const autodreamOptsSchema = z.object({
398
+ 'reason': z.string().optional(),
399
+ 'limit': z.number().optional(),
400
+ 'runId': z.string().optional(),
401
+ 'snapshotId': z.string().optional(),
402
+ 'scope': z.string().optional(),
403
+ }).readonly()
404
+
405
+ export const TYPERT = {
406
+ package: 'sage-mem',
407
+ face: 'host',
408
+ schemas: [],
409
+ invocations: [
410
+ {
411
+ id: 'sage-mem#memory/listFiles',
412
+ service: 'memory',
413
+ namespace: 'memory',
414
+ method: 'listFiles',
415
+ invocation: { kind: 'direct' },
416
+ parameters: [],
417
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileList', schema: listResultSchema, create: () => listResultSchema },
418
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
419
+ },
420
+ {
421
+ id: 'sage-mem#memory/readFile',
422
+ service: 'memory',
423
+ namespace: 'memory',
424
+ method: 'readFile',
425
+ invocation: { kind: 'direct' },
426
+ parameters: [
427
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
428
+ ],
429
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: readResultSchema, create: () => readResultSchema },
430
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
431
+ },
432
+ {
433
+ id: 'sage-mem#memory/writeFile',
434
+ service: 'memory',
435
+ namespace: 'memory',
436
+ method: 'writeFile',
437
+ invocation: { kind: 'direct' },
438
+ parameters: [
439
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
440
+ { name: 'content', wire: 'content', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: fileContentSchema, create: () => fileContentSchema } },
441
+ ],
442
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#WriteResult', schema: writeResultSchema, create: () => writeResultSchema },
443
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
444
+ },
445
+ {
446
+ id: 'sage-mem#memory/deleteFile',
447
+ service: 'memory',
448
+ namespace: 'memory',
449
+ method: 'deleteFile',
450
+ invocation: { kind: 'direct' },
451
+ parameters: [
452
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
453
+ ],
454
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#DeleteResult', schema: deleteResultSchema, create: () => deleteResultSchema },
455
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
456
+ },
457
+ {
458
+ id: 'sage-mem#memory/archive',
459
+ service: 'memory',
460
+ namespace: 'memory',
461
+ method: 'archive',
462
+ invocation: { kind: 'direct' },
463
+ parameters: [
464
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
465
+ { name: 'reason', wire: 'reason', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchiveReason', schema: archiveReasonSchema, create: () => archiveReasonSchema } },
466
+ ],
467
+ // 归档与恢复都回「成不成、动的哪个文件」;失败分支没有 file(名字本身可能就非法),
468
+ // 所以用 ArchiveResult(file / error 都 optional),不能复用 file 必填的 writeResultSchema。
469
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchiveResult', schema: archiveResultSchema, create: () => archiveResultSchema },
470
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
471
+ },
472
+ {
473
+ id: 'sage-mem#memory/restore',
474
+ service: 'memory',
475
+ namespace: 'memory',
476
+ method: 'restore',
477
+ invocation: { kind: 'direct' },
478
+ parameters: [
479
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
480
+ ],
481
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchiveResult', schema: archiveResultSchema, create: () => archiveResultSchema },
482
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
483
+ },
484
+ {
485
+ id: 'sage-mem#memory/listArchived',
486
+ service: 'memory',
487
+ namespace: 'memory',
488
+ method: 'listArchived',
489
+ invocation: { kind: 'direct' },
490
+ parameters: [],
491
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchivedList', schema: archivedListSchema, create: () => archivedListSchema },
492
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
493
+ },
494
+ {
495
+ id: 'sage-mem#memory/readArchived',
496
+ service: 'memory',
497
+ namespace: 'memory',
498
+ method: 'readArchived',
499
+ invocation: { kind: 'direct' },
500
+ parameters: [
501
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchivedFileName', schema: fileNameSchema, create: () => fileNameSchema } },
502
+ ],
503
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchivedFileContent', schema: archivedReadResultSchema, create: () => archivedReadResultSchema },
504
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
505
+ },
506
+ {
507
+ id: 'sage-mem#memory/writeArchived',
508
+ service: 'memory',
509
+ namespace: 'memory',
510
+ method: 'writeArchived',
511
+ invocation: { kind: 'direct' },
512
+ parameters: [
513
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchivedFileName', schema: fileNameSchema, create: () => fileNameSchema } },
514
+ // 正文与「写活跃记忆」共用同一个 512 KB 上限 schema;类型名沿用 #ArchivedFileContent
515
+ // 是为了与「读归档」那一侧对称(活跃记忆那套也是 FileContent 一符两用)。
516
+ { name: 'content', wire: 'content', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchivedFileContent', schema: fileContentSchema, create: () => fileContentSchema } },
517
+ ],
518
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchivedWriteResult', schema: archivedWriteResultSchema, create: () => archivedWriteResultSchema },
519
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
520
+ },
521
+ {
522
+ id: 'sage-mem#memory/audit',
523
+ service: 'memory',
524
+ namespace: 'memory',
525
+ method: 'audit',
526
+ invocation: { kind: 'direct' },
527
+ parameters: [],
528
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AuditReport', schema: auditReportSchema, create: () => auditReportSchema },
529
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
530
+ },
531
+ {
532
+ id: 'sage-mem#memory/archiveCandidates',
533
+ service: 'memory',
534
+ namespace: 'memory',
535
+ method: 'archiveCandidates',
536
+ invocation: { kind: 'direct' },
537
+ parameters: [],
538
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#ArchiveCandidates', schema: archiveCandidatesResultSchema, create: () => archiveCandidatesResultSchema },
539
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
540
+ },
541
+ {
542
+ id: 'sage-mem#memory/getSettings',
543
+ service: 'memory',
544
+ namespace: 'memory',
545
+ method: 'getSettings',
546
+ invocation: { kind: 'direct' },
547
+ parameters: [],
548
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#MemorySettings', schema: settingsSchema, create: () => settingsSchema },
549
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
550
+ },
551
+ {
552
+ id: 'sage-mem#memory/setSettings',
553
+ service: 'memory',
554
+ namespace: 'memory',
555
+ method: 'setSettings',
556
+ invocation: { kind: 'direct' },
557
+ parameters: [
558
+ // 补丁式:面板一次只改一项时不该把没碰过的字段用旧值覆盖回去。
559
+ { name: 'patch', wire: 'patch', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#MemorySettingsPatch', schema: settingsPatchSchema, create: () => settingsPatchSchema } },
560
+ ],
561
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#MemorySettingsResult', schema: settingsResultSchema, create: () => settingsResultSchema },
562
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
563
+ },
564
+ {
565
+ id: 'sage-mem#memory/readRaw',
566
+ service: 'memory',
567
+ namespace: 'memory',
568
+ method: 'readRaw',
569
+ invocation: { kind: 'direct' },
570
+ parameters: [
571
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#ReservedFileName', schema: fileNameSchema, create: () => fileNameSchema } },
572
+ ],
573
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#RawFileContent', schema: rawReadResultSchema, create: () => rawReadResultSchema },
574
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
575
+ },
576
+ {
577
+ id: 'sage-mem#memory/writeRaw',
578
+ service: 'memory',
579
+ namespace: 'memory',
580
+ method: 'writeRaw',
581
+ invocation: { kind: 'direct' },
582
+ parameters: [
583
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#ReservedFileName', schema: fileNameSchema, create: () => fileNameSchema } },
584
+ // 4 MB:与 fileContentSchema(512 KB)**不是同一个上限**,见 rawFileContentSchema 的注释。
585
+ { name: 'content', wire: 'content', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#RawFileContent', schema: rawFileContentSchema, create: () => rawFileContentSchema } },
586
+ ],
587
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#RawWriteResult', schema: rawWriteResultSchema, create: () => rawWriteResultSchema },
588
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
589
+ },
590
+ {
591
+ id: 'sage-mem#starmap/listStars',
592
+ service: 'starmap',
593
+ namespace: 'starmap',
594
+ method: 'listStars',
595
+ invocation: { kind: 'direct' },
596
+ parameters: [
597
+ { name: 'includeArchived', wire: 'includeArchived', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#StarmapIncludeArchived', schema: includeArchivedSchema, create: () => includeArchivedSchema } },
598
+ ],
599
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#StarmapList', schema: starmapListSchema, create: () => starmapListSchema },
600
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
601
+ },
602
+ {
603
+ id: 'sage-mem#starmap/readFile',
604
+ service: 'starmap',
605
+ namespace: 'starmap',
606
+ method: 'readFile',
607
+ invocation: { kind: 'direct' },
608
+ parameters: [
609
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#FileName', schema: fileNameSchema, create: () => fileNameSchema } },
610
+ ],
611
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#StarmapRead', schema: starmapReadSchema, create: () => starmapReadSchema },
612
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
613
+ },
614
+ // ── autodream 的七个方法 ──
615
+ // 全部挂在 package `sage-mem` 下(和 memory 同一份 manifest),
616
+ // 所以前端直接 ctx.get('remote.autodream') 就能用,不需要像 starmap 那样
617
+ // 在 client 侧再 $mount 一次 —— 那个 mount 是因为 starmap 曾是独立包
618
+ // (package: 'sage-starmap'),合并进 sage-mem 后一直没改回来。
619
+ {
620
+ id: 'sage-mem#autodream/getConfig',
621
+ service: 'autodream',
622
+ namespace: 'autodream',
623
+ method: 'getConfig',
624
+ invocation: { kind: 'direct' },
625
+ parameters: [],
626
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamConfigResult', schema: autodreamConfigResultSchema, create: () => autodreamConfigResultSchema },
627
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
628
+ },
629
+ {
630
+ id: 'sage-mem#autodream/setConfig',
631
+ service: 'autodream',
632
+ namespace: 'autodream',
633
+ method: 'setConfig',
634
+ invocation: { kind: 'direct' },
635
+ parameters: [
636
+ { name: 'patch', wire: 'patch', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamPatch', schema: autodreamPatchSchema, create: () => autodreamPatchSchema } },
637
+ ],
638
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamConfigResult', schema: autodreamConfigResultSchema, create: () => autodreamConfigResultSchema },
639
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
640
+ },
641
+ {
642
+ id: 'sage-mem#autodream/status',
643
+ service: 'autodream',
644
+ namespace: 'autodream',
645
+ method: 'status',
646
+ invocation: { kind: 'direct' },
647
+ parameters: [],
648
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamStatus', schema: autodreamStatusSchema, create: () => autodreamStatusSchema },
649
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
650
+ },
651
+ {
652
+ id: 'sage-mem#autodream/runNow',
653
+ service: 'autodream',
654
+ namespace: 'autodream',
655
+ method: 'runNow',
656
+ invocation: { kind: 'direct' },
657
+ parameters: [
658
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
659
+ ],
660
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRunResult', schema: autodreamRunResultSchema, create: () => autodreamRunResultSchema },
661
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
662
+ },
663
+ {
664
+ id: 'sage-mem#autodream/listReports',
665
+ service: 'autodream',
666
+ namespace: 'autodream',
667
+ method: 'listReports',
668
+ invocation: { kind: 'direct' },
669
+ parameters: [],
670
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamReportList', schema: reportListSchema, create: () => reportListSchema },
671
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
672
+ },
673
+ {
674
+ id: 'sage-mem#autodream/readReport',
675
+ service: 'autodream',
676
+ namespace: 'autodream',
677
+ method: 'readReport',
678
+ invocation: { kind: 'direct' },
679
+ parameters: [
680
+ { name: 'name', wire: 'name', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamReportRef', schema: reportRefSchema, create: () => reportRefSchema } },
681
+ ],
682
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#FileContent', schema: readResultSchema, create: () => readResultSchema },
683
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
684
+ },
685
+ {
686
+ id: 'sage-mem#autodream/listSnapshots',
687
+ service: 'autodream',
688
+ namespace: 'autodream',
689
+ method: 'listSnapshots',
690
+ invocation: { kind: 'direct' },
691
+ parameters: [],
692
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamSnapshotList', schema: snapshotListSchema, create: () => snapshotListSchema },
693
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
694
+ },
695
+ {
696
+ id: 'sage-mem#autodream/listRuns',
697
+ service: 'autodream',
698
+ namespace: 'autodream',
699
+ method: 'listRuns',
700
+ invocation: { kind: 'direct' },
701
+ parameters: [
702
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
703
+ ],
704
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRunList', schema: runListSchema, create: () => runListSchema },
705
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
706
+ },
707
+ {
708
+ id: 'sage-mem#autodream/readDeclaration',
709
+ service: 'autodream',
710
+ namespace: 'autodream',
711
+ method: 'readDeclaration',
712
+ invocation: { kind: 'direct' },
713
+ parameters: [
714
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
715
+ ],
716
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamDeclaration', schema: declarationSchema, create: () => declarationSchema },
717
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
718
+ },
719
+ {
720
+ id: 'sage-mem#autodream/rollback',
721
+ service: 'autodream',
722
+ namespace: 'autodream',
723
+ method: 'rollback',
724
+ invocation: { kind: 'direct' },
725
+ parameters: [
726
+ { name: 'opts', wire: 'opts', source: 'json', codec: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamOpts', schema: autodreamOptsSchema, create: () => autodreamOptsSchema } },
727
+ ],
728
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamRollbackResult', schema: rollbackResultSchema, create: () => rollbackResultSchema },
729
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
730
+ },
731
+ {
732
+ id: 'sage-mem#autodream/listModels',
733
+ service: 'autodream',
734
+ namespace: 'autodream',
735
+ method: 'listModels',
736
+ invocation: { kind: 'direct' },
737
+ parameters: [],
738
+ result: { mode: 'strict', typeSymbol: 'sage-mem/types#AutodreamModelList', schema: modelListSchema, create: () => modelListSchema },
739
+ sourceLocation: { "file": "lib/index.js", "line": 1, "column": 1 },
740
+ },
741
+ ],
742
+ model: {
743
+ "services": [],
744
+ "events": [],
745
+ "objects": [],
746
+ },
747
+ }