@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
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Memory Writer
|
|
2
|
+
* Memory Writer(LLM Wiki 文件读写与路径安全)。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
5
|
+
* - `sources/` 保存原始证据,`wiki/` 保存整理后的长期记忆。
|
|
6
|
+
* - 所有外部传入路径都必须限制在 `.downcity/memory` 或 session working memory 内。
|
|
7
|
+
* - 无 LLM 注入时使用 append fallback,保证 MemoryPlugin 仍然可用。
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import fs from "node:fs/promises";
|
|
10
11
|
import path from "node:path";
|
|
11
12
|
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
12
13
|
import type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
MemoryReadPayload,
|
|
15
|
+
MemoryReadResponse,
|
|
16
|
+
MemoryRevisePayload,
|
|
17
|
+
MemoryReviseResponse,
|
|
18
|
+
MemoryWikiPageDraft,
|
|
18
19
|
} from "@/memory/types/Memory.js";
|
|
19
|
-
import type { MemoryRuntimeState } from "./Store.js";
|
|
20
20
|
|
|
21
21
|
function nowIso(): string {
|
|
22
22
|
return new Date().toISOString();
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function
|
|
25
|
+
function dateStamp(now: Date = new Date()): string {
|
|
26
26
|
return now.toISOString().slice(0, 10);
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -37,77 +37,42 @@ function isWithin(parentPath: string, childPath: string): boolean {
|
|
|
37
37
|
return child.startsWith(`${parent}${path.sep}`);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
if (target === "daily") {
|
|
50
|
-
const date = resolveDateStamp();
|
|
51
|
-
const absPath = path.join(context.rootPath, ".downcity", "memory", "daily", `${date}.md`);
|
|
52
|
-
return { absPath, relPath: toRelPath(context.rootPath, absPath) };
|
|
53
|
-
}
|
|
54
|
-
const key = String(sessionId || "").trim();
|
|
55
|
-
if (!key) {
|
|
56
|
-
throw new Error("sessionId is required for working memory");
|
|
57
|
-
}
|
|
58
|
-
const absPath = path.join(
|
|
59
|
-
context.paths.getDowncitySessionDirPath(key),
|
|
60
|
-
"memory",
|
|
61
|
-
"working.md",
|
|
62
|
-
);
|
|
63
|
-
return { absPath, relPath: toRelPath(context.rootPath, absPath) };
|
|
40
|
+
function slugify(value: string): string {
|
|
41
|
+
const text = String(value || "")
|
|
42
|
+
.trim()
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.replace(/[^\p{L}\p{N}]+/gu, "-")
|
|
45
|
+
.replace(/^-+|-+$/g, "")
|
|
46
|
+
.slice(0, 80);
|
|
47
|
+
return text || "inbox";
|
|
64
48
|
}
|
|
65
49
|
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return "# Daily Memory\n";
|
|
72
|
-
}
|
|
73
|
-
return "# Working Memory\n";
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function formatEntry(content: string): string {
|
|
77
|
-
const clean = String(content || "").trim();
|
|
50
|
+
function normalizeMarkdownPath(value: string): string {
|
|
51
|
+
const clean = String(value || "")
|
|
52
|
+
.replace(/\\/g, "/")
|
|
53
|
+
.replace(/^\/+/, "")
|
|
54
|
+
.trim();
|
|
78
55
|
if (!clean) return "";
|
|
79
|
-
return
|
|
56
|
+
return clean.toLowerCase().endsWith(".md") ? clean : `${clean}.md`;
|
|
80
57
|
}
|
|
81
58
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
context
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
94
|
-
throw new Error("
|
|
59
|
+
function resolveWikiPath(context: AgentContext, requestedPath?: string, title?: string): {
|
|
60
|
+
absPath: string;
|
|
61
|
+
relPath: string;
|
|
62
|
+
} {
|
|
63
|
+
const memoryRoot = path.join(context.rootPath, ".downcity", "memory");
|
|
64
|
+
const wikiRoot = path.join(memoryRoot, "wiki");
|
|
65
|
+
const normalized = normalizeMarkdownPath(requestedPath || slugify(title || "inbox"));
|
|
66
|
+
const withoutPrefix = normalized
|
|
67
|
+
.replace(/^\.downcity\/memory\/wiki\//, "")
|
|
68
|
+
.replace(/^wiki\//, "");
|
|
69
|
+
const absPath = path.resolve(wikiRoot, withoutPrefix);
|
|
70
|
+
if (!isWithin(wikiRoot, absPath)) {
|
|
71
|
+
throw new Error("wiki path is not allowed");
|
|
95
72
|
}
|
|
96
|
-
const resolved = resolveStoreTargetPath(context, target, payload.sessionId);
|
|
97
|
-
await fs.mkdir(path.dirname(resolved.absPath), { recursive: true });
|
|
98
|
-
const exists = await fs
|
|
99
|
-
.access(resolved.absPath)
|
|
100
|
-
.then(() => true)
|
|
101
|
-
.catch(() => false);
|
|
102
|
-
if (!exists) {
|
|
103
|
-
await fs.writeFile(resolved.absPath, ensureHeading(target), "utf-8");
|
|
104
|
-
}
|
|
105
|
-
const entry = formatEntry(content);
|
|
106
|
-
await fs.appendFile(resolved.absPath, `\n${entry}`, "utf-8");
|
|
107
73
|
return {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
writtenChars: entry.length,
|
|
74
|
+
absPath,
|
|
75
|
+
relPath: toRelPath(context.rootPath, absPath),
|
|
111
76
|
};
|
|
112
77
|
}
|
|
113
78
|
|
|
@@ -131,13 +96,96 @@ function resolveAllowedReadPath(context: AgentContext, relPath: string): string
|
|
|
131
96
|
return absPath;
|
|
132
97
|
}
|
|
133
98
|
|
|
99
|
+
function buildSourceEntry(content: string, source?: string): string {
|
|
100
|
+
const clean = String(content || "").trim();
|
|
101
|
+
const sourceText = source ? `Source: ${source}\n\n` : "";
|
|
102
|
+
return `## ${nowIso()}\n\n${sourceText}${clean}\n`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function buildFallbackWikiEntry(payload: {
|
|
106
|
+
content: string;
|
|
107
|
+
sourcePath?: string;
|
|
108
|
+
instruction?: string;
|
|
109
|
+
}): string {
|
|
110
|
+
const lines = [
|
|
111
|
+
`## ${nowIso()}`,
|
|
112
|
+
"",
|
|
113
|
+
...(payload.instruction ? [`Instruction: ${payload.instruction}`, ""] : []),
|
|
114
|
+
payload.content.trim(),
|
|
115
|
+
"",
|
|
116
|
+
...(payload.sourcePath ? [`Source: ${payload.sourcePath}`, ""] : []),
|
|
117
|
+
];
|
|
118
|
+
return lines.join("\n");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function ensureFrontmatter(draft: MemoryWikiPageDraft): string {
|
|
122
|
+
const content = String(draft.content || "").trim();
|
|
123
|
+
if (content.startsWith("---")) {
|
|
124
|
+
return `${content}\n`;
|
|
125
|
+
}
|
|
126
|
+
const title = String(draft.title || "Memory Page").trim();
|
|
127
|
+
const tags = draft.tags && draft.tags.length > 0
|
|
128
|
+
? draft.tags.map((tag) => String(tag).trim()).filter(Boolean)
|
|
129
|
+
: ["memory"];
|
|
130
|
+
return [
|
|
131
|
+
"---",
|
|
132
|
+
`title: ${JSON.stringify(title)}`,
|
|
133
|
+
`date: ${dateStamp()}`,
|
|
134
|
+
`tags: [${tags.map((tag) => JSON.stringify(tag)).join(", ")}]`,
|
|
135
|
+
"---",
|
|
136
|
+
"",
|
|
137
|
+
content,
|
|
138
|
+
"",
|
|
139
|
+
].join("\n");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function readTextIfExists(absPath: string): Promise<string> {
|
|
143
|
+
try {
|
|
144
|
+
return String(await fs.readFile(absPath, "utf-8"));
|
|
145
|
+
} catch {
|
|
146
|
+
return "";
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 初始化 memory wiki 目录结构(幂等)。
|
|
152
|
+
*/
|
|
153
|
+
export async function ensureMemoryDirectories(rootPath: string): Promise<void> {
|
|
154
|
+
const memoryRoot = path.join(rootPath, ".downcity", "memory");
|
|
155
|
+
await fs.mkdir(path.join(memoryRoot, "wiki"), { recursive: true });
|
|
156
|
+
await fs.mkdir(path.join(memoryRoot, "sources", "manual"), { recursive: true });
|
|
157
|
+
await fs.mkdir(path.join(memoryRoot, "sources", "sessions"), { recursive: true });
|
|
158
|
+
|
|
159
|
+
const indexPath = path.join(memoryRoot, "wiki", "index.md");
|
|
160
|
+
const exists = await fs
|
|
161
|
+
.access(indexPath)
|
|
162
|
+
.then(() => true)
|
|
163
|
+
.catch(() => false);
|
|
164
|
+
if (!exists) {
|
|
165
|
+
await fs.writeFile(
|
|
166
|
+
indexPath,
|
|
167
|
+
[
|
|
168
|
+
"---",
|
|
169
|
+
'title: "Memory Index"',
|
|
170
|
+
`date: ${dateStamp()}`,
|
|
171
|
+
'tags: ["memory", "index"]',
|
|
172
|
+
"---",
|
|
173
|
+
"",
|
|
174
|
+
"This is the root index for the agent-maintained LLM Wiki memory.",
|
|
175
|
+
"",
|
|
176
|
+
].join("\n"),
|
|
177
|
+
"utf-8",
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
134
182
|
/**
|
|
135
183
|
* 读取指定记忆文件(支持行区间)。
|
|
136
184
|
*/
|
|
137
|
-
export async function
|
|
185
|
+
export async function readMemory(
|
|
138
186
|
context: AgentContext,
|
|
139
|
-
payload:
|
|
140
|
-
): Promise<
|
|
187
|
+
payload: MemoryReadPayload,
|
|
188
|
+
): Promise<MemoryReadResponse> {
|
|
141
189
|
const requestedPath = String(payload.path || "").trim();
|
|
142
190
|
if (!requestedPath) {
|
|
143
191
|
throw new Error("path is required");
|
|
@@ -165,9 +213,142 @@ export async function getMemory(
|
|
|
165
213
|
}
|
|
166
214
|
|
|
167
215
|
/**
|
|
168
|
-
*
|
|
216
|
+
* 读取 wiki index 内容。
|
|
169
217
|
*/
|
|
170
|
-
export async function
|
|
171
|
-
const
|
|
172
|
-
await
|
|
218
|
+
export async function readWikiIndex(context: AgentContext): Promise<string> {
|
|
219
|
+
const indexPath = path.join(context.rootPath, ".downcity", "memory", "wiki", "index.md");
|
|
220
|
+
return await readTextIfExists(indexPath);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 归档手动 source。
|
|
225
|
+
*/
|
|
226
|
+
export async function appendManualSource(
|
|
227
|
+
context: AgentContext,
|
|
228
|
+
content: string,
|
|
229
|
+
source?: string,
|
|
230
|
+
): Promise<{ path: string; writtenChars: number }> {
|
|
231
|
+
const absPath = path.join(
|
|
232
|
+
context.rootPath,
|
|
233
|
+
".downcity",
|
|
234
|
+
"memory",
|
|
235
|
+
"sources",
|
|
236
|
+
"manual",
|
|
237
|
+
`${dateStamp()}.md`,
|
|
238
|
+
);
|
|
239
|
+
await fs.mkdir(path.dirname(absPath), { recursive: true });
|
|
240
|
+
const entry = buildSourceEntry(content, source);
|
|
241
|
+
await fs.appendFile(absPath, `\n${entry}`, "utf-8");
|
|
242
|
+
return {
|
|
243
|
+
path: toRelPath(context.rootPath, absPath),
|
|
244
|
+
writtenChars: entry.length,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 写入 session source。
|
|
250
|
+
*/
|
|
251
|
+
export async function writeSessionSource(
|
|
252
|
+
context: AgentContext,
|
|
253
|
+
sessionId: string,
|
|
254
|
+
content: string,
|
|
255
|
+
): Promise<{ path: string; writtenChars: number }> {
|
|
256
|
+
const safeSessionId = slugify(sessionId);
|
|
257
|
+
const absPath = path.join(
|
|
258
|
+
context.rootPath,
|
|
259
|
+
".downcity",
|
|
260
|
+
"memory",
|
|
261
|
+
"sources",
|
|
262
|
+
"sessions",
|
|
263
|
+
`${safeSessionId}.md`,
|
|
264
|
+
);
|
|
265
|
+
const text = [
|
|
266
|
+
"---",
|
|
267
|
+
`title: ${JSON.stringify(`Session ${sessionId}`)}`,
|
|
268
|
+
`date: ${dateStamp()}`,
|
|
269
|
+
'tags: ["memory-source", "session"]',
|
|
270
|
+
"---",
|
|
271
|
+
"",
|
|
272
|
+
`# Session ${sessionId}`,
|
|
273
|
+
"",
|
|
274
|
+
content.trim(),
|
|
275
|
+
"",
|
|
276
|
+
].join("\n");
|
|
277
|
+
await fs.mkdir(path.dirname(absPath), { recursive: true });
|
|
278
|
+
await fs.writeFile(absPath, text, "utf-8");
|
|
279
|
+
return {
|
|
280
|
+
path: toRelPath(context.rootPath, absPath),
|
|
281
|
+
writtenChars: text.length,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* 写入完整 wiki page。
|
|
287
|
+
*/
|
|
288
|
+
export async function writeWikiPage(
|
|
289
|
+
context: AgentContext,
|
|
290
|
+
draft: MemoryWikiPageDraft,
|
|
291
|
+
): Promise<{ path: string; writtenChars: number }> {
|
|
292
|
+
const resolved = resolveWikiPath(context, draft.path, draft.title);
|
|
293
|
+
const content = ensureFrontmatter(draft);
|
|
294
|
+
await fs.mkdir(path.dirname(resolved.absPath), { recursive: true });
|
|
295
|
+
await fs.writeFile(resolved.absPath, content, "utf-8");
|
|
296
|
+
return {
|
|
297
|
+
path: resolved.relPath,
|
|
298
|
+
writtenChars: content.length,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* 追加写入 wiki page。
|
|
304
|
+
*/
|
|
305
|
+
export async function appendWikiPage(
|
|
306
|
+
context: AgentContext,
|
|
307
|
+
payload: {
|
|
308
|
+
path?: string;
|
|
309
|
+
title?: string;
|
|
310
|
+
content: string;
|
|
311
|
+
sourcePath?: string;
|
|
312
|
+
instruction?: string;
|
|
313
|
+
},
|
|
314
|
+
): Promise<{ path: string; writtenChars: number }> {
|
|
315
|
+
const resolved = resolveWikiPath(context, payload.path, payload.title);
|
|
316
|
+
await fs.mkdir(path.dirname(resolved.absPath), { recursive: true });
|
|
317
|
+
const exists = await fs
|
|
318
|
+
.access(resolved.absPath)
|
|
319
|
+
.then(() => true)
|
|
320
|
+
.catch(() => false);
|
|
321
|
+
if (!exists) {
|
|
322
|
+
await writeWikiPage(context, {
|
|
323
|
+
path: resolved.relPath,
|
|
324
|
+
title: payload.title || "Memory Inbox",
|
|
325
|
+
content: "This page is maintained by MemoryPlugin fallback writes.",
|
|
326
|
+
tags: ["memory"],
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
const entry = buildFallbackWikiEntry(payload);
|
|
330
|
+
await fs.appendFile(resolved.absPath, `\n${entry}`, "utf-8");
|
|
331
|
+
return {
|
|
332
|
+
path: resolved.relPath,
|
|
333
|
+
writtenChars: entry.length,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* 使用 fallback 方式修订 wiki page。
|
|
339
|
+
*/
|
|
340
|
+
export async function appendMemoryRevision(
|
|
341
|
+
context: AgentContext,
|
|
342
|
+
payload: MemoryRevisePayload,
|
|
343
|
+
): Promise<MemoryReviseResponse> {
|
|
344
|
+
const written = await appendWikiPage(context, {
|
|
345
|
+
path: payload.path,
|
|
346
|
+
content: String(payload.evidence || "").trim() || "(no evidence)",
|
|
347
|
+
instruction: payload.instruction,
|
|
348
|
+
});
|
|
349
|
+
return {
|
|
350
|
+
path: written.path,
|
|
351
|
+
mode: "appended",
|
|
352
|
+
writtenChars: written.writtenChars,
|
|
353
|
+
};
|
|
173
354
|
}
|