@downcity/plugins 1.0.60 → 1.0.61

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 (91) hide show
  1. package/bin/BuiltinPlugins.d.ts +15 -0
  2. package/bin/BuiltinPlugins.d.ts.map +1 -1
  3. package/bin/BuiltinPlugins.js +7 -1
  4. package/bin/BuiltinPlugins.js.map +1 -1
  5. package/bin/index.d.ts +6 -0
  6. package/bin/index.d.ts.map +1 -1
  7. package/bin/index.js +3 -0
  8. package/bin/index.js.map +1 -1
  9. package/bin/memory/Action.d.ts +15 -10
  10. package/bin/memory/Action.d.ts.map +1 -1
  11. package/bin/memory/Action.js +233 -16
  12. package/bin/memory/Action.js.map +1 -1
  13. package/bin/memory/MemoryPlugin.d.ts +10 -4
  14. package/bin/memory/MemoryPlugin.d.ts.map +1 -1
  15. package/bin/memory/MemoryPlugin.js +79 -37
  16. package/bin/memory/MemoryPlugin.js.map +1 -1
  17. package/bin/memory/runtime/Search.d.ts +1 -1
  18. package/bin/memory/runtime/Search.d.ts.map +1 -1
  19. package/bin/memory/runtime/Search.js +11 -7
  20. package/bin/memory/runtime/Search.js.map +1 -1
  21. package/bin/memory/runtime/Store.d.ts +8 -23
  22. package/bin/memory/runtime/Store.d.ts.map +1 -1
  23. package/bin/memory/runtime/Store.js +28 -43
  24. package/bin/memory/runtime/Store.js.map +1 -1
  25. package/bin/memory/runtime/SystemProvider.d.ts +4 -8
  26. package/bin/memory/runtime/SystemProvider.d.ts.map +1 -1
  27. package/bin/memory/runtime/SystemProvider.js +55 -62
  28. package/bin/memory/runtime/SystemProvider.js.map +1 -1
  29. package/bin/memory/runtime/Writer.d.ts +48 -10
  30. package/bin/memory/runtime/Writer.d.ts.map +1 -1
  31. package/bin/memory/runtime/Writer.js +197 -60
  32. package/bin/memory/runtime/Writer.js.map +1 -1
  33. package/bin/memory/types/Memory.d.ts +222 -33
  34. package/bin/memory/types/Memory.d.ts.map +1 -1
  35. package/bin/memory/types/Memory.js +4 -3
  36. package/bin/memory/types/Memory.js.map +1 -1
  37. package/bin/shell/ShellPlugin.d.ts +2 -1
  38. package/bin/shell/ShellPlugin.d.ts.map +1 -1
  39. package/bin/shell/ShellPlugin.js +3 -3
  40. package/bin/shell/ShellPlugin.js.map +1 -1
  41. package/bin/shell/ShellRuntimeTypes.d.ts +7 -2
  42. package/bin/shell/ShellRuntimeTypes.d.ts.map +1 -1
  43. package/bin/shell/runtime/ShellActionRuntime.d.ts.map +1 -1
  44. package/bin/shell/runtime/ShellActionRuntime.js +6 -6
  45. package/bin/shell/runtime/ShellActionRuntime.js.map +1 -1
  46. package/bin/shell/runtime/ShellActionRuntimeSupport.d.ts +14 -5
  47. package/bin/shell/runtime/ShellActionRuntimeSupport.d.ts.map +1 -1
  48. package/bin/shell/runtime/ShellActionRuntimeSupport.js +58 -22
  49. package/bin/shell/runtime/ShellActionRuntimeSupport.js.map +1 -1
  50. package/bin/shell/runtime/ShellProcessEvents.js +3 -3
  51. package/bin/shell/runtime/ShellProcessEvents.js.map +1 -1
  52. package/bin/shell/types/ShellPluginOptions.d.ts +95 -0
  53. package/bin/shell/types/ShellPluginOptions.d.ts.map +1 -0
  54. package/bin/shell/types/ShellPluginOptions.js +10 -0
  55. package/bin/shell/types/ShellPluginOptions.js.map +1 -0
  56. package/bin/task/Scheduler.d.ts +8 -0
  57. package/bin/task/Scheduler.d.ts.map +1 -1
  58. package/bin/task/Scheduler.js +7 -9
  59. package/bin/task/Scheduler.js.map +1 -1
  60. package/bin/task/TaskPlugin.d.ts +18 -1
  61. package/bin/task/TaskPlugin.d.ts.map +1 -1
  62. package/bin/task/TaskPlugin.js +23 -1
  63. package/bin/task/TaskPlugin.js.map +1 -1
  64. package/bin/task/types/TaskPluginOptions.d.ts +22 -0
  65. package/bin/task/types/TaskPluginOptions.d.ts.map +1 -0
  66. package/bin/task/types/TaskPluginOptions.js +9 -0
  67. package/bin/task/types/TaskPluginOptions.js.map +1 -0
  68. package/package.json +2 -2
  69. package/src/BuiltinPlugins.ts +27 -1
  70. package/src/index.ts +35 -0
  71. package/src/memory/Action.ts +292 -25
  72. package/src/memory/MemoryPlugin.ts +82 -40
  73. package/src/memory/runtime/Search.ts +16 -9
  74. package/src/memory/runtime/Store.ts +52 -49
  75. package/src/memory/runtime/SystemProvider.ts +55 -69
  76. package/src/memory/runtime/Writer.ts +262 -81
  77. package/src/memory/types/Memory.ts +296 -35
  78. package/src/shell/ShellPlugin.ts +4 -3
  79. package/src/shell/ShellRuntimeTypes.ts +7 -2
  80. package/src/shell/runtime/ShellActionRuntime.ts +18 -9
  81. package/src/shell/runtime/ShellActionRuntimeSupport.ts +106 -21
  82. package/src/shell/runtime/ShellProcessEvents.ts +3 -3
  83. package/src/shell/types/ShellPluginOptions.ts +112 -0
  84. package/src/task/Scheduler.ts +15 -9
  85. package/src/task/TaskPlugin.ts +27 -1
  86. package/src/task/types/TaskPluginOptions.ts +22 -0
  87. package/bin/memory/runtime/Flush.d.ts +0 -15
  88. package/bin/memory/runtime/Flush.d.ts.map +0 -1
  89. package/bin/memory/runtime/Flush.js +0 -63
  90. package/bin/memory/runtime/Flush.js.map +0 -1
  91. package/src/memory/runtime/Flush.ts +0 -83
@@ -12,6 +12,7 @@ import { registerTaskCronJobs } from "../task/Scheduler.js";
12
12
  import { createTaskPluginActions, } from "../task/runtime/TaskPluginActions.js";
13
13
  import { reloadTaskSchedulerAfterMutation, } from "../task/runtime/TaskActionExecution.js";
14
14
  import { TASK_PLUGIN_PROMPT } from "../task/runtime/TaskPluginSystem.js";
15
+ import { resolveRuntimeTimezone } from "@downcity/agent/internal/utils/Time.js";
15
16
  const TASK_LOG_PREFIX = "[TASK]";
16
17
  function formatTaskLogMessage(message) {
17
18
  return `${TASK_LOG_PREFIX} ${message}`;
@@ -32,6 +33,10 @@ export class TaskPlugin extends BasePlugin {
32
33
  * task plugin 的 action 定义表。
33
34
  */
34
35
  actions;
36
+ /**
37
+ * 当前实例持有的显式配置。
38
+ */
39
+ options;
35
40
  /**
36
41
  * 当前实例持有的 cron engine。
37
42
  *
@@ -40,8 +45,17 @@ export class TaskPlugin extends BasePlugin {
40
45
  * - 不再复用 module-global 单例。
41
46
  */
42
47
  cronEngine = null;
43
- constructor() {
48
+ /**
49
+ * 当前实例持有的运行中 task 锁。
50
+ *
51
+ * 关键点(中文)
52
+ * - scheduler reload 会替换 cron engine。
53
+ * - 锁必须挂在 plugin 实例上,避免 reload 后同一 task 被新旧调度器并发触发。
54
+ */
55
+ runningTaskIds = new Set();
56
+ constructor(options) {
44
57
  super();
58
+ this.options = options || {};
45
59
  this.actions = createTaskPluginActions({
46
60
  reloadSchedulerAfterMutation: async (params) => this.reloadSchedulerAfterMutation(params),
47
61
  });
@@ -84,6 +98,8 @@ export class TaskPlugin extends BasePlugin {
84
98
  const registerResult = await registerTaskCronJobs({
85
99
  context,
86
100
  engine,
101
+ timezone: this.resolveTimezone(),
102
+ runningTaskIds: this.runningTaskIds,
87
103
  });
88
104
  await engine.start();
89
105
  this.cronEngine = engine;
@@ -122,5 +138,11 @@ export class TaskPlugin extends BasePlugin {
122
138
  reloadScheduler: async (context) => this.restartCronRuntime(context),
123
139
  });
124
140
  }
141
+ /**
142
+ * 解析当前 task cron 使用的时区。
143
+ */
144
+ resolveTimezone() {
145
+ return String(this.options.timezone || "").trim() || resolveRuntimeTimezone();
146
+ }
125
147
  }
126
148
  //# sourceMappingURL=TaskPlugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TaskPlugin.js","sourceRoot":"","sources":["../../src/task/TaskPlugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskPlugin.js","sourceRoot":"","sources":["../../src/task/TaskPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * TaskPluginOptions:TaskPlugin 构造参数。
3
+ *
4
+ * 关键点(中文)
5
+ * - TaskPlugin 本身就是定时任务 runtime,不提供 enabled 开关。
6
+ * - 只暴露用户能直接理解的时区配置,内部调度实现细节不进入 constructor。
7
+ */
8
+ /**
9
+ * TaskPlugin 构造参数。
10
+ */
11
+ export interface TaskPluginOptions {
12
+ /**
13
+ * cron task 使用的 IANA 时区。
14
+ *
15
+ * 说明(中文)
16
+ * - 例如 `Asia/Shanghai`、`America/Los_Angeles`。
17
+ * - 省略时使用当前运行机器的本机时区。
18
+ * - `time:<ISO8601-with-timezone>` 一次性任务以 ISO 字符串自身的 offset 为准,这里的时区主要影响 cron 表达式。
19
+ */
20
+ timezone?: string;
21
+ }
22
+ //# sourceMappingURL=TaskPluginOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskPluginOptions.d.ts","sourceRoot":"","sources":["../../../src/task/types/TaskPluginOptions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * TaskPluginOptions:TaskPlugin 构造参数。
3
+ *
4
+ * 关键点(中文)
5
+ * - TaskPlugin 本身就是定时任务 runtime,不提供 enabled 开关。
6
+ * - 只暴露用户能直接理解的时区配置,内部调度实现细节不进入 constructor。
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=TaskPluginOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskPluginOptions.js","sourceRoot":"","sources":["../../../src/task/types/TaskPluginOptions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@downcity/plugins",
3
- "version": "1.0.60",
3
+ "version": "1.0.61",
4
4
  "type": "module",
5
5
  "description": "Downcity 内建 plugin 集合包",
6
6
  "main": "./bin/index.js",
@@ -22,7 +22,7 @@
22
22
  "node-cron": "^4.2.1",
23
23
  "ws": "^8.21.0",
24
24
  "zod": "^4.4.3",
25
- "@downcity/agent": "^1.1.106"
25
+ "@downcity/agent": "^1.1.107"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/better-sqlite3": "^7.6.13",
@@ -22,6 +22,9 @@ import { TtsPlugin } from "@/tts/Plugin.js";
22
22
  import type { ImagePluginOptions } from "@/image/types/ImagePlugin.js";
23
23
  import type { AsrPluginOptions } from "@/asr/types/AsrPlugin.js";
24
24
  import type { TtsPluginOptions } from "@/tts/types/TtsPlugin.js";
25
+ import type { TaskPluginOptions } from "@/task/types/TaskPluginOptions.js";
26
+ import type { MemoryPluginOptions } from "@/memory/types/Memory.js";
27
+ import type { ShellPluginOptions } from "@/shell/types/ShellPluginOptions.js";
25
28
 
26
29
  /**
27
30
  * 内建 plugin class 构造器。
@@ -62,13 +65,36 @@ export interface BuiltinPluginOptions {
62
65
  * 文本转语音 plugin 的 City AI 能力注入。
63
66
  */
64
67
  tts?: TtsPluginOptions;
68
+
69
+ /**
70
+ * task plugin 的定时任务运行参数。
71
+ */
72
+ task?: TaskPluginOptions;
73
+
74
+ /**
75
+ * memory plugin 的 LLM Wiki 能力注入。
76
+ */
77
+ memory?: MemoryPluginOptions;
78
+
79
+ /**
80
+ * shell plugin 的可选 runtime 参数。
81
+ */
82
+ shell?: ShellPluginOptions;
65
83
  }
66
84
 
67
85
  /**
68
86
  * 创建完整内建 plugin 实例集合。
69
87
  */
70
88
  export function createBuiltinPlugins(options: BuiltinPluginOptions = {}): BasePlugin[] {
71
- const plugins = BUILTIN_PLUGIN_CLASSES.map((PluginClass) => new PluginClass());
89
+ const plugins = BUILTIN_PLUGIN_CLASSES.map((PluginClass) =>
90
+ PluginClass === TaskPlugin
91
+ ? new TaskPlugin(options.task)
92
+ : PluginClass === MemoryPlugin
93
+ ? new MemoryPlugin(options.memory)
94
+ : PluginClass === ShellPlugin
95
+ ? new ShellPlugin(options.shell)
96
+ : new PluginClass(),
97
+ );
72
98
  if (options.image?.image_create && options.image?.image_result) {
73
99
  plugins.push(new ImagePlugin(options.image));
74
100
  }
package/src/index.ts CHANGED
@@ -29,6 +29,9 @@ export { WebPlugin } from "./web/Plugin.js";
29
29
  export { AsrPlugin } from "./asr/Plugin.js";
30
30
  export { TtsPlugin } from "./tts/Plugin.js";
31
31
  export { WorkboardPlugin } from "./workboard/Plugin.js";
32
+ export { TaskPlugin } from "./task/TaskPlugin.js";
33
+ export { MemoryPlugin } from "./memory/MemoryPlugin.js";
34
+ export { ShellPlugin } from "./shell/ShellPlugin.js";
32
35
  export {
33
36
  listChatAuthorizationRoles,
34
37
  readChatAuthorizationConfigSync,
@@ -59,6 +62,38 @@ export type {
59
62
  ChatPluginOptions,
60
63
  } from "./chat/types/ChatPluginOptions.js";
61
64
  export type { ContactPluginOptions } from "./contact/types/ContactPluginOptions.js";
65
+ export type { TaskPluginOptions } from "./task/types/TaskPluginOptions.js";
66
+ export type {
67
+ ResolvedShellPluginOptions,
68
+ ShellPluginOptions,
69
+ } from "./shell/types/ShellPluginOptions.js";
70
+ export type {
71
+ MemoryActionPayload,
72
+ MemoryDefaults,
73
+ MemoryDigestHandler,
74
+ MemoryDigestHandlerInput,
75
+ MemoryDigestHandlerOutput,
76
+ MemoryDigestPayload,
77
+ MemoryDigestResponse,
78
+ MemoryPluginOptions,
79
+ MemoryReadPayload,
80
+ MemoryReadResponse,
81
+ MemoryRememberPayload,
82
+ MemoryRememberResponse,
83
+ MemoryReviseHandler,
84
+ MemoryReviseHandlerInput,
85
+ MemoryReviseHandlerOutput,
86
+ MemoryRevisePayload,
87
+ MemoryReviseResponse,
88
+ MemorySearchMode,
89
+ MemorySearchPayload,
90
+ MemorySearchResponse,
91
+ MemorySearchResultItem,
92
+ MemorySourceStat,
93
+ MemorySourceType,
94
+ MemoryStatusResponse,
95
+ MemoryWikiPageDraft,
96
+ } from "./memory/types/Memory.js";
62
97
  export type {
63
98
  AsrPluginInput,
64
99
  AsrPluginOptions,
@@ -1,21 +1,28 @@
1
1
  /**
2
- * Memory Service Action 逻辑。
2
+ * Memory Plugin action 逻辑。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 只处理业务动作,不包含 CLI/API 参数映射细节。
6
- * - 所有动作统一返回结构化结果,失败不抛给上层。
5
+ * - action 面向 agent 的记忆语义:search/read/remember/digest/revise。
6
+ * - 原始证据先进入 sources,长期知识进入 wiki。
7
+ * - LLM digest/revise 能力由 MemoryPlugin constructor 注入。
7
8
  */
8
9
 
10
+ import type { UIDataTypes, UIMessagePart, UITools } from "ai";
11
+ import { isTextUIPart } from "ai";
9
12
  import type { PluginActionResult } from "@downcity/agent/internal/plugin/types/Plugin.js";
10
13
  import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
11
14
  import type { JsonValue } from "@downcity/agent/internal/types/common/Json.js";
12
15
  import type {
13
- MemoryFlushPayload,
14
- MemoryGetPayload,
16
+ MemoryDigestPayload,
17
+ MemoryDigestResponse,
18
+ MemoryPluginOptions,
19
+ MemoryReadPayload,
20
+ MemoryRememberPayload,
21
+ MemoryRememberResponse,
22
+ MemoryRevisePayload,
23
+ MemoryReviseResponse,
15
24
  MemorySearchPayload,
16
- MemoryStorePayload,
17
25
  } from "@/memory/types/Memory.js";
18
- import { flushMemory } from "./runtime/Flush.js";
19
26
  import {
20
27
  collectMemoryStatus,
21
28
  searchMemory,
@@ -24,7 +31,93 @@ import {
24
31
  MEMORY_DEFAULTS,
25
32
  type MemoryRuntimeState,
26
33
  } from "./runtime/Store.js";
27
- import { getMemory, storeMemory } from "./runtime/Writer.js";
34
+ import {
35
+ appendManualSource,
36
+ appendMemoryRevision,
37
+ appendWikiPage,
38
+ readMemory,
39
+ readWikiIndex,
40
+ writeSessionSource,
41
+ writeWikiPage,
42
+ } from "./runtime/Writer.js";
43
+
44
+ type AnyUiMessagePart = UIMessagePart<UIDataTypes, UITools>;
45
+
46
+ function toUiParts(message: { parts?: AnyUiMessagePart[] } | null | undefined): AnyUiMessagePart[] {
47
+ return Array.isArray(message?.parts) ? message.parts : [];
48
+ }
49
+
50
+ function extractReadableLine(message: {
51
+ role?: string;
52
+ parts?: AnyUiMessagePart[];
53
+ }): string {
54
+ const role = String(message.role || "").toLowerCase() === "user" ? "User" : "Assistant";
55
+ const text = toUiParts(message)
56
+ .filter(isTextUIPart)
57
+ .map((part) => String(part.text || "").trim())
58
+ .filter(Boolean)
59
+ .join("\n")
60
+ .trim();
61
+ if (!text) {
62
+ return "";
63
+ }
64
+ return `${role}: ${text}`;
65
+ }
66
+
67
+ function readDigestPages(result: Awaited<ReturnType<NonNullable<MemoryPluginOptions["digest"]>>>): {
68
+ pages: Array<{ path?: string; title?: string; content: string; tags?: string[] }>;
69
+ summary?: string;
70
+ } {
71
+ if (typeof result === "string") {
72
+ return {
73
+ pages: [{ title: "Memory Digest", content: result, tags: ["memory", "digest"] }],
74
+ };
75
+ }
76
+ return {
77
+ pages: result.pages,
78
+ summary: result.summary,
79
+ };
80
+ }
81
+
82
+ function readReviseResult(
83
+ result: Awaited<ReturnType<NonNullable<MemoryPluginOptions["revise"]>>>,
84
+ fallbackPath: string,
85
+ ): { path: string; content: string; summary?: string } {
86
+ if (typeof result === "string") {
87
+ return {
88
+ path: fallbackPath,
89
+ content: result,
90
+ };
91
+ }
92
+ return {
93
+ path: result.path || fallbackPath,
94
+ content: result.content,
95
+ summary: result.summary,
96
+ };
97
+ }
98
+
99
+ function slugify(value: string): string {
100
+ const text = String(value || "")
101
+ .trim()
102
+ .toLowerCase()
103
+ .replace(/[^\p{L}\p{N}]+/gu, "-")
104
+ .replace(/^-+|-+$/g, "")
105
+ .slice(0, 80);
106
+ return text || "inbox";
107
+ }
108
+
109
+ function toWikiMemoryPath(value: string): string {
110
+ const clean = String(value || "").replace(/\\/g, "/").replace(/^\/+/, "").trim();
111
+ if (!clean) return ".downcity/memory/wiki/inbox.md";
112
+ if (clean.startsWith(".downcity/memory/wiki/")) {
113
+ return clean.toLowerCase().endsWith(".md") ? clean : `${clean}.md`;
114
+ }
115
+ const withoutPrefix = clean.replace(/^wiki\//, "");
116
+ const withExt = withoutPrefix.toLowerCase().endsWith(".md")
117
+ ? withoutPrefix
118
+ : `${withoutPrefix}.md`;
119
+ return `.downcity/memory/wiki/${withExt}`;
120
+ }
28
121
 
29
122
  /**
30
123
  * status action。
@@ -70,14 +163,14 @@ export async function searchMemoryAction(
70
163
  }
71
164
 
72
165
  /**
73
- * get action。
166
+ * read action。
74
167
  */
75
- export async function getMemoryAction(
168
+ export async function readMemoryAction(
76
169
  context: AgentContext,
77
- payload: MemoryGetPayload,
170
+ payload: MemoryReadPayload,
78
171
  ): Promise<PluginActionResult<JsonValue>> {
79
172
  try {
80
- const data = await getMemory(context, payload);
173
+ const data = await readMemory(context, payload);
81
174
  return { success: true, data: data as unknown as JsonValue };
82
175
  } catch (error) {
83
176
  return {
@@ -88,16 +181,65 @@ export async function getMemoryAction(
88
181
  }
89
182
 
90
183
  /**
91
- * store action。
184
+ * remember action。
92
185
  */
93
- export async function storeMemoryAction(
186
+ export async function rememberMemoryAction(
94
187
  context: AgentContext,
95
- state: MemoryRuntimeState,
96
- payload: MemoryStorePayload,
188
+ options: MemoryPluginOptions,
189
+ payload: MemoryRememberPayload,
97
190
  ): Promise<PluginActionResult<JsonValue>> {
98
191
  try {
99
- const data = await storeMemory(context, state, payload);
100
- return { success: true, data: data as unknown as JsonValue };
192
+ const content = String(payload.content || "").trim();
193
+ if (!content) {
194
+ throw new Error("content is required");
195
+ }
196
+ const source = await appendManualSource(context, content, payload.source);
197
+ const targetPath = toWikiMemoryPath(payload.path || slugify(payload.topic || "inbox"));
198
+
199
+ if (options.revise) {
200
+ const current = await readMemory(context, { path: targetPath }).catch(() => ({
201
+ path: targetPath,
202
+ text: "",
203
+ }));
204
+ const revised = readReviseResult(
205
+ await options.revise({
206
+ rootPath: context.rootPath,
207
+ path: targetPath,
208
+ currentContent: current.text,
209
+ instruction: "Integrate this new memory into the wiki page. Deduplicate and keep it concise.",
210
+ evidence: `${content}\n\nSource: ${source.path}`,
211
+ }),
212
+ targetPath,
213
+ );
214
+ const written = await writeWikiPage(context, {
215
+ path: revised.path,
216
+ title: payload.topic,
217
+ content: revised.content,
218
+ tags: ["memory"],
219
+ });
220
+ const response: MemoryRememberResponse = {
221
+ sourcePath: source.path,
222
+ wikiPath: written.path,
223
+ mode: "revised",
224
+ writtenChars: written.writtenChars,
225
+ summary: revised.summary,
226
+ };
227
+ return { success: true, data: response as unknown as JsonValue };
228
+ }
229
+
230
+ const written = await appendWikiPage(context, {
231
+ path: targetPath,
232
+ title: payload.topic || "Memory Inbox",
233
+ content,
234
+ sourcePath: source.path,
235
+ });
236
+ const response: MemoryRememberResponse = {
237
+ sourcePath: source.path,
238
+ wikiPath: written.path,
239
+ mode: "appended",
240
+ writtenChars: written.writtenChars,
241
+ };
242
+ return { success: true, data: response as unknown as JsonValue };
101
243
  } catch (error) {
102
244
  return {
103
245
  success: false,
@@ -107,16 +249,135 @@ export async function storeMemoryAction(
107
249
  }
108
250
 
109
251
  /**
110
- * flush action。
252
+ * digest action。
111
253
  */
112
- export async function flushMemoryAction(
254
+ export async function digestMemoryAction(
113
255
  context: AgentContext,
114
- state: MemoryRuntimeState,
115
- payload: MemoryFlushPayload,
116
- ): Promise<PluginActionResult> {
256
+ options: MemoryPluginOptions,
257
+ payload: MemoryDigestPayload,
258
+ ): Promise<PluginActionResult<JsonValue>> {
117
259
  try {
118
- const data = await flushMemory(context, state, payload);
119
- return { success: true, data: data as unknown as JsonValue };
260
+ const sessionId = String(payload.sessionId || "").trim();
261
+ if (!sessionId) {
262
+ throw new Error("sessionId is required");
263
+ }
264
+ const maxMessages = Number.isFinite(payload.maxMessages)
265
+ ? Math.max(1, Math.floor(payload.maxMessages as number))
266
+ : 30;
267
+ const historyStore = context.session.get(sessionId).getHistoryStore();
268
+ const total = await historyStore.size();
269
+ const start = Math.max(0, total - maxMessages);
270
+ const messages = await historyStore.slice(start, total);
271
+ const lines = messages
272
+ .map((msg) => extractReadableLine(msg))
273
+ .filter((line) => line.length > 0);
274
+ const transcript =
275
+ lines.length > 0
276
+ ? lines.join("\n\n")
277
+ : "本次 digest 未找到可写入的用户/助手文本内容。";
278
+ const sourceText = [
279
+ `Window: ${start}-${Math.max(start, total - 1)}`,
280
+ "",
281
+ transcript,
282
+ ].join("\n");
283
+ const source = await writeSessionSource(context, sessionId, sourceText);
284
+
285
+ if (options.digest) {
286
+ const wikiIndex = await readWikiIndex(context);
287
+ const digested = readDigestPages(
288
+ await options.digest({
289
+ rootPath: context.rootPath,
290
+ sourceText,
291
+ sourcePath: source.path,
292
+ sessionId,
293
+ wikiIndex,
294
+ }),
295
+ );
296
+ const wikiPaths: string[] = [];
297
+ for (const page of digested.pages) {
298
+ const written = await writeWikiPage(context, page);
299
+ wikiPaths.push(written.path);
300
+ }
301
+ const response: MemoryDigestResponse = {
302
+ sourcePath: source.path,
303
+ wikiPaths,
304
+ messageCount: lines.length,
305
+ mode: "digested",
306
+ summary: digested.summary,
307
+ };
308
+ return { success: true, data: response as unknown as JsonValue };
309
+ }
310
+
311
+ const written = await appendWikiPage(context, {
312
+ path: "session-digests",
313
+ title: "Session Digests",
314
+ content: sourceText,
315
+ sourcePath: source.path,
316
+ });
317
+ const response: MemoryDigestResponse = {
318
+ sourcePath: source.path,
319
+ wikiPaths: [written.path],
320
+ messageCount: lines.length,
321
+ mode: "archived",
322
+ };
323
+ return { success: true, data: response as unknown as JsonValue };
324
+ } catch (error) {
325
+ return {
326
+ success: false,
327
+ error: String(error),
328
+ };
329
+ }
330
+ }
331
+
332
+ /**
333
+ * revise action。
334
+ */
335
+ export async function reviseMemoryAction(
336
+ context: AgentContext,
337
+ options: MemoryPluginOptions,
338
+ payload: MemoryRevisePayload,
339
+ ): Promise<PluginActionResult<JsonValue>> {
340
+ try {
341
+ const targetPath = toWikiMemoryPath(String(payload.path || "").trim());
342
+ if (!targetPath) {
343
+ throw new Error("path is required");
344
+ }
345
+ const instruction = String(payload.instruction || "").trim();
346
+ if (!instruction) {
347
+ throw new Error("instruction is required");
348
+ }
349
+
350
+ if (options.revise) {
351
+ const current = await readMemory(context, { path: targetPath }).catch(() => ({
352
+ path: targetPath,
353
+ text: "",
354
+ }));
355
+ const revised = readReviseResult(
356
+ await options.revise({
357
+ rootPath: context.rootPath,
358
+ path: targetPath,
359
+ currentContent: current.text,
360
+ instruction,
361
+ evidence: String(payload.evidence || ""),
362
+ }),
363
+ targetPath,
364
+ );
365
+ const written = await writeWikiPage(context, {
366
+ path: revised.path,
367
+ content: revised.content,
368
+ tags: ["memory"],
369
+ });
370
+ const response: MemoryReviseResponse = {
371
+ path: written.path,
372
+ mode: "revised",
373
+ writtenChars: written.writtenChars,
374
+ summary: revised.summary,
375
+ };
376
+ return { success: true, data: response as unknown as JsonValue };
377
+ }
378
+
379
+ const response = await appendMemoryRevision(context, payload);
380
+ return { success: true, data: response as unknown as JsonValue };
120
381
  } catch (error) {
121
382
  return {
122
383
  success: false,
@@ -143,5 +404,11 @@ export function toSearchPayload(input: Record<string, unknown>): MemorySearchPay
143
404
  : typeof input.minScore === "string"
144
405
  ? Number(input.minScore)
145
406
  : MEMORY_DEFAULTS.minScore,
407
+ includeSources:
408
+ typeof input.includeSources === "boolean"
409
+ ? input.includeSources
410
+ : typeof input.includeSources === "string"
411
+ ? input.includeSources === "true"
412
+ : undefined,
146
413
  };
147
414
  }