dsh-mnemon 0.5.8 → 0.5.10
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/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/bin/repair-legacy-session.mjs +547 -25
- package/lib/client.js +169 -8
- package/lib/index.js +242 -52
- package/lib/types/src/client/locales.d.ts +32 -0
- package/lib/types/src/host/protocol.d.ts +38 -0
- package/package.json +4 -4
package/lib/index.js
CHANGED
|
@@ -20,6 +20,11 @@ import { spawn } from "node:child_process";
|
|
|
20
20
|
import { StringDecoder } from "node:string_decoder";
|
|
21
21
|
import { z as z$1 } from "zod";
|
|
22
22
|
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
23
|
+
//#region src/host/view-protocol.ts
|
|
24
|
+
const MNEMON_VIEW_CHANNEL = "/dsh-mnemon-view";
|
|
25
|
+
const MNEMON_VIEW_WRITE_CHANNEL = "/dsh-mnemon-view-settings";
|
|
26
|
+
const MNEMON_VIEW_SETTINGS_NAMESPACE = "mnemon-view";
|
|
27
|
+
//#endregion
|
|
23
28
|
//#region src/host/display-mode.ts
|
|
24
29
|
/** Keep the historical misspelling at input boundaries, never in UI or runtime state. */
|
|
25
30
|
function normalizeDisplayMode(value) {
|
|
@@ -28,11 +33,6 @@ function normalizeDisplayMode(value) {
|
|
|
28
33
|
throw new Error("dsh-mnemon: displayMode must be sidebar or builtin (legacy buildin is accepted)");
|
|
29
34
|
}
|
|
30
35
|
//#endregion
|
|
31
|
-
//#region src/host/view-protocol.ts
|
|
32
|
-
const MNEMON_VIEW_CHANNEL = "/dsh-mnemon-view";
|
|
33
|
-
const MNEMON_VIEW_WRITE_CHANNEL = "/dsh-mnemon-view-settings";
|
|
34
|
-
const MNEMON_VIEW_SETTINGS_NAMESPACE = "mnemon-view";
|
|
35
|
-
//#endregion
|
|
36
36
|
//#region src/host/protocol.ts
|
|
37
37
|
/** Starter Entry ids remain reserved when DSH nests them under an include. */
|
|
38
38
|
function isDefaultSourceInstance(instanceKey, sourceTypeId) {
|
|
@@ -48,6 +48,15 @@ const MNEMON_SETTINGS_NAMESPACE = "mnemon";
|
|
|
48
48
|
function isWorkspaceStorageScope(scope) {
|
|
49
49
|
return scope === "workspace" || scope === "workspaces";
|
|
50
50
|
}
|
|
51
|
+
const DEFAULT_IDLE_REVIEW = {
|
|
52
|
+
enabled: true,
|
|
53
|
+
provider: "spawn",
|
|
54
|
+
fallback: "spawn",
|
|
55
|
+
minIntervalMs: 3e5,
|
|
56
|
+
maxPerSession: 20,
|
|
57
|
+
maxContextChars: 24e3,
|
|
58
|
+
maxTokens: 4096
|
|
59
|
+
};
|
|
51
60
|
const CATEGORIES = [
|
|
52
61
|
"preference",
|
|
53
62
|
"decision",
|
|
@@ -151,6 +160,15 @@ const RuntimeMemorySchema = z.object({
|
|
|
151
160
|
userLimitBytes: z.number().step(1).min(1).max(MAX_RUNTIME_MEMORY_LIMIT_BYTES).default(DEFAULT_RUNTIME_USER_LIMIT_BYTES),
|
|
152
161
|
maintenanceMaxTokens: z.number().step(1).min(1).max(MAX_RUNTIME_MAINTENANCE_MAX_TOKENS).default(DEFAULT_RUNTIME_MAINTENANCE_MAX_TOKENS)
|
|
153
162
|
});
|
|
163
|
+
const IdleReviewSchema = z.object({
|
|
164
|
+
enabled: z.boolean().default(DEFAULT_IDLE_REVIEW.enabled),
|
|
165
|
+
provider: z.union(["spawn", "fork"]).default(DEFAULT_IDLE_REVIEW.provider),
|
|
166
|
+
fallback: z.union(["spawn", "skip"]).default(DEFAULT_IDLE_REVIEW.fallback),
|
|
167
|
+
minIntervalMs: z.number().step(1).min(5e3).max(864e5).default(DEFAULT_IDLE_REVIEW.minIntervalMs),
|
|
168
|
+
maxPerSession: z.number().step(1).min(0).max(200).default(DEFAULT_IDLE_REVIEW.maxPerSession),
|
|
169
|
+
maxContextChars: z.number().step(1).min(1e3).max(1e6).default(DEFAULT_IDLE_REVIEW.maxContextChars),
|
|
170
|
+
maxTokens: z.number().step(1).min(128).max(131072).default(DEFAULT_IDLE_REVIEW.maxTokens)
|
|
171
|
+
});
|
|
154
172
|
const MemoryParticipationModeSchema = z.union([
|
|
155
173
|
"off",
|
|
156
174
|
"manual",
|
|
@@ -224,6 +242,7 @@ const Config = z.object({
|
|
|
224
242
|
recallMode: z.union(["guided", "off"]).default("guided"),
|
|
225
243
|
writebackMode: z.union(["guided", "off"]).default("guided"),
|
|
226
244
|
idleReviewMs: z.number().step(1).min(5e3).max(6e5).default(DEFAULT_IDLE_REVIEW_MS),
|
|
245
|
+
idleReview: IdleReviewSchema.default(DEFAULT_IDLE_REVIEW),
|
|
227
246
|
conversationInteraction: z.object({
|
|
228
247
|
toolviews: z.boolean().default(false),
|
|
229
248
|
turnBar: z.boolean().default(true),
|
|
@@ -394,6 +413,7 @@ function resolveConfig(config = {}) {
|
|
|
394
413
|
recallMode: config.recallMode ?? "guided",
|
|
395
414
|
writebackMode: config.writebackMode ?? "guided",
|
|
396
415
|
idleReviewMs: config.idleReviewMs ?? 3e4,
|
|
416
|
+
idleReview: IdleReviewSchema(config.idleReview ?? {}),
|
|
397
417
|
conversationInteraction: {
|
|
398
418
|
toolviews: config.conversationInteraction?.toolviews ?? false,
|
|
399
419
|
turnBar: config.conversationInteraction?.turnBar ?? true,
|
|
@@ -424,7 +444,7 @@ const COMPONENT_ORDER = [
|
|
|
424
444
|
];
|
|
425
445
|
const BODY_ID = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
426
446
|
const SQLITE_HEADER = Buffer.from("SQLite format 3\0", "binary");
|
|
427
|
-
function record$
|
|
447
|
+
function record$3(value) {
|
|
428
448
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
429
449
|
}
|
|
430
450
|
function utf8(bytes, label) {
|
|
@@ -467,7 +487,7 @@ function componentsForScope(scope) {
|
|
|
467
487
|
return [scope];
|
|
468
488
|
}
|
|
469
489
|
function parseManifest(value) {
|
|
470
|
-
const manifest = record$
|
|
490
|
+
const manifest = record$3(value);
|
|
471
491
|
if (manifest?.format !== "mnemonpack" || manifest.version !== 1) throw new Error("unsupported Mnemon Pack format or version");
|
|
472
492
|
if (manifest.scope !== "full" && !COMPONENT_ORDER.includes(manifest.scope)) throw new Error("Mnemon Pack scope is invalid");
|
|
473
493
|
if (typeof manifest.exportedAt !== "string") throw new Error("Mnemon Pack exportedAt is invalid");
|
|
@@ -476,11 +496,11 @@ function parseManifest(value) {
|
|
|
476
496
|
if (components.length === 0 || new Set(components).size !== components.length || components.some((component) => !COMPONENT_ORDER.includes(component))) throw new Error("Mnemon Pack components are invalid");
|
|
477
497
|
const expected = componentsForScope(manifest.scope);
|
|
478
498
|
if (components.length !== expected.length || expected.some((component) => !components.includes(component))) throw new Error("Mnemon Pack scope does not match its components");
|
|
479
|
-
const source = record$
|
|
499
|
+
const source = record$3(manifest.source);
|
|
480
500
|
if (source?.plugin !== "dsh-mnemon" || typeof source.pluginVersion !== "string") throw new Error("Mnemon Pack source is invalid");
|
|
481
501
|
if (!Array.isArray(manifest.summary)) throw new Error("Mnemon Pack summary is invalid");
|
|
482
502
|
const summary = manifest.summary.map((entry) => {
|
|
483
|
-
const item = record$
|
|
503
|
+
const item = record$3(entry);
|
|
484
504
|
const component = item?.component;
|
|
485
505
|
if (!COMPONENT_ORDER.includes(component) || !Number.isSafeInteger(item?.files) || !Number.isSafeInteger(item?.bytes) || !Number.isSafeInteger(item?.items) || Number(item?.files) < 0 || Number(item?.bytes) < 0 || Number(item?.items) < 0) throw new Error("Mnemon Pack summary entry is invalid");
|
|
486
506
|
return {
|
|
@@ -530,8 +550,8 @@ function parseArchive(base64, runtimeLimits = RUNTIME_MEMORY_LIMITS) {
|
|
|
530
550
|
if (path !== "manifest.json" && path !== "checksums.json" && !allowedPayloadPath(path)) throw new Error(`unsupported Mnemon Pack entry: ${path}`);
|
|
531
551
|
}
|
|
532
552
|
const manifest = parseManifest(json$1(files["manifest.json"], "manifest.json"));
|
|
533
|
-
const checksumValue = record$
|
|
534
|
-
const checksumFiles = record$
|
|
553
|
+
const checksumValue = record$3(json$1(files["checksums.json"], "checksums.json"));
|
|
554
|
+
const checksumFiles = record$3(checksumValue?.files);
|
|
535
555
|
if (checksumValue?.algorithm !== "sha256" || checksumFiles === void 0) throw new Error("Mnemon Pack checksums are invalid");
|
|
536
556
|
const payloadNames = names.filter((path) => path.startsWith("payload/")).sort();
|
|
537
557
|
if (Object.keys(checksumFiles).length !== payloadNames.length) throw new Error("Mnemon Pack checksum inventory does not match the payload");
|
|
@@ -554,10 +574,10 @@ function parseArchive(base64, runtimeLimits = RUNTIME_MEMORY_LIMITS) {
|
|
|
554
574
|
};
|
|
555
575
|
}
|
|
556
576
|
function parseRuntime(value, limits = RUNTIME_MEMORY_LIMITS) {
|
|
557
|
-
const source = record$
|
|
577
|
+
const source = record$3(value);
|
|
558
578
|
if (source?.version !== RUNTIME_MEMORY_VERSION || !Array.isArray(source.entries)) throw new Error("runtime memories.json is invalid");
|
|
559
579
|
const entries = source.entries.map((raw) => {
|
|
560
|
-
const entry = record$
|
|
580
|
+
const entry = record$3(raw);
|
|
561
581
|
if (typeof entry?.content !== "string" || entry.target !== "memory" && entry.target !== "user" || ![
|
|
562
582
|
"critical",
|
|
563
583
|
"normal",
|
|
@@ -588,13 +608,13 @@ function runtimeProjection(entries, target) {
|
|
|
588
608
|
return content === "" ? "" : `${content}\n`;
|
|
589
609
|
}
|
|
590
610
|
function parseDocumentIndex(value) {
|
|
591
|
-
const index = record$
|
|
611
|
+
const index = record$3(value);
|
|
592
612
|
if (index?.version !== DOCUMENTS_VERSION || !Array.isArray(index.documents)) throw new Error("Documents index.json is invalid");
|
|
593
613
|
const ids = /* @__PURE__ */ new Set();
|
|
594
614
|
return {
|
|
595
615
|
version: 1,
|
|
596
616
|
documents: index.documents.map((raw) => {
|
|
597
|
-
const item = record$
|
|
617
|
+
const item = record$3(raw);
|
|
598
618
|
if (typeof item?.id !== "string" || item.id.trim() === "" || ids.has(item.id)) throw new Error("Documents index contains an invalid or duplicate id");
|
|
599
619
|
if (typeof item.title !== "string" || typeof item.description !== "string" || item.status !== "active" && item.status !== "archived") throw new Error("Documents index contains an invalid record");
|
|
600
620
|
if (typeof item.filename !== "string" || basename(item.filename) !== item.filename || !/^[a-zA-Z0-9._-]+\.md$/u.test(item.filename)) throw new Error("Documents index contains an unsafe filename");
|
|
@@ -624,13 +644,13 @@ function parseDocumentIndex(value) {
|
|
|
624
644
|
};
|
|
625
645
|
}
|
|
626
646
|
function parseRegistry(value) {
|
|
627
|
-
const registry = record$
|
|
647
|
+
const registry = record$3(value);
|
|
628
648
|
if (registry?.version !== 1 || !Array.isArray(registry.bodies)) throw new Error("Memory Space registry is invalid");
|
|
629
649
|
const ids = /* @__PURE__ */ new Set();
|
|
630
650
|
return {
|
|
631
651
|
version: 1,
|
|
632
652
|
bodies: registry.bodies.map((raw) => {
|
|
633
|
-
const body = record$
|
|
653
|
+
const body = record$3(raw);
|
|
634
654
|
if (typeof body?.id !== "string" || !BODY_ID.test(body.id) || ids.has(body.id)) throw new Error("Memory Space registry contains an invalid or duplicate id");
|
|
635
655
|
if (typeof body.name !== "string" || body.name.trim() === "" || body.name.length > 100 || typeof body.description !== "string" || body.description.length > 1e3) throw new Error("Memory Space registry contains invalid metadata");
|
|
636
656
|
if (typeof body.createdAt !== "string" || typeof body.updatedAt !== "string") throw new Error("Memory Space registry contains invalid timestamps");
|
|
@@ -1263,7 +1283,7 @@ function safeBytes(path) {
|
|
|
1263
1283
|
function readJson(path) {
|
|
1264
1284
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
1265
1285
|
}
|
|
1266
|
-
function record$
|
|
1286
|
+
function record$2(value) {
|
|
1267
1287
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1268
1288
|
}
|
|
1269
1289
|
function missing(kind, path) {
|
|
@@ -1281,9 +1301,9 @@ function runtimeArea(root) {
|
|
|
1281
1301
|
const source = join(path, "memories.json");
|
|
1282
1302
|
if (!existsSync(source)) return missing("runtime", path);
|
|
1283
1303
|
try {
|
|
1284
|
-
const file = record$
|
|
1304
|
+
const file = record$2(readJson(source));
|
|
1285
1305
|
if (file === void 0 || !Array.isArray(file.entries)) throw new Error("memories.json is not a valid runtime-memory source");
|
|
1286
|
-
const entries = file.entries.map(record$
|
|
1306
|
+
const entries = file.entries.map(record$2).filter((entry) => entry !== void 0);
|
|
1287
1307
|
const userEntries = entries.filter((entry) => entry.target === "user").length;
|
|
1288
1308
|
const memoryEntries = entries.filter((entry) => entry.target === "memory").length;
|
|
1289
1309
|
const projectionsHealthy = existsSync(join(path, "USER.md")) && existsSync(join(path, "MEMORY.md"));
|
|
@@ -1318,8 +1338,8 @@ function memorySpacesArea(root) {
|
|
|
1318
1338
|
if (!existsSync(path)) return missing("memory-bodies", path);
|
|
1319
1339
|
try {
|
|
1320
1340
|
const registryPath = join(path, ".dsh-memory-bodies.json");
|
|
1321
|
-
const registry = existsSync(registryPath) ? record$
|
|
1322
|
-
const bodies = Array.isArray(registry?.bodies) ? registry.bodies.map(record$
|
|
1341
|
+
const registry = existsSync(registryPath) ? record$2(readJson(registryPath)) : void 0;
|
|
1342
|
+
const bodies = Array.isArray(registry?.bodies) ? registry.bodies.map(record$2).filter((body) => body !== void 0) : [];
|
|
1323
1343
|
const databaseCount = readdirSync(path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && existsSync(join(path, entry.name, "mnemon.db"))).length;
|
|
1324
1344
|
const activeCount = bodies.filter((body) => body.active === true).length;
|
|
1325
1345
|
const invalidRegistry = existsSync(registryPath) && (registry?.version !== 1 || !Array.isArray(registry.bodies));
|
|
@@ -1354,9 +1374,9 @@ function documentsArea(root) {
|
|
|
1354
1374
|
const indexPath = join(path, "index.json");
|
|
1355
1375
|
if (!existsSync(indexPath)) return missing("documents", path);
|
|
1356
1376
|
try {
|
|
1357
|
-
const index = record$
|
|
1377
|
+
const index = record$2(readJson(indexPath));
|
|
1358
1378
|
if (index === void 0 || !Array.isArray(index.documents)) throw new Error("index.json is not a valid Documents index");
|
|
1359
|
-
const documents = index.documents.map(record$
|
|
1379
|
+
const documents = index.documents.map(record$2).filter((document) => document !== void 0);
|
|
1360
1380
|
const active = documents.filter((document) => document.status === "active").length;
|
|
1361
1381
|
const archived = documents.filter((document) => document.status === "archived").length;
|
|
1362
1382
|
return {
|
|
@@ -1392,9 +1412,9 @@ function stateArea(root) {
|
|
|
1392
1412
|
let providerConnections = 0;
|
|
1393
1413
|
let providerServices = 0;
|
|
1394
1414
|
if (existsSync(providerRegistry)) try {
|
|
1395
|
-
const registry = record$
|
|
1415
|
+
const registry = record$2(readJson(providerRegistry));
|
|
1396
1416
|
providerConnections = Array.isArray(registry?.bodies) ? registry.bodies.length : 0;
|
|
1397
|
-
providerServices = record$
|
|
1417
|
+
providerServices = record$2(registry?.services) === void 0 ? 0 : Object.keys(record$2(registry?.services)).length;
|
|
1398
1418
|
} catch {}
|
|
1399
1419
|
return {
|
|
1400
1420
|
kind: "state",
|
|
@@ -2615,12 +2635,21 @@ function hostSessionEventAt(session, seq) {
|
|
|
2615
2635
|
//#region src/host/review-tools.ts
|
|
2616
2636
|
const startingReview = new AsyncLocalStorage();
|
|
2617
2637
|
/**
|
|
2638
|
+
* The published Agent Teams alpha.2 tool suite installs its policy before a
|
|
2639
|
+
* provider publishes a child descriptor. Both rc.2 in-process providers then
|
|
2640
|
+
* lose membership on step two. Inspect public services/capabilities only and
|
|
2641
|
+
* skip before creating a child; do not remove another plugin's policy.
|
|
2642
|
+
*/
|
|
2643
|
+
function idleReviewBlockReason(parent) {
|
|
2644
|
+
return parent.ctx?.get?.("agentTeams") !== void 0 && parent.ctx.tools?.get?.("spawn_teammate", parent) !== void 0 ? "agent-team" : void 0;
|
|
2645
|
+
}
|
|
2646
|
+
/**
|
|
2618
2647
|
* DSH restrict() filters inherited capabilities, leaving own-scope plugin tools
|
|
2619
2648
|
* visible. Attach its monotonic execution guard during publication, before a
|
|
2620
2649
|
* review child can run. Async context attributes concurrent provider starts;
|
|
2621
2650
|
* public registry ownership verifies the exact causal parent.
|
|
2622
2651
|
*/
|
|
2623
|
-
async function startGuardedReview(host, parent, toolNames, start) {
|
|
2652
|
+
async function startGuardedReview(host, parent, toolNames, start, published) {
|
|
2624
2653
|
const agents = host.agents;
|
|
2625
2654
|
if (typeof agents?.isOwnedBy !== "function") throw new Error("Mnemon review requires DSH Agent ownership and scoped tool guard support");
|
|
2626
2655
|
const pending = Symbol("Mnemon review publication");
|
|
@@ -2639,6 +2668,7 @@ async function startGuardedReview(host, parent, toolNames, start) {
|
|
|
2639
2668
|
});
|
|
2640
2669
|
if (typeof dispose !== "function") throw new Error("Mnemon review tool guard did not return a disposer");
|
|
2641
2670
|
guards.set(agent, dispose);
|
|
2671
|
+
published?.(agent);
|
|
2642
2672
|
} catch (error) {
|
|
2643
2673
|
attachmentError = error;
|
|
2644
2674
|
throw error;
|
|
@@ -2692,6 +2722,51 @@ async function startGuardedReview(host, parent, toolNames, start) {
|
|
|
2692
2722
|
}
|
|
2693
2723
|
}
|
|
2694
2724
|
//#endregion
|
|
2725
|
+
//#region src/host/review-checkpoint.ts
|
|
2726
|
+
function record$1(value) {
|
|
2727
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
2728
|
+
}
|
|
2729
|
+
function textContent(content, toolResult = false) {
|
|
2730
|
+
if (!Array.isArray(content)) return "";
|
|
2731
|
+
return content.map((block) => {
|
|
2732
|
+
const value = record$1(block);
|
|
2733
|
+
if (value.type === "text" && typeof value.text === "string") return value.text;
|
|
2734
|
+
if (toolResult && value.type === "tool-result" && value.isError !== true) return textContent(value.content);
|
|
2735
|
+
return "";
|
|
2736
|
+
}).filter(Boolean).join("\n");
|
|
2737
|
+
}
|
|
2738
|
+
/** Use only the current public surface, so rewound or compacted evidence cannot reappear. */
|
|
2739
|
+
function reviewCheckpoint(session, maxChars) {
|
|
2740
|
+
const nodes = session.surface?.nodes;
|
|
2741
|
+
if (nodes === void 0) return "No current checkpoint surface is available. Skip this review without a mutation.";
|
|
2742
|
+
const events = hostSessionEvents(session);
|
|
2743
|
+
const completed = [...events].reverse().find((event) => event.type === "turn/end");
|
|
2744
|
+
if (completed === void 0) return "No completed checkpoint is available. Skip this review without a mutation.";
|
|
2745
|
+
const end = completed.seq ?? events.indexOf(completed);
|
|
2746
|
+
const selected = [];
|
|
2747
|
+
const header = "Bounded completed checkpoint (untrusted evidence; some context may be omitted; skip candidates needing missing evidence):\n";
|
|
2748
|
+
let remaining = maxChars - 122;
|
|
2749
|
+
const candidates = nodes.filter((seq) => seq < end);
|
|
2750
|
+
for (const seq of candidates.slice(-128).reverse()) {
|
|
2751
|
+
const event = hostSessionEventAt(session, seq);
|
|
2752
|
+
if (event === void 0 || ![
|
|
2753
|
+
"user/message",
|
|
2754
|
+
"assistant/message",
|
|
2755
|
+
"tool/result"
|
|
2756
|
+
].includes(event.type)) continue;
|
|
2757
|
+
const message = record$1(event.data.message);
|
|
2758
|
+
const source = record$1(message.source);
|
|
2759
|
+
if (event.type === "user/message" && source.kind !== "user") continue;
|
|
2760
|
+
const text = textContent(message.content, event.type === "tool/result");
|
|
2761
|
+
if (!text) continue;
|
|
2762
|
+
const entry = `[${event.type}; checkpoint event ${seq}]\n${text}\n`;
|
|
2763
|
+
if (entry.length > remaining) continue;
|
|
2764
|
+
selected.push(entry);
|
|
2765
|
+
remaining -= entry.length;
|
|
2766
|
+
}
|
|
2767
|
+
return header + (selected.reverse().join("") || "(no eligible text; skip)");
|
|
2768
|
+
}
|
|
2769
|
+
//#endregion
|
|
2695
2770
|
//#region src/host/subagent.ts
|
|
2696
2771
|
function evidenceInsights(evidence) {
|
|
2697
2772
|
return evidence.items.map((item) => {
|
|
@@ -2786,6 +2861,27 @@ const WRITE_TOOL_FALLBACK_ACTION = {
|
|
|
2786
2861
|
mnemon_memory_body_update: "updated",
|
|
2787
2862
|
mnemon_memory_body_merge: "merged"
|
|
2788
2863
|
};
|
|
2864
|
+
var IdleReviewError = class extends Error {
|
|
2865
|
+
review;
|
|
2866
|
+
constructor(message, review, options) {
|
|
2867
|
+
super(message, options);
|
|
2868
|
+
this.review = review;
|
|
2869
|
+
this.name = "IdleReviewError";
|
|
2870
|
+
}
|
|
2871
|
+
};
|
|
2872
|
+
function reviewReceipt(receipt) {
|
|
2873
|
+
if (!mutationResultCommitted(receipt.value)) return void 0;
|
|
2874
|
+
const value = object$4(receipt.value);
|
|
2875
|
+
const args = optionalObject(receipt.arguments);
|
|
2876
|
+
const document = optionalObject(value.document);
|
|
2877
|
+
return {
|
|
2878
|
+
tool: receipt.name,
|
|
2879
|
+
action: typeof value.action === "string" ? value.action : "committed",
|
|
2880
|
+
...typeof document?.id === "string" ? { documentId: document.id } : {},
|
|
2881
|
+
...typeof args?.target === "string" ? { target: args.target } : {},
|
|
2882
|
+
...typeof value.revision === "string" ? { revision: value.revision } : {}
|
|
2883
|
+
};
|
|
2884
|
+
}
|
|
2789
2885
|
const WRITE_SCHEMA = {
|
|
2790
2886
|
type: "object",
|
|
2791
2887
|
properties: {
|
|
@@ -3727,7 +3823,11 @@ var MnemonSubagentCoordinator = class {
|
|
|
3727
3823
|
return {
|
|
3728
3824
|
source,
|
|
3729
3825
|
cleanup,
|
|
3730
|
-
memoryBodyIds: new Set(strings(object$4(grant.value).memoryBodyIds))
|
|
3826
|
+
memoryBodyIds: new Set(strings(object$4(grant.value).memoryBodyIds)),
|
|
3827
|
+
writeScope: {
|
|
3828
|
+
viewId: view.id,
|
|
3829
|
+
grant
|
|
3830
|
+
}
|
|
3731
3831
|
};
|
|
3732
3832
|
}
|
|
3733
3833
|
runtimeModel(scope, parent, signal, operation, label, prompt, schema, persona) {
|
|
@@ -3781,7 +3881,28 @@ ${naturalRequest(request)}`;
|
|
|
3781
3881
|
};
|
|
3782
3882
|
}
|
|
3783
3883
|
async review(parent, signal) {
|
|
3784
|
-
|
|
3884
|
+
if (idleReviewBlockReason(parent) !== void 0) return {
|
|
3885
|
+
delegated: false,
|
|
3886
|
+
action: "skipped",
|
|
3887
|
+
summary: "Idle review is paused while Agent Teams tools are active because the published child policy is incompatible.",
|
|
3888
|
+
documentIds: []
|
|
3889
|
+
};
|
|
3890
|
+
const config = this.runtimeSource.config.idleReview;
|
|
3891
|
+
let preferred = config.provider;
|
|
3892
|
+
if (preferred === "fork") try {
|
|
3893
|
+
this.provider("fork");
|
|
3894
|
+
} catch (error) {
|
|
3895
|
+
if (config.fallback === "skip") return {
|
|
3896
|
+
delegated: false,
|
|
3897
|
+
action: "skipped",
|
|
3898
|
+
summary: "Fork provider unavailable; idle review skipped.",
|
|
3899
|
+
documentIds: []
|
|
3900
|
+
};
|
|
3901
|
+
preferred = "spawn";
|
|
3902
|
+
}
|
|
3903
|
+
const prompt = preferred === "fork" ? "Review the inherited completed checkpoint now." : reviewCheckpoint(parent.session, config.maxContextChars);
|
|
3904
|
+
const persona = preferred === "fork" ? REVIEW_PERSONA : REVIEW_PERSONA.replaceAll("inherited", "supplied bounded");
|
|
3905
|
+
const { provider, runId, result } = await this.delegate(parent, "review", "Mnemon idle checkpoint review", prompt, REVIEW_TOOLS, WRITE_SCHEMA, signal, preferred, persona, { terminalTools: ["mnemon_runtime_memory", "mnemon_document_create"] });
|
|
3785
3906
|
const value = object$4(result.structured);
|
|
3786
3907
|
return {
|
|
3787
3908
|
delegated: true,
|
|
@@ -3973,13 +4094,27 @@ ${naturalRequest(request)}`;
|
|
|
3973
4094
|
if (request.target === "user") return this.compactUserAndCommit(context, request, plan, signal);
|
|
3974
4095
|
const archive = await context.memorySpaces();
|
|
3975
4096
|
const memoryService = archive.source;
|
|
3976
|
-
|
|
4097
|
+
let allowed = archive.memoryBodyIds;
|
|
4098
|
+
const readDirectory = async () => {
|
|
4099
|
+
const catalog = await memoryService.read("body-directory", archive.writeScope === void 0 ? null : { writeScope: archive.writeScope }, signal);
|
|
4100
|
+
allowed = archive.memoryBodyIds;
|
|
4101
|
+
if (catalog.writeScope !== void 0) {
|
|
4102
|
+
const scope = catalog.writeScope;
|
|
4103
|
+
if (archive.writeScope === void 0 || scope === null || scope.viewId !== archive.writeScope.viewId || scope.sourceInstanceKey !== archive.writeScope.grant.sourceInstanceKey || !Array.isArray(scope.memoryBodyIds) || scope.memoryBodyIds.length > 1e4 || scope.memoryBodyIds.some((id) => typeof id !== "string" || id.trim() === "" || id !== id.trim())) throw new Error("Runtime archival received an invalid Memory Spaces write scope; pending write was not committed; retry the same request in a new turn");
|
|
4104
|
+
allowed = new Set(scope.memoryBodyIds);
|
|
4105
|
+
}
|
|
4106
|
+
return catalog;
|
|
4107
|
+
};
|
|
4108
|
+
const catalog = await readDirectory();
|
|
4109
|
+
const writable = (body) => body.active && body.providerEnabled !== false && body.provider.capabilities.remember === true && (allowed === void 0 || allowed.has(body.id));
|
|
3977
4110
|
const eligible = (body) => writable(body) && body.provider.capabilities.writeMode === "exact" && body.provider.capabilities.forget === true;
|
|
3978
|
-
const catalog = await memoryService.read("body-directory", null, signal);
|
|
3979
4111
|
const eligibleBodies = catalog.items.filter(eligible);
|
|
3980
4112
|
if (eligibleBodies.length === 0) {
|
|
3981
|
-
const
|
|
3982
|
-
|
|
4113
|
+
const writableBodies = catalog.items.filter(writable);
|
|
4114
|
+
const unsupported = writableBodies.map((body) => `${body.id} (provider=${body.provider.id}, writeMode=${body.provider.capabilities.writeMode}, forget=${body.provider.capabilities.forget})`).join(", ");
|
|
4115
|
+
const reason = catalog.items.length === 0 ? "Memory Space body-directory is empty" : allowed?.size === 0 ? "current View write scope is empty" : allowed !== void 0 && catalog.items.some((body) => body.active && body.providerEnabled !== false && body.provider.capabilities.remember && !allowed?.has(body.id)) && writableBodies.length === 0 ? "current View write scope excludes the active writable Memory Spaces" : writableBodies.length === 0 ? "no active writable Memory Space in the authorized scope" : "authorized destinations lack exact writes or safe forget";
|
|
4116
|
+
const scope = archive.writeScope === void 0 ? "management" : `${archive.writeScope.grant.sourceInstanceKey}/${catalog.writeScope === void 0 ? "pinned-read" : "source-write"}`;
|
|
4117
|
+
throw new Error(`runtime memory archival requires an existing active writable Memory Space with exact writes and safe forget; ${reason}; scope=${scope}, catalog=${catalog.items.length}, authorized=${allowed?.size ?? "management"}, writable=${writableBodies.length}; pending write was not committed and existing runtime entries are unchanged; retry the same request in a new turn after activating a supported authorized Memory Space, or increase runtimeMemory.memoryLimitBytes${unsupported === "" ? "" : `; unsupported destinations: ${unsupported}`}`);
|
|
3983
4118
|
}
|
|
3984
4119
|
const eligibleById = new Map(eligibleBodies.map((body) => [body.id, body]));
|
|
3985
4120
|
const budget = compactedBudget(plan);
|
|
@@ -4043,7 +4178,7 @@ ${chunk.context}
|
|
|
4043
4178
|
...branches === void 0 ? {} : { branches }
|
|
4044
4179
|
}));
|
|
4045
4180
|
if ((await runtimeMemory.read("maintenance-plan", request, signal)).revision !== plan.revision) throw new Error("runtime memory changed while archival was running; no archive writes were attempted");
|
|
4046
|
-
const destinations = await
|
|
4181
|
+
const destinations = await readDirectory();
|
|
4047
4182
|
for (const memoryBodyId of new Set(routed.values())) if (!destinations.items.some((body) => body.id === memoryBodyId && eligible(body))) throw new Error(`runtime archive Memory Space ${memoryBodyId} is no longer eligible; no archive writes were attempted`);
|
|
4048
4183
|
signal.throwIfAborted();
|
|
4049
4184
|
context.assertWritable?.();
|
|
@@ -4067,6 +4202,7 @@ ${chunk.context}
|
|
|
4067
4202
|
for (const memoryBodyId of new Set(routed.values())) {
|
|
4068
4203
|
signal.throwIfAborted();
|
|
4069
4204
|
context.assertWritable?.();
|
|
4205
|
+
if (archive.writeScope !== void 0 && !(await readDirectory()).items.some((body) => body.id === memoryBodyId && eligible(body))) throw new Error(`runtime archive Memory Space ${memoryBodyId} is no longer authorized or eligible; pending write was not committed`);
|
|
4070
4206
|
const batch = sources.filter((source) => routed.get(source.index) === memoryBodyId);
|
|
4071
4207
|
const written = await memoryService.mutate("remember-many", { requests: batch.map((source) => requests[source.index - 1]) }, signal);
|
|
4072
4208
|
for (const [offset, result] of written.entries()) {
|
|
@@ -4252,8 +4388,11 @@ ${runtimeSnapshotContext("user", plan.entries)}`;
|
|
|
4252
4388
|
const staged = /* @__PURE__ */ new WeakMap();
|
|
4253
4389
|
const recoverableTools = new Set(recovery?.terminalTools ?? []);
|
|
4254
4390
|
const committedReceipts = [];
|
|
4391
|
+
const reviewReceipts = [];
|
|
4392
|
+
let reviewChildId;
|
|
4255
4393
|
const stagedReceipts = /* @__PURE__ */ new Map();
|
|
4256
4394
|
let run;
|
|
4395
|
+
let completed;
|
|
4257
4396
|
let failure;
|
|
4258
4397
|
let disposeResultObserver;
|
|
4259
4398
|
let releaseWorkflow;
|
|
@@ -4265,7 +4404,14 @@ ${runtimeSnapshotContext("user", plan.entries)}`;
|
|
|
4265
4404
|
}
|
|
4266
4405
|
if (this.disposed) throw new Error("dsh-mnemon subagent coordinator is disposed");
|
|
4267
4406
|
const observer = this.resultRuntime.on("tools/result", ((execution, result) => {
|
|
4268
|
-
if (
|
|
4407
|
+
if (!this.resultRequests.has(requestId)) return;
|
|
4408
|
+
if (operation === "review" && execution.agent?.id === reviewChildId && execution.name !== void 0 && recoverableTools.has(execution.name) && result.isError !== true && Object.hasOwn(result, "value")) reviewReceipts.push({
|
|
4409
|
+
agentId: execution.agent.id,
|
|
4410
|
+
name: execution.name,
|
|
4411
|
+
arguments: execution.arguments,
|
|
4412
|
+
value: result.value
|
|
4413
|
+
});
|
|
4414
|
+
if (signal.aborted) return;
|
|
4269
4415
|
if (execution.token !== void 0) {
|
|
4270
4416
|
const entries = stagedReceipts.get(execution.token);
|
|
4271
4417
|
if (entries !== void 0) {
|
|
@@ -4330,7 +4476,7 @@ ${runtimeSnapshotContext("user", plan.entries)}`;
|
|
|
4330
4476
|
Completion protocol: call \`${resultToolName}\` exactly once with requestId \`${requestId}\` and result matching this JSON schema:
|
|
4331
4477
|
${JSON.stringify(outputSchema)}
|
|
4332
4478
|
This is the only completion channel for this run. Do not finish with a plain-text answer. The requestId expires when this run finishes or is cancelled.`;
|
|
4333
|
-
const perOpMaxTokens = operation === "migration" || operation === "compaction" ? this.runtimeMaintenanceMaxTokensResolver?.() ?? 8192 : operation === "document-archive" ? 8192 : operation === "metadata-maintenance" ? 4096 : void 0;
|
|
4479
|
+
const perOpMaxTokens = operation === "migration" || operation === "compaction" ? this.runtimeMaintenanceMaxTokensResolver?.() ?? 8192 : operation === "document-archive" ? 8192 : operation === "metadata-maintenance" ? 4096 : operation === "review" ? this.runtimeSource.config.idleReview.maxTokens : void 0;
|
|
4334
4480
|
const fixed = this.taskAgentModelResolver?.();
|
|
4335
4481
|
const baseAgentOptions = perOpMaxTokens === void 0 ? void 0 : { maxTokens: perOpMaxTokens };
|
|
4336
4482
|
const resolvedAgentOptions = fixed === void 0 ? baseAgentOptions : {
|
|
@@ -4351,7 +4497,9 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
4351
4497
|
toolFilter: { allow: [...tools, resultToolName] },
|
|
4352
4498
|
persona: completionPersona
|
|
4353
4499
|
});
|
|
4354
|
-
run = operation === "review" ? await startGuardedReview(this.resultRuntime, parent, [...tools, resultToolName], start)
|
|
4500
|
+
run = operation === "review" ? await startGuardedReview(this.resultRuntime, parent, [...tools, resultToolName], start, (child) => {
|
|
4501
|
+
reviewChildId = child.id;
|
|
4502
|
+
}) : await start();
|
|
4355
4503
|
const activeRun = run;
|
|
4356
4504
|
const result = await activeRun.result;
|
|
4357
4505
|
if (captured !== void 0 && captured.agentId !== activeRun.id) throw new Error("Mnemon subagent result was recorded by a different child");
|
|
@@ -4363,11 +4511,12 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
4363
4511
|
throw new Error(`memory subagent stopped with ${result.stopReason}${detail === void 0 ? "" : `: ${detail}`}`);
|
|
4364
4512
|
}
|
|
4365
4513
|
if (structured === void 0) throw new Error("memory subagent completed without recording its result");
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4514
|
+
if (operation === "review" && [
|
|
4515
|
+
"failed",
|
|
4516
|
+
"partial",
|
|
4517
|
+
"unknown"
|
|
4518
|
+
].includes(String(object$4(structured).action))) throw new Error(`memory review reported ${object$4(structured).action}`);
|
|
4519
|
+
completed = {
|
|
4371
4520
|
provider,
|
|
4372
4521
|
runId: activeRun.id,
|
|
4373
4522
|
result: {
|
|
@@ -4378,8 +4527,14 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
4378
4527
|
};
|
|
4379
4528
|
} catch (error) {
|
|
4380
4529
|
this.counters.failures += 1;
|
|
4381
|
-
|
|
4382
|
-
|
|
4530
|
+
const receipts = reviewReceipts.map(reviewReceipt).filter((receipt) => receipt !== void 0);
|
|
4531
|
+
failure = operation === "review" ? new IdleReviewError(error instanceof Error ? error.message : String(error), {
|
|
4532
|
+
status: receipts.length > 0 ? "partial" : "failed",
|
|
4533
|
+
provider,
|
|
4534
|
+
...reviewChildId === void 0 ? {} : { runId: reviewChildId },
|
|
4535
|
+
receipts
|
|
4536
|
+
}, { cause: error }) : error;
|
|
4537
|
+
throw failure;
|
|
4383
4538
|
} finally {
|
|
4384
4539
|
this.resultRequests.delete(requestId);
|
|
4385
4540
|
let cleanupFailure;
|
|
@@ -4394,8 +4549,24 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
4394
4549
|
if (failure === void 0 && cleanupFailure === void 0) cleanupFailure = error;
|
|
4395
4550
|
}
|
|
4396
4551
|
releaseWorkflow?.();
|
|
4397
|
-
if (cleanupFailure !== void 0)
|
|
4552
|
+
if (cleanupFailure !== void 0) {
|
|
4553
|
+
this.counters.failures += 1;
|
|
4554
|
+
if (operation !== "review") throw cleanupFailure;
|
|
4555
|
+
const receipts = reviewReceipts.map(reviewReceipt).filter((receipt) => receipt !== void 0);
|
|
4556
|
+
throw new IdleReviewError(cleanupFailure instanceof Error ? cleanupFailure.message : String(cleanupFailure), {
|
|
4557
|
+
status: receipts.length > 0 ? "partial" : "failed",
|
|
4558
|
+
provider,
|
|
4559
|
+
...reviewChildId === void 0 ? {} : { runId: reviewChildId },
|
|
4560
|
+
receipts
|
|
4561
|
+
}, { cause: cleanupFailure });
|
|
4562
|
+
}
|
|
4398
4563
|
}
|
|
4564
|
+
if (completed === void 0) throw new Error("memory subagent did not complete");
|
|
4565
|
+
this.counters[operation === "write" ? "writes" : operation === "review" ? "reviews" : operation === "placement" ? "placements" : operation === "migration" ? "migrations" : operation === "compaction" ? "compactions" : operation === "document-archive" ? "documentArchives" : operation === "metadata-maintenance" ? "metadataMaintenances" : "answers"] += 1;
|
|
4566
|
+
this.counters.lastRunId = completed.runId;
|
|
4567
|
+
if (operation !== "answer") this.counters.lastOperation = operation;
|
|
4568
|
+
this.counters.lastAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4569
|
+
return completed;
|
|
4399
4570
|
}
|
|
4400
4571
|
provider(preferred) {
|
|
4401
4572
|
const names = this.subagents.list();
|
|
@@ -5098,6 +5269,9 @@ var MnemonAgentLifecycle = class {
|
|
|
5098
5269
|
lastReviewAction;
|
|
5099
5270
|
lastReviewScore;
|
|
5100
5271
|
lastReviewDocumentIds;
|
|
5272
|
+
idleReviewAttempts = 0;
|
|
5273
|
+
lastReviewAttemptAt;
|
|
5274
|
+
lastReviewFailure;
|
|
5101
5275
|
lastPhase = "idle";
|
|
5102
5276
|
lastAt;
|
|
5103
5277
|
lastError;
|
|
@@ -5147,6 +5321,10 @@ var MnemonAgentLifecycle = class {
|
|
|
5147
5321
|
idleReviewPending: this.idleReviewTimer !== void 0,
|
|
5148
5322
|
reviewRunning: this.reviewRunning,
|
|
5149
5323
|
reviewActivity: this.reviewActivity(),
|
|
5324
|
+
idleReviewAttempts: this.idleReviewAttempts,
|
|
5325
|
+
...idleReviewBlockReason(this.agent) === void 0 ? {} : { idleReviewBlocked: "agent-team" },
|
|
5326
|
+
...this.lastReviewAttemptAt === void 0 ? {} : { nextReviewAt: new Date(this.lastReviewAttemptAt + this.config.idleReview.minIntervalMs).toISOString() },
|
|
5327
|
+
...this.lastReviewFailure === void 0 ? {} : { lastReviewFailure: this.lastReviewFailure },
|
|
5150
5328
|
lastPhase: this.lastPhase,
|
|
5151
5329
|
...this.lastReviewAt === void 0 ? {} : { lastReviewAt: this.lastReviewAt },
|
|
5152
5330
|
...this.lastReviewAction === void 0 ? {} : { lastReviewAction: this.lastReviewAction },
|
|
@@ -5272,9 +5450,9 @@ var MnemonAgentLifecycle = class {
|
|
|
5272
5450
|
this.releaseView(turn);
|
|
5273
5451
|
}
|
|
5274
5452
|
scheduleIdleReview(turn) {
|
|
5275
|
-
if (!this.config.lifecycleEnabled || !this.config.writeEnabled || this.config.writebackMode !== "guided") return;
|
|
5276
|
-
if (this.config.memoryTopology.strategyId !== "default-three-tier") return;
|
|
5277
5453
|
this.cancelIdleReview(true);
|
|
5454
|
+
if (!this.idleReviewAllowed()) return;
|
|
5455
|
+
if (this.config.memoryTopology.strategyId !== "default-three-tier") return;
|
|
5278
5456
|
const activity = this.ensureTurnActivity(turn);
|
|
5279
5457
|
const tools = completedToolActivity(hostSessionEvents(this.agent.session), turn);
|
|
5280
5458
|
activity.toolCallCount = tools.count;
|
|
@@ -5282,15 +5460,24 @@ var MnemonAgentLifecycle = class {
|
|
|
5282
5460
|
if (!this.reviewActivity().eligible || !this.reviewAdmitted(turn)) return;
|
|
5283
5461
|
this.idleReviewTimer = setTimeout(() => {
|
|
5284
5462
|
this.idleReviewTimer = void 0;
|
|
5285
|
-
if (this.
|
|
5463
|
+
if (!this.idleReviewAllowed() || this.reviewRunning) return;
|
|
5464
|
+
if (this.lastReviewAttemptAt !== void 0 && Date.now() < this.lastReviewAttemptAt + this.config.idleReview.minIntervalMs) {
|
|
5465
|
+
this.scheduleIdleReview(turn);
|
|
5466
|
+
return;
|
|
5467
|
+
}
|
|
5286
5468
|
if (this.agent.status !== "idle") return;
|
|
5287
5469
|
if (!hostSessionEvents(this.agent.session).some((event) => event.type === "turn/end" && eventTurn(event) === turn) || !this.reviewActivity().eligible || !this.reviewAdmitted(turn)) return;
|
|
5288
5470
|
this.runIdleReview();
|
|
5289
|
-
}, this.config.idleReviewMs);
|
|
5471
|
+
}, Math.max(this.config.idleReviewMs, (this.lastReviewAttemptAt ?? -Infinity) + this.config.idleReview.minIntervalMs - Date.now()));
|
|
5472
|
+
}
|
|
5473
|
+
idleReviewAllowed() {
|
|
5474
|
+
return this.config.lifecycleEnabled && this.config.writeEnabled && this.config.writebackMode === "guided" && this.config.idleReview.enabled && this.idleReviewAttempts < this.config.idleReview.maxPerSession && idleReviewBlockReason(this.agent) === void 0 && this.config.memoryTopology.strategyId === "default-three-tier";
|
|
5290
5475
|
}
|
|
5291
5476
|
async runIdleReview() {
|
|
5292
5477
|
const controller = new AbortController();
|
|
5293
5478
|
const triggeredScore = this.reviewActivity().score;
|
|
5479
|
+
this.idleReviewAttempts += 1;
|
|
5480
|
+
this.lastReviewAttemptAt = Date.now();
|
|
5294
5481
|
this.reviewRunning = true;
|
|
5295
5482
|
this.reviewController = controller;
|
|
5296
5483
|
this.mark("review");
|
|
@@ -5301,11 +5488,13 @@ var MnemonAgentLifecycle = class {
|
|
|
5301
5488
|
this.lastReviewAction = result.action;
|
|
5302
5489
|
this.lastReviewScore = triggeredScore;
|
|
5303
5490
|
this.lastReviewDocumentIds = result.documentIds;
|
|
5491
|
+
this.lastReviewFailure = void 0;
|
|
5304
5492
|
this.turnActivity.clear();
|
|
5305
5493
|
this.lastError = void 0;
|
|
5306
5494
|
this.mark("review");
|
|
5307
5495
|
} catch (error) {
|
|
5308
|
-
if (
|
|
5496
|
+
if (error instanceof IdleReviewError) this.lastReviewFailure = error.review;
|
|
5497
|
+
if (!controller.signal.aborted || error instanceof IdleReviewError && error.review.status === "partial") this.fail(error);
|
|
5309
5498
|
} finally {
|
|
5310
5499
|
if (this.reviewController === controller) {
|
|
5311
5500
|
this.reviewRunning = false;
|
|
@@ -7099,6 +7288,7 @@ const MUTABLE_FIELDS = [
|
|
|
7099
7288
|
"recallMode",
|
|
7100
7289
|
"writebackMode",
|
|
7101
7290
|
"idleReviewMs",
|
|
7291
|
+
"idleReview",
|
|
7102
7292
|
"displayMode",
|
|
7103
7293
|
"tabEnabled",
|
|
7104
7294
|
"writeEnabled",
|
|
@@ -7655,7 +7845,7 @@ function registerTools(ctx, runtimeSource, coordinator) {
|
|
|
7655
7845
|
},
|
|
7656
7846
|
old_text: {
|
|
7657
7847
|
type: "string",
|
|
7658
|
-
description: "
|
|
7848
|
+
description: "Full content of the existing entry, or a unique substring. A unique full-content match takes precedence within the selected target. Required for replace and remove."
|
|
7659
7849
|
},
|
|
7660
7850
|
importance: {
|
|
7661
7851
|
type: "string",
|
|
@@ -7705,7 +7895,7 @@ function registerTools(ctx, runtimeSource, coordinator) {
|
|
|
7705
7895
|
}));
|
|
7706
7896
|
ctx.tools.register(definition({
|
|
7707
7897
|
name: "mnemon_remember",
|
|
7708
|
-
description: "Archive one durable insight in a selected provider-backed Memory Space. Ordinary new hot memory belongs in mnemon_runtime_memory; use direct archival only for explicit long-term persistence or runtime capacity migration. Choose the narrowest existing space, search it first, verify capabilities.remember=true, and wait for the provider receipt.
|
|
7898
|
+
description: "Archive one durable insight in a selected provider-backed Memory Space. Ordinary new hot memory belongs in mnemon_runtime_memory; use direct archival only for explicit long-term persistence or runtime capacity migration. Choose the narrowest existing space, search it first, verify capabilities.remember=true, and wait for the provider receipt. Exact writes require confirmed persistence; providers using semantic extraction may truthfully return skipped. Do not dump transcripts, temporary progress, routine observations, or repository-obvious facts.",
|
|
7709
7899
|
parameters: {
|
|
7710
7900
|
type: "object",
|
|
7711
7901
|
properties: {
|