@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.
- package/bin/BuiltinPlugins.d.ts +15 -0
- package/bin/BuiltinPlugins.d.ts.map +1 -1
- package/bin/BuiltinPlugins.js +7 -1
- package/bin/BuiltinPlugins.js.map +1 -1
- package/bin/index.d.ts +6 -0
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +3 -0
- package/bin/index.js.map +1 -1
- package/bin/memory/Action.d.ts +15 -10
- package/bin/memory/Action.d.ts.map +1 -1
- package/bin/memory/Action.js +233 -16
- package/bin/memory/Action.js.map +1 -1
- package/bin/memory/MemoryPlugin.d.ts +10 -4
- package/bin/memory/MemoryPlugin.d.ts.map +1 -1
- package/bin/memory/MemoryPlugin.js +79 -37
- package/bin/memory/MemoryPlugin.js.map +1 -1
- package/bin/memory/runtime/Search.d.ts +1 -1
- package/bin/memory/runtime/Search.d.ts.map +1 -1
- package/bin/memory/runtime/Search.js +11 -7
- package/bin/memory/runtime/Search.js.map +1 -1
- package/bin/memory/runtime/Store.d.ts +8 -23
- package/bin/memory/runtime/Store.d.ts.map +1 -1
- package/bin/memory/runtime/Store.js +28 -43
- package/bin/memory/runtime/Store.js.map +1 -1
- package/bin/memory/runtime/SystemProvider.d.ts +4 -8
- package/bin/memory/runtime/SystemProvider.d.ts.map +1 -1
- package/bin/memory/runtime/SystemProvider.js +55 -62
- package/bin/memory/runtime/SystemProvider.js.map +1 -1
- package/bin/memory/runtime/Writer.d.ts +48 -10
- package/bin/memory/runtime/Writer.d.ts.map +1 -1
- package/bin/memory/runtime/Writer.js +197 -60
- package/bin/memory/runtime/Writer.js.map +1 -1
- package/bin/memory/types/Memory.d.ts +222 -33
- package/bin/memory/types/Memory.d.ts.map +1 -1
- package/bin/memory/types/Memory.js +4 -3
- package/bin/memory/types/Memory.js.map +1 -1
- package/bin/shell/ShellPlugin.d.ts +2 -1
- package/bin/shell/ShellPlugin.d.ts.map +1 -1
- package/bin/shell/ShellPlugin.js +3 -3
- package/bin/shell/ShellPlugin.js.map +1 -1
- package/bin/shell/ShellRuntimeTypes.d.ts +7 -2
- package/bin/shell/ShellRuntimeTypes.d.ts.map +1 -1
- package/bin/shell/runtime/ShellActionRuntime.d.ts.map +1 -1
- package/bin/shell/runtime/ShellActionRuntime.js +6 -6
- package/bin/shell/runtime/ShellActionRuntime.js.map +1 -1
- package/bin/shell/runtime/ShellActionRuntimeSupport.d.ts +14 -5
- package/bin/shell/runtime/ShellActionRuntimeSupport.d.ts.map +1 -1
- package/bin/shell/runtime/ShellActionRuntimeSupport.js +58 -22
- package/bin/shell/runtime/ShellActionRuntimeSupport.js.map +1 -1
- package/bin/shell/runtime/ShellProcessEvents.js +3 -3
- package/bin/shell/runtime/ShellProcessEvents.js.map +1 -1
- package/bin/shell/types/ShellPluginOptions.d.ts +95 -0
- package/bin/shell/types/ShellPluginOptions.d.ts.map +1 -0
- package/bin/shell/types/ShellPluginOptions.js +10 -0
- package/bin/shell/types/ShellPluginOptions.js.map +1 -0
- package/bin/task/Scheduler.d.ts +8 -0
- package/bin/task/Scheduler.d.ts.map +1 -1
- package/bin/task/Scheduler.js +7 -9
- package/bin/task/Scheduler.js.map +1 -1
- package/bin/task/TaskPlugin.d.ts +18 -1
- package/bin/task/TaskPlugin.d.ts.map +1 -1
- package/bin/task/TaskPlugin.js +23 -1
- package/bin/task/TaskPlugin.js.map +1 -1
- package/bin/task/types/TaskPluginOptions.d.ts +22 -0
- package/bin/task/types/TaskPluginOptions.d.ts.map +1 -0
- package/bin/task/types/TaskPluginOptions.js +9 -0
- package/bin/task/types/TaskPluginOptions.js.map +1 -0
- package/package.json +2 -2
- package/src/BuiltinPlugins.ts +27 -1
- package/src/index.ts +35 -0
- package/src/memory/Action.ts +292 -25
- package/src/memory/MemoryPlugin.ts +82 -40
- package/src/memory/runtime/Search.ts +16 -9
- package/src/memory/runtime/Store.ts +52 -49
- package/src/memory/runtime/SystemProvider.ts +55 -69
- package/src/memory/runtime/Writer.ts +262 -81
- package/src/memory/types/Memory.ts +296 -35
- package/src/shell/ShellPlugin.ts +4 -3
- package/src/shell/ShellRuntimeTypes.ts +7 -2
- package/src/shell/runtime/ShellActionRuntime.ts +18 -9
- package/src/shell/runtime/ShellActionRuntimeSupport.ts +106 -21
- package/src/shell/runtime/ShellProcessEvents.ts +3 -3
- package/src/shell/types/ShellPluginOptions.ts +112 -0
- package/src/task/Scheduler.ts +15 -9
- package/src/task/TaskPlugin.ts +27 -1
- package/src/task/types/TaskPluginOptions.ts +22 -0
- package/bin/memory/runtime/Flush.d.ts +0 -15
- package/bin/memory/runtime/Flush.d.ts.map +0 -1
- package/bin/memory/runtime/Flush.js +0 -63
- package/bin/memory/runtime/Flush.js.map +0 -1
- package/src/memory/runtime/Flush.ts +0 -83
package/bin/task/TaskPlugin.js
CHANGED
|
@@ -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
|
-
|
|
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":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oDAAoD,CAAC;
|
|
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 @@
|
|
|
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.
|
|
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.
|
|
25
|
+
"@downcity/agent": "^1.1.107"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/better-sqlite3": "^7.6.13",
|
package/src/BuiltinPlugins.ts
CHANGED
|
@@ -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) =>
|
|
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,
|
package/src/memory/Action.ts
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Memory
|
|
2
|
+
* Memory Plugin action 逻辑。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
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
|
-
|
|
14
|
-
|
|
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 {
|
|
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
|
-
*
|
|
166
|
+
* read action。
|
|
74
167
|
*/
|
|
75
|
-
export async function
|
|
168
|
+
export async function readMemoryAction(
|
|
76
169
|
context: AgentContext,
|
|
77
|
-
payload:
|
|
170
|
+
payload: MemoryReadPayload,
|
|
78
171
|
): Promise<PluginActionResult<JsonValue>> {
|
|
79
172
|
try {
|
|
80
|
-
const data = await
|
|
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
|
-
*
|
|
184
|
+
* remember action。
|
|
92
185
|
*/
|
|
93
|
-
export async function
|
|
186
|
+
export async function rememberMemoryAction(
|
|
94
187
|
context: AgentContext,
|
|
95
|
-
|
|
96
|
-
payload:
|
|
188
|
+
options: MemoryPluginOptions,
|
|
189
|
+
payload: MemoryRememberPayload,
|
|
97
190
|
): Promise<PluginActionResult<JsonValue>> {
|
|
98
191
|
try {
|
|
99
|
-
const
|
|
100
|
-
|
|
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
|
-
*
|
|
252
|
+
* digest action。
|
|
111
253
|
*/
|
|
112
|
-
export async function
|
|
254
|
+
export async function digestMemoryAction(
|
|
113
255
|
context: AgentContext,
|
|
114
|
-
|
|
115
|
-
payload:
|
|
116
|
-
): Promise<PluginActionResult
|
|
256
|
+
options: MemoryPluginOptions,
|
|
257
|
+
payload: MemoryDigestPayload,
|
|
258
|
+
): Promise<PluginActionResult<JsonValue>> {
|
|
117
259
|
try {
|
|
118
|
-
const
|
|
119
|
-
|
|
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
|
}
|