@downcity/plugins 1.0.252 → 1.0.254

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/bin/memory/Action.d.ts +27 -36
  2. package/bin/memory/Action.d.ts.map +1 -1
  3. package/bin/memory/Action.js +71 -311
  4. package/bin/memory/Action.js.map +1 -1
  5. package/bin/memory/Index.d.ts +3 -1
  6. package/bin/memory/Index.d.ts.map +1 -1
  7. package/bin/memory/Index.js +3 -1
  8. package/bin/memory/Index.js.map +1 -1
  9. package/bin/memory/MemoryPlugin.d.ts +20 -37
  10. package/bin/memory/MemoryPlugin.d.ts.map +1 -1
  11. package/bin/memory/MemoryPlugin.js +231 -233
  12. package/bin/memory/MemoryPlugin.js.map +1 -1
  13. package/bin/memory/adapters/FileMemoryStorageAdapter.d.ts +43 -0
  14. package/bin/memory/adapters/FileMemoryStorageAdapter.d.ts.map +1 -0
  15. package/bin/memory/adapters/FileMemoryStorageAdapter.js +163 -0
  16. package/bin/memory/adapters/FileMemoryStorageAdapter.js.map +1 -0
  17. package/bin/memory/providers/BuiltinMemoryProvider.d.ts +63 -0
  18. package/bin/memory/providers/BuiltinMemoryProvider.d.ts.map +1 -0
  19. package/bin/memory/providers/BuiltinMemoryProvider.js +772 -0
  20. package/bin/memory/providers/BuiltinMemoryProvider.js.map +1 -0
  21. package/bin/memory/runtime/SystemProvider.d.ts +7 -12
  22. package/bin/memory/runtime/SystemProvider.d.ts.map +1 -1
  23. package/bin/memory/runtime/SystemProvider.js +30 -89
  24. package/bin/memory/runtime/SystemProvider.js.map +1 -1
  25. package/bin/memory/types/BuiltinMemoryProvider.d.ts +88 -0
  26. package/bin/memory/types/BuiltinMemoryProvider.d.ts.map +1 -0
  27. package/bin/memory/types/BuiltinMemoryProvider.js +9 -0
  28. package/bin/memory/types/BuiltinMemoryProvider.js.map +1 -0
  29. package/bin/memory/types/Memory.d.ts +249 -408
  30. package/bin/memory/types/Memory.d.ts.map +1 -1
  31. package/bin/memory/types/Memory.js +4 -4
  32. package/bin/memory/types/MemoryStorage.d.ts +35 -0
  33. package/bin/memory/types/MemoryStorage.d.ts.map +1 -0
  34. package/bin/memory/types/MemoryStorage.js +10 -0
  35. package/bin/memory/types/MemoryStorage.js.map +1 -0
  36. package/bin/memory.d.ts +6 -2
  37. package/bin/memory.d.ts.map +1 -1
  38. package/bin/memory.js +3 -1
  39. package/bin/memory.js.map +1 -1
  40. package/package.json +4 -3
  41. package/scripts/memory-plugin.test.mjs +227 -0
  42. package/scripts/plugin-subpaths.test.mjs +8 -0
  43. package/src/memory/Action.ts +106 -377
  44. package/src/memory/Index.ts +6 -1
  45. package/src/memory/MemoryPlugin.ts +254 -246
  46. package/src/memory/adapters/FileMemoryStorageAdapter.ts +197 -0
  47. package/src/memory/providers/BuiltinMemoryProvider.ts +905 -0
  48. package/src/memory/runtime/SystemProvider.ts +32 -95
  49. package/src/memory/types/BuiltinMemoryProvider.ts +121 -0
  50. package/src/memory/types/Memory.ts +322 -456
  51. package/src/memory/types/MemoryStorage.ts +44 -0
  52. package/src/memory.ts +48 -24
  53. package/bin/memory/runtime/Search.d.ts +0 -19
  54. package/bin/memory/runtime/Search.d.ts.map +0 -1
  55. package/bin/memory/runtime/Search.js +0 -262
  56. package/bin/memory/runtime/Search.js.map +0 -1
  57. package/bin/memory/runtime/Store.d.ts +0 -42
  58. package/bin/memory/runtime/Store.d.ts.map +0 -1
  59. package/bin/memory/runtime/Store.js +0 -94
  60. package/bin/memory/runtime/Store.js.map +0 -1
  61. package/bin/memory/runtime/Writer.d.ts +0 -61
  62. package/bin/memory/runtime/Writer.d.ts.map +0 -1
  63. package/bin/memory/runtime/Writer.js +0 -274
  64. package/bin/memory/runtime/Writer.js.map +0 -1
  65. package/src/memory/runtime/Search.ts +0 -327
  66. package/src/memory/runtime/Store.ts +0 -158
  67. package/src/memory/runtime/Writer.ts +0 -351
@@ -1,422 +1,430 @@
1
1
  /**
2
- * MemoryPlugin:agent 的长期记忆 plugin
2
+ * MemoryPlugin:Agent 长期记忆的 provider-neutral facade
3
3
  *
4
- * 关键点(中文)
5
- * - 对外仍然是 MemoryPlugin,内部使用 LLM Wiki 方式组织知识。
6
- * - constructor 注入 digest/revise 能力,plugin 不绑定具体 LLM 服务。
7
- * - action 面向 agent 语义,而不是暴露底层文件写入细节。
4
+ * 职责说明(中文)
5
+ * - Agent 暴露稳定的 Memory actions 与 system 使用约束。
6
+ * - Agent/Session 上下文映射为结构化 Memory scope。
7
+ * - 将记忆形成、存储、召回、修订和删除委托给唯一 MemoryProvider。
8
+ *
9
+ * 边界说明(中文)
10
+ * - 不读取或拼接任何物理存储路径。
11
+ * - 不依赖 Workspace FileSystem,也不规定 Markdown、SQLite 或远程服务。
12
+ * - Provider 生命周期跟随当前 Plugin 实例,由 Agent 统一启动和释放。
8
13
  */
9
14
 
10
15
  import type { Command } from "commander";
11
- import type { JsonObject, JsonValue } from "@downcity/agent";
12
- import type { PluginContext } from "@downcity/agent";
13
- import type { PluginActions } from "@downcity/agent";
14
- import { BasePlugin } from "@downcity/agent";
15
- import { create_action } from "@downcity/agent";
16
+ import { BasePlugin, create_action } from "@downcity/agent";
17
+ import type {
18
+ JsonObject,
19
+ JsonValue,
20
+ PluginActions,
21
+ PluginContext,
22
+ } from "@downcity/agent";
16
23
  import { z } from "zod";
17
24
  import {
18
- digestMemoryAction,
19
- readMemoryAction,
20
- rememberMemoryAction,
21
- reviseMemoryAction,
22
- searchMemoryAction,
23
- statusMemoryAction,
24
- } from "./Action.js";
25
- import {
26
- createMemoryRuntimeState,
27
- type MemoryRuntimeState,
28
- } from "./runtime/Store.js";
29
- import { buildMemoryPluginSystemText } from "./runtime/SystemProvider.js";
30
- import { ensureMemoryDirectories } from "./runtime/Writer.js";
31
- import type { MemoryPluginOptions } from "./types/Memory.js";
25
+ digest_memory_action,
26
+ forget_memory_action,
27
+ read_memory_action,
28
+ remember_memory_action,
29
+ revise_memory_action,
30
+ search_memory_action,
31
+ status_memory_action,
32
+ } from "@/memory/Action.js";
33
+ import { build_memory_plugin_system_text } from "@/memory/runtime/SystemProvider.js";
34
+ import type {
35
+ MemoryPluginOptions,
36
+ MemoryProvider,
37
+ MemoryType,
38
+ } from "@/memory/types/Memory.js";
39
+
40
+ const memory_type_schema = z.enum([
41
+ "fact",
42
+ "preference",
43
+ "decision",
44
+ "episode",
45
+ "procedure",
46
+ "document",
47
+ ]);
32
48
 
33
- function parsePositiveInteger(value: string): number {
49
+ /** 解析正整数 CLI 参数。 */
50
+ function parse_positive_integer(value: string): number {
34
51
  const text = String(value || "").trim();
35
- if (!/^\d+$/.test(text)) {
36
- throw new Error(`Invalid positive integer: ${value}`);
37
- }
38
- const num = Number(text);
39
- if (!Number.isFinite(num) || num < 1) {
52
+ if (!/^\d+$/u.test(text)) throw new Error(`Invalid positive integer: ${value}`);
53
+ const number_value = Number(text);
54
+ if (!Number.isFinite(number_value) || number_value < 1) {
40
55
  throw new Error(`Invalid positive integer: ${value}`);
41
56
  }
42
- return num;
57
+ return number_value;
43
58
  }
44
59
 
45
- function parseNumber(value: string): number {
46
- const text = String(value || "").trim();
47
- if (!text) {
48
- throw new Error("number is required");
49
- }
50
- const num = Number(text);
51
- if (!Number.isFinite(num)) {
52
- throw new Error(`Invalid number: ${value}`);
53
- }
54
- return num;
60
+ /** 解析任意有限数值 CLI 参数。 */
61
+ function parse_number(value: string): number {
62
+ const number_value = Number(String(value || "").trim());
63
+ if (!Number.isFinite(number_value)) throw new Error(`Invalid number: ${value}`);
64
+ return number_value;
55
65
  }
56
66
 
57
- function readBodyObject(rawBody: JsonValue): JsonObject {
58
- if (!rawBody || typeof rawBody !== "object" || Array.isArray(rawBody)) {
59
- return {};
60
- }
61
- return rawBody as JsonObject;
67
+ /** Action JSON 输入归一化为普通对象。 */
68
+ function read_body_object(raw_body: JsonValue): JsonObject {
69
+ return raw_body && typeof raw_body === "object" && !Array.isArray(raw_body)
70
+ ? raw_body as JsonObject
71
+ : {};
62
72
  }
63
73
 
64
- function readString(body: JsonObject, key: string): string {
65
- const value = body[key];
66
- return typeof value === "string" ? value : "";
74
+ /** 读取必填或可选字符串字段。 */
75
+ function read_string(body: JsonObject, key: string): string {
76
+ return typeof body[key] === "string" ? String(body[key]) : "";
67
77
  }
68
78
 
69
- function readOptionalString(body: JsonObject, key: string): string | undefined {
70
- const value = body[key];
71
- return typeof value === "string" ? value : undefined;
79
+ /** 读取可选字符串字段。 */
80
+ function read_optional_string(body: JsonObject, key: string): string | undefined {
81
+ const value = read_string(body, key).trim();
82
+ return value || undefined;
72
83
  }
73
84
 
74
- function readOptionalNumber(body: JsonObject, key: string): number | undefined {
75
- const value = body[key];
76
- return typeof value === "number" ? value : undefined;
85
+ /** 读取可选数值字段。 */
86
+ function read_optional_number(body: JsonObject, key: string): number | undefined {
87
+ return typeof body[key] === "number" ? Number(body[key]) : undefined;
77
88
  }
78
89
 
79
- function readOptionalBoolean(body: JsonObject, key: string): boolean | undefined {
80
- const value = body[key];
81
- return typeof value === "boolean" ? value : undefined;
90
+ /** 读取可选布尔字段。 */
91
+ function read_optional_boolean(body: JsonObject, key: string): boolean | undefined {
92
+ return typeof body[key] === "boolean" ? Boolean(body[key]) : undefined;
82
93
  }
83
94
 
84
- /**
85
- * Memory plugin 类实现。
86
- */
95
+ /** 读取可选 MemoryType 字段。 */
96
+ function read_optional_memory_type(body: JsonObject): MemoryType | undefined {
97
+ const result = memory_type_schema.safeParse(body.memory_type);
98
+ return result.success ? result.data : undefined;
99
+ }
100
+
101
+ /** Agent 长期记忆 Plugin。 */
87
102
  export class MemoryPlugin extends BasePlugin {
88
- /**
89
- * plugin 名称。
90
- */
103
+ /** Plugin 稳定名称。 */
91
104
  readonly name = "memory";
92
105
 
93
- /**
94
- * 当前实例持有的 memory plugin state。
95
- */
96
- public runtimeState: MemoryRuntimeState | null = null;
106
+ /** 当前 Plugin 唯一绑定的 Memory Provider。 */
107
+ readonly provider: MemoryProvider;
97
108
 
98
- /**
99
- * 创建 MemoryPlugin。
100
- */
101
- constructor(private readonly options: MemoryPluginOptions = {}) {
109
+ constructor(options: MemoryPluginOptions) {
102
110
  super();
111
+ if (!options?.provider) throw new Error("MemoryPlugin requires provider");
112
+ const provider_name = String(options.provider.name || "").trim();
113
+ if (!provider_name) throw new Error("MemoryPlugin provider requires name");
114
+ this.provider = options.provider;
103
115
  }
104
116
 
105
- /**
106
- * 当前 plugin 的 system 文本提供器。
107
- */
117
+ /** 构建 provider-neutral Memory system 内容。 */
108
118
  async system(context: PluginContext): Promise<string> {
109
- return await buildMemoryPluginSystemText(context);
119
+ return await build_memory_plugin_system_text(context, this.provider);
110
120
  }
111
121
 
112
- /**
113
- * 当前 plugin 生命周期。
114
- */
122
+ /** Provider 生命周期与当前 Agent Plugin 实例保持一致。 */
115
123
  readonly lifecycle = {
116
124
  start: async (context: PluginContext): Promise<void> => {
117
- await ensureMemoryDirectories(context.workspace_path);
118
- this.getOrCreateRuntimeState(context);
125
+ await this.provider.initialize({
126
+ agent_id: context.agent_id,
127
+ });
119
128
  },
120
129
  stop: async (): Promise<void> => {
121
- this.runtimeState = null;
130
+ await this.provider.dispose();
122
131
  },
123
132
  };
124
133
 
125
- /**
126
- * 当前 plugin action 定义表。
127
- */
134
+ /** Memory 对 Agent 暴露的稳定 Action 集合。 */
128
135
  readonly actions: PluginActions = {
129
136
  status: create_action({
130
- description: "View memory wiki status (wiki/source/working).",
137
+ description: "Inspect the active Memory Provider and its capabilities.",
131
138
  input_schema: {
132
139
  zod: z.object({}).passthrough(),
133
- json_schema: { type: "object", properties: {} },
140
+ json_schema: { type: "object", additionalProperties: false, properties: {} },
134
141
  },
135
- examples: [{ title: "View status", payload: {} }],
142
+ examples: [{ title: "View Memory Provider status", payload: {} }],
136
143
  command: {
137
- description: "View memory wiki status (wiki/source/working).",
138
- map_input() {
139
- return {};
140
- },
141
- },
142
- execute: async (params) => {
143
- const state = this.getOrCreateRuntimeState(params.context);
144
- return await statusMemoryAction(params.context, state);
144
+ description: "Inspect the active Memory Provider.",
145
+ map_input: () => ({}),
145
146
  },
147
+ execute: async () => await status_memory_action(this.provider),
146
148
  }),
149
+
147
150
  search: create_action({
148
- description: "Search memory wiki, optionally extending into the source layer.",
151
+ description: "Recall scoped long-term memories for a focused query.",
149
152
  input_schema: {
150
153
  zod: z.object({
151
154
  query: z.string(),
152
- maxResults: z.number().optional(),
153
- minScore: z.number().optional(),
154
- includeSources: z.boolean().optional(),
155
+ max_results: z.number().optional(),
156
+ min_score: z.number().optional(),
157
+ include_evidence: z.boolean().optional(),
155
158
  }),
156
159
  json_schema: {
157
160
  type: "object",
161
+ additionalProperties: false,
158
162
  required: ["query"],
159
163
  properties: {
160
- query: { type: "string", description: "Search query." },
161
- maxResults: { type: "number", description: "Maximum number of results." },
162
- minScore: { type: "number", description: "Minimum relevance score." },
163
- includeSources: { type: "boolean", description: "Whether to include the source layer." },
164
+ query: { type: "string", description: "Focused recall query." },
165
+ max_results: { type: "number", description: "Maximum result count." },
166
+ min_score: { type: "number", minimum: 0, maximum: 1 },
167
+ include_evidence: { type: "boolean", description: "Include raw evidence records." },
164
168
  },
165
169
  },
166
170
  },
167
- examples: [
168
- { title: "Search memory", payload: { query: "user preferences" } },
169
- ],
171
+ examples: [{ title: "Recall preferences", payload: { query: "user preferences" } }],
170
172
  command: {
171
- description: "Search memory wiki.",
173
+ description: "Recall scoped long-term memories.",
172
174
  configure(command: Command) {
173
175
  command
174
176
  .argument("<query>")
175
- .option("--max-results <number>", "Maximum number of results.", parsePositiveInteger)
176
- .option("--min-score <number>", "Minimum relevance score.", parseNumber)
177
- .option("--include-sources", "Also search the raw source layer.");
177
+ .option("--max-results <number>", "Maximum result count.", parse_positive_integer)
178
+ .option("--min-score <number>", "Minimum relevance score.", parse_number)
179
+ .option("--include-evidence", "Include raw evidence records.");
178
180
  },
179
181
  map_input({ args, opts }) {
180
- const payload: JsonObject = {
182
+ return {
181
183
  query: String(args[0] || ""),
184
+ ...(typeof opts.maxResults === "number" ? { max_results: opts.maxResults } : {}),
185
+ ...(typeof opts.minScore === "number" ? { min_score: opts.minScore } : {}),
186
+ ...(opts.includeEvidence === true ? { include_evidence: true } : {}),
182
187
  };
183
- if (typeof opts.maxResults === "number") {
184
- payload.maxResults = opts.maxResults;
185
- }
186
- if (typeof opts.minScore === "number") {
187
- payload.minScore = opts.minScore;
188
- }
189
- if (opts.includeSources === true) {
190
- payload.includeSources = true;
191
- }
192
- return payload;
193
188
  },
194
189
  },
195
- execute: async (params) => {
196
- const body = readBodyObject(params.input);
197
- const state = this.getOrCreateRuntimeState(params.context);
198
- return await searchMemoryAction(params.context, state, {
199
- query: readString(body, "query"),
200
- maxResults: readOptionalNumber(body, "maxResults"),
201
- minScore: readOptionalNumber(body, "minScore"),
202
- includeSources: readOptionalBoolean(body, "includeSources"),
190
+ execute: async ({ context, input }) => {
191
+ const body = read_body_object(input);
192
+ return await search_memory_action(context, this.provider, {
193
+ query: read_string(body, "query"),
194
+ max_results: read_optional_number(body, "max_results"),
195
+ min_score: read_optional_number(body, "min_score"),
196
+ include_evidence: read_optional_boolean(body, "include_evidence"),
203
197
  });
204
198
  },
205
199
  }),
200
+
206
201
  read: create_action({
207
- description: "Read a memory wiki/source file excerpt.",
202
+ description: "Read one exact memory by memory_id.",
208
203
  input_schema: {
209
204
  zod: z.object({
210
- path: z.string(),
211
- from: z.number().optional(),
212
- lines: z.number().optional(),
205
+ memory_id: z.string(),
206
+ from_line: z.number().optional(),
207
+ line_count: z.number().optional(),
213
208
  }),
214
209
  json_schema: {
215
210
  type: "object",
216
- required: ["path"],
211
+ additionalProperties: false,
212
+ required: ["memory_id"],
217
213
  properties: {
218
- path: { type: "string", description: "Memory file path relative to the project root." },
219
- from: { type: "number", description: "Starting line, 1-based." },
220
- lines: { type: "number", description: "Number of lines to read." },
214
+ memory_id: { type: "string", description: "Stable logical memory identifier." },
215
+ from_line: { type: "number", minimum: 1 },
216
+ line_count: { type: "number", minimum: 1 },
221
217
  },
222
218
  },
223
219
  },
224
- examples: [
225
- { title: "Read full page", payload: { path: ".downcity/memory/wiki/index.md" } },
226
- ],
220
+ examples: [{ title: "Read a memory", payload: { memory_id: "wiki/user-preferences" } }],
227
221
  command: {
228
- description: "Read a memory wiki/source file excerpt.",
222
+ description: "Read one exact memory.",
229
223
  configure(command: Command) {
230
224
  command
231
- .argument("<memoryPath>", "Memory file path relative to the project root.")
232
- .option("--from <number>", "Starting line, 1-based.", parsePositiveInteger)
233
- .option("--lines <number>", "Number of lines to read.", parsePositiveInteger);
225
+ .argument("<memory_id>")
226
+ .option("--from-line <number>", "Starting line, 1-based.", parse_positive_integer)
227
+ .option("--line-count <number>", "Maximum line count.", parse_positive_integer);
234
228
  },
235
229
  map_input({ args, opts }) {
236
- const payload: JsonObject = {
237
- path: String(args[0] || ""),
230
+ return {
231
+ memory_id: String(args[0] || ""),
232
+ ...(typeof opts.fromLine === "number" ? { from_line: opts.fromLine } : {}),
233
+ ...(typeof opts.lineCount === "number" ? { line_count: opts.lineCount } : {}),
238
234
  };
239
- if (typeof opts.from === "number") {
240
- payload.from = opts.from;
241
- }
242
- if (typeof opts.lines === "number") {
243
- payload.lines = opts.lines;
244
- }
245
- return payload;
246
235
  },
247
236
  },
248
- execute: async (params) => {
249
- const body = readBodyObject(params.input);
250
- return await readMemoryAction(params.context, {
251
- path: readString(body, "path"),
252
- from: readOptionalNumber(body, "from"),
253
- lines: readOptionalNumber(body, "lines"),
237
+ execute: async ({ context, input }) => {
238
+ const body = read_body_object(input);
239
+ return await read_memory_action(context, this.provider, {
240
+ memory_id: read_string(body, "memory_id"),
241
+ from_line: read_optional_number(body, "from_line"),
242
+ line_count: read_optional_number(body, "line_count"),
254
243
  });
255
244
  },
256
245
  }),
246
+
257
247
  remember: create_action({
258
- description: "Record facts, preferences, or decisions into memory wiki.",
248
+ description: "Store a durable fact, preference, decision, episode, procedure, or document.",
259
249
  input_schema: {
260
250
  zod: z.object({
261
251
  content: z.string(),
262
252
  topic: z.string().optional(),
263
- path: z.string().optional(),
253
+ memory_type: memory_type_schema.optional(),
264
254
  source: z.string().optional(),
265
255
  }),
266
256
  json_schema: {
267
257
  type: "object",
258
+ additionalProperties: false,
268
259
  required: ["content"],
269
260
  properties: {
270
261
  content: { type: "string", description: "Content to remember." },
271
- topic: { type: "string", description: "Memory topic." },
272
- path: { type: "string", description: "Target wiki page path." },
273
- source: { type: "string", description: "Source note." },
262
+ topic: { type: "string", description: "Optional organization hint." },
263
+ memory_type: {
264
+ type: "string",
265
+ enum: ["fact", "preference", "decision", "episode", "procedure", "document"],
266
+ },
267
+ source: { type: "string", description: "Optional evidence label." },
274
268
  },
275
269
  },
276
270
  },
277
- examples: [
278
- { title: "Remember preference", payload: { content: "User prefers concise answers", topic: "user-prefs" } },
279
- ],
271
+ examples: [{
272
+ title: "Remember a preference",
273
+ payload: {
274
+ content: "User prefers concise answers.",
275
+ topic: "user-preferences",
276
+ memory_type: "preference",
277
+ },
278
+ }],
280
279
  command: {
281
- description: "Record facts, preferences, or decisions into memory wiki.",
280
+ description: "Store a durable memory.",
282
281
  configure(command: Command) {
283
282
  command
284
283
  .requiredOption("--content <text>", "Content to remember.")
285
- .option("--topic <topic>", "Memory topic.")
286
- .option("--wiki-path <path>", "Target wiki page path.")
287
- .option("--source <source>", "Source note.");
284
+ .option("--topic <topic>", "Optional organization hint.")
285
+ .option("--memory-type <type>", "Memory type.")
286
+ .option("--source <source>", "Optional evidence label.");
288
287
  },
289
288
  map_input({ opts }) {
290
- const payload: JsonObject = {
289
+ return {
291
290
  content: String(opts.content || ""),
291
+ ...(typeof opts.topic === "string" ? { topic: opts.topic } : {}),
292
+ ...(typeof opts.memoryType === "string" ? { memory_type: opts.memoryType } : {}),
293
+ ...(typeof opts.source === "string" ? { source: opts.source } : {}),
292
294
  };
293
- if (typeof opts.topic === "string") {
294
- payload.topic = String(opts.topic).trim();
295
- }
296
- if (typeof opts.wikiPath === "string") {
297
- payload.path = String(opts.wikiPath).trim();
298
- }
299
- if (typeof opts.source === "string") {
300
- payload.source = String(opts.source).trim();
301
- }
302
- return payload;
303
295
  },
304
296
  },
305
- execute: async (params) => {
306
- const body = readBodyObject(params.input);
307
- return await rememberMemoryAction(params.context, this.options, {
308
- content: readString(body, "content"),
309
- topic: readOptionalString(body, "topic"),
310
- path: readOptionalString(body, "path"),
311
- source: readOptionalString(body, "source"),
297
+ execute: async ({ context, input }) => {
298
+ const body = read_body_object(input);
299
+ return await remember_memory_action(context, this.provider, {
300
+ content: read_string(body, "content"),
301
+ topic: read_optional_string(body, "topic"),
302
+ memory_type: read_optional_memory_type(body),
303
+ source: read_optional_string(body, "source"),
312
304
  });
313
305
  },
314
306
  }),
307
+
315
308
  digest: create_action({
316
- description: "Digest a session into memory wiki.",
309
+ description: "Digest a canonical Session transcript into long-term memory.",
317
310
  input_schema: {
318
311
  zod: z.object({
319
312
  session_id: z.string(),
320
- maxMessages: z.number().optional(),
313
+ max_messages: z.number().optional(),
321
314
  }),
322
315
  json_schema: {
323
316
  type: "object",
317
+ additionalProperties: false,
324
318
  required: ["session_id"],
325
319
  properties: {
326
- session_id: { type: "string", description: "Session ID." },
327
- maxMessages: { type: "number", description: "Message extraction window." },
320
+ session_id: { type: "string" },
321
+ max_messages: { type: "number", minimum: 1 },
328
322
  },
329
323
  },
330
324
  },
331
- examples: [
332
- { title: "Digest session", payload: { session_id: "sess-1" } },
333
- ],
325
+ examples: [{ title: "Digest a Session", payload: { session_id: "sess-1" } }],
334
326
  command: {
335
- description: "Digest a session into memory wiki.",
327
+ description: "Digest a canonical Session transcript.",
336
328
  configure(command: Command) {
337
329
  command
338
- .requiredOption("--session-id <session_id>", "Session ID.")
339
- .option("--max-messages <number>", "Message extraction window.", parsePositiveInteger);
330
+ .requiredOption("--session-id <session_id>", "Session identifier.")
331
+ .option("--max-messages <number>", "Maximum message count.", parse_positive_integer);
340
332
  },
341
333
  map_input({ opts }) {
342
- const payload: JsonObject = {
343
- session_id: String(opts.session_id || ""),
334
+ return {
335
+ session_id: String(opts.sessionId || ""),
336
+ ...(typeof opts.maxMessages === "number" ? { max_messages: opts.maxMessages } : {}),
344
337
  };
345
- if (typeof opts.maxMessages === "number") {
346
- payload.maxMessages = opts.maxMessages;
347
- }
348
- return payload;
349
338
  },
350
339
  },
351
- execute: async (params) => {
352
- const body = readBodyObject(params.input);
353
- return await digestMemoryAction(params.context, this.options, {
354
- session_id: readString(body, "session_id"),
355
- maxMessages: readOptionalNumber(body, "maxMessages"),
340
+ execute: async ({ context, input }) => {
341
+ const body = read_body_object(input);
342
+ return await digest_memory_action(context, this.provider, {
343
+ session_id: read_string(body, "session_id"),
344
+ max_messages: read_optional_number(body, "max_messages"),
356
345
  });
357
346
  },
358
347
  }),
348
+
359
349
  revise: create_action({
360
- description: "Revise a memory wiki page based on new evidence.",
350
+ description: "Revise one memory using new evidence.",
361
351
  input_schema: {
362
352
  zod: z.object({
363
- path: z.string(),
353
+ memory_id: z.string(),
364
354
  instruction: z.string(),
365
355
  evidence: z.string().optional(),
366
356
  }),
367
357
  json_schema: {
368
358
  type: "object",
369
- required: ["path", "instruction"],
359
+ additionalProperties: false,
360
+ required: ["memory_id", "instruction"],
370
361
  properties: {
371
- path: { type: "string", description: "Target wiki page path." },
372
- instruction: { type: "string", description: "Revision instruction." },
373
- evidence: { type: "string", description: "New evidence." },
362
+ memory_id: { type: "string" },
363
+ instruction: { type: "string" },
364
+ evidence: { type: "string" },
374
365
  },
375
366
  },
376
367
  },
377
- examples: [
378
- {
379
- title: "Revise entry",
380
- payload: { path: "wiki/preferences.md", instruction: "Replace with latest preference." },
368
+ examples: [{
369
+ title: "Revise a preference",
370
+ payload: {
371
+ memory_id: "wiki/user-preferences",
372
+ instruction: "Replace the old preference with the latest one.",
381
373
  },
382
- ],
374
+ }],
383
375
  command: {
384
- description: "Revise a memory wiki page based on new evidence.",
376
+ description: "Revise one memory using new evidence.",
385
377
  configure(command: Command) {
386
378
  command
387
- .argument("<memoryPath>", "Target wiki page path.")
379
+ .argument("<memory_id>")
388
380
  .requiredOption("--instruction <text>", "Revision instruction.")
389
381
  .option("--evidence <text>", "New evidence.");
390
382
  },
391
383
  map_input({ args, opts }) {
392
- const payload: JsonObject = {
393
- path: String(args[0] || ""),
384
+ return {
385
+ memory_id: String(args[0] || ""),
394
386
  instruction: String(opts.instruction || ""),
387
+ ...(typeof opts.evidence === "string" ? { evidence: opts.evidence } : {}),
395
388
  };
396
- if (typeof opts.evidence === "string") {
397
- payload.evidence = String(opts.evidence).trim();
398
- }
399
- return payload;
400
389
  },
401
390
  },
402
- execute: async (params) => {
403
- const body = readBodyObject(params.input);
404
- return await reviseMemoryAction(params.context, this.options, {
405
- path: readString(body, "path"),
406
- instruction: readString(body, "instruction"),
407
- evidence: readOptionalString(body, "evidence"),
391
+ execute: async ({ context, input }) => {
392
+ const body = read_body_object(input);
393
+ return await revise_memory_action(context, this.provider, {
394
+ memory_id: read_string(body, "memory_id"),
395
+ instruction: read_string(body, "instruction"),
396
+ evidence: read_optional_string(body, "evidence"),
408
397
  });
409
398
  },
410
399
  }),
411
- };
412
400
 
413
- /**
414
- * 获取或创建当前实例绑定的 memory plugin state。
415
- */
416
- private getOrCreateRuntimeState(context: PluginContext): MemoryRuntimeState {
417
- if (!this.runtimeState) {
418
- this.runtimeState = createMemoryRuntimeState(context);
419
- }
420
- return this.runtimeState;
421
- }
401
+ forget: create_action({
402
+ description: "Delete or invalidate one memory by memory_id.",
403
+ input_schema: {
404
+ zod: z.object({ memory_id: z.string() }),
405
+ json_schema: {
406
+ type: "object",
407
+ additionalProperties: false,
408
+ required: ["memory_id"],
409
+ properties: { memory_id: { type: "string" } },
410
+ },
411
+ },
412
+ examples: [{ title: "Forget a memory", payload: { memory_id: "wiki/obsolete" } }],
413
+ command: {
414
+ description: "Delete or invalidate one memory.",
415
+ configure(command: Command) {
416
+ command.argument("<memory_id>");
417
+ },
418
+ map_input({ args }) {
419
+ return { memory_id: String(args[0] || "") };
420
+ },
421
+ },
422
+ execute: async ({ context, input }) => {
423
+ const body = read_body_object(input);
424
+ return await forget_memory_action(context, this.provider, {
425
+ memory_id: read_string(body, "memory_id"),
426
+ });
427
+ },
428
+ }),
429
+ };
422
430
  }