@remnic/plugin-openclaw 1.0.11 → 1.0.13
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/dist/capsule-cli-GBM3WPAM.js +33 -0
- package/dist/capsule-export-IXVERCQG.js +17 -0
- package/dist/{capsule-import-CFX7BY5W.js → capsule-import-IA6VIOPQ.js} +3 -3
- package/dist/{capsule-merge-7RVOHJK3.js → capsule-merge-IWOQ34KL.js} +2 -2
- package/dist/{causal-consolidation-JD6KJJH6.js → causal-consolidation-YI53C2AO.js} +3 -3
- package/dist/{chunk-K7EUBNDD.js → chunk-4LYQ4ONL.js} +1 -1
- package/dist/{chunk-N7EOZY6F.js → chunk-6F6EKSVP.js} +54 -1
- package/dist/{chunk-TNH24SF6.js → chunk-7UZNLMW5.js} +301 -125
- package/dist/{chunk-TVKKIS53.js → chunk-CDAZGIGT.js} +1 -1
- package/dist/{chunk-XMSDA5WA.js → chunk-EXDYWXMB.js} +1 -0
- package/dist/{capsule-export-CVA3CKUQ.js → chunk-FGTYFLL5.js} +21 -12
- package/dist/{chunk-ETJZRIAM.js → chunk-L6I4MQKO.js} +1 -1
- package/dist/{capsule-cli-TFKLAG3S.js → chunk-LLUROTZJ.js} +11 -12
- package/dist/{chunk-L4PRBB2A.js → chunk-OAE7AQ6R.js} +63 -91
- package/dist/{chunk-3I7RHWYT.js → chunk-RKR6PTPA.js} +105 -11
- package/dist/{chunk-P3DIW2SD.js → chunk-TILAJIJR.js} +1 -1
- package/dist/{engine-VMTFKFGO.js → engine-BIYI3P4J.js} +6 -4
- package/dist/index.js +1864 -381
- package/dist/{memory-governance-DWGFV4FX.js → memory-governance-SJ5DGRB3.js} +3 -3
- package/dist/{secure-store-FWJ7LBPH.js → secure-store-A4NGCNXV.js} +8 -2
- package/dist/{storage-T2OGFUF4.js → storage-PTQ2H2YJ.js} +2 -2
- package/dist/{types-H5R5D3WF.js → types-R4DO7AKM.js} +2 -2
- package/openclaw.plugin.json +10 -0
- package/package.json +2 -2
- package/dist/chunk-YGXXBRV7.js +0 -10
package/dist/index.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compareVersions
|
|
3
3
|
} from "./chunk-GUSMRW4H.js";
|
|
4
|
-
import {
|
|
5
|
-
EXPORT_FORMAT,
|
|
6
|
-
EXPORT_SCHEMA_VERSION
|
|
7
|
-
} from "./chunk-YGXXBRV7.js";
|
|
8
4
|
import {
|
|
9
5
|
isSafeRouteNamespace,
|
|
10
6
|
selectRouteRule,
|
|
@@ -12,10 +8,20 @@ import {
|
|
|
12
8
|
} from "./chunk-FQRSVYY4.js";
|
|
13
9
|
import {
|
|
14
10
|
importCapsule
|
|
15
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-L6I4MQKO.js";
|
|
16
12
|
import {
|
|
13
|
+
EXPORT_FORMAT,
|
|
14
|
+
EXPORT_SCHEMA_VERSION,
|
|
15
|
+
exportCapsule,
|
|
16
|
+
isValidCapsuleSince
|
|
17
|
+
} from "./chunk-FGTYFLL5.js";
|
|
18
|
+
import {
|
|
19
|
+
CAPSULE_ID_PATTERN,
|
|
17
20
|
ExportBundleV1Schema
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-4LYQ4ONL.js";
|
|
22
|
+
import {
|
|
23
|
+
defaultCapsulesDir
|
|
24
|
+
} from "./chunk-LLUROTZJ.js";
|
|
19
25
|
import {
|
|
20
26
|
TierMigrationExecutor
|
|
21
27
|
} from "./chunk-BU5KJVWF.js";
|
|
@@ -37,7 +43,7 @@ import {
|
|
|
37
43
|
readMemoryGovernanceRunArtifact,
|
|
38
44
|
restoreMemoryGovernanceRun,
|
|
39
45
|
runMemoryGovernance
|
|
40
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-CDAZGIGT.js";
|
|
41
47
|
import {
|
|
42
48
|
clamp01,
|
|
43
49
|
clampLifecycleThreshold,
|
|
@@ -84,7 +90,7 @@ import {
|
|
|
84
90
|
parseOperatorAwareConsolidationResponse,
|
|
85
91
|
renderExtensionsFooter,
|
|
86
92
|
resolveExtensionsRoot
|
|
87
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-TILAJIJR.js";
|
|
88
94
|
import {
|
|
89
95
|
BoxBuilder,
|
|
90
96
|
countRecallTokenOverlap,
|
|
@@ -109,11 +115,12 @@ import {
|
|
|
109
115
|
CompoundingEngine,
|
|
110
116
|
SharedContextManager,
|
|
111
117
|
defaultTierMigrationCycleBudget
|
|
112
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-OAE7AQ6R.js";
|
|
113
119
|
import {
|
|
120
|
+
ZodError,
|
|
114
121
|
external_exports
|
|
115
|
-
} from "./chunk-
|
|
116
|
-
import "./chunk-
|
|
122
|
+
} from "./chunk-EXDYWXMB.js";
|
|
123
|
+
import "./chunk-6F6EKSVP.js";
|
|
117
124
|
import {
|
|
118
125
|
keyring_exports,
|
|
119
126
|
secureStoreDir
|
|
@@ -181,11 +188,11 @@ import {
|
|
|
181
188
|
sortMemoryLifecycleEvents,
|
|
182
189
|
stripCitationForTemplate,
|
|
183
190
|
toMemoryPathRel
|
|
184
|
-
} from "./chunk-
|
|
191
|
+
} from "./chunk-7UZNLMW5.js";
|
|
185
192
|
import {
|
|
186
193
|
sidecarKey
|
|
187
194
|
} from "./chunk-6OJAU466.js";
|
|
188
|
-
import "./chunk-
|
|
195
|
+
import "./chunk-RKR6PTPA.js";
|
|
189
196
|
import {
|
|
190
197
|
initLogger,
|
|
191
198
|
log
|
|
@@ -1899,6 +1906,8 @@ function parseConfig(raw) {
|
|
|
1899
1906
|
lcmRecallBudgetShare: typeof cfg.lcmRecallBudgetShare === "number" ? Math.max(0, Math.min(1, cfg.lcmRecallBudgetShare)) : 0.15,
|
|
1900
1907
|
lcmDeterministicMaxTokens: typeof cfg.lcmDeterministicMaxTokens === "number" ? Math.max(64, Math.floor(cfg.lcmDeterministicMaxTokens)) : 512,
|
|
1901
1908
|
lcmArchiveRetentionDays: typeof cfg.lcmArchiveRetentionDays === "number" ? Math.max(1, Math.floor(cfg.lcmArchiveRetentionDays)) : 90,
|
|
1909
|
+
messagePartsEnabled: coerceBooleanLike(cfg.messagePartsEnabled) === true,
|
|
1910
|
+
messagePartsRecallMaxResults: typeof cfg.messagePartsRecallMaxResults === "number" ? Math.max(0, Math.floor(cfg.messagePartsRecallMaxResults)) : 6,
|
|
1902
1911
|
// v9.1 Parallel Specialized Retrieval
|
|
1903
1912
|
parallelRetrievalEnabled: cfg.parallelRetrievalEnabled === true,
|
|
1904
1913
|
parallelAgentWeights: (() => {
|
|
@@ -19342,7 +19351,9 @@ var RECALL_XRAY_SERVED_BY_VALUES = [
|
|
|
19342
19351
|
"graph",
|
|
19343
19352
|
"recent-scan",
|
|
19344
19353
|
"procedural",
|
|
19345
|
-
"review-context"
|
|
19354
|
+
"review-context",
|
|
19355
|
+
"lcm-file-parts",
|
|
19356
|
+
"lcm-tool-parts"
|
|
19346
19357
|
];
|
|
19347
19358
|
function isRecallXrayServedBy(value) {
|
|
19348
19359
|
return typeof value === "string" && RECALL_XRAY_SERVED_BY_VALUES.includes(value);
|
|
@@ -26173,7 +26184,7 @@ function validateReplayTurn(turn, index) {
|
|
|
26173
26184
|
// ../remnic-core/src/lcm/schema.ts
|
|
26174
26185
|
import path37 from "path";
|
|
26175
26186
|
import { mkdir as mkdir26 } from "fs/promises";
|
|
26176
|
-
var LCM_SCHEMA_VERSION =
|
|
26187
|
+
var LCM_SCHEMA_VERSION = 2;
|
|
26177
26188
|
function openLcmDatabase(memoryDir) {
|
|
26178
26189
|
const dbPath = path37.join(memoryDir, "state", "lcm.sqlite");
|
|
26179
26190
|
const db = openBetterSqlite3(dbPath);
|
|
@@ -26219,6 +26230,23 @@ function createTables(db) {
|
|
|
26219
26230
|
CREATE INDEX IF NOT EXISTS idx_lcm_messages_session
|
|
26220
26231
|
ON lcm_messages(session_id, turn_index);
|
|
26221
26232
|
|
|
26233
|
+
CREATE TABLE IF NOT EXISTS lcm_message_parts (
|
|
26234
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26235
|
+
message_id INTEGER NOT NULL REFERENCES lcm_messages(id) ON DELETE CASCADE,
|
|
26236
|
+
ordinal INTEGER NOT NULL,
|
|
26237
|
+
kind TEXT NOT NULL,
|
|
26238
|
+
payload TEXT NOT NULL,
|
|
26239
|
+
tool_name TEXT,
|
|
26240
|
+
file_path TEXT,
|
|
26241
|
+
created_at TEXT NOT NULL
|
|
26242
|
+
);
|
|
26243
|
+
CREATE INDEX IF NOT EXISTS idx_lcm_message_parts_msg
|
|
26244
|
+
ON lcm_message_parts(message_id, ordinal);
|
|
26245
|
+
CREATE INDEX IF NOT EXISTS idx_lcm_message_parts_tool
|
|
26246
|
+
ON lcm_message_parts(tool_name);
|
|
26247
|
+
CREATE INDEX IF NOT EXISTS idx_lcm_message_parts_file
|
|
26248
|
+
ON lcm_message_parts(file_path);
|
|
26249
|
+
|
|
26222
26250
|
CREATE TABLE IF NOT EXISTS lcm_summary_nodes (
|
|
26223
26251
|
id TEXT PRIMARY KEY,
|
|
26224
26252
|
session_id TEXT NOT NULL,
|
|
@@ -26271,6 +26299,423 @@ function createTables(db) {
|
|
|
26271
26299
|
);
|
|
26272
26300
|
}
|
|
26273
26301
|
|
|
26302
|
+
// ../remnic-core/src/message-parts/index.ts
|
|
26303
|
+
var LCM_MESSAGE_PART_KINDS = [
|
|
26304
|
+
"text",
|
|
26305
|
+
"tool_call",
|
|
26306
|
+
"tool_result",
|
|
26307
|
+
"patch",
|
|
26308
|
+
"file_read",
|
|
26309
|
+
"file_write",
|
|
26310
|
+
"step_start",
|
|
26311
|
+
"step_finish",
|
|
26312
|
+
"snapshot",
|
|
26313
|
+
"retry"
|
|
26314
|
+
];
|
|
26315
|
+
var SECRET_KEY_RE = /(api[_-]?key|authorization|bearer|credential|password|secret|token)/i;
|
|
26316
|
+
var MAX_PAYLOAD_STRING = 8e3;
|
|
26317
|
+
var MAX_FILE_SCAN_CHARS = 2e4;
|
|
26318
|
+
function isLcmMessagePartKind(value) {
|
|
26319
|
+
return typeof value === "string" && LCM_MESSAGE_PART_KINDS.includes(value);
|
|
26320
|
+
}
|
|
26321
|
+
function parseMessageParts(input, options = {}) {
|
|
26322
|
+
const explicit = normalizeExplicitParts(input);
|
|
26323
|
+
if (explicit.length > 0) return explicit;
|
|
26324
|
+
const format = options.sourceFormat ?? inferSourceFormat(input);
|
|
26325
|
+
switch (format) {
|
|
26326
|
+
case "openai":
|
|
26327
|
+
return withRenderedFallback(parseOpenAiMessageParts(input, options), options);
|
|
26328
|
+
case "anthropic":
|
|
26329
|
+
return withRenderedFallback(parseAnthropicMessageParts(input, options), options);
|
|
26330
|
+
case "openclaw":
|
|
26331
|
+
return withRenderedFallback(parseOpenClawMessageParts(input, options), options);
|
|
26332
|
+
case "lossless-claw":
|
|
26333
|
+
case "remnic":
|
|
26334
|
+
return withRenderedFallback(normalizeExplicitParts(input), options);
|
|
26335
|
+
default:
|
|
26336
|
+
return renderedFallbackParts(options);
|
|
26337
|
+
}
|
|
26338
|
+
}
|
|
26339
|
+
function normalizeExplicitParts(input) {
|
|
26340
|
+
const rawParts = pickArray(input, "parts") ?? pickArray(input, "message_parts");
|
|
26341
|
+
if (!rawParts) return [];
|
|
26342
|
+
const parts = [];
|
|
26343
|
+
rawParts.forEach((raw, index) => {
|
|
26344
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
|
|
26345
|
+
const obj = raw;
|
|
26346
|
+
const kind = normalizeKind(obj.kind ?? obj.type);
|
|
26347
|
+
if (!kind) return;
|
|
26348
|
+
const payload = obj.payload && typeof obj.payload === "object" && !Array.isArray(obj.payload) ? obj.payload : { value: sanitizePayload(obj) };
|
|
26349
|
+
const toolName = asNonEmptyString(obj.toolName ?? obj.tool_name ?? obj.name);
|
|
26350
|
+
const filePath = asNonEmptyString(obj.filePath ?? obj.file_path ?? obj.path);
|
|
26351
|
+
const ordinal = typeof obj.ordinal === "number" && Number.isInteger(obj.ordinal) ? Math.max(0, obj.ordinal) : index;
|
|
26352
|
+
parts.push({
|
|
26353
|
+
ordinal,
|
|
26354
|
+
kind,
|
|
26355
|
+
payload: sanitizePayload(payload),
|
|
26356
|
+
toolName,
|
|
26357
|
+
filePath,
|
|
26358
|
+
createdAt: asNonEmptyString(obj.createdAt ?? obj.created_at)
|
|
26359
|
+
});
|
|
26360
|
+
});
|
|
26361
|
+
return parts;
|
|
26362
|
+
}
|
|
26363
|
+
function parseOpenAiMessageParts(input, _options = {}) {
|
|
26364
|
+
const items = gatherOpenAiItems(input);
|
|
26365
|
+
const parts = [];
|
|
26366
|
+
for (const item of items) {
|
|
26367
|
+
const type = asNonEmptyString(item.type) ?? asNonEmptyString(item.kind);
|
|
26368
|
+
if (!type) continue;
|
|
26369
|
+
if (isOpenAiContentBlock(item)) {
|
|
26370
|
+
const text = asNonEmptyString(item.text ?? item.content);
|
|
26371
|
+
if (text) parts.push(makePart("text", { type, text }, { filePath: firstFilePath(text) }));
|
|
26372
|
+
continue;
|
|
26373
|
+
}
|
|
26374
|
+
if (type === "message") {
|
|
26375
|
+
for (const block of gatherContentBlocks(item.content)) {
|
|
26376
|
+
const text = asNonEmptyString(block.text ?? block.content);
|
|
26377
|
+
if (text) parts.push(makePart("text", { type, text }, { filePath: firstFilePath(text) }));
|
|
26378
|
+
}
|
|
26379
|
+
continue;
|
|
26380
|
+
}
|
|
26381
|
+
if (type === "function_call") {
|
|
26382
|
+
const toolName = asNonEmptyString(item.name ?? item.tool_name);
|
|
26383
|
+
const payload = {
|
|
26384
|
+
id: item.id ?? item.call_id,
|
|
26385
|
+
name: toolName,
|
|
26386
|
+
arguments: parseMaybeJson(item.arguments)
|
|
26387
|
+
};
|
|
26388
|
+
parts.push(classifyToolPart(toolName, payload));
|
|
26389
|
+
continue;
|
|
26390
|
+
}
|
|
26391
|
+
if (type === "function_call_output") {
|
|
26392
|
+
const output = asNonEmptyString(item.output) ?? JSON.stringify(sanitizePayload(item.output ?? item));
|
|
26393
|
+
parts.push(makePart("tool_result", { id: item.id ?? item.call_id, output }, {
|
|
26394
|
+
filePath: firstFilePath(output)
|
|
26395
|
+
}));
|
|
26396
|
+
continue;
|
|
26397
|
+
}
|
|
26398
|
+
if (type === "reasoning") {
|
|
26399
|
+
parts.push(makePart("step_start", { type, summary: sanitizePayload(item.summary ?? item) }));
|
|
26400
|
+
continue;
|
|
26401
|
+
}
|
|
26402
|
+
if (type === "retry") {
|
|
26403
|
+
parts.push(makePart("retry", { type, item: sanitizePayload(item) }));
|
|
26404
|
+
}
|
|
26405
|
+
}
|
|
26406
|
+
return withOrdinals(parts);
|
|
26407
|
+
}
|
|
26408
|
+
function parseAnthropicMessageParts(input, _options = {}) {
|
|
26409
|
+
const blocks = gatherContentBlocks(
|
|
26410
|
+
Array.isArray(input) ? input : input && typeof input === "object" ? input.content : input
|
|
26411
|
+
);
|
|
26412
|
+
const parts = [];
|
|
26413
|
+
for (const block of blocks) {
|
|
26414
|
+
const type = asNonEmptyString(block.type);
|
|
26415
|
+
if (type === "text") {
|
|
26416
|
+
const text = asNonEmptyString(block.text);
|
|
26417
|
+
if (text) parts.push(makePart("text", { type, text }, { filePath: firstFilePath(text) }));
|
|
26418
|
+
continue;
|
|
26419
|
+
}
|
|
26420
|
+
if (type === "tool_use") {
|
|
26421
|
+
const toolName = asNonEmptyString(block.name);
|
|
26422
|
+
parts.push(classifyToolPart(toolName, {
|
|
26423
|
+
id: block.id,
|
|
26424
|
+
name: toolName,
|
|
26425
|
+
input: sanitizePayload(block.input)
|
|
26426
|
+
}));
|
|
26427
|
+
continue;
|
|
26428
|
+
}
|
|
26429
|
+
if (type === "tool_result") {
|
|
26430
|
+
const content = block.content;
|
|
26431
|
+
const rendered = renderUnknownContent(content);
|
|
26432
|
+
parts.push(makePart("tool_result", { id: block.tool_use_id, content: sanitizePayload(content) }, {
|
|
26433
|
+
filePath: firstFilePath(rendered)
|
|
26434
|
+
}));
|
|
26435
|
+
continue;
|
|
26436
|
+
}
|
|
26437
|
+
if (type === "thinking") {
|
|
26438
|
+
parts.push(makePart("step_start", {
|
|
26439
|
+
type,
|
|
26440
|
+
thinking: truncateString(asNonEmptyString(block.thinking) ?? ""),
|
|
26441
|
+
signature: asNonEmptyString(block.signature)
|
|
26442
|
+
}));
|
|
26443
|
+
continue;
|
|
26444
|
+
}
|
|
26445
|
+
if (type === "redacted_thinking") {
|
|
26446
|
+
parts.push(makePart("step_finish", { type }));
|
|
26447
|
+
}
|
|
26448
|
+
}
|
|
26449
|
+
return withOrdinals(parts);
|
|
26450
|
+
}
|
|
26451
|
+
function parseOpenClawMessageParts(input, options = {}) {
|
|
26452
|
+
const explicit = normalizeExplicitParts(input);
|
|
26453
|
+
if (explicit.length > 0) return explicit;
|
|
26454
|
+
if (!input || typeof input !== "object") return [];
|
|
26455
|
+
const obj = input;
|
|
26456
|
+
const content = obj.content;
|
|
26457
|
+
if (Array.isArray(content)) {
|
|
26458
|
+
const hasOpenAiBlocks = content.some(isOpenAiContentBlock);
|
|
26459
|
+
if (hasOpenAiBlocks) return parseOpenAiMessageParts(content, options);
|
|
26460
|
+
const hasAnthropicBlocks = content.some(
|
|
26461
|
+
(block) => block && typeof block === "object" && typeof block.type === "string"
|
|
26462
|
+
);
|
|
26463
|
+
if (hasAnthropicBlocks) return parseAnthropicMessageParts({ content }, options);
|
|
26464
|
+
}
|
|
26465
|
+
const toolName = asNonEmptyString(obj.toolName ?? obj.tool_name ?? obj.name);
|
|
26466
|
+
if (toolName) {
|
|
26467
|
+
return withOrdinals([
|
|
26468
|
+
classifyToolPart(toolName, {
|
|
26469
|
+
name: toolName,
|
|
26470
|
+
input: sanitizePayload(obj.input ?? obj.arguments ?? obj.params),
|
|
26471
|
+
output: sanitizePayload(obj.output ?? obj.result)
|
|
26472
|
+
})
|
|
26473
|
+
]);
|
|
26474
|
+
}
|
|
26475
|
+
const rendered = options.renderedContent ?? asNonEmptyString(obj.content);
|
|
26476
|
+
return rendered ? withOrdinals(partsFromRenderedText(rendered)) : [];
|
|
26477
|
+
}
|
|
26478
|
+
function partsFromRenderedText(text) {
|
|
26479
|
+
if (text.includes("*** Begin Patch")) {
|
|
26480
|
+
const paths2 = extractFilePaths(text);
|
|
26481
|
+
const patchPaths = extractPatchPaths(text);
|
|
26482
|
+
return withOrdinals((patchPaths.length > 0 ? patchPaths : paths2).map(
|
|
26483
|
+
(filePath) => makePart("patch", { text: truncateString(text) }, { filePath })
|
|
26484
|
+
));
|
|
26485
|
+
}
|
|
26486
|
+
const paths = extractFilePaths(text);
|
|
26487
|
+
if (paths.length === 0) return [];
|
|
26488
|
+
return withOrdinals(paths.map(
|
|
26489
|
+
(filePath) => makePart("file_read", { text: truncateString(text) }, { filePath })
|
|
26490
|
+
));
|
|
26491
|
+
}
|
|
26492
|
+
function inferSourceFormat(input) {
|
|
26493
|
+
if (input && typeof input === "object") {
|
|
26494
|
+
const obj = input;
|
|
26495
|
+
const explicit = asNonEmptyString(obj.sourceFormat ?? obj.source_format);
|
|
26496
|
+
if (explicit === "openai" || explicit === "anthropic" || explicit === "openclaw" || explicit === "lossless-claw" || explicit === "remnic") {
|
|
26497
|
+
return explicit;
|
|
26498
|
+
}
|
|
26499
|
+
if (Array.isArray(obj.output)) return "openai";
|
|
26500
|
+
if (isOpenAiResponseItem(obj)) return "openai";
|
|
26501
|
+
if (Array.isArray(obj.content) && obj.content.some(isOpenAiContentBlock)) return "openai";
|
|
26502
|
+
if (Array.isArray(obj.content)) return "anthropic";
|
|
26503
|
+
}
|
|
26504
|
+
if (Array.isArray(input)) {
|
|
26505
|
+
return input.some(
|
|
26506
|
+
(item) => isRecord3(item) && (isOpenAiResponseItem(item) || isOpenAiContentBlock(item))
|
|
26507
|
+
) ? "openai" : "anthropic";
|
|
26508
|
+
}
|
|
26509
|
+
return void 0;
|
|
26510
|
+
}
|
|
26511
|
+
function isOpenAiResponseItem(obj) {
|
|
26512
|
+
const type = asNonEmptyString(obj.type ?? obj.kind);
|
|
26513
|
+
return type === "message" || type === "function_call" || type === "function_call_output" || type === "reasoning" || type === "retry";
|
|
26514
|
+
}
|
|
26515
|
+
function isOpenAiContentBlock(value) {
|
|
26516
|
+
if (!isRecord3(value)) return false;
|
|
26517
|
+
const type = asNonEmptyString(value.type);
|
|
26518
|
+
return type === "input_text" || type === "output_text" || type === "input_image" || type === "input_file" || type === "refusal";
|
|
26519
|
+
}
|
|
26520
|
+
function gatherOpenAiItems(input) {
|
|
26521
|
+
if (Array.isArray(input)) return input.filter(isRecord3);
|
|
26522
|
+
if (!isRecord3(input)) return [];
|
|
26523
|
+
if (Array.isArray(input.output)) return input.output.filter(isRecord3);
|
|
26524
|
+
if (Array.isArray(input.items)) return input.items.filter(isRecord3);
|
|
26525
|
+
return [input];
|
|
26526
|
+
}
|
|
26527
|
+
function gatherContentBlocks(input) {
|
|
26528
|
+
if (Array.isArray(input)) return input.filter(isRecord3);
|
|
26529
|
+
if (typeof input === "string") return [{ type: "text", text: input }];
|
|
26530
|
+
if (isRecord3(input)) return [input];
|
|
26531
|
+
return [];
|
|
26532
|
+
}
|
|
26533
|
+
function classifyToolPart(toolName, payload) {
|
|
26534
|
+
const normalized = (toolName ?? "").toLowerCase();
|
|
26535
|
+
const rendered = renderUnknownContent(payload);
|
|
26536
|
+
const filePath = firstFilePathFromObject(payload) ?? firstFilePath(rendered) ?? null;
|
|
26537
|
+
if (normalized.includes("apply_patch") || rendered.includes("*** Begin Patch")) {
|
|
26538
|
+
return makePart("patch", payload, { toolName, filePath: filePath ?? extractPatchPaths(rendered)[0] ?? null });
|
|
26539
|
+
}
|
|
26540
|
+
if (/(write|edit|multiedit|create|save)/i.test(normalized)) {
|
|
26541
|
+
return makePart("file_write", payload, { toolName, filePath });
|
|
26542
|
+
}
|
|
26543
|
+
if (/(read|grep|glob|search|list|ls)/i.test(normalized)) {
|
|
26544
|
+
return makePart("file_read", payload, { toolName, filePath });
|
|
26545
|
+
}
|
|
26546
|
+
return makePart("tool_call", payload, { toolName, filePath });
|
|
26547
|
+
}
|
|
26548
|
+
function makePart(kind, payload, options = {}) {
|
|
26549
|
+
return {
|
|
26550
|
+
kind,
|
|
26551
|
+
payload: sanitizePayload(payload),
|
|
26552
|
+
toolName: options.toolName ?? null,
|
|
26553
|
+
filePath: options.filePath ?? null
|
|
26554
|
+
};
|
|
26555
|
+
}
|
|
26556
|
+
function withOrdinals(parts) {
|
|
26557
|
+
return parts.map((part, ordinal) => ({ ...part, ordinal: part.ordinal ?? ordinal }));
|
|
26558
|
+
}
|
|
26559
|
+
function withRenderedFallback(parts, options) {
|
|
26560
|
+
return parts.length > 0 ? parts : renderedFallbackParts(options);
|
|
26561
|
+
}
|
|
26562
|
+
function renderedFallbackParts(options) {
|
|
26563
|
+
const rendered = asNonEmptyString(options.renderedContent);
|
|
26564
|
+
return rendered ? partsFromRenderedText(rendered) : [];
|
|
26565
|
+
}
|
|
26566
|
+
function normalizeKind(value) {
|
|
26567
|
+
if (isLcmMessagePartKind(value)) return value;
|
|
26568
|
+
if (value === "tool_use" || value === "function_call") return "tool_call";
|
|
26569
|
+
if (value === "function_call_output") return "tool_result";
|
|
26570
|
+
if (value === "thinking" || value === "reasoning") return "step_start";
|
|
26571
|
+
return null;
|
|
26572
|
+
}
|
|
26573
|
+
function pickArray(input, key) {
|
|
26574
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
26575
|
+
const value = input[key];
|
|
26576
|
+
return Array.isArray(value) ? value : null;
|
|
26577
|
+
}
|
|
26578
|
+
function asNonEmptyString(value) {
|
|
26579
|
+
if (typeof value !== "string") return null;
|
|
26580
|
+
const trimmed = value.trim();
|
|
26581
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
26582
|
+
}
|
|
26583
|
+
function isRecord3(value) {
|
|
26584
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
26585
|
+
}
|
|
26586
|
+
function parseMaybeJson(value) {
|
|
26587
|
+
if (typeof value !== "string") return sanitizePayload(value);
|
|
26588
|
+
try {
|
|
26589
|
+
return sanitizePayload(JSON.parse(value));
|
|
26590
|
+
} catch {
|
|
26591
|
+
return truncateString(value);
|
|
26592
|
+
}
|
|
26593
|
+
}
|
|
26594
|
+
function sanitizePayload(value, depth = 0) {
|
|
26595
|
+
if (value === null || value === void 0) return value;
|
|
26596
|
+
if (typeof value === "string") return truncateString(value);
|
|
26597
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
26598
|
+
if (Array.isArray(value)) {
|
|
26599
|
+
if (depth >= 4) return "[truncated]";
|
|
26600
|
+
return value.slice(0, 100).map((item) => sanitizePayload(item, depth + 1));
|
|
26601
|
+
}
|
|
26602
|
+
if (typeof value === "object") {
|
|
26603
|
+
if (depth >= 4) return "[truncated]";
|
|
26604
|
+
const out = {};
|
|
26605
|
+
for (const [key, child] of Object.entries(value)) {
|
|
26606
|
+
out[key] = SECRET_KEY_RE.test(key) ? "[redacted]" : sanitizePayload(child, depth + 1);
|
|
26607
|
+
}
|
|
26608
|
+
return out;
|
|
26609
|
+
}
|
|
26610
|
+
return String(value);
|
|
26611
|
+
}
|
|
26612
|
+
function truncateString(value) {
|
|
26613
|
+
return value.length > MAX_PAYLOAD_STRING ? `${value.slice(0, MAX_PAYLOAD_STRING)}...[truncated]` : value;
|
|
26614
|
+
}
|
|
26615
|
+
function renderUnknownContent(value) {
|
|
26616
|
+
if (typeof value === "string") return value;
|
|
26617
|
+
try {
|
|
26618
|
+
return JSON.stringify(value ?? "");
|
|
26619
|
+
} catch {
|
|
26620
|
+
return String(value ?? "");
|
|
26621
|
+
}
|
|
26622
|
+
}
|
|
26623
|
+
function firstFilePathFromObject(value) {
|
|
26624
|
+
if (!isRecord3(value)) return null;
|
|
26625
|
+
const keys = ["file_path", "filePath", "path", "filename", "cwd"];
|
|
26626
|
+
for (const key of keys) {
|
|
26627
|
+
const candidate = asNonEmptyString(value[key]);
|
|
26628
|
+
if (candidate) return candidate;
|
|
26629
|
+
}
|
|
26630
|
+
for (const child of Object.values(value)) {
|
|
26631
|
+
if (typeof child === "string") {
|
|
26632
|
+
const fromText = extractPatchPaths(child)[0] ?? firstFilePath(child);
|
|
26633
|
+
if (fromText) return fromText;
|
|
26634
|
+
}
|
|
26635
|
+
if (isRecord3(child)) {
|
|
26636
|
+
const nested = firstFilePathFromObject(child);
|
|
26637
|
+
if (nested) return nested;
|
|
26638
|
+
}
|
|
26639
|
+
}
|
|
26640
|
+
return null;
|
|
26641
|
+
}
|
|
26642
|
+
function firstFilePath(text) {
|
|
26643
|
+
return extractFilePaths(text)[0] ?? null;
|
|
26644
|
+
}
|
|
26645
|
+
function extractFilePaths(text) {
|
|
26646
|
+
const out = /* @__PURE__ */ new Set();
|
|
26647
|
+
let token = "";
|
|
26648
|
+
const scanLength = Math.min(text.length, MAX_FILE_SCAN_CHARS);
|
|
26649
|
+
for (let index = 0; index <= scanLength; index += 1) {
|
|
26650
|
+
const char = index < scanLength ? text[index] : " ";
|
|
26651
|
+
if (isFilePathTokenSeparator(char)) {
|
|
26652
|
+
addFilePathCandidate(out, token);
|
|
26653
|
+
token = "";
|
|
26654
|
+
continue;
|
|
26655
|
+
}
|
|
26656
|
+
token += char;
|
|
26657
|
+
if (token.length > 512) {
|
|
26658
|
+
addFilePathCandidate(out, token);
|
|
26659
|
+
token = "";
|
|
26660
|
+
}
|
|
26661
|
+
}
|
|
26662
|
+
return [...out].slice(0, 20);
|
|
26663
|
+
}
|
|
26664
|
+
function isFilePathTokenSeparator(char) {
|
|
26665
|
+
return char === " " || char === "\n" || char === "\r" || char === " " || char === '"' || char === "'" || char === "`" || char === "(" || char === ")" || char === "[" || char === "]" || char === "{" || char === "}" || char === "<" || char === ">" || char === ",";
|
|
26666
|
+
}
|
|
26667
|
+
function addFilePathCandidate(out, raw) {
|
|
26668
|
+
const candidate = trimFilePathPunctuation(raw);
|
|
26669
|
+
if (candidate.length === 0 || candidate.includes("://")) return;
|
|
26670
|
+
if (isLikelyFilePath(candidate)) out.add(candidate);
|
|
26671
|
+
}
|
|
26672
|
+
function trimFilePathPunctuation(raw) {
|
|
26673
|
+
let start = 0;
|
|
26674
|
+
let end = raw.length;
|
|
26675
|
+
while (start < end && isLeadingFilePathPunctuation(raw[start])) start += 1;
|
|
26676
|
+
while (end > start && isTrailingFilePathPunctuation(raw[end - 1])) end -= 1;
|
|
26677
|
+
return raw.slice(start, end);
|
|
26678
|
+
}
|
|
26679
|
+
function isLeadingFilePathPunctuation(char) {
|
|
26680
|
+
return char === ":" || char === ";" || char === "!" || char === "?" || char === "|" || char === "*" || char === "=";
|
|
26681
|
+
}
|
|
26682
|
+
function isTrailingFilePathPunctuation(char) {
|
|
26683
|
+
return char === "." || char === ":" || char === ";" || char === "!" || char === "?" || char === "|" || char === "*" || char === "=";
|
|
26684
|
+
}
|
|
26685
|
+
function isLikelyFilePath(value) {
|
|
26686
|
+
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("~/")) {
|
|
26687
|
+
return hasValidFileExtension(value);
|
|
26688
|
+
}
|
|
26689
|
+
if (value.includes("/")) return hasValidFileExtension(value);
|
|
26690
|
+
return hasValidFileExtension(value);
|
|
26691
|
+
}
|
|
26692
|
+
function hasValidFileExtension(value) {
|
|
26693
|
+
const lastSlash = value.lastIndexOf("/");
|
|
26694
|
+
const basename3 = value.slice(lastSlash + 1);
|
|
26695
|
+
const dot = basename3.lastIndexOf(".");
|
|
26696
|
+
if (dot <= 0 || dot === basename3.length - 1) return false;
|
|
26697
|
+
const ext = basename3.slice(dot + 1);
|
|
26698
|
+
if (ext.length < 1 || ext.length > 12) return false;
|
|
26699
|
+
for (const char of ext) {
|
|
26700
|
+
if (!isFileExtensionChar(char)) return false;
|
|
26701
|
+
}
|
|
26702
|
+
return true;
|
|
26703
|
+
}
|
|
26704
|
+
function isFileExtensionChar(char) {
|
|
26705
|
+
const code = char.charCodeAt(0);
|
|
26706
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "_" || char === "+" || char === "-";
|
|
26707
|
+
}
|
|
26708
|
+
function extractPatchPaths(text) {
|
|
26709
|
+
const out = /* @__PURE__ */ new Set();
|
|
26710
|
+
for (const line of text.split(/\r?\n/)) {
|
|
26711
|
+
const match = line.match(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/);
|
|
26712
|
+
if (match?.[1]) out.add(match[1].trim());
|
|
26713
|
+
const move = line.match(/^\*\*\* Move to: (.+)$/);
|
|
26714
|
+
if (move?.[1]) out.add(move[1].trim());
|
|
26715
|
+
}
|
|
26716
|
+
return [...out].slice(0, 20);
|
|
26717
|
+
}
|
|
26718
|
+
|
|
26274
26719
|
// ../remnic-core/src/lcm/archive.ts
|
|
26275
26720
|
function estimateTokens3(text) {
|
|
26276
26721
|
return Math.ceil(text.length / 4);
|
|
@@ -26281,7 +26726,7 @@ var LcmArchive = class {
|
|
|
26281
26726
|
}
|
|
26282
26727
|
db;
|
|
26283
26728
|
/** Append a message to the archive. Returns the row id. */
|
|
26284
|
-
appendMessage(sessionId, turnIndex, role, content, metadata) {
|
|
26729
|
+
appendMessage(sessionId, turnIndex, role, content, metadata, parts) {
|
|
26285
26730
|
const tokenCount = estimateTokens3(content);
|
|
26286
26731
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26287
26732
|
const metaJson = metadata ? JSON.stringify(metadata) : null;
|
|
@@ -26292,18 +26737,58 @@ var LcmArchive = class {
|
|
|
26292
26737
|
const result = stmt.run(sessionId, turnIndex, role, content, tokenCount, now, metaJson);
|
|
26293
26738
|
const rowId = Number(result.lastInsertRowid);
|
|
26294
26739
|
this.db.prepare("INSERT INTO lcm_messages_fts (rowid, content) VALUES (?, ?)").run(rowId, content);
|
|
26740
|
+
if (parts && parts.length > 0) {
|
|
26741
|
+
this.insertMessageParts(rowId, parts, now);
|
|
26742
|
+
}
|
|
26295
26743
|
return rowId;
|
|
26296
26744
|
}
|
|
26297
26745
|
/** Append multiple messages in a single transaction. */
|
|
26298
|
-
appendMessages(sessionId, messages) {
|
|
26746
|
+
appendMessages(sessionId, messages, options = {}) {
|
|
26299
26747
|
if (messages.length === 0) return;
|
|
26748
|
+
const captureMessageParts = options.messagePartsEnabled !== false;
|
|
26300
26749
|
const txn = this.db.transaction(() => {
|
|
26301
26750
|
for (const msg of messages) {
|
|
26302
|
-
|
|
26751
|
+
const explicitParts = msg.parts && msg.parts.length > 0 ? msg.parts : void 0;
|
|
26752
|
+
const rawContent = msg.rawContent ?? msg.content;
|
|
26753
|
+
const parts = captureMessageParts ? explicitParts ?? parseMessageParts(rawContent, {
|
|
26754
|
+
sourceFormat: msg.sourceFormat,
|
|
26755
|
+
renderedContent: msg.content
|
|
26756
|
+
}) : void 0;
|
|
26757
|
+
this.appendMessage(
|
|
26758
|
+
sessionId,
|
|
26759
|
+
msg.turnIndex,
|
|
26760
|
+
msg.role,
|
|
26761
|
+
msg.content,
|
|
26762
|
+
msg.metadata,
|
|
26763
|
+
parts
|
|
26764
|
+
);
|
|
26303
26765
|
}
|
|
26304
26766
|
});
|
|
26305
26767
|
txn();
|
|
26306
26768
|
}
|
|
26769
|
+
insertMessageParts(messageId, parts, fallbackCreatedAt) {
|
|
26770
|
+
if (parts.length === 0) return;
|
|
26771
|
+
const stmt = this.db.prepare(`
|
|
26772
|
+
INSERT INTO lcm_message_parts (message_id, ordinal, kind, payload, tool_name, file_path, created_at)
|
|
26773
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
26774
|
+
`);
|
|
26775
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
26776
|
+
const part = parts[index];
|
|
26777
|
+
const rawPart = part;
|
|
26778
|
+
const toolName = part.toolName ?? asNullableString(rawPart.tool_name);
|
|
26779
|
+
const filePath = part.filePath ?? asNullableString(rawPart.file_path);
|
|
26780
|
+
const createdAt = part.createdAt ?? asNullableString(rawPart.created_at);
|
|
26781
|
+
stmt.run(
|
|
26782
|
+
messageId,
|
|
26783
|
+
part.ordinal ?? index,
|
|
26784
|
+
part.kind,
|
|
26785
|
+
JSON.stringify(part.payload ?? {}),
|
|
26786
|
+
toolName ?? null,
|
|
26787
|
+
filePath ?? null,
|
|
26788
|
+
createdAt ?? fallbackCreatedAt
|
|
26789
|
+
);
|
|
26790
|
+
}
|
|
26791
|
+
}
|
|
26307
26792
|
/** Get the highest turn_index for a session, or -1 if none. */
|
|
26308
26793
|
getMaxTurnIndex(sessionId) {
|
|
26309
26794
|
const row = this.db.prepare("SELECT MAX(turn_index) as max_turn FROM lcm_messages WHERE session_id = ?").get(sessionId);
|
|
@@ -26425,6 +26910,55 @@ var LcmArchive = class {
|
|
|
26425
26910
|
return [];
|
|
26426
26911
|
}
|
|
26427
26912
|
}
|
|
26913
|
+
searchStructuredParts(query, limit, sessionId) {
|
|
26914
|
+
const cappedLimit = Math.max(0, Math.min(20, Math.floor(limit)));
|
|
26915
|
+
if (cappedLimit === 0) return [];
|
|
26916
|
+
const fileTerms = extractStructuredFileTerms(query);
|
|
26917
|
+
const toolTerms = extractStructuredToolTerms(query);
|
|
26918
|
+
if (fileTerms.length === 0 && toolTerms.length === 0) return [];
|
|
26919
|
+
const matchWhere = [];
|
|
26920
|
+
const whereParams = [];
|
|
26921
|
+
for (const term of fileTerms) {
|
|
26922
|
+
matchWhere.push("(p.file_path = ? OR p.file_path LIKE ? ESCAPE '\\')");
|
|
26923
|
+
whereParams.push(term, `%${escapeLike(term)}%`);
|
|
26924
|
+
}
|
|
26925
|
+
for (const term of toolTerms) {
|
|
26926
|
+
matchWhere.push("p.tool_name LIKE ? ESCAPE '\\'");
|
|
26927
|
+
whereParams.push(`%${escapeLike(term)}%`);
|
|
26928
|
+
}
|
|
26929
|
+
const where = [`(${matchWhere.join(" OR ")})`];
|
|
26930
|
+
if (sessionId) {
|
|
26931
|
+
where.push("m.session_id = ?");
|
|
26932
|
+
whereParams.push(sessionId);
|
|
26933
|
+
}
|
|
26934
|
+
const exactFileScoreParams = [...fileTerms];
|
|
26935
|
+
const sqlParams = [...exactFileScoreParams, ...whereParams, cappedLimit];
|
|
26936
|
+
const rows = this.db.prepare(`
|
|
26937
|
+
SELECT
|
|
26938
|
+
p.id AS part_id,
|
|
26939
|
+
p.message_id AS message_id,
|
|
26940
|
+
m.turn_index AS turn_index,
|
|
26941
|
+
m.role AS role,
|
|
26942
|
+
m.content AS content,
|
|
26943
|
+
m.session_id AS session_id,
|
|
26944
|
+
p.kind AS kind,
|
|
26945
|
+
p.tool_name AS tool_name,
|
|
26946
|
+
p.file_path AS file_path,
|
|
26947
|
+
p.payload AS payload,
|
|
26948
|
+
CASE
|
|
26949
|
+
WHEN p.file_path IN (${fileTerms.map(() => "?").join(",") || "NULL"}) THEN 3
|
|
26950
|
+
WHEN p.file_path IS NOT NULL THEN 2
|
|
26951
|
+
WHEN p.tool_name IS NOT NULL THEN 1
|
|
26952
|
+
ELSE 0
|
|
26953
|
+
END AS score
|
|
26954
|
+
FROM lcm_message_parts p
|
|
26955
|
+
JOIN lcm_messages m ON m.id = p.message_id
|
|
26956
|
+
WHERE ${where.join(" AND ")}
|
|
26957
|
+
ORDER BY score DESC, m.turn_index DESC, p.ordinal ASC
|
|
26958
|
+
LIMIT ?
|
|
26959
|
+
`).all(...sqlParams);
|
|
26960
|
+
return rows;
|
|
26961
|
+
}
|
|
26428
26962
|
/** Get total message count for a session. */
|
|
26429
26963
|
getMessageCount(sessionId) {
|
|
26430
26964
|
const row = this.db.prepare("SELECT COUNT(*) as cnt FROM lcm_messages WHERE session_id = ?").get(sessionId);
|
|
@@ -26576,6 +27110,72 @@ var STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
26576
27110
|
"we",
|
|
26577
27111
|
"they"
|
|
26578
27112
|
]);
|
|
27113
|
+
function extractStructuredFileTerms(query) {
|
|
27114
|
+
const terms = /* @__PURE__ */ new Set();
|
|
27115
|
+
for (const raw of splitQueryTerms(query)) {
|
|
27116
|
+
const cleaned = trimStructuredQueryTerm(raw);
|
|
27117
|
+
if (cleaned.includes("/") || hasStructuredFileExtension(cleaned)) {
|
|
27118
|
+
terms.add(cleaned);
|
|
27119
|
+
const basename3 = cleaned.split("/").pop();
|
|
27120
|
+
if (basename3 && basename3 !== cleaned) terms.add(basename3);
|
|
27121
|
+
}
|
|
27122
|
+
}
|
|
27123
|
+
return [...terms].filter((term) => term.length > 1).slice(0, 12);
|
|
27124
|
+
}
|
|
27125
|
+
function splitQueryTerms(query) {
|
|
27126
|
+
const terms = [];
|
|
27127
|
+
let term = "";
|
|
27128
|
+
for (const char of query.slice(0, 2e4)) {
|
|
27129
|
+
if (char === " " || char === "\n" || char === "\r" || char === " ") {
|
|
27130
|
+
if (term.length > 0) terms.push(term);
|
|
27131
|
+
term = "";
|
|
27132
|
+
continue;
|
|
27133
|
+
}
|
|
27134
|
+
term += char;
|
|
27135
|
+
if (term.length > 512) {
|
|
27136
|
+
terms.push(term);
|
|
27137
|
+
term = "";
|
|
27138
|
+
}
|
|
27139
|
+
}
|
|
27140
|
+
if (term.length > 0) terms.push(term);
|
|
27141
|
+
return terms;
|
|
27142
|
+
}
|
|
27143
|
+
function trimStructuredQueryTerm(raw) {
|
|
27144
|
+
const leading = /* @__PURE__ */ new Set(["`", "'", '"', "(", "[", "{"]);
|
|
27145
|
+
const trailing = /* @__PURE__ */ new Set(["`", "'", '"', ",", ".", "?", "!", ":", ";", ")", "]", "}"]);
|
|
27146
|
+
let start = 0;
|
|
27147
|
+
let end = raw.length;
|
|
27148
|
+
while (start < end && leading.has(raw[start])) start += 1;
|
|
27149
|
+
while (end > start && trailing.has(raw[end - 1])) end -= 1;
|
|
27150
|
+
return raw.slice(start, end);
|
|
27151
|
+
}
|
|
27152
|
+
function hasStructuredFileExtension(value) {
|
|
27153
|
+
const slash = value.lastIndexOf("/");
|
|
27154
|
+
const basename3 = value.slice(slash + 1);
|
|
27155
|
+
const dot = basename3.lastIndexOf(".");
|
|
27156
|
+
if (dot <= 0 || dot === basename3.length - 1) return false;
|
|
27157
|
+
const ext = basename3.slice(dot + 1);
|
|
27158
|
+
if (ext.length < 1 || ext.length > 12) return false;
|
|
27159
|
+
for (const char of ext) {
|
|
27160
|
+
const code = char.charCodeAt(0);
|
|
27161
|
+
const valid = code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "_" || char === "+" || char === "-";
|
|
27162
|
+
if (!valid) return false;
|
|
27163
|
+
}
|
|
27164
|
+
return true;
|
|
27165
|
+
}
|
|
27166
|
+
function extractStructuredToolTerms(query) {
|
|
27167
|
+
const lower = query.toLowerCase();
|
|
27168
|
+
if (!/\b(tool|command|invocation|called|used|ran|read|write|patch|edit|grep|search)\b/.test(lower)) {
|
|
27169
|
+
return [];
|
|
27170
|
+
}
|
|
27171
|
+
return query.replace(/[^\w.-]/g, " ").split(/\s+/).filter((term) => term.length > 2 && !STOPWORDS.has(term.toLowerCase())).slice(0, 8);
|
|
27172
|
+
}
|
|
27173
|
+
function escapeLike(value) {
|
|
27174
|
+
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
27175
|
+
}
|
|
27176
|
+
function asNullableString(value) {
|
|
27177
|
+
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
27178
|
+
}
|
|
26579
27179
|
function sanitizeFtsQuery(raw) {
|
|
26580
27180
|
const words = raw.replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 1 && !STOPWORDS.has(w.toLowerCase()));
|
|
26581
27181
|
if (words.length === 0) {
|
|
@@ -27045,7 +27645,9 @@ function extractLcmConfig(cfg) {
|
|
|
27045
27645
|
maxDepth: cfg.lcmMaxDepth ?? 5,
|
|
27046
27646
|
deterministicMaxTokens: cfg.lcmDeterministicMaxTokens ?? 512,
|
|
27047
27647
|
archiveRetentionDays: cfg.lcmArchiveRetentionDays ?? 90,
|
|
27048
|
-
recallBudgetShare: cfg.lcmRecallBudgetShare ?? 0.15
|
|
27648
|
+
recallBudgetShare: cfg.lcmRecallBudgetShare ?? 0.15,
|
|
27649
|
+
messagePartsEnabled: cfg.messagePartsEnabled === true,
|
|
27650
|
+
messagePartsRecallMaxResults: typeof cfg.messagePartsRecallMaxResults === "number" ? Math.max(0, Math.floor(cfg.messagePartsRecallMaxResults)) : 6
|
|
27049
27651
|
};
|
|
27050
27652
|
}
|
|
27051
27653
|
var LcmEngine = class {
|
|
@@ -27177,9 +27779,14 @@ var LcmEngine = class {
|
|
|
27177
27779
|
const newMessages = messages.map((m, i) => ({
|
|
27178
27780
|
turnIndex: currentMax + 1 + i,
|
|
27179
27781
|
role: m.role,
|
|
27180
|
-
content: m.content
|
|
27782
|
+
content: m.content,
|
|
27783
|
+
parts: this.config.messagePartsEnabled ? m.parts : void 0,
|
|
27784
|
+
rawContent: this.config.messagePartsEnabled ? m.rawContent : void 0,
|
|
27785
|
+
sourceFormat: this.config.messagePartsEnabled ? m.sourceFormat : void 0
|
|
27181
27786
|
}));
|
|
27182
|
-
this.archive.appendMessages(sessionId, newMessages
|
|
27787
|
+
this.archive.appendMessages(sessionId, newMessages, {
|
|
27788
|
+
messagePartsEnabled: this.config.messagePartsEnabled
|
|
27789
|
+
});
|
|
27183
27790
|
try {
|
|
27184
27791
|
await this.summarizer.summarizeIncremental(sessionId);
|
|
27185
27792
|
} catch (err) {
|
|
@@ -27257,6 +27864,28 @@ var LcmEngine = class {
|
|
|
27257
27864
|
budgetChars: effectiveBudget
|
|
27258
27865
|
});
|
|
27259
27866
|
}
|
|
27867
|
+
async searchStructuredParts(sessionId, query, limit = this.config.messagePartsRecallMaxResults) {
|
|
27868
|
+
if (!this.config.enabled || !this.config.messagePartsEnabled) return [];
|
|
27869
|
+
await this.ensureInitialized();
|
|
27870
|
+
if (!this.archive) return [];
|
|
27871
|
+
return this.archive.searchStructuredParts(query, limit, sessionId);
|
|
27872
|
+
}
|
|
27873
|
+
formatStructuredRecall(matches, budgetChars) {
|
|
27874
|
+
if (matches.length === 0 || budgetChars <= 0) return "";
|
|
27875
|
+
const lines = [];
|
|
27876
|
+
let used = "## Structured Session Matches\n\n".length;
|
|
27877
|
+
for (const match of matches) {
|
|
27878
|
+
const label = match.file_path ? `${match.kind} ${match.file_path}` : match.tool_name ? `${match.kind} ${match.tool_name}` : match.kind;
|
|
27879
|
+
const excerpt = match.content.replace(/\s+/g, " ").slice(0, 220);
|
|
27880
|
+
const line = `- turn ${match.turn_index} (${match.role}): ${label} \u2014 ${excerpt}`;
|
|
27881
|
+
if (used + line.length + 1 > budgetChars) break;
|
|
27882
|
+
lines.push(line);
|
|
27883
|
+
used += line.length + 1;
|
|
27884
|
+
}
|
|
27885
|
+
return lines.length > 0 ? `## Structured Session Matches
|
|
27886
|
+
|
|
27887
|
+
${lines.join("\n")}` : "";
|
|
27888
|
+
}
|
|
27260
27889
|
/** Flush pending summaries before compaction (called from before_compaction hook). */
|
|
27261
27890
|
async preCompactionFlush(sessionId) {
|
|
27262
27891
|
if (!this.config.enabled) return;
|
|
@@ -32443,7 +33072,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
32443
33072
|
this.conversationFaiss = conversationIndexRuntime.faiss;
|
|
32444
33073
|
this.conversationIndexBackend = conversationIndexRuntime.backend;
|
|
32445
33074
|
this.sharedContext = config.sharedContextEnabled ? new SharedContextManager(config) : void 0;
|
|
32446
|
-
this.compounding = config.compoundingEnabled ? new CompoundingEngine(config) : void 0;
|
|
33075
|
+
this.compounding = config.compoundingEnabled ? new CompoundingEngine(config, this.storage) : void 0;
|
|
32447
33076
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
32448
33077
|
this.transcript = new TranscriptManager(config);
|
|
32449
33078
|
this.conversationIndexDir = path43.join(
|
|
@@ -32745,8 +33374,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
32745
33374
|
promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
|
|
32746
33375
|
});
|
|
32747
33376
|
if (this.config.factDeduplicationEnabled) {
|
|
32748
|
-
|
|
32749
|
-
this.contentHashIndex = new ContentHashIndex(stateDir2);
|
|
33377
|
+
this.contentHashIndex = this.storage.createContentHashIndex();
|
|
32750
33378
|
await this.contentHashIndex.load();
|
|
32751
33379
|
log.info(
|
|
32752
33380
|
`content-hash dedup: loaded ${this.contentHashIndex.size} hashes`
|
|
@@ -33404,7 +34032,7 @@ ${doc.content}` : doc.content,
|
|
|
33404
34032
|
}
|
|
33405
34033
|
async runDeepSleepGovernanceNow(options) {
|
|
33406
34034
|
const targetStorage = options?.storage ?? this.storage;
|
|
33407
|
-
const { runMemoryGovernance: runMemoryGovernance2 } = await import("./memory-governance-
|
|
34035
|
+
const { runMemoryGovernance: runMemoryGovernance2 } = await import("./memory-governance-SJ5DGRB3.js");
|
|
33408
34036
|
const { summarizeGovernanceResultForDreams } = await import("./dreams-ledger-3I52ISYR.js");
|
|
33409
34037
|
const govResult = await runMemoryGovernance2({
|
|
33410
34038
|
memoryDir: targetStorage.dir,
|
|
@@ -35498,6 +36126,7 @@ ${r.snippet.trim()}
|
|
|
35498
36126
|
let recalledMemoryIds = [];
|
|
35499
36127
|
let recalledMemoryPaths = [];
|
|
35500
36128
|
let xrayRecalledResults = [];
|
|
36129
|
+
const lcmStructuredXrayResults = [];
|
|
35501
36130
|
const xrayBranchPoolSize = {
|
|
35502
36131
|
hot_qmd: 0,
|
|
35503
36132
|
hot_embedding: 0,
|
|
@@ -37421,6 +38050,32 @@ ${tmtNode.summary}`
|
|
|
37421
38050
|
}
|
|
37422
38051
|
if (this.lcmEngine?.enabled && recallMode !== "minimal" && recallMode !== "no_recall") {
|
|
37423
38052
|
try {
|
|
38053
|
+
const structuredMatches = await this.lcmEngine.searchStructuredParts(
|
|
38054
|
+
sessionKey ?? "default",
|
|
38055
|
+
retrievalQuery
|
|
38056
|
+
);
|
|
38057
|
+
const structuredSection = this.lcmEngine.formatStructuredRecall(
|
|
38058
|
+
structuredMatches,
|
|
38059
|
+
Math.ceil(this.config.recallBudgetChars * 0.08)
|
|
38060
|
+
);
|
|
38061
|
+
if (structuredSection) {
|
|
38062
|
+
const structuredAppended = this.appendRecallSection(
|
|
38063
|
+
sectionBuckets,
|
|
38064
|
+
"lcm-message-parts",
|
|
38065
|
+
structuredSection
|
|
38066
|
+
);
|
|
38067
|
+
if (structuredAppended) {
|
|
38068
|
+
for (const match of structuredMatches) {
|
|
38069
|
+
lcmStructuredXrayResults.push({
|
|
38070
|
+
memoryId: `lcm-message-part-${match.part_id}`,
|
|
38071
|
+
path: `lcm://${match.session_id}/turn/${match.turn_index}/part/${match.part_id}`,
|
|
38072
|
+
servedBy: match.file_path ? "lcm-file-parts" : "lcm-tool-parts",
|
|
38073
|
+
scoreDecomposition: { final: match.score },
|
|
38074
|
+
admittedBy: ["lcm-message-parts"]
|
|
38075
|
+
});
|
|
38076
|
+
}
|
|
38077
|
+
}
|
|
38078
|
+
}
|
|
37424
38079
|
const lcmSection = await this.lcmEngine.assembleRecall(
|
|
37425
38080
|
sessionKey ?? "default",
|
|
37426
38081
|
this.config.recallBudgetChars
|
|
@@ -38321,10 +38976,17 @@ _Context: ${topQuestion.context}_`
|
|
|
38321
38976
|
admitted: recalledMemoryIds.length
|
|
38322
38977
|
}
|
|
38323
38978
|
];
|
|
38979
|
+
if (lcmStructuredXrayResults.length > 0) {
|
|
38980
|
+
filters.push({
|
|
38981
|
+
name: "lcm-message-parts",
|
|
38982
|
+
considered: lcmStructuredXrayResults.length,
|
|
38983
|
+
admitted: lcmStructuredXrayResults.length
|
|
38984
|
+
});
|
|
38985
|
+
}
|
|
38324
38986
|
this.lastXraySnapshot = buildXraySnapshot({
|
|
38325
38987
|
query: retrievalQuery,
|
|
38326
38988
|
tierExplain: null,
|
|
38327
|
-
results,
|
|
38989
|
+
results: [...results, ...lcmStructuredXrayResults],
|
|
38328
38990
|
filters,
|
|
38329
38991
|
budget: {
|
|
38330
38992
|
chars: this.getRecallBudgetChars(options.budgetCharsOverride),
|
|
@@ -38491,13 +39153,28 @@ _Context: ${topQuestion.context}_`
|
|
|
38491
39153
|
role: turn.role,
|
|
38492
39154
|
content: turn.content,
|
|
38493
39155
|
timestamp: turn.timestamp,
|
|
38494
|
-
sessionKey: key
|
|
39156
|
+
sessionKey: key,
|
|
39157
|
+
parts: turn.parts,
|
|
39158
|
+
rawContent: turn.rawContent,
|
|
39159
|
+
sourceFormat: turn.sourceFormat
|
|
38495
39160
|
});
|
|
38496
39161
|
bySession.set(key, list);
|
|
38497
39162
|
}
|
|
38498
39163
|
const replayTasks = [];
|
|
38499
39164
|
for (const [key, sessionTurns] of bySession.entries()) {
|
|
38500
39165
|
if (sessionTurns.length === 0) continue;
|
|
39166
|
+
if (options.archiveLcm !== false && this.lcmEngine?.enabled) {
|
|
39167
|
+
await this.lcmEngine.observeMessages(
|
|
39168
|
+
key,
|
|
39169
|
+
sessionTurns.map((turn) => ({
|
|
39170
|
+
role: turn.role,
|
|
39171
|
+
content: turn.content,
|
|
39172
|
+
parts: turn.parts,
|
|
39173
|
+
rawContent: turn.rawContent,
|
|
39174
|
+
sourceFormat: turn.sourceFormat
|
|
39175
|
+
}))
|
|
39176
|
+
);
|
|
39177
|
+
}
|
|
38501
39178
|
replayTasks.push(
|
|
38502
39179
|
new Promise((resolve2, reject) => {
|
|
38503
39180
|
void this.queueBufferedExtraction(sessionTurns, "trigger_mode", {
|
|
@@ -38586,10 +39263,25 @@ _Context: ${topQuestion.context}_`
|
|
|
38586
39263
|
role: turn.role,
|
|
38587
39264
|
content: turn.content,
|
|
38588
39265
|
timestamp: turn.timestamp,
|
|
38589
|
-
sessionKey
|
|
39266
|
+
sessionKey,
|
|
39267
|
+
parts: turn.parts,
|
|
39268
|
+
rawContent: turn.rawContent,
|
|
39269
|
+
sourceFormat: turn.sourceFormat
|
|
38590
39270
|
});
|
|
38591
39271
|
}
|
|
38592
39272
|
if (sessionTurns.length === 0) return;
|
|
39273
|
+
if (this.lcmEngine?.enabled) {
|
|
39274
|
+
await this.lcmEngine.observeMessages(
|
|
39275
|
+
sessionKey,
|
|
39276
|
+
sessionTurns.map((turn) => ({
|
|
39277
|
+
role: turn.role,
|
|
39278
|
+
content: turn.content,
|
|
39279
|
+
parts: turn.parts,
|
|
39280
|
+
rawContent: turn.rawContent,
|
|
39281
|
+
sourceFormat: turn.sourceFormat
|
|
39282
|
+
}))
|
|
39283
|
+
);
|
|
39284
|
+
}
|
|
38593
39285
|
await new Promise((resolve2, reject) => {
|
|
38594
39286
|
void this.queueBufferedExtraction(sessionTurns, "trigger_mode", {
|
|
38595
39287
|
skipDedupeCheck: true,
|
|
@@ -43118,13 +43810,13 @@ function toolJsonResult(value, options) {
|
|
|
43118
43810
|
function workLayerTextResult(text, options) {
|
|
43119
43811
|
return toolResult2(wrapWorkLayerContext(text, { linkToMemory: options?.linkToMemory === true }));
|
|
43120
43812
|
}
|
|
43121
|
-
function
|
|
43813
|
+
function asNonEmptyString2(value) {
|
|
43122
43814
|
if (typeof value !== "string") return void 0;
|
|
43123
43815
|
const trimmed = value.trim();
|
|
43124
43816
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
43125
43817
|
}
|
|
43126
43818
|
function normalizeToolNamespace(value) {
|
|
43127
|
-
return
|
|
43819
|
+
return asNonEmptyString2(value);
|
|
43128
43820
|
}
|
|
43129
43821
|
function clampUnitInterval(value, fallback) {
|
|
43130
43822
|
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
@@ -43173,17 +43865,17 @@ var WORK_TASK_STATUSES = /* @__PURE__ */ new Set(["todo", "in_progress", "blocke
|
|
|
43173
43865
|
var WORK_TASK_PRIORITIES = /* @__PURE__ */ new Set(["low", "medium", "high"]);
|
|
43174
43866
|
var WORK_PROJECT_STATUSES = /* @__PURE__ */ new Set(["active", "on_hold", "completed", "archived"]);
|
|
43175
43867
|
function asTaskStatus(value) {
|
|
43176
|
-
const normalized =
|
|
43868
|
+
const normalized = asNonEmptyString2(value);
|
|
43177
43869
|
if (!normalized || !WORK_TASK_STATUSES.has(normalized)) return void 0;
|
|
43178
43870
|
return normalized;
|
|
43179
43871
|
}
|
|
43180
43872
|
function asTaskPriority(value) {
|
|
43181
|
-
const normalized =
|
|
43873
|
+
const normalized = asNonEmptyString2(value);
|
|
43182
43874
|
if (!normalized || !WORK_TASK_PRIORITIES.has(normalized)) return void 0;
|
|
43183
43875
|
return normalized;
|
|
43184
43876
|
}
|
|
43185
43877
|
function asProjectStatus(value) {
|
|
43186
|
-
const normalized =
|
|
43878
|
+
const normalized = asNonEmptyString2(value);
|
|
43187
43879
|
if (!normalized || !WORK_PROJECT_STATUSES.has(normalized)) return void 0;
|
|
43188
43880
|
return normalized;
|
|
43189
43881
|
}
|
|
@@ -43323,7 +44015,7 @@ function registerTools(api, orchestrator) {
|
|
|
43323
44015
|
return createHash10("sha256").update(input).digest("hex").slice(0, 16);
|
|
43324
44016
|
}
|
|
43325
44017
|
function normalizeMemoryCategory(value, fallback) {
|
|
43326
|
-
const normalized =
|
|
44018
|
+
const normalized = asNonEmptyString2(value);
|
|
43327
44019
|
if (!normalized) return fallback;
|
|
43328
44020
|
if (!VALID_MEMORY_CATEGORIES.has(normalized)) return void 0;
|
|
43329
44021
|
return normalized;
|
|
@@ -43332,8 +44024,8 @@ function registerTools(api, orchestrator) {
|
|
|
43332
44024
|
return typeof value === "string" && actionTypeSet.has(value);
|
|
43333
44025
|
}
|
|
43334
44026
|
function buildActionInputSummary(action, params) {
|
|
43335
|
-
const primary =
|
|
43336
|
-
const content =
|
|
44027
|
+
const primary = asNonEmptyString2(params.memoryId) ?? asNonEmptyString2(params.category) ?? asNonEmptyString2(params.linkTargetId);
|
|
44028
|
+
const content = asNonEmptyString2(params.content);
|
|
43337
44029
|
let summary = primary ? `${action} => ${primary}` : action;
|
|
43338
44030
|
if (content) {
|
|
43339
44031
|
summary += ` | ${content.slice(0, 120)}`;
|
|
@@ -44218,14 +44910,14 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
|
|
|
44218
44910
|
return toolResult2(`Recorded context checkpoint telemetry in namespace=${ns}.`);
|
|
44219
44911
|
}
|
|
44220
44912
|
const validationErrors = [];
|
|
44221
|
-
if (!
|
|
44913
|
+
if (!asNonEmptyString2(sessionKey)) validationErrors.push("sessionKey is required");
|
|
44222
44914
|
if (!Array.isArray(turns) || turns.length === 0) validationErrors.push("turns must be a non-empty array");
|
|
44223
44915
|
const baseEvent = {
|
|
44224
44916
|
action: "summarize_node",
|
|
44225
44917
|
namespace: ns,
|
|
44226
44918
|
actor: "tool.context_checkpoint",
|
|
44227
44919
|
subsystem: "tools.context_checkpoint",
|
|
44228
|
-
sourceSessionKey:
|
|
44920
|
+
sourceSessionKey: asNonEmptyString2(sessionKey),
|
|
44229
44921
|
inputSummary: summary,
|
|
44230
44922
|
checkpointTurnCount: Array.isArray(turns) ? turns.length : void 0,
|
|
44231
44923
|
dryRun: dryRun === true,
|
|
@@ -44387,10 +45079,10 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
|
|
|
44387
45079
|
return toolResult2(`Validation failed: invalid action ${String(action)}.`);
|
|
44388
45080
|
}
|
|
44389
45081
|
const validationErrors = [];
|
|
44390
|
-
const contentValue =
|
|
44391
|
-
const memoryIdValue =
|
|
44392
|
-
const linkTargetIdValue =
|
|
44393
|
-
const linkTypeValue =
|
|
45082
|
+
const contentValue = asNonEmptyString2(content);
|
|
45083
|
+
const memoryIdValue = asNonEmptyString2(memoryId);
|
|
45084
|
+
const linkTargetIdValue = asNonEmptyString2(linkTargetId);
|
|
45085
|
+
const linkTypeValue = asNonEmptyString2(linkType);
|
|
44394
45086
|
const structuredActionRequest = execute === true || Object.prototype.hasOwnProperty.call(params, "content") || Object.prototype.hasOwnProperty.call(params, "category") || Object.prototype.hasOwnProperty.call(params, "linkTargetId") || Object.prototype.hasOwnProperty.call(params, "linkType") || Object.prototype.hasOwnProperty.call(params, "linkStrength") || Object.prototype.hasOwnProperty.call(params, "artifactType");
|
|
44395
45087
|
const baseEvent = {
|
|
44396
45088
|
action,
|
|
@@ -44399,7 +45091,7 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
|
|
|
44399
45091
|
subsystem: "tools.memory_action_apply",
|
|
44400
45092
|
reason,
|
|
44401
45093
|
memoryId: memoryIdValue,
|
|
44402
|
-
sourceSessionKey:
|
|
45094
|
+
sourceSessionKey: asNonEmptyString2(sessionKey),
|
|
44403
45095
|
inputSummary: buildActionInputSummary(action, params),
|
|
44404
45096
|
promptHash: promptHashForTelemetry(sourcePrompt)
|
|
44405
45097
|
};
|
|
@@ -45309,16 +46001,16 @@ Best for:
|
|
|
45309
46001
|
description: typeof p.description === "string" ? p.description : void 0,
|
|
45310
46002
|
status: asTaskStatus(p.status),
|
|
45311
46003
|
priority: asTaskPriority(p.priority),
|
|
45312
|
-
owner:
|
|
45313
|
-
assignee:
|
|
45314
|
-
projectId:
|
|
46004
|
+
owner: asNonEmptyString2(p.owner),
|
|
46005
|
+
assignee: asNonEmptyString2(p.assignee),
|
|
46006
|
+
projectId: asNonEmptyString2(p.projectId),
|
|
45315
46007
|
tags: Array.isArray(p.tags) ? p.tags.filter((x) => typeof x === "string") : void 0,
|
|
45316
|
-
dueAt:
|
|
46008
|
+
dueAt: asNonEmptyString2(p.dueAt)
|
|
45317
46009
|
});
|
|
45318
46010
|
return toolJsonResult({ action, task: created });
|
|
45319
46011
|
}
|
|
45320
46012
|
if (action === "get") {
|
|
45321
|
-
const taskId =
|
|
46013
|
+
const taskId = asNonEmptyString2(p.id);
|
|
45322
46014
|
if (!taskId) {
|
|
45323
46015
|
return workLayerTextResult("work_task.get requires `id`.");
|
|
45324
46016
|
}
|
|
@@ -45328,14 +46020,14 @@ Best for:
|
|
|
45328
46020
|
if (action === "list") {
|
|
45329
46021
|
const tasks = await storage.listTasks({
|
|
45330
46022
|
status: asTaskStatus(p.status),
|
|
45331
|
-
owner:
|
|
45332
|
-
assignee:
|
|
45333
|
-
projectId:
|
|
46023
|
+
owner: asNonEmptyString2(p.owner),
|
|
46024
|
+
assignee: asNonEmptyString2(p.assignee),
|
|
46025
|
+
projectId: asNonEmptyString2(p.projectId)
|
|
45334
46026
|
});
|
|
45335
46027
|
return toolJsonResult({ action, count: tasks.length, tasks });
|
|
45336
46028
|
}
|
|
45337
46029
|
if (action === "update") {
|
|
45338
|
-
const taskId =
|
|
46030
|
+
const taskId = asNonEmptyString2(p.id);
|
|
45339
46031
|
if (!taskId) {
|
|
45340
46032
|
return workLayerTextResult("work_task.update requires `id`.");
|
|
45341
46033
|
}
|
|
@@ -45359,8 +46051,8 @@ Best for:
|
|
|
45359
46051
|
return toolJsonResult({ action, task: updated });
|
|
45360
46052
|
}
|
|
45361
46053
|
if (action === "transition") {
|
|
45362
|
-
const taskId =
|
|
45363
|
-
const rawStatus =
|
|
46054
|
+
const taskId = asNonEmptyString2(p.id);
|
|
46055
|
+
const rawStatus = asNonEmptyString2(p.status);
|
|
45364
46056
|
if (!taskId || !rawStatus) {
|
|
45365
46057
|
return workLayerTextResult("work_task.transition requires `id` and `status`.");
|
|
45366
46058
|
}
|
|
@@ -45372,7 +46064,7 @@ Best for:
|
|
|
45372
46064
|
return toolJsonResult({ action, task });
|
|
45373
46065
|
}
|
|
45374
46066
|
if (action === "delete") {
|
|
45375
|
-
const taskId =
|
|
46067
|
+
const taskId = asNonEmptyString2(p.id);
|
|
45376
46068
|
if (!taskId) {
|
|
45377
46069
|
return workLayerTextResult("work_task.delete requires `id`.");
|
|
45378
46070
|
}
|
|
@@ -45420,13 +46112,13 @@ Best for:
|
|
|
45420
46112
|
name: p.name,
|
|
45421
46113
|
description: typeof p.description === "string" ? p.description : void 0,
|
|
45422
46114
|
status: asProjectStatus(p.status),
|
|
45423
|
-
owner:
|
|
46115
|
+
owner: asNonEmptyString2(p.owner),
|
|
45424
46116
|
tags: Array.isArray(p.tags) ? p.tags.filter((x) => typeof x === "string") : void 0
|
|
45425
46117
|
});
|
|
45426
46118
|
return toolJsonResult({ action, project });
|
|
45427
46119
|
}
|
|
45428
46120
|
if (action === "get") {
|
|
45429
|
-
const projectId =
|
|
46121
|
+
const projectId = asNonEmptyString2(p.id);
|
|
45430
46122
|
if (!projectId) {
|
|
45431
46123
|
return workLayerTextResult("work_project.get requires `id`.");
|
|
45432
46124
|
}
|
|
@@ -45438,7 +46130,7 @@ Best for:
|
|
|
45438
46130
|
return toolJsonResult({ action, count: projects.length, projects });
|
|
45439
46131
|
}
|
|
45440
46132
|
if (action === "update") {
|
|
45441
|
-
const projectId =
|
|
46133
|
+
const projectId = asNonEmptyString2(p.id);
|
|
45442
46134
|
if (!projectId) {
|
|
45443
46135
|
return workLayerTextResult("work_project.update requires `id`.");
|
|
45444
46136
|
}
|
|
@@ -45454,7 +46146,7 @@ Best for:
|
|
|
45454
46146
|
return toolJsonResult({ action, project });
|
|
45455
46147
|
}
|
|
45456
46148
|
if (action === "delete") {
|
|
45457
|
-
const projectId =
|
|
46149
|
+
const projectId = asNonEmptyString2(p.id);
|
|
45458
46150
|
if (!projectId) {
|
|
45459
46151
|
return workLayerTextResult("work_project.delete requires `id`.");
|
|
45460
46152
|
}
|
|
@@ -45462,8 +46154,8 @@ Best for:
|
|
|
45462
46154
|
return toolJsonResult({ action, deleted });
|
|
45463
46155
|
}
|
|
45464
46156
|
if (action === "link_task") {
|
|
45465
|
-
const taskId =
|
|
45466
|
-
const projectId =
|
|
46157
|
+
const taskId = asNonEmptyString2(p.taskId);
|
|
46158
|
+
const projectId = asNonEmptyString2(p.projectId);
|
|
45467
46159
|
if (!taskId || !projectId) {
|
|
45468
46160
|
return workLayerTextResult("work_project.link_task requires `taskId` and `projectId`.");
|
|
45469
46161
|
}
|
|
@@ -45499,7 +46191,7 @@ Best for:
|
|
|
45499
46191
|
async execute(_toolCallId, params) {
|
|
45500
46192
|
const p = params;
|
|
45501
46193
|
const action = String(p.action ?? "");
|
|
45502
|
-
const projectId =
|
|
46194
|
+
const projectId = asNonEmptyString2(p.projectId);
|
|
45503
46195
|
const linkToMemory = p.linkToMemory === true;
|
|
45504
46196
|
try {
|
|
45505
46197
|
await new WorkStorage(orchestrator.config.memoryDir).ensureDirectories();
|
|
@@ -45519,7 +46211,7 @@ Best for:
|
|
|
45519
46211
|
const result = await importWorkBoardSnapshot({
|
|
45520
46212
|
memoryDir: orchestrator.config.memoryDir,
|
|
45521
46213
|
snapshot,
|
|
45522
|
-
projectId:
|
|
46214
|
+
projectId: asNonEmptyString2(p.projectId)
|
|
45523
46215
|
});
|
|
45524
46216
|
return toolJsonResult({ action, result }, { linkToMemory });
|
|
45525
46217
|
}
|
|
@@ -45785,7 +46477,7 @@ Returns: Performance trace data with timing breakdown`,
|
|
|
45785
46477
|
"Profiling is disabled. Set profilingEnabled: true in your plugin config to enable."
|
|
45786
46478
|
);
|
|
45787
46479
|
}
|
|
45788
|
-
const format =
|
|
46480
|
+
const format = asNonEmptyString2(params.format) ?? "ascii";
|
|
45789
46481
|
const limit = Math.min(typeof params.limit === "number" ? params.limit : 5, 20);
|
|
45790
46482
|
const traces = profiler.getRecentTraces(limit);
|
|
45791
46483
|
const stats = profiler.getStats();
|
|
@@ -45856,7 +46548,7 @@ Returns: Performance trace data with timing breakdown`,
|
|
|
45856
46548
|
"Profiling is disabled. Set profilingEnabled: true in your plugin config to enable."
|
|
45857
46549
|
);
|
|
45858
46550
|
}
|
|
45859
|
-
const format =
|
|
46551
|
+
const format = asNonEmptyString2(params.format) ?? "ascii";
|
|
45860
46552
|
const limit = Math.min(typeof params.limit === "number" ? params.limit : 5, 20);
|
|
45861
46553
|
const traces = profiler.getRecentTraces(limit);
|
|
45862
46554
|
const stats = profiler.getStats();
|
|
@@ -45905,8 +46597,8 @@ Returns: Performance trace data with timing breakdown`,
|
|
|
45905
46597
|
|
|
45906
46598
|
// ../remnic-core/src/cli.ts
|
|
45907
46599
|
import path74 from "path";
|
|
45908
|
-
import { access as
|
|
45909
|
-
import { createHash as
|
|
46600
|
+
import { access as access7, readFile as readFile47, readdir as readdir28, unlink as unlink12 } from "fs/promises";
|
|
46601
|
+
import { createHash as createHash14 } from "crypto";
|
|
45910
46602
|
|
|
45911
46603
|
// ../remnic-core/src/transfer/export-json.ts
|
|
45912
46604
|
import path45 from "path";
|
|
@@ -46020,7 +46712,7 @@ async function backupMemoryDir(opts) {
|
|
|
46020
46712
|
const ts = timestampDirName(/* @__PURE__ */ new Date());
|
|
46021
46713
|
if (opts.encrypt === true) {
|
|
46022
46714
|
const { listFilesRecursive: listFilesRecursive3, toPosixRelPath: toPosixRelPath2 } = await import("./fs-utils-PZRI2HDZ.js");
|
|
46023
|
-
const { readFile:
|
|
46715
|
+
const { readFile: readFile54 } = await import("fs/promises");
|
|
46024
46716
|
const memoryDirAbs = path47.resolve(opts.memoryDir);
|
|
46025
46717
|
const filesAbs = await listFilesRecursive3(memoryDirAbs);
|
|
46026
46718
|
const includeTranscripts = opts.includeTranscripts === true;
|
|
@@ -46030,7 +46722,7 @@ async function backupMemoryDir(opts) {
|
|
|
46030
46722
|
const parts = relPosix.split("/");
|
|
46031
46723
|
if (parts.some((p) => p === "node_modules" || p === ".git" || p === ".secure-store" || p === ".capsules")) continue;
|
|
46032
46724
|
if (!includeTranscripts && parts[0] === "transcripts") continue;
|
|
46033
|
-
const content = await
|
|
46725
|
+
const content = await readFile54(abs, "utf-8");
|
|
46034
46726
|
records.push({ path: relPosix, content });
|
|
46035
46727
|
}
|
|
46036
46728
|
records.sort((a, b) => a.path.localeCompare(b.path));
|
|
@@ -49052,7 +49744,7 @@ function removeManagedCaptureInstructions(existing) {
|
|
|
49052
49744
|
async function runOperatorSetup(options) {
|
|
49053
49745
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
49054
49746
|
const configStatus = await loadCliPluginConfig(options.configPath);
|
|
49055
|
-
const storage =
|
|
49747
|
+
const storage = options.orchestrator.storage;
|
|
49056
49748
|
await storage.ensureDirectories();
|
|
49057
49749
|
await mkdir42(options.orchestrator.config.workspaceDir, { recursive: true });
|
|
49058
49750
|
const qmdAvailable = await options.orchestrator.qmd.probe();
|
|
@@ -49329,6 +50021,7 @@ async function runOperatorDoctor(options) {
|
|
|
49329
50021
|
const configStatus = await loadCliPluginConfig(options.configPath);
|
|
49330
50022
|
const checks = [];
|
|
49331
50023
|
const config = options.orchestrator.config;
|
|
50024
|
+
const storage = options.orchestrator.storage;
|
|
49332
50025
|
const configReview = await buildOperatorConfigReviewReport({
|
|
49333
50026
|
now,
|
|
49334
50027
|
configStatus,
|
|
@@ -49379,7 +50072,7 @@ async function runOperatorDoctor(options) {
|
|
|
49379
50072
|
remediation: conversationIndex.enabled && conversationIndex.status !== "ok" ? "Run `openclaw engram rebuild-index` to refresh the conversation index artifacts." : void 0,
|
|
49380
50073
|
details: conversationIndex
|
|
49381
50074
|
});
|
|
49382
|
-
const meta = await
|
|
50075
|
+
const meta = await storage.loadMeta();
|
|
49383
50076
|
checks.push({
|
|
49384
50077
|
key: "maintenance",
|
|
49385
50078
|
status: meta.lastExtractionAt || meta.lastConsolidationAt ? "ok" : "warn",
|
|
@@ -49412,14 +50105,14 @@ async function runOperatorDoctor(options) {
|
|
|
49412
50105
|
warnRatio: config.fileHygiene.lintWarnRatio
|
|
49413
50106
|
}) : [];
|
|
49414
50107
|
checks.push(summarizeHygieneWarnings(warnings, config.fileHygiene));
|
|
49415
|
-
checks.push(await summarizeMemoryWorthLegacyCounters(
|
|
50108
|
+
checks.push(await summarizeMemoryWorthLegacyCounters(storage));
|
|
49416
50109
|
checks.push(
|
|
49417
|
-
await summarizeBufferSurpriseDistribution(
|
|
50110
|
+
await summarizeBufferSurpriseDistribution(storage, config)
|
|
49418
50111
|
);
|
|
49419
|
-
checks.push(await summarizeConsolidationProvenance(
|
|
50112
|
+
checks.push(await summarizeConsolidationProvenance(storage, config));
|
|
49420
50113
|
checks.push(await summarizeGraphEdgeDecayStatus(config));
|
|
49421
50114
|
checks.push(await summarizeTierDistribution(options.orchestrator.storage));
|
|
49422
|
-
checks.push(await summarizeDreamsPhases(config));
|
|
50115
|
+
checks.push(await summarizeDreamsPhases(config, storage));
|
|
49423
50116
|
checks.push(summarizeSecurityMitigations(config));
|
|
49424
50117
|
checks.push(await summarizeObservationThroughput(config.memoryDir));
|
|
49425
50118
|
const summary = checks.reduce(
|
|
@@ -49569,8 +50262,8 @@ async function summarizeTierDistribution(storage) {
|
|
|
49569
50262
|
const sevenDaysAgoMs = Date.now() - 7 * 864e5;
|
|
49570
50263
|
if (journalPath) {
|
|
49571
50264
|
try {
|
|
49572
|
-
const { readFile:
|
|
49573
|
-
const raw = await
|
|
50265
|
+
const { readFile: readFile54 } = await import("fs/promises");
|
|
50266
|
+
const raw = await readFile54(journalPath, "utf-8");
|
|
49574
50267
|
for (const line of raw.split("\n")) {
|
|
49575
50268
|
const trimmed = line.trim();
|
|
49576
50269
|
if (trimmed.length === 0) continue;
|
|
@@ -49615,9 +50308,8 @@ async function summarizeTierDistribution(storage) {
|
|
|
49615
50308
|
};
|
|
49616
50309
|
}
|
|
49617
50310
|
}
|
|
49618
|
-
async function summarizeDreamsPhases(config) {
|
|
50311
|
+
async function summarizeDreamsPhases(config, storage = new StorageManager(config.memoryDir)) {
|
|
49619
50312
|
const phases = config.dreamsPhases;
|
|
49620
|
-
const storage = new StorageManager(config.memoryDir);
|
|
49621
50313
|
const meta = await storage.loadMeta();
|
|
49622
50314
|
let deepSleepLastRun = null;
|
|
49623
50315
|
let deepSleepLastRunWarning = null;
|
|
@@ -50868,6 +51560,8 @@ var GraphDashboardServer = class {
|
|
|
50868
51560
|
// ../remnic-core/src/access-service.ts
|
|
50869
51561
|
import { stat as stat19 } from "fs/promises";
|
|
50870
51562
|
import * as nodeFs from "fs/promises";
|
|
51563
|
+
import { constants as fsConstants2 } from "fs";
|
|
51564
|
+
import { createHash as createHash13 } from "crypto";
|
|
50871
51565
|
|
|
50872
51566
|
// ../remnic-core/src/access-idempotency.ts
|
|
50873
51567
|
import { mkdir as mkdir44, open as open4, readFile as readFile40, rename as rename7, stat as stat18, unlink as unlink11, utimes as utimes2, writeFile as writeFile39 } from "fs/promises";
|
|
@@ -53338,6 +54032,18 @@ async function recordMemoryOutcome(storage, input) {
|
|
|
53338
54032
|
// ../remnic-core/src/access-service.ts
|
|
53339
54033
|
var EngramAccessInputError = class extends Error {
|
|
53340
54034
|
};
|
|
54035
|
+
var cachedPackageVersion = null;
|
|
54036
|
+
async function getPackageVersion() {
|
|
54037
|
+
if (cachedPackageVersion !== null) return cachedPackageVersion;
|
|
54038
|
+
try {
|
|
54039
|
+
const raw = await nodeFs.readFile(new URL("../package.json", import.meta.url), "utf-8");
|
|
54040
|
+
const parsed = JSON.parse(raw);
|
|
54041
|
+
cachedPackageVersion = typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : "unknown";
|
|
54042
|
+
} catch {
|
|
54043
|
+
cachedPackageVersion = "unknown";
|
|
54044
|
+
}
|
|
54045
|
+
return cachedPackageVersion;
|
|
54046
|
+
}
|
|
53341
54047
|
function normalizeTrustZoneInputError(error) {
|
|
53342
54048
|
const message = error instanceof Error ? error.message : null;
|
|
53343
54049
|
if (!message) {
|
|
@@ -54942,6 +55648,147 @@ var EngramAccessService = class {
|
|
|
54942
55648
|
});
|
|
54943
55649
|
return { namespace: resolvedNamespace, ...report };
|
|
54944
55650
|
}
|
|
55651
|
+
async memorySummarizeHourly() {
|
|
55652
|
+
await this.orchestrator.summarizer.runHourly();
|
|
55653
|
+
return {
|
|
55654
|
+
ok: true,
|
|
55655
|
+
message: "Hourly summarization completed. Check the summaries directory for results."
|
|
55656
|
+
};
|
|
55657
|
+
}
|
|
55658
|
+
async conversationIndexUpdate(request = {}) {
|
|
55659
|
+
if (!this.orchestrator.config.conversationIndexEnabled) {
|
|
55660
|
+
return {
|
|
55661
|
+
enabled: false,
|
|
55662
|
+
sessions: 0,
|
|
55663
|
+
chunks: 0,
|
|
55664
|
+
skipped: 0,
|
|
55665
|
+
skippedSessionKeys: [],
|
|
55666
|
+
embeddedRuns: 0,
|
|
55667
|
+
reason: "disabled"
|
|
55668
|
+
};
|
|
55669
|
+
}
|
|
55670
|
+
const hours = typeof request.hours === "number" && Number.isFinite(request.hours) ? Math.max(1, Math.floor(request.hours)) : 24;
|
|
55671
|
+
let sessionKey;
|
|
55672
|
+
if (request.sessionKey !== void 0) {
|
|
55673
|
+
if (typeof request.sessionKey !== "string" || request.sessionKey.trim().length === 0) {
|
|
55674
|
+
throw new EngramAccessInputError("sessionKey must be a non-empty string when provided");
|
|
55675
|
+
}
|
|
55676
|
+
sessionKey = request.sessionKey.trim();
|
|
55677
|
+
}
|
|
55678
|
+
if (sessionKey) {
|
|
55679
|
+
const result = await this.orchestrator.updateConversationIndex(
|
|
55680
|
+
sessionKey,
|
|
55681
|
+
hours,
|
|
55682
|
+
{ embed: request.embed }
|
|
55683
|
+
);
|
|
55684
|
+
return {
|
|
55685
|
+
enabled: true,
|
|
55686
|
+
sessionKey,
|
|
55687
|
+
sessions: 1,
|
|
55688
|
+
chunks: result.chunks,
|
|
55689
|
+
skipped: result.skipped ? 1 : 0,
|
|
55690
|
+
skippedSessionKeys: result.skipped ? [sessionKey] : [],
|
|
55691
|
+
embeddedRuns: result.embedded ? 1 : 0,
|
|
55692
|
+
reason: result.reason,
|
|
55693
|
+
retryAfterMs: result.retryAfterMs
|
|
55694
|
+
};
|
|
55695
|
+
}
|
|
55696
|
+
const sessionKeys = await this.orchestrator.transcript.listSessionKeys();
|
|
55697
|
+
let chunks = 0;
|
|
55698
|
+
let skipped = 0;
|
|
55699
|
+
const skippedSessionKeys = [];
|
|
55700
|
+
let embeddedRuns = 0;
|
|
55701
|
+
for (const sessionKey2 of sessionKeys) {
|
|
55702
|
+
const result = await this.orchestrator.updateConversationIndex(
|
|
55703
|
+
sessionKey2,
|
|
55704
|
+
hours,
|
|
55705
|
+
{ embed: request.embed }
|
|
55706
|
+
);
|
|
55707
|
+
chunks += result.chunks;
|
|
55708
|
+
if (result.skipped) {
|
|
55709
|
+
skipped += 1;
|
|
55710
|
+
skippedSessionKeys.push(sessionKey2);
|
|
55711
|
+
}
|
|
55712
|
+
if (result.embedded) {
|
|
55713
|
+
embeddedRuns += 1;
|
|
55714
|
+
}
|
|
55715
|
+
}
|
|
55716
|
+
return {
|
|
55717
|
+
enabled: true,
|
|
55718
|
+
sessions: sessionKeys.length,
|
|
55719
|
+
chunks,
|
|
55720
|
+
skipped,
|
|
55721
|
+
skippedSessionKeys,
|
|
55722
|
+
embeddedRuns
|
|
55723
|
+
};
|
|
55724
|
+
}
|
|
55725
|
+
async profilingReport(request = {}) {
|
|
55726
|
+
const profiler = this.orchestrator.profiler;
|
|
55727
|
+
if (!profiler.isEnabled) {
|
|
55728
|
+
return {
|
|
55729
|
+
enabled: false,
|
|
55730
|
+
reason: "disabled",
|
|
55731
|
+
message: "Profiling is disabled. Set profilingEnabled: true in your plugin config to enable."
|
|
55732
|
+
};
|
|
55733
|
+
}
|
|
55734
|
+
const format = request.format ?? "ascii";
|
|
55735
|
+
if (format !== "ascii" && format !== "json") {
|
|
55736
|
+
throw new EngramAccessInputError("format must be one of: ascii, json");
|
|
55737
|
+
}
|
|
55738
|
+
const limit = request.limit ?? 5;
|
|
55739
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 20) {
|
|
55740
|
+
throw new EngramAccessInputError("limit must be an integer between 1 and 20");
|
|
55741
|
+
}
|
|
55742
|
+
const traces = profiler.getRecentTraces(limit);
|
|
55743
|
+
const stats = profiler.getStats();
|
|
55744
|
+
const bottleneck = profiler.identifyBottleneck();
|
|
55745
|
+
if (format === "json") {
|
|
55746
|
+
return {
|
|
55747
|
+
enabled: true,
|
|
55748
|
+
format,
|
|
55749
|
+
traces,
|
|
55750
|
+
stats,
|
|
55751
|
+
bottleneck
|
|
55752
|
+
};
|
|
55753
|
+
}
|
|
55754
|
+
const lines = [];
|
|
55755
|
+
lines.push("Engram Profiling Report");
|
|
55756
|
+
lines.push("=".repeat(60));
|
|
55757
|
+
lines.push("");
|
|
55758
|
+
const allBuckets = [
|
|
55759
|
+
["byKind", stats.byKind],
|
|
55760
|
+
["bySpan", stats.bySpan]
|
|
55761
|
+
];
|
|
55762
|
+
const hasStats = allBuckets.some(([, entries]) => Object.keys(entries).length > 0);
|
|
55763
|
+
if (hasStats) {
|
|
55764
|
+
lines.push("Aggregate Stats (all retained traces):");
|
|
55765
|
+
for (const [bucket, entries] of allBuckets) {
|
|
55766
|
+
for (const [key, summary] of Object.entries(entries)) {
|
|
55767
|
+
lines.push(
|
|
55768
|
+
` ${bucket}/${key}: avg=${summary.avgMs}ms p50=${summary.p50Ms}ms p95=${summary.p95Ms}ms max=${summary.maxMs}ms (n=${summary.count})`
|
|
55769
|
+
);
|
|
55770
|
+
}
|
|
55771
|
+
}
|
|
55772
|
+
lines.push("");
|
|
55773
|
+
}
|
|
55774
|
+
if (bottleneck) {
|
|
55775
|
+
lines.push(`Bottleneck: ${bottleneck}`);
|
|
55776
|
+
lines.push("");
|
|
55777
|
+
}
|
|
55778
|
+
if (traces.length === 0) {
|
|
55779
|
+
lines.push("No traces recorded yet. Trigger a recall or extraction to see timing data.");
|
|
55780
|
+
} else {
|
|
55781
|
+
for (const trace of traces) {
|
|
55782
|
+
lines.push(formatProfileTraceAscii(trace));
|
|
55783
|
+
lines.push("");
|
|
55784
|
+
}
|
|
55785
|
+
}
|
|
55786
|
+
return {
|
|
55787
|
+
enabled: true,
|
|
55788
|
+
format,
|
|
55789
|
+
report: lines.join("\n")
|
|
55790
|
+
};
|
|
55791
|
+
}
|
|
54945
55792
|
async trustZoneStatus(namespace, principal) {
|
|
54946
55793
|
const resolvedNamespace = this.resolveReadableNamespace(namespace, principal);
|
|
54947
55794
|
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
@@ -55159,10 +56006,15 @@ var EngramAccessService = class {
|
|
|
55159
56006
|
sessionKey: lcmSessionKey,
|
|
55160
56007
|
role: m.role,
|
|
55161
56008
|
content: m.content,
|
|
56009
|
+
parts: m.parts,
|
|
56010
|
+
rawContent: m.rawContent,
|
|
56011
|
+
sourceFormat: m.sourceFormat,
|
|
55162
56012
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
55163
56013
|
}));
|
|
55164
56014
|
try {
|
|
55165
|
-
const extractionPromise = this.orchestrator.ingestReplayBatch(turns
|
|
56015
|
+
const extractionPromise = this.orchestrator.ingestReplayBatch(turns, {
|
|
56016
|
+
archiveLcm: false
|
|
56017
|
+
});
|
|
55166
56018
|
extractionPromise.catch((err) => {
|
|
55167
56019
|
log.error(`access-observe background extraction failed: ${err}`);
|
|
55168
56020
|
});
|
|
@@ -55861,22 +56713,82 @@ ${next}`);
|
|
|
55861
56713
|
});
|
|
55862
56714
|
return { promoted: true, memoryId: request.memoryId };
|
|
55863
56715
|
}
|
|
56716
|
+
async memoryActionApply(request) {
|
|
56717
|
+
const actionTypes = /* @__PURE__ */ new Set([
|
|
56718
|
+
"store_episode",
|
|
56719
|
+
"store_note",
|
|
56720
|
+
"update_note",
|
|
56721
|
+
"create_artifact",
|
|
56722
|
+
"summarize_node",
|
|
56723
|
+
"discard",
|
|
56724
|
+
"link_graph"
|
|
56725
|
+
]);
|
|
56726
|
+
if (!actionTypes.has(request.action)) {
|
|
56727
|
+
throw new EngramAccessInputError(
|
|
56728
|
+
`memory_action_apply: invalid action ${JSON.stringify(request.action)}`
|
|
56729
|
+
);
|
|
56730
|
+
}
|
|
56731
|
+
if (this.orchestrator.config.contextCompressionActionsEnabled !== true) {
|
|
56732
|
+
throw new EngramAccessInputError(
|
|
56733
|
+
"memory_action_apply is disabled; enable contextCompressionActionsEnabled to use this tool"
|
|
56734
|
+
);
|
|
56735
|
+
}
|
|
56736
|
+
const outcome = request.outcome ?? "skipped";
|
|
56737
|
+
if (outcome !== "applied" && outcome !== "skipped" && outcome !== "failed") {
|
|
56738
|
+
throw new EngramAccessInputError(
|
|
56739
|
+
`memory_action_apply: outcome must be "applied", "skipped", or "failed"; got ${JSON.stringify(outcome)}`
|
|
56740
|
+
);
|
|
56741
|
+
}
|
|
56742
|
+
const resolvedNs = this.resolveWritableNamespace(
|
|
56743
|
+
request.namespace,
|
|
56744
|
+
request.sessionKey,
|
|
56745
|
+
request.principal
|
|
56746
|
+
);
|
|
56747
|
+
const inputSummaryParts = [
|
|
56748
|
+
request.content,
|
|
56749
|
+
request.category ? `category=${request.category}` : void 0,
|
|
56750
|
+
request.linkTargetId ? `linkTargetId=${request.linkTargetId}` : void 0,
|
|
56751
|
+
request.linkType ? `linkType=${request.linkType}` : void 0,
|
|
56752
|
+
typeof request.linkStrength === "number" ? `linkStrength=${request.linkStrength}` : void 0,
|
|
56753
|
+
request.artifactType ? `artifactType=${request.artifactType}` : void 0,
|
|
56754
|
+
typeof request.execute === "boolean" ? `execute=${request.execute}` : void 0
|
|
56755
|
+
].filter((part) => typeof part === "string" && part.length > 0);
|
|
56756
|
+
const event = {
|
|
56757
|
+
action: request.action,
|
|
56758
|
+
outcome,
|
|
56759
|
+
namespace: resolvedNs,
|
|
56760
|
+
actor: "access.memory_action_apply",
|
|
56761
|
+
subsystem: "access.memory_action_apply",
|
|
56762
|
+
reason: request.reason,
|
|
56763
|
+
memoryId: request.memoryId,
|
|
56764
|
+
sourceSessionKey: request.sessionKey,
|
|
56765
|
+
inputSummary: inputSummaryParts.length > 0 ? inputSummaryParts.join(" | ").slice(0, 500) : void 0,
|
|
56766
|
+
dryRun: request.dryRun === true,
|
|
56767
|
+
promptHash: typeof request.sourcePrompt === "string" && request.sourcePrompt.length > 0 ? createHash13("sha256").update(request.sourcePrompt).digest("hex") : void 0
|
|
56768
|
+
};
|
|
56769
|
+
const preview = this.orchestrator.previewMemoryActionEvent(event);
|
|
56770
|
+
if (request.dryRun === true) {
|
|
56771
|
+
return { recorded: false, dryRun: true, event: preview };
|
|
56772
|
+
}
|
|
56773
|
+
const recorded = await this.orchestrator.appendMemoryActionEvent(event);
|
|
56774
|
+
return { recorded, event: preview };
|
|
56775
|
+
}
|
|
55864
56776
|
async contextCheckpoint(request) {
|
|
55865
56777
|
const resolvedNs = this.resolveWritableNamespace(request.namespace, request.sessionKey, request.principal);
|
|
55866
56778
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
55867
56779
|
const storageDir = storage.dir;
|
|
55868
56780
|
const { writeFile: writeFile45, mkdir: mkdir52 } = await import("fs/promises");
|
|
55869
|
-
const { join:
|
|
56781
|
+
const { join: join6, resolve: resolve2 } = await import("path");
|
|
55870
56782
|
const safeKey = request.sessionKey.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
55871
56783
|
if (!safeKey) throw new EngramAccessInputError("sessionKey is required");
|
|
55872
|
-
const checkpointDir =
|
|
56784
|
+
const checkpointDir = join6(storageDir, "checkpoints", safeKey);
|
|
55873
56785
|
const resolved = resolve2(checkpointDir);
|
|
55874
56786
|
if (!resolved.startsWith(resolve2(storageDir))) {
|
|
55875
56787
|
throw new EngramAccessInputError("Invalid sessionKey");
|
|
55876
56788
|
}
|
|
55877
56789
|
await mkdir52(checkpointDir, { recursive: true });
|
|
55878
56790
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
55879
|
-
const filePath =
|
|
56791
|
+
const filePath = join6(checkpointDir, `checkpoint-${ts}.md`);
|
|
55880
56792
|
await writeFile45(filePath, request.context, "utf-8");
|
|
55881
56793
|
return { saved: true };
|
|
55882
56794
|
}
|
|
@@ -56157,13 +57069,158 @@ ${next}`);
|
|
|
56157
57069
|
* caller having to construct the config object.
|
|
56158
57070
|
*/
|
|
56159
57071
|
async capsuleImport(opts) {
|
|
56160
|
-
const
|
|
56161
|
-
const
|
|
57072
|
+
const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...importOptions } = opts;
|
|
57073
|
+
const resolvedNamespace = this.resolveWritableNamespace(namespace, void 0, principal);
|
|
57074
|
+
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
57075
|
+
const root = explicitRoot ?? storage.dir;
|
|
57076
|
+
const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
|
|
57077
|
+
const versioning = importOptions.versioning ?? {
|
|
56162
57078
|
enabled: this.orchestrator.config.versioningEnabled,
|
|
56163
57079
|
maxVersionsPerPage: this.orchestrator.config.versioningMaxPerPage,
|
|
56164
57080
|
sidecarDir: this.orchestrator.config.versioningSidecarDir
|
|
56165
57081
|
};
|
|
56166
|
-
|
|
57082
|
+
await this.validateCapsuleImportArchivePath(importOptions.archivePath);
|
|
57083
|
+
try {
|
|
57084
|
+
return await importCapsule({ ...importOptions, root, memoryDir, versioning });
|
|
57085
|
+
} catch (err) {
|
|
57086
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
57087
|
+
if (this.isCapsuleImportArchiveInputError(err, message)) {
|
|
57088
|
+
throw new EngramAccessInputError(`capsule import failed: ${message}`);
|
|
57089
|
+
}
|
|
57090
|
+
throw err;
|
|
57091
|
+
}
|
|
57092
|
+
}
|
|
57093
|
+
async validateCapsuleImportArchivePath(archivePath) {
|
|
57094
|
+
let archiveStat;
|
|
57095
|
+
try {
|
|
57096
|
+
archiveStat = await stat19(archivePath);
|
|
57097
|
+
} catch (err) {
|
|
57098
|
+
if (!this.isCapsuleImportPathInputFsError(err)) throw err;
|
|
57099
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
57100
|
+
throw new EngramAccessInputError(`capsule import failed: archive is not readable: ${message}`);
|
|
57101
|
+
}
|
|
57102
|
+
if (!archiveStat.isFile()) {
|
|
57103
|
+
throw new EngramAccessInputError("capsule import failed: archivePath must point to a file");
|
|
57104
|
+
}
|
|
57105
|
+
try {
|
|
57106
|
+
await nodeFs.access(archivePath, fsConstants2.R_OK);
|
|
57107
|
+
} catch (err) {
|
|
57108
|
+
if (!this.isCapsuleImportPathInputFsError(err)) throw err;
|
|
57109
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
57110
|
+
throw new EngramAccessInputError(`capsule import failed: archive is not readable: ${message}`);
|
|
57111
|
+
}
|
|
57112
|
+
}
|
|
57113
|
+
isCapsuleImportPathInputFsError(err) {
|
|
57114
|
+
const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
57115
|
+
return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM" || code === "ELOOP";
|
|
57116
|
+
}
|
|
57117
|
+
isCapsuleImportArchiveInputError(err, message) {
|
|
57118
|
+
if (err instanceof ZodError) return true;
|
|
57119
|
+
const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
57120
|
+
if (typeof code === "string" && code.startsWith("Z_")) return true;
|
|
57121
|
+
return message.startsWith("importCapsule: archive") || message.startsWith("importCapsule: bundle") || message.startsWith("importCapsule: manifest") || message.startsWith("importCapsule: record") || /incorrect header check|invalid stored block lengths|not in gzip format|unexpected end of file/i.test(message);
|
|
57122
|
+
}
|
|
57123
|
+
/**
|
|
57124
|
+
* Export a capsule archive from the orchestrator's memory directory.
|
|
57125
|
+
*
|
|
57126
|
+
* HTTP and future MCP surfaces use this rather than calling the transfer
|
|
57127
|
+
* helper directly so namespace ACL checks stay consistent with the archive
|
|
57128
|
+
* write side effect. The exporter still owns archive construction and
|
|
57129
|
+
* validation.
|
|
57130
|
+
*/
|
|
57131
|
+
async capsuleExport(opts) {
|
|
57132
|
+
const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...exportOptions } = opts;
|
|
57133
|
+
const resolvedNamespace = this.resolveWritableNamespace(namespace, void 0, principal);
|
|
57134
|
+
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
57135
|
+
const root = explicitRoot ?? storage.dir;
|
|
57136
|
+
const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
|
|
57137
|
+
const pluginVersion = exportOptions.pluginVersion ?? await getPackageVersion();
|
|
57138
|
+
return exportCapsule({
|
|
57139
|
+
...exportOptions,
|
|
57140
|
+
pluginVersion,
|
|
57141
|
+
root,
|
|
57142
|
+
memoryDir: exportOptions.encrypt === true ? memoryDir : void 0
|
|
57143
|
+
});
|
|
57144
|
+
}
|
|
57145
|
+
/**
|
|
57146
|
+
* List capsule archives in the namespace-scoped capsule store.
|
|
57147
|
+
*
|
|
57148
|
+
* MCP uses this access-layer method instead of reading arbitrary paths so
|
|
57149
|
+
* capsule discovery remains bound to the same namespace ACLs as export and
|
|
57150
|
+
* import.
|
|
57151
|
+
*/
|
|
57152
|
+
async capsuleList(options) {
|
|
57153
|
+
const resolvedNamespace = this.resolveReadableNamespace(options?.namespace, options?.principal);
|
|
57154
|
+
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
57155
|
+
const capsulesDir = defaultCapsulesDir(storage.dir);
|
|
57156
|
+
let dirEntries;
|
|
57157
|
+
try {
|
|
57158
|
+
const capsulesDirStat = await nodeFs.lstat(capsulesDir);
|
|
57159
|
+
if (capsulesDirStat.isSymbolicLink()) {
|
|
57160
|
+
throw new EngramAccessInputError("capsule list failed: capsule store directory must not be a symlink");
|
|
57161
|
+
}
|
|
57162
|
+
if (!capsulesDirStat.isDirectory()) {
|
|
57163
|
+
throw new EngramAccessInputError("capsule list failed: capsule store path must be a directory");
|
|
57164
|
+
}
|
|
57165
|
+
dirEntries = await nodeFs.readdir(capsulesDir, { withFileTypes: true });
|
|
57166
|
+
} catch (err) {
|
|
57167
|
+
const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
57168
|
+
if (code === "ENOENT") {
|
|
57169
|
+
return { namespace: resolvedNamespace, capsulesDir, capsules: [] };
|
|
57170
|
+
}
|
|
57171
|
+
throw err;
|
|
57172
|
+
}
|
|
57173
|
+
const archiveNames = dirEntries.filter(
|
|
57174
|
+
(entry) => entry.isFile() && (entry.name.endsWith(".capsule.json.gz") || entry.name.endsWith(".capsule.json.gz.enc"))
|
|
57175
|
+
).map((entry) => entry.name).sort();
|
|
57176
|
+
const capsules = [];
|
|
57177
|
+
for (const archiveName of archiveNames) {
|
|
57178
|
+
const archivePath = nodePath.join(capsulesDir, archiveName);
|
|
57179
|
+
const id = archiveName.replace(/\.capsule\.json\.gz\.enc$/, "").replace(/\.capsule\.json\.gz$/, "");
|
|
57180
|
+
const manifestPath2 = nodePath.join(capsulesDir, `${id}.manifest.json`);
|
|
57181
|
+
let createdAt = null;
|
|
57182
|
+
let pluginVersion = null;
|
|
57183
|
+
let fileCount = null;
|
|
57184
|
+
let description = null;
|
|
57185
|
+
let manifestPathOrNull = manifestPath2;
|
|
57186
|
+
try {
|
|
57187
|
+
const manifestStat = await nodeFs.lstat(manifestPath2);
|
|
57188
|
+
if (manifestStat.isSymbolicLink() || !manifestStat.isFile()) {
|
|
57189
|
+
capsules.push({
|
|
57190
|
+
id,
|
|
57191
|
+
archivePath,
|
|
57192
|
+
manifestPath: manifestPathOrNull,
|
|
57193
|
+
createdAt,
|
|
57194
|
+
pluginVersion,
|
|
57195
|
+
fileCount,
|
|
57196
|
+
description
|
|
57197
|
+
});
|
|
57198
|
+
continue;
|
|
57199
|
+
}
|
|
57200
|
+
const raw = await nodeFs.readFile(manifestPath2, "utf-8");
|
|
57201
|
+
const sidecar = JSON.parse(raw);
|
|
57202
|
+
createdAt = typeof sidecar.createdAt === "string" ? sidecar.createdAt : null;
|
|
57203
|
+
pluginVersion = typeof sidecar.pluginVersion === "string" ? sidecar.pluginVersion : null;
|
|
57204
|
+
fileCount = Array.isArray(sidecar.files) ? sidecar.files.length : null;
|
|
57205
|
+
const capsule = sidecar.capsule;
|
|
57206
|
+
description = capsule && typeof capsule.description === "string" ? capsule.description : null;
|
|
57207
|
+
} catch (err) {
|
|
57208
|
+
const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
57209
|
+
if (code === "ENOENT") {
|
|
57210
|
+
manifestPathOrNull = null;
|
|
57211
|
+
}
|
|
57212
|
+
}
|
|
57213
|
+
capsules.push({
|
|
57214
|
+
id,
|
|
57215
|
+
archivePath,
|
|
57216
|
+
manifestPath: manifestPathOrNull,
|
|
57217
|
+
createdAt,
|
|
57218
|
+
pluginVersion,
|
|
57219
|
+
fileCount,
|
|
57220
|
+
description
|
|
57221
|
+
});
|
|
57222
|
+
}
|
|
57223
|
+
return { namespace: resolvedNamespace, capsulesDir, capsules };
|
|
56167
57224
|
}
|
|
56168
57225
|
// ── Dreams pipeline telemetry surfaces (issue #678 PR 3+4) ──────────────
|
|
56169
57226
|
/**
|
|
@@ -56257,14 +57314,273 @@ import { createServer as createServer3 } from "http";
|
|
|
56257
57314
|
import { randomUUID as randomUUID6, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
56258
57315
|
import { AsyncLocalStorage } from "async_hooks";
|
|
56259
57316
|
import { existsSync as existsSync9 } from "fs";
|
|
56260
|
-
import { readFile as
|
|
57317
|
+
import { readFile as readFile44 } from "fs/promises";
|
|
56261
57318
|
import path70 from "path";
|
|
56262
57319
|
import { fileURLToPath as fileURLToPath3, URL as URL3 } from "url";
|
|
56263
57320
|
|
|
56264
57321
|
// ../remnic-core/src/access-mcp.ts
|
|
56265
|
-
import { readFile as
|
|
57322
|
+
import { readFile as readFile43 } from "fs/promises";
|
|
56266
57323
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
56267
57324
|
|
|
57325
|
+
// ../remnic-core/src/access-schema.ts
|
|
57326
|
+
function formatZodError(error) {
|
|
57327
|
+
return {
|
|
57328
|
+
error: "request validation failed",
|
|
57329
|
+
code: "validation_error",
|
|
57330
|
+
details: error.issues.map((issue) => ({
|
|
57331
|
+
field: issue.path.join(".") || "(root)",
|
|
57332
|
+
message: issue.message
|
|
57333
|
+
}))
|
|
57334
|
+
};
|
|
57335
|
+
}
|
|
57336
|
+
var namespaceSchema = external_exports.string().trim().max(256).optional();
|
|
57337
|
+
var sessionKeySchema = external_exports.string().trim().min(1).max(512).optional();
|
|
57338
|
+
var idempotencyKeySchema = external_exports.string().trim().min(1).max(256).optional();
|
|
57339
|
+
var dryRunSchema = external_exports.boolean().optional();
|
|
57340
|
+
var schemaVersionSchema = external_exports.number().int().optional();
|
|
57341
|
+
var codingContextSchema = external_exports.object({
|
|
57342
|
+
projectId: external_exports.string().trim().min(1, "codingContext.projectId is required").max(128),
|
|
57343
|
+
branch: external_exports.string().trim().max(256).nullable(),
|
|
57344
|
+
rootPath: external_exports.string().trim().min(1, "codingContext.rootPath is required").max(1024),
|
|
57345
|
+
defaultBranch: external_exports.string().trim().max(256).nullable()
|
|
57346
|
+
}).nullable();
|
|
57347
|
+
var recallDisclosureSchema = external_exports.enum(["chunk", "section", "raw"]);
|
|
57348
|
+
var tagMatchSchema = external_exports.enum(["any", "all"]);
|
|
57349
|
+
var recallRequestSchema = external_exports.object({
|
|
57350
|
+
query: external_exports.string().min(1, "query is required"),
|
|
57351
|
+
sessionKey: sessionKeySchema,
|
|
57352
|
+
namespace: namespaceSchema,
|
|
57353
|
+
topK: external_exports.number().int().min(0).max(200).optional(),
|
|
57354
|
+
mode: external_exports.enum(["auto", "no_recall", "minimal", "full", "graph_mode"]).optional(),
|
|
57355
|
+
includeDebug: external_exports.boolean().optional(),
|
|
57356
|
+
disclosure: recallDisclosureSchema.optional(),
|
|
57357
|
+
codingContext: codingContextSchema.optional(),
|
|
57358
|
+
/** Working directory for auto git-context resolution (issue #569). */
|
|
57359
|
+
cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
|
|
57360
|
+
/**
|
|
57361
|
+
* Arbitrary project tag for non-git-based project scoping (issue #569).
|
|
57362
|
+
* Creates a coding context with `projectId: "tag:<projectTag>"`.
|
|
57363
|
+
*/
|
|
57364
|
+
projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional(),
|
|
57365
|
+
/**
|
|
57366
|
+
* Historical recall pin (issue #680). ISO 8601 timestamp. The
|
|
57367
|
+
* schema only enforces the basic shape; the access service runs
|
|
57368
|
+
* `Date.parse` and emits a structured 400 on malformed input
|
|
57369
|
+
* (CLAUDE.md rule 51).
|
|
57370
|
+
*/
|
|
57371
|
+
asOf: external_exports.string().trim().min(1, "asOf must be a non-empty ISO 8601 timestamp").max(64).optional(),
|
|
57372
|
+
/**
|
|
57373
|
+
* Free-form recall tag filter (issue #689). When provided, recall results
|
|
57374
|
+
* whose frontmatter `tags` do not match the filter are removed before the
|
|
57375
|
+
* response is returned. Comparison is case-sensitive exact match.
|
|
57376
|
+
*/
|
|
57377
|
+
tags: external_exports.array(external_exports.string().trim().min(1).max(256)).max(50).optional(),
|
|
57378
|
+
/**
|
|
57379
|
+
* Match mode for `tags` (issue #689). Defaults to `"any"` when `tags` is
|
|
57380
|
+
* provided and `tagMatch` is omitted. Ignored when `tags` is absent.
|
|
57381
|
+
*/
|
|
57382
|
+
tagMatch: tagMatchSchema.optional(),
|
|
57383
|
+
/**
|
|
57384
|
+
* Include graph edges below `graphTraversalConfidenceFloor` for diagnostic
|
|
57385
|
+
* recall traversal (issue #681). Defaults to false.
|
|
57386
|
+
*/
|
|
57387
|
+
includeLowConfidence: external_exports.boolean().optional()
|
|
57388
|
+
});
|
|
57389
|
+
var recallExplainRequestSchema = external_exports.object({
|
|
57390
|
+
sessionKey: sessionKeySchema,
|
|
57391
|
+
namespace: namespaceSchema
|
|
57392
|
+
});
|
|
57393
|
+
var setCodingContextRequestSchema = external_exports.object({
|
|
57394
|
+
sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
|
|
57395
|
+
codingContext: codingContextSchema
|
|
57396
|
+
});
|
|
57397
|
+
var messageSchema = external_exports.object({
|
|
57398
|
+
role: external_exports.enum(["user", "assistant"]),
|
|
57399
|
+
content: external_exports.string().min(1, "message content must be non-empty"),
|
|
57400
|
+
sourceFormat: external_exports.enum(["openai", "anthropic", "openclaw", "lossless-claw", "remnic"]).nullable().optional(),
|
|
57401
|
+
rawContent: external_exports.unknown().nullable().optional(),
|
|
57402
|
+
parts: external_exports.array(
|
|
57403
|
+
external_exports.object({
|
|
57404
|
+
ordinal: external_exports.number().int().min(0).nullable().optional(),
|
|
57405
|
+
kind: external_exports.enum([
|
|
57406
|
+
"text",
|
|
57407
|
+
"tool_call",
|
|
57408
|
+
"tool_result",
|
|
57409
|
+
"patch",
|
|
57410
|
+
"file_read",
|
|
57411
|
+
"file_write",
|
|
57412
|
+
"step_start",
|
|
57413
|
+
"step_finish",
|
|
57414
|
+
"snapshot",
|
|
57415
|
+
"retry"
|
|
57416
|
+
]),
|
|
57417
|
+
payload: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
57418
|
+
toolName: external_exports.string().nullable().optional(),
|
|
57419
|
+
tool_name: external_exports.string().nullable().optional(),
|
|
57420
|
+
filePath: external_exports.string().nullable().optional(),
|
|
57421
|
+
file_path: external_exports.string().nullable().optional(),
|
|
57422
|
+
createdAt: external_exports.string().nullable().optional(),
|
|
57423
|
+
created_at: external_exports.string().nullable().optional()
|
|
57424
|
+
})
|
|
57425
|
+
).nullable().optional()
|
|
57426
|
+
});
|
|
57427
|
+
var observeRequestSchema = external_exports.object({
|
|
57428
|
+
sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
|
|
57429
|
+
messages: external_exports.array(messageSchema).min(1, "messages must be a non-empty array"),
|
|
57430
|
+
namespace: namespaceSchema,
|
|
57431
|
+
skipExtraction: external_exports.boolean().optional(),
|
|
57432
|
+
/** Working directory for auto git-context resolution (issue #569). */
|
|
57433
|
+
cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
|
|
57434
|
+
/**
|
|
57435
|
+
* Arbitrary project tag for non-git-based project scoping (issue #569).
|
|
57436
|
+
* Creates a coding context with `projectId: "tag:<projectTag>"`.
|
|
57437
|
+
*/
|
|
57438
|
+
projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional()
|
|
57439
|
+
});
|
|
57440
|
+
var writeContentSchema = external_exports.string().min(1, "content is required").max(5e4);
|
|
57441
|
+
var categorySchema = external_exports.enum([
|
|
57442
|
+
"fact",
|
|
57443
|
+
"preference",
|
|
57444
|
+
"correction",
|
|
57445
|
+
"entity",
|
|
57446
|
+
"decision",
|
|
57447
|
+
"relationship",
|
|
57448
|
+
"principle",
|
|
57449
|
+
"commitment",
|
|
57450
|
+
"moment",
|
|
57451
|
+
"skill",
|
|
57452
|
+
"rule",
|
|
57453
|
+
"procedure",
|
|
57454
|
+
"reasoning_trace"
|
|
57455
|
+
]).optional();
|
|
57456
|
+
var confidenceSchema = external_exports.number().min(0).max(1).optional();
|
|
57457
|
+
var tagsSchema = external_exports.array(external_exports.string().max(256)).max(50).optional();
|
|
57458
|
+
var entityRefSchema = external_exports.string().trim().max(512).optional();
|
|
57459
|
+
var ttlSchema = external_exports.string().trim().max(128).optional();
|
|
57460
|
+
var sourceReasonSchema = external_exports.string().trim().max(2e3).optional();
|
|
57461
|
+
var memoryStoreRequestSchema = external_exports.object({
|
|
57462
|
+
schemaVersion: schemaVersionSchema,
|
|
57463
|
+
idempotencyKey: idempotencyKeySchema,
|
|
57464
|
+
dryRun: dryRunSchema,
|
|
57465
|
+
sessionKey: sessionKeySchema,
|
|
57466
|
+
content: writeContentSchema,
|
|
57467
|
+
category: categorySchema,
|
|
57468
|
+
confidence: confidenceSchema,
|
|
57469
|
+
namespace: namespaceSchema,
|
|
57470
|
+
tags: tagsSchema,
|
|
57471
|
+
entityRef: entityRefSchema,
|
|
57472
|
+
ttl: ttlSchema,
|
|
57473
|
+
sourceReason: sourceReasonSchema
|
|
57474
|
+
});
|
|
57475
|
+
var suggestionSubmitRequestSchema = memoryStoreRequestSchema;
|
|
57476
|
+
var reviewDispositionRequestSchema = external_exports.object({
|
|
57477
|
+
memoryId: external_exports.string().trim().min(1, "memoryId is required"),
|
|
57478
|
+
status: external_exports.enum([
|
|
57479
|
+
"active",
|
|
57480
|
+
"pending_review",
|
|
57481
|
+
"quarantined",
|
|
57482
|
+
"rejected",
|
|
57483
|
+
"superseded",
|
|
57484
|
+
"archived"
|
|
57485
|
+
]),
|
|
57486
|
+
reasonCode: external_exports.string().trim().min(1, "reasonCode is required"),
|
|
57487
|
+
namespace: namespaceSchema
|
|
57488
|
+
});
|
|
57489
|
+
var trustZonePromoteRequestSchema = external_exports.object({
|
|
57490
|
+
recordId: external_exports.string().trim().min(1, "recordId is required"),
|
|
57491
|
+
targetZone: external_exports.enum(["working", "trusted"], {
|
|
57492
|
+
errorMap: () => ({ message: "targetZone must be 'working' or 'trusted'" })
|
|
57493
|
+
}),
|
|
57494
|
+
promotionReason: external_exports.string().trim().min(1, "promotionReason is required"),
|
|
57495
|
+
recordedAt: external_exports.string().trim().optional(),
|
|
57496
|
+
summary: external_exports.string().trim().max(5e3).optional(),
|
|
57497
|
+
dryRun: dryRunSchema,
|
|
57498
|
+
namespace: namespaceSchema
|
|
57499
|
+
});
|
|
57500
|
+
var trustZoneDemoSeedRequestSchema = external_exports.object({
|
|
57501
|
+
scenario: external_exports.string().trim().max(256).optional(),
|
|
57502
|
+
recordedAt: external_exports.string().trim().optional(),
|
|
57503
|
+
dryRun: dryRunSchema,
|
|
57504
|
+
namespace: namespaceSchema
|
|
57505
|
+
});
|
|
57506
|
+
var lcmSearchRequestSchema = external_exports.object({
|
|
57507
|
+
query: external_exports.string().min(1, "query is required"),
|
|
57508
|
+
sessionKey: sessionKeySchema,
|
|
57509
|
+
namespace: namespaceSchema,
|
|
57510
|
+
limit: external_exports.number().int().min(1).max(100).optional()
|
|
57511
|
+
});
|
|
57512
|
+
var daySummaryRequestSchema = external_exports.object({
|
|
57513
|
+
memories: external_exports.string().max(1e5).optional(),
|
|
57514
|
+
sessionKey: sessionKeySchema,
|
|
57515
|
+
namespace: namespaceSchema
|
|
57516
|
+
});
|
|
57517
|
+
var capsuleTopLevelSegmentSchema = external_exports.string().trim().min(1).max(128).refine(
|
|
57518
|
+
(value) => !value.includes("/") && !value.includes("\\"),
|
|
57519
|
+
"must be a top-level directory name without path separators"
|
|
57520
|
+
);
|
|
57521
|
+
var capsulePeerIdSchema = external_exports.string().trim().min(1).max(256).refine(
|
|
57522
|
+
(value) => value !== "." && value !== ".." && !value.includes("/") && !value.includes("\\"),
|
|
57523
|
+
"must be a plain peer id without path separators"
|
|
57524
|
+
);
|
|
57525
|
+
var capsuleIsoSinceSchema = external_exports.string().trim().min(1, "since must be a non-empty ISO 8601 timestamp").max(128).refine(
|
|
57526
|
+
isValidCapsuleSince,
|
|
57527
|
+
"since must be a valid ISO 8601 timestamp with no calendar overflow"
|
|
57528
|
+
);
|
|
57529
|
+
var capsuleExportRequestSchema = external_exports.object({
|
|
57530
|
+
name: external_exports.string().trim().min(1, "name is required").max(64, "name must be 64 characters or fewer").regex(
|
|
57531
|
+
CAPSULE_ID_PATTERN,
|
|
57532
|
+
"name must be alphanumeric with single dashes (no spaces, no leading/trailing dashes)"
|
|
57533
|
+
),
|
|
57534
|
+
namespace: namespaceSchema,
|
|
57535
|
+
since: capsuleIsoSinceSchema.optional(),
|
|
57536
|
+
includeKinds: external_exports.array(capsuleTopLevelSegmentSchema).max(50).optional(),
|
|
57537
|
+
peerIds: external_exports.array(capsulePeerIdSchema).max(100).optional(),
|
|
57538
|
+
includeTranscripts: external_exports.boolean().optional(),
|
|
57539
|
+
encrypt: external_exports.boolean().optional()
|
|
57540
|
+
});
|
|
57541
|
+
var capsuleImportRequestSchema = external_exports.object({
|
|
57542
|
+
archivePath: external_exports.string().trim().min(1, "archivePath is required").max(4096),
|
|
57543
|
+
namespace: namespaceSchema,
|
|
57544
|
+
mode: external_exports.enum(["skip", "overwrite", "fork"]).optional()
|
|
57545
|
+
});
|
|
57546
|
+
var capsuleListRequestSchema = external_exports.object({
|
|
57547
|
+
namespace: namespaceSchema
|
|
57548
|
+
});
|
|
57549
|
+
var schemas = {
|
|
57550
|
+
recall: recallRequestSchema,
|
|
57551
|
+
recallExplain: recallExplainRequestSchema,
|
|
57552
|
+
setCodingContext: setCodingContextRequestSchema,
|
|
57553
|
+
observe: observeRequestSchema,
|
|
57554
|
+
memoryStore: memoryStoreRequestSchema,
|
|
57555
|
+
suggestionSubmit: suggestionSubmitRequestSchema,
|
|
57556
|
+
reviewDisposition: reviewDispositionRequestSchema,
|
|
57557
|
+
trustZonePromote: trustZonePromoteRequestSchema,
|
|
57558
|
+
trustZoneDemoSeed: trustZoneDemoSeedRequestSchema,
|
|
57559
|
+
lcmSearch: lcmSearchRequestSchema,
|
|
57560
|
+
daySummary: daySummaryRequestSchema,
|
|
57561
|
+
capsuleExport: capsuleExportRequestSchema,
|
|
57562
|
+
capsuleImport: capsuleImportRequestSchema,
|
|
57563
|
+
capsuleList: capsuleListRequestSchema
|
|
57564
|
+
};
|
|
57565
|
+
function validateRequest(schemaName, body) {
|
|
57566
|
+
const schema = schemas[schemaName];
|
|
57567
|
+
if (!schema) {
|
|
57568
|
+
return {
|
|
57569
|
+
success: false,
|
|
57570
|
+
error: {
|
|
57571
|
+
error: `unknown schema: ${schemaName}`,
|
|
57572
|
+
code: "validation_error",
|
|
57573
|
+
details: []
|
|
57574
|
+
}
|
|
57575
|
+
};
|
|
57576
|
+
}
|
|
57577
|
+
const result = schema.safeParse(body);
|
|
57578
|
+
if (result.success) {
|
|
57579
|
+
return { success: true, data: result.data };
|
|
57580
|
+
}
|
|
57581
|
+
return { success: false, error: formatZodError(result.error) };
|
|
57582
|
+
}
|
|
57583
|
+
|
|
56268
57584
|
// ../remnic-core/src/citations.ts
|
|
56269
57585
|
var OPEN_TAG = "<oai-mem-citation>";
|
|
56270
57586
|
var CLOSE_TAG = "</oai-mem-citation>";
|
|
@@ -56321,12 +57637,43 @@ function withToolAliases(tool) {
|
|
|
56321
57637
|
if (canonicalName === tool.name) return [canonicalTool];
|
|
56322
57638
|
return [canonicalTool, tool];
|
|
56323
57639
|
}
|
|
57640
|
+
var STRICT_MCP_SCHEMA_KEYS = {
|
|
57641
|
+
capsuleExport: [
|
|
57642
|
+
"name",
|
|
57643
|
+
"namespace",
|
|
57644
|
+
"since",
|
|
57645
|
+
"includeKinds",
|
|
57646
|
+
"peerIds",
|
|
57647
|
+
"includeTranscripts",
|
|
57648
|
+
"encrypt"
|
|
57649
|
+
],
|
|
57650
|
+
capsuleImport: ["archivePath", "namespace", "mode"],
|
|
57651
|
+
capsuleList: ["namespace"]
|
|
57652
|
+
};
|
|
57653
|
+
function parseMcpRequest(schemaName, args) {
|
|
57654
|
+
const allowedKeys = STRICT_MCP_SCHEMA_KEYS[schemaName];
|
|
57655
|
+
if (allowedKeys) {
|
|
57656
|
+
const allowed = new Set(allowedKeys);
|
|
57657
|
+
const unexpected = Object.keys(args).filter((key) => !allowed.has(key));
|
|
57658
|
+
if (unexpected.length > 0) {
|
|
57659
|
+
throw new EngramAccessInputError(
|
|
57660
|
+
`request validation failed: (root): Unrecognized key(s) in object: ${unexpected.join(", ")}`
|
|
57661
|
+
);
|
|
57662
|
+
}
|
|
57663
|
+
}
|
|
57664
|
+
const validation = validateRequest(schemaName, args);
|
|
57665
|
+
if (validation.success) return validation.data;
|
|
57666
|
+
const details = validation.error.details.map((detail) => `${detail.field}: ${detail.message}`).join("; ");
|
|
57667
|
+
throw new EngramAccessInputError(
|
|
57668
|
+
details.length > 0 ? `${validation.error.error}: ${details}` : validation.error.error
|
|
57669
|
+
);
|
|
57670
|
+
}
|
|
56324
57671
|
async function getMcpServerVersion() {
|
|
56325
57672
|
const envVersion = readEnvVar("OPENCLAW_ENGRAM_VERSION")?.trim() || readEnvVar("npm_package_version")?.trim();
|
|
56326
57673
|
if (envVersion) return envVersion;
|
|
56327
57674
|
try {
|
|
56328
57675
|
const pkgPath = new URL("../package.json", import.meta.url);
|
|
56329
|
-
const raw = await
|
|
57676
|
+
const raw = await readFile43(pkgPath, "utf-8");
|
|
56330
57677
|
const parsed = JSON.parse(raw);
|
|
56331
57678
|
return parsed.version?.trim() || "unknown";
|
|
56332
57679
|
} catch {
|
|
@@ -56494,6 +57841,70 @@ var EngramMcpServer = class {
|
|
|
56494
57841
|
additionalProperties: false
|
|
56495
57842
|
}
|
|
56496
57843
|
},
|
|
57844
|
+
{
|
|
57845
|
+
name: "engram.capsule_export",
|
|
57846
|
+
description: "Export a portable Remnic capsule archive from the namespace-scoped memory store.",
|
|
57847
|
+
inputSchema: {
|
|
57848
|
+
type: "object",
|
|
57849
|
+
properties: {
|
|
57850
|
+
name: {
|
|
57851
|
+
type: "string",
|
|
57852
|
+
description: "Capsule id (alphanumeric with single dashes, max 64 characters)."
|
|
57853
|
+
},
|
|
57854
|
+
namespace: { type: "string" },
|
|
57855
|
+
since: {
|
|
57856
|
+
type: "string",
|
|
57857
|
+
description: "Only include files modified on or after this ISO 8601 timestamp."
|
|
57858
|
+
},
|
|
57859
|
+
includeKinds: {
|
|
57860
|
+
type: "array",
|
|
57861
|
+
items: { type: "string" },
|
|
57862
|
+
description: "Optional top-level directory allow-list."
|
|
57863
|
+
},
|
|
57864
|
+
peerIds: {
|
|
57865
|
+
type: "array",
|
|
57866
|
+
items: { type: "string" },
|
|
57867
|
+
description: "Optional peer id allow-list for the peers/ subtree."
|
|
57868
|
+
},
|
|
57869
|
+
includeTranscripts: { type: "boolean" },
|
|
57870
|
+
encrypt: { type: "boolean" }
|
|
57871
|
+
},
|
|
57872
|
+
required: ["name"],
|
|
57873
|
+
additionalProperties: false
|
|
57874
|
+
}
|
|
57875
|
+
},
|
|
57876
|
+
{
|
|
57877
|
+
name: "engram.capsule_import",
|
|
57878
|
+
description: "Import a Remnic capsule archive into the namespace-scoped memory store.",
|
|
57879
|
+
inputSchema: {
|
|
57880
|
+
type: "object",
|
|
57881
|
+
properties: {
|
|
57882
|
+
archivePath: {
|
|
57883
|
+
type: "string",
|
|
57884
|
+
description: "Path to a .capsule.json.gz or .capsule.json.gz.enc archive."
|
|
57885
|
+
},
|
|
57886
|
+
namespace: { type: "string" },
|
|
57887
|
+
mode: {
|
|
57888
|
+
type: "string",
|
|
57889
|
+
enum: ["skip", "overwrite", "fork"],
|
|
57890
|
+
description: "Conflict handling mode. Defaults to skip."
|
|
57891
|
+
}
|
|
57892
|
+
},
|
|
57893
|
+
required: ["archivePath"],
|
|
57894
|
+
additionalProperties: false
|
|
57895
|
+
}
|
|
57896
|
+
},
|
|
57897
|
+
{
|
|
57898
|
+
name: "engram.capsule_list",
|
|
57899
|
+
description: "List capsule archives in the namespace-scoped capsule store.",
|
|
57900
|
+
inputSchema: {
|
|
57901
|
+
type: "object",
|
|
57902
|
+
properties: {
|
|
57903
|
+
namespace: { type: "string" }
|
|
57904
|
+
},
|
|
57905
|
+
additionalProperties: false
|
|
57906
|
+
}
|
|
57907
|
+
},
|
|
56497
57908
|
{
|
|
56498
57909
|
name: "engram.memory_governance_run",
|
|
56499
57910
|
description: "Run Remnic memory governance in a bounded shadow/apply pass.",
|
|
@@ -56657,9 +58068,51 @@ var EngramMcpServer = class {
|
|
|
56657
58068
|
type: "object",
|
|
56658
58069
|
properties: {
|
|
56659
58070
|
role: { type: "string", enum: ["user", "assistant"] },
|
|
56660
|
-
content: { type: "string" }
|
|
58071
|
+
content: { type: "string" },
|
|
58072
|
+
sourceFormat: {
|
|
58073
|
+
type: "string",
|
|
58074
|
+
enum: ["openai", "anthropic", "openclaw", "lossless-claw", "remnic"]
|
|
58075
|
+
},
|
|
58076
|
+
rawContent: {
|
|
58077
|
+
description: "Optional native provider content blocks for structured message-part capture."
|
|
58078
|
+
},
|
|
58079
|
+
parts: {
|
|
58080
|
+
type: "array",
|
|
58081
|
+
description: "Optional normalized Remnic LCM message parts.",
|
|
58082
|
+
items: {
|
|
58083
|
+
type: "object",
|
|
58084
|
+
properties: {
|
|
58085
|
+
ordinal: { type: ["number", "null"], minimum: 0 },
|
|
58086
|
+
kind: {
|
|
58087
|
+
type: "string",
|
|
58088
|
+
enum: [
|
|
58089
|
+
"text",
|
|
58090
|
+
"tool_call",
|
|
58091
|
+
"tool_result",
|
|
58092
|
+
"patch",
|
|
58093
|
+
"file_read",
|
|
58094
|
+
"file_write",
|
|
58095
|
+
"step_start",
|
|
58096
|
+
"step_finish",
|
|
58097
|
+
"snapshot",
|
|
58098
|
+
"retry"
|
|
58099
|
+
]
|
|
58100
|
+
},
|
|
58101
|
+
payload: { type: "object", additionalProperties: true },
|
|
58102
|
+
toolName: { type: ["string", "null"] },
|
|
58103
|
+
tool_name: { type: ["string", "null"] },
|
|
58104
|
+
filePath: { type: ["string", "null"] },
|
|
58105
|
+
file_path: { type: ["string", "null"] },
|
|
58106
|
+
createdAt: { type: ["string", "null"] },
|
|
58107
|
+
created_at: { type: ["string", "null"] }
|
|
58108
|
+
},
|
|
58109
|
+
required: ["kind", "payload"],
|
|
58110
|
+
additionalProperties: false
|
|
58111
|
+
}
|
|
58112
|
+
}
|
|
56661
58113
|
},
|
|
56662
|
-
required: ["role", "content"]
|
|
58114
|
+
required: ["role", "content"],
|
|
58115
|
+
additionalProperties: false
|
|
56663
58116
|
},
|
|
56664
58117
|
description: "Conversation messages to observe"
|
|
56665
58118
|
},
|
|
@@ -57149,6 +58602,43 @@ var EngramMcpServer = class {
|
|
|
57149
58602
|
additionalProperties: false
|
|
57150
58603
|
}
|
|
57151
58604
|
},
|
|
58605
|
+
{
|
|
58606
|
+
name: "engram.memory_action_apply",
|
|
58607
|
+
description: "Record a memory-action application event for policy-learning telemetry.",
|
|
58608
|
+
inputSchema: {
|
|
58609
|
+
type: "object",
|
|
58610
|
+
properties: {
|
|
58611
|
+
action: {
|
|
58612
|
+
type: "string",
|
|
58613
|
+
enum: [
|
|
58614
|
+
"store_episode",
|
|
58615
|
+
"store_note",
|
|
58616
|
+
"update_note",
|
|
58617
|
+
"create_artifact",
|
|
58618
|
+
"summarize_node",
|
|
58619
|
+
"discard",
|
|
58620
|
+
"link_graph"
|
|
58621
|
+
]
|
|
58622
|
+
},
|
|
58623
|
+
category: { type: "string" },
|
|
58624
|
+
content: { type: "string" },
|
|
58625
|
+
outcome: { type: "string", enum: ["applied", "skipped", "failed"] },
|
|
58626
|
+
reason: { type: "string" },
|
|
58627
|
+
memoryId: { type: "string" },
|
|
58628
|
+
sessionKey: { type: "string" },
|
|
58629
|
+
linkTargetId: { type: "string" },
|
|
58630
|
+
linkType: { type: "string" },
|
|
58631
|
+
linkStrength: { type: "number" },
|
|
58632
|
+
artifactType: { type: "string" },
|
|
58633
|
+
execute: { type: "boolean" },
|
|
58634
|
+
sourcePrompt: { type: "string" },
|
|
58635
|
+
namespace: { type: "string" },
|
|
58636
|
+
dryRun: { type: "boolean" }
|
|
58637
|
+
},
|
|
58638
|
+
required: ["action"],
|
|
58639
|
+
additionalProperties: false
|
|
58640
|
+
}
|
|
58641
|
+
},
|
|
57152
58642
|
{
|
|
57153
58643
|
name: "engram.context_checkpoint",
|
|
57154
58644
|
description: "Save a structured context checkpoint for a session (preserves conversation state to disk).",
|
|
@@ -57220,6 +58710,49 @@ var EngramMcpServer = class {
|
|
|
57220
58710
|
additionalProperties: false
|
|
57221
58711
|
}
|
|
57222
58712
|
},
|
|
58713
|
+
{
|
|
58714
|
+
name: "engram.memory_summarize_hourly",
|
|
58715
|
+
description: "Generate hourly summaries for recent conversations.",
|
|
58716
|
+
inputSchema: {
|
|
58717
|
+
type: "object",
|
|
58718
|
+
properties: {},
|
|
58719
|
+
additionalProperties: false
|
|
58720
|
+
}
|
|
58721
|
+
},
|
|
58722
|
+
{
|
|
58723
|
+
name: "engram.conversation_index_update",
|
|
58724
|
+
description: "Chunk transcript history into conversation-index documents.",
|
|
58725
|
+
inputSchema: {
|
|
58726
|
+
type: "object",
|
|
58727
|
+
properties: {
|
|
58728
|
+
sessionKey: { type: "string" },
|
|
58729
|
+
hours: { type: "number", description: "How many hours of transcript history to include." },
|
|
58730
|
+
embed: { type: "boolean", description: "If true, run QMD embed after update for this invocation." }
|
|
58731
|
+
},
|
|
58732
|
+
additionalProperties: false
|
|
58733
|
+
}
|
|
58734
|
+
},
|
|
58735
|
+
{
|
|
58736
|
+
name: "engram.profiling_report",
|
|
58737
|
+
description: "Return timing and performance data for Remnic recall and extraction pipelines. Requires profilingEnabled: true.",
|
|
58738
|
+
inputSchema: {
|
|
58739
|
+
type: "object",
|
|
58740
|
+
properties: {
|
|
58741
|
+
format: {
|
|
58742
|
+
type: "string",
|
|
58743
|
+
enum: ["ascii", "json"],
|
|
58744
|
+
description: "Output format. Defaults to ascii."
|
|
58745
|
+
},
|
|
58746
|
+
limit: {
|
|
58747
|
+
type: "integer",
|
|
58748
|
+
minimum: 1,
|
|
58749
|
+
maximum: 20,
|
|
58750
|
+
description: "Number of recent traces to include. Defaults to 5."
|
|
58751
|
+
}
|
|
58752
|
+
},
|
|
58753
|
+
additionalProperties: false
|
|
58754
|
+
}
|
|
58755
|
+
},
|
|
57223
58756
|
{
|
|
57224
58757
|
name: "engram.graph_edge_decay_run",
|
|
57225
58758
|
description: "Run the graph-edge-confidence decay maintenance pass (issue #681 PR 2/3). Respects graphEdgeDecayEnabled; writes a structured telemetry record to state/graph-edge-decay-status.json.",
|
|
@@ -57472,8 +59005,14 @@ var EngramMcpServer = class {
|
|
|
57472
59005
|
if (method === "tools/call") {
|
|
57473
59006
|
const params = request.params ?? {};
|
|
57474
59007
|
const name = typeof params.name === "string" ? params.name : "";
|
|
57475
|
-
const argumentsObject = params.arguments && typeof params.arguments === "object" && !Array.isArray(params.arguments) ? params.arguments : {};
|
|
57476
59008
|
try {
|
|
59009
|
+
let argumentsObject = {};
|
|
59010
|
+
if ("arguments" in params && params.arguments !== void 0) {
|
|
59011
|
+
if (params.arguments === null || typeof params.arguments !== "object" || Array.isArray(params.arguments)) {
|
|
59012
|
+
throw new EngramAccessInputError("tools/call arguments must be an object when provided");
|
|
59013
|
+
}
|
|
59014
|
+
argumentsObject = params.arguments;
|
|
59015
|
+
}
|
|
57477
59016
|
const effectivePrincipal = options?.principalOverride ?? this.authenticatedPrincipal;
|
|
57478
59017
|
const result = await this.callTool(name, argumentsObject, effectivePrincipal, options?.sessionId);
|
|
57479
59018
|
return {
|
|
@@ -57792,6 +59331,35 @@ ${body}`;
|
|
|
57792
59331
|
sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
|
|
57793
59332
|
namespace: typeof args.namespace === "string" ? args.namespace : void 0
|
|
57794
59333
|
});
|
|
59334
|
+
case "engram.capsule_export": {
|
|
59335
|
+
const body = parseMcpRequest("capsuleExport", args);
|
|
59336
|
+
return this.service.capsuleExport({
|
|
59337
|
+
name: body.name,
|
|
59338
|
+
namespace: body.namespace,
|
|
59339
|
+
principal: effectivePrincipal,
|
|
59340
|
+
since: body.since,
|
|
59341
|
+
includeKinds: body.includeKinds,
|
|
59342
|
+
peerIds: body.peerIds,
|
|
59343
|
+
includeTranscripts: body.includeTranscripts,
|
|
59344
|
+
encrypt: body.encrypt
|
|
59345
|
+
});
|
|
59346
|
+
}
|
|
59347
|
+
case "engram.capsule_import": {
|
|
59348
|
+
const body = parseMcpRequest("capsuleImport", args);
|
|
59349
|
+
return this.service.capsuleImport({
|
|
59350
|
+
archivePath: expandTildePath(body.archivePath),
|
|
59351
|
+
namespace: body.namespace,
|
|
59352
|
+
principal: effectivePrincipal,
|
|
59353
|
+
mode: body.mode
|
|
59354
|
+
});
|
|
59355
|
+
}
|
|
59356
|
+
case "engram.capsule_list": {
|
|
59357
|
+
const body = parseMcpRequest("capsuleList", args);
|
|
59358
|
+
return this.service.capsuleList({
|
|
59359
|
+
namespace: body.namespace,
|
|
59360
|
+
principal: effectivePrincipal
|
|
59361
|
+
});
|
|
59362
|
+
}
|
|
57795
59363
|
case "engram.memory_governance_run":
|
|
57796
59364
|
return this.service.governanceRun({
|
|
57797
59365
|
namespace: typeof args.namespace === "string" ? args.namespace : void 0,
|
|
@@ -57885,20 +59453,21 @@ ${body}`;
|
|
|
57885
59453
|
effectivePrincipal
|
|
57886
59454
|
);
|
|
57887
59455
|
case "engram.observe": {
|
|
57888
|
-
|
|
57889
|
-
throw new EngramAccessInputError("cwd must be a string");
|
|
57890
|
-
}
|
|
57891
|
-
if ("projectTag" in args && args.projectTag !== void 0 && args.projectTag !== null && typeof args.projectTag !== "string") {
|
|
57892
|
-
throw new EngramAccessInputError("projectTag must be a string");
|
|
57893
|
-
}
|
|
59456
|
+
const body = parseMcpRequest("observe", args);
|
|
57894
59457
|
return this.service.observe({
|
|
57895
|
-
sessionKey:
|
|
57896
|
-
messages:
|
|
57897
|
-
|
|
59458
|
+
sessionKey: body.sessionKey,
|
|
59459
|
+
messages: body.messages.map((message) => ({
|
|
59460
|
+
role: message.role,
|
|
59461
|
+
content: message.content,
|
|
59462
|
+
parts: message.parts ?? void 0,
|
|
59463
|
+
rawContent: message.rawContent ?? void 0,
|
|
59464
|
+
sourceFormat: message.sourceFormat ?? void 0
|
|
59465
|
+
})),
|
|
59466
|
+
namespace: body.namespace,
|
|
57898
59467
|
authenticatedPrincipal: effectivePrincipal,
|
|
57899
|
-
skipExtraction:
|
|
57900
|
-
cwd:
|
|
57901
|
-
projectTag:
|
|
59468
|
+
skipExtraction: body.skipExtraction === true,
|
|
59469
|
+
cwd: body.cwd,
|
|
59470
|
+
projectTag: body.projectTag
|
|
57902
59471
|
});
|
|
57903
59472
|
}
|
|
57904
59473
|
case "engram.lcm_search":
|
|
@@ -58176,6 +59745,25 @@ ${body}`;
|
|
|
58176
59745
|
timestamp: typeof args.timestamp === "string" ? args.timestamp : void 0
|
|
58177
59746
|
});
|
|
58178
59747
|
}
|
|
59748
|
+
case "engram.memory_action_apply":
|
|
59749
|
+
return this.service.memoryActionApply({
|
|
59750
|
+
action: typeof args.action === "string" ? args.action : "",
|
|
59751
|
+
outcome: typeof args.outcome === "string" ? args.outcome : void 0,
|
|
59752
|
+
reason: typeof args.reason === "string" ? args.reason : void 0,
|
|
59753
|
+
memoryId: typeof args.memoryId === "string" ? args.memoryId : void 0,
|
|
59754
|
+
namespace: typeof args.namespace === "string" ? args.namespace : void 0,
|
|
59755
|
+
principal: effectivePrincipal,
|
|
59756
|
+
sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
|
|
59757
|
+
content: typeof args.content === "string" ? args.content : void 0,
|
|
59758
|
+
category: typeof args.category === "string" ? args.category : void 0,
|
|
59759
|
+
linkTargetId: typeof args.linkTargetId === "string" ? args.linkTargetId : void 0,
|
|
59760
|
+
linkType: typeof args.linkType === "string" ? args.linkType : void 0,
|
|
59761
|
+
linkStrength: typeof args.linkStrength === "number" ? args.linkStrength : void 0,
|
|
59762
|
+
artifactType: typeof args.artifactType === "string" ? args.artifactType : void 0,
|
|
59763
|
+
execute: typeof args.execute === "boolean" ? args.execute : void 0,
|
|
59764
|
+
sourcePrompt: typeof args.sourcePrompt === "string" ? args.sourcePrompt : void 0,
|
|
59765
|
+
dryRun: args.dryRun === true
|
|
59766
|
+
});
|
|
58179
59767
|
case "engram.context_checkpoint":
|
|
58180
59768
|
return this.service.contextCheckpoint({
|
|
58181
59769
|
sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : "",
|
|
@@ -58235,6 +59823,34 @@ ${body}`;
|
|
|
58235
59823
|
namespace: typeof args.namespace === "string" ? args.namespace : void 0
|
|
58236
59824
|
});
|
|
58237
59825
|
}
|
|
59826
|
+
case "engram.memory_summarize_hourly":
|
|
59827
|
+
case "remnic.memory_summarize_hourly":
|
|
59828
|
+
return this.service.memorySummarizeHourly();
|
|
59829
|
+
case "engram.conversation_index_update":
|
|
59830
|
+
case "remnic.conversation_index_update": {
|
|
59831
|
+
if ("sessionKey" in args && args.sessionKey !== void 0 && typeof args.sessionKey !== "string") {
|
|
59832
|
+
throw new Error("sessionKey must be a string when provided");
|
|
59833
|
+
}
|
|
59834
|
+
const sessionKey = typeof args.sessionKey === "string" ? args.sessionKey : void 0;
|
|
59835
|
+
return this.service.conversationIndexUpdate({
|
|
59836
|
+
sessionKey,
|
|
59837
|
+
hours: typeof args.hours === "number" && Number.isFinite(args.hours) ? args.hours : void 0,
|
|
59838
|
+
embed: typeof args.embed === "boolean" ? args.embed : void 0
|
|
59839
|
+
});
|
|
59840
|
+
}
|
|
59841
|
+
case "engram.profiling_report":
|
|
59842
|
+
case "remnic.profiling_report": {
|
|
59843
|
+
if ("format" in args && args.format !== void 0 && typeof args.format !== "string") {
|
|
59844
|
+
throw new EngramAccessInputError("format must be a string when provided");
|
|
59845
|
+
}
|
|
59846
|
+
if ("limit" in args && args.limit !== void 0 && typeof args.limit !== "number") {
|
|
59847
|
+
throw new EngramAccessInputError("limit must be a number when provided");
|
|
59848
|
+
}
|
|
59849
|
+
return this.service.profilingReport({
|
|
59850
|
+
format: typeof args.format === "string" ? args.format : void 0,
|
|
59851
|
+
limit: typeof args.limit === "number" ? args.limit : void 0
|
|
59852
|
+
});
|
|
59853
|
+
}
|
|
58238
59854
|
case "engram.graph_edge_decay_run":
|
|
58239
59855
|
case "remnic.graph_edge_decay_run": {
|
|
58240
59856
|
const cfg = this.service.configRef;
|
|
@@ -58383,204 +59999,6 @@ ${body}`;
|
|
|
58383
59999
|
}
|
|
58384
60000
|
};
|
|
58385
60001
|
|
|
58386
|
-
// ../remnic-core/src/access-schema.ts
|
|
58387
|
-
function formatZodError(error) {
|
|
58388
|
-
return {
|
|
58389
|
-
error: "request validation failed",
|
|
58390
|
-
code: "validation_error",
|
|
58391
|
-
details: error.issues.map((issue) => ({
|
|
58392
|
-
field: issue.path.join(".") || "(root)",
|
|
58393
|
-
message: issue.message
|
|
58394
|
-
}))
|
|
58395
|
-
};
|
|
58396
|
-
}
|
|
58397
|
-
var namespaceSchema = external_exports.string().trim().max(256).optional();
|
|
58398
|
-
var sessionKeySchema = external_exports.string().trim().min(1).max(512).optional();
|
|
58399
|
-
var idempotencyKeySchema = external_exports.string().trim().min(1).max(256).optional();
|
|
58400
|
-
var dryRunSchema = external_exports.boolean().optional();
|
|
58401
|
-
var schemaVersionSchema = external_exports.number().int().optional();
|
|
58402
|
-
var codingContextSchema = external_exports.object({
|
|
58403
|
-
projectId: external_exports.string().trim().min(1, "codingContext.projectId is required").max(128),
|
|
58404
|
-
branch: external_exports.string().trim().max(256).nullable(),
|
|
58405
|
-
rootPath: external_exports.string().trim().min(1, "codingContext.rootPath is required").max(1024),
|
|
58406
|
-
defaultBranch: external_exports.string().trim().max(256).nullable()
|
|
58407
|
-
}).nullable();
|
|
58408
|
-
var recallDisclosureSchema = external_exports.enum(["chunk", "section", "raw"]);
|
|
58409
|
-
var tagMatchSchema = external_exports.enum(["any", "all"]);
|
|
58410
|
-
var recallRequestSchema = external_exports.object({
|
|
58411
|
-
query: external_exports.string().min(1, "query is required"),
|
|
58412
|
-
sessionKey: sessionKeySchema,
|
|
58413
|
-
namespace: namespaceSchema,
|
|
58414
|
-
topK: external_exports.number().int().min(0).max(200).optional(),
|
|
58415
|
-
mode: external_exports.enum(["auto", "no_recall", "minimal", "full", "graph_mode"]).optional(),
|
|
58416
|
-
includeDebug: external_exports.boolean().optional(),
|
|
58417
|
-
disclosure: recallDisclosureSchema.optional(),
|
|
58418
|
-
codingContext: codingContextSchema.optional(),
|
|
58419
|
-
/** Working directory for auto git-context resolution (issue #569). */
|
|
58420
|
-
cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
|
|
58421
|
-
/**
|
|
58422
|
-
* Arbitrary project tag for non-git-based project scoping (issue #569).
|
|
58423
|
-
* Creates a coding context with `projectId: "tag:<projectTag>"`.
|
|
58424
|
-
*/
|
|
58425
|
-
projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional(),
|
|
58426
|
-
/**
|
|
58427
|
-
* Historical recall pin (issue #680). ISO 8601 timestamp. The
|
|
58428
|
-
* schema only enforces the basic shape; the access service runs
|
|
58429
|
-
* `Date.parse` and emits a structured 400 on malformed input
|
|
58430
|
-
* (CLAUDE.md rule 51).
|
|
58431
|
-
*/
|
|
58432
|
-
asOf: external_exports.string().trim().min(1, "asOf must be a non-empty ISO 8601 timestamp").max(64).optional(),
|
|
58433
|
-
/**
|
|
58434
|
-
* Free-form recall tag filter (issue #689). When provided, recall results
|
|
58435
|
-
* whose frontmatter `tags` do not match the filter are removed before the
|
|
58436
|
-
* response is returned. Comparison is case-sensitive exact match.
|
|
58437
|
-
*/
|
|
58438
|
-
tags: external_exports.array(external_exports.string().trim().min(1).max(256)).max(50).optional(),
|
|
58439
|
-
/**
|
|
58440
|
-
* Match mode for `tags` (issue #689). Defaults to `"any"` when `tags` is
|
|
58441
|
-
* provided and `tagMatch` is omitted. Ignored when `tags` is absent.
|
|
58442
|
-
*/
|
|
58443
|
-
tagMatch: tagMatchSchema.optional(),
|
|
58444
|
-
/**
|
|
58445
|
-
* Include graph edges below `graphTraversalConfidenceFloor` for diagnostic
|
|
58446
|
-
* recall traversal (issue #681). Defaults to false.
|
|
58447
|
-
*/
|
|
58448
|
-
includeLowConfidence: external_exports.boolean().optional()
|
|
58449
|
-
});
|
|
58450
|
-
var recallExplainRequestSchema = external_exports.object({
|
|
58451
|
-
sessionKey: sessionKeySchema,
|
|
58452
|
-
namespace: namespaceSchema
|
|
58453
|
-
});
|
|
58454
|
-
var setCodingContextRequestSchema = external_exports.object({
|
|
58455
|
-
sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
|
|
58456
|
-
codingContext: codingContextSchema
|
|
58457
|
-
});
|
|
58458
|
-
var messageSchema = external_exports.object({
|
|
58459
|
-
role: external_exports.enum(["user", "assistant"]),
|
|
58460
|
-
content: external_exports.string().min(1, "message content must be non-empty")
|
|
58461
|
-
});
|
|
58462
|
-
var observeRequestSchema = external_exports.object({
|
|
58463
|
-
sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
|
|
58464
|
-
messages: external_exports.array(messageSchema).min(1, "messages must be a non-empty array"),
|
|
58465
|
-
namespace: namespaceSchema,
|
|
58466
|
-
skipExtraction: external_exports.boolean().optional(),
|
|
58467
|
-
/** Working directory for auto git-context resolution (issue #569). */
|
|
58468
|
-
cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
|
|
58469
|
-
/**
|
|
58470
|
-
* Arbitrary project tag for non-git-based project scoping (issue #569).
|
|
58471
|
-
* Creates a coding context with `projectId: "tag:<projectTag>"`.
|
|
58472
|
-
*/
|
|
58473
|
-
projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional()
|
|
58474
|
-
});
|
|
58475
|
-
var writeContentSchema = external_exports.string().min(1, "content is required").max(5e4);
|
|
58476
|
-
var categorySchema = external_exports.enum([
|
|
58477
|
-
"fact",
|
|
58478
|
-
"preference",
|
|
58479
|
-
"correction",
|
|
58480
|
-
"entity",
|
|
58481
|
-
"decision",
|
|
58482
|
-
"relationship",
|
|
58483
|
-
"principle",
|
|
58484
|
-
"commitment",
|
|
58485
|
-
"moment",
|
|
58486
|
-
"skill",
|
|
58487
|
-
"rule",
|
|
58488
|
-
"procedure",
|
|
58489
|
-
"reasoning_trace"
|
|
58490
|
-
]).optional();
|
|
58491
|
-
var confidenceSchema = external_exports.number().min(0).max(1).optional();
|
|
58492
|
-
var tagsSchema = external_exports.array(external_exports.string().max(256)).max(50).optional();
|
|
58493
|
-
var entityRefSchema = external_exports.string().trim().max(512).optional();
|
|
58494
|
-
var ttlSchema = external_exports.string().trim().max(128).optional();
|
|
58495
|
-
var sourceReasonSchema = external_exports.string().trim().max(2e3).optional();
|
|
58496
|
-
var memoryStoreRequestSchema = external_exports.object({
|
|
58497
|
-
schemaVersion: schemaVersionSchema,
|
|
58498
|
-
idempotencyKey: idempotencyKeySchema,
|
|
58499
|
-
dryRun: dryRunSchema,
|
|
58500
|
-
sessionKey: sessionKeySchema,
|
|
58501
|
-
content: writeContentSchema,
|
|
58502
|
-
category: categorySchema,
|
|
58503
|
-
confidence: confidenceSchema,
|
|
58504
|
-
namespace: namespaceSchema,
|
|
58505
|
-
tags: tagsSchema,
|
|
58506
|
-
entityRef: entityRefSchema,
|
|
58507
|
-
ttl: ttlSchema,
|
|
58508
|
-
sourceReason: sourceReasonSchema
|
|
58509
|
-
});
|
|
58510
|
-
var suggestionSubmitRequestSchema = memoryStoreRequestSchema;
|
|
58511
|
-
var reviewDispositionRequestSchema = external_exports.object({
|
|
58512
|
-
memoryId: external_exports.string().trim().min(1, "memoryId is required"),
|
|
58513
|
-
status: external_exports.enum([
|
|
58514
|
-
"active",
|
|
58515
|
-
"pending_review",
|
|
58516
|
-
"quarantined",
|
|
58517
|
-
"rejected",
|
|
58518
|
-
"superseded",
|
|
58519
|
-
"archived"
|
|
58520
|
-
]),
|
|
58521
|
-
reasonCode: external_exports.string().trim().min(1, "reasonCode is required"),
|
|
58522
|
-
namespace: namespaceSchema
|
|
58523
|
-
});
|
|
58524
|
-
var trustZonePromoteRequestSchema = external_exports.object({
|
|
58525
|
-
recordId: external_exports.string().trim().min(1, "recordId is required"),
|
|
58526
|
-
targetZone: external_exports.enum(["working", "trusted"], {
|
|
58527
|
-
errorMap: () => ({ message: "targetZone must be 'working' or 'trusted'" })
|
|
58528
|
-
}),
|
|
58529
|
-
promotionReason: external_exports.string().trim().min(1, "promotionReason is required"),
|
|
58530
|
-
recordedAt: external_exports.string().trim().optional(),
|
|
58531
|
-
summary: external_exports.string().trim().max(5e3).optional(),
|
|
58532
|
-
dryRun: dryRunSchema,
|
|
58533
|
-
namespace: namespaceSchema
|
|
58534
|
-
});
|
|
58535
|
-
var trustZoneDemoSeedRequestSchema = external_exports.object({
|
|
58536
|
-
scenario: external_exports.string().trim().max(256).optional(),
|
|
58537
|
-
recordedAt: external_exports.string().trim().optional(),
|
|
58538
|
-
dryRun: dryRunSchema,
|
|
58539
|
-
namespace: namespaceSchema
|
|
58540
|
-
});
|
|
58541
|
-
var lcmSearchRequestSchema = external_exports.object({
|
|
58542
|
-
query: external_exports.string().min(1, "query is required"),
|
|
58543
|
-
sessionKey: sessionKeySchema,
|
|
58544
|
-
namespace: namespaceSchema,
|
|
58545
|
-
limit: external_exports.number().int().min(1).max(100).optional()
|
|
58546
|
-
});
|
|
58547
|
-
var daySummaryRequestSchema = external_exports.object({
|
|
58548
|
-
memories: external_exports.string().max(1e5).optional(),
|
|
58549
|
-
sessionKey: sessionKeySchema,
|
|
58550
|
-
namespace: namespaceSchema
|
|
58551
|
-
});
|
|
58552
|
-
var schemas = {
|
|
58553
|
-
recall: recallRequestSchema,
|
|
58554
|
-
recallExplain: recallExplainRequestSchema,
|
|
58555
|
-
setCodingContext: setCodingContextRequestSchema,
|
|
58556
|
-
observe: observeRequestSchema,
|
|
58557
|
-
memoryStore: memoryStoreRequestSchema,
|
|
58558
|
-
suggestionSubmit: suggestionSubmitRequestSchema,
|
|
58559
|
-
reviewDisposition: reviewDispositionRequestSchema,
|
|
58560
|
-
trustZonePromote: trustZonePromoteRequestSchema,
|
|
58561
|
-
trustZoneDemoSeed: trustZoneDemoSeedRequestSchema,
|
|
58562
|
-
lcmSearch: lcmSearchRequestSchema,
|
|
58563
|
-
daySummary: daySummaryRequestSchema
|
|
58564
|
-
};
|
|
58565
|
-
function validateRequest(schemaName, body) {
|
|
58566
|
-
const schema = schemas[schemaName];
|
|
58567
|
-
if (!schema) {
|
|
58568
|
-
return {
|
|
58569
|
-
success: false,
|
|
58570
|
-
error: {
|
|
58571
|
-
error: `unknown schema: ${schemaName}`,
|
|
58572
|
-
code: "validation_error",
|
|
58573
|
-
details: []
|
|
58574
|
-
}
|
|
58575
|
-
};
|
|
58576
|
-
}
|
|
58577
|
-
const result = schema.safeParse(body);
|
|
58578
|
-
if (result.success) {
|
|
58579
|
-
return { success: true, data: result.data };
|
|
58580
|
-
}
|
|
58581
|
-
return { success: false, error: formatZodError(result.error) };
|
|
58582
|
-
}
|
|
58583
|
-
|
|
58584
60002
|
// ../remnic-core/src/adapters/types.ts
|
|
58585
60003
|
function headerValue(headers, key) {
|
|
58586
60004
|
const raw = headers[key];
|
|
@@ -59099,6 +60517,36 @@ var EngramAccessHttpServer = class {
|
|
|
59099
60517
|
this.respondJson(res, 200, { ok: true });
|
|
59100
60518
|
return;
|
|
59101
60519
|
}
|
|
60520
|
+
if (req.method === "POST" && (pathname === "/engram/v1/capsules/export" || pathname === "/remnic/v1/capsules/export")) {
|
|
60521
|
+
const body = await this.readValidatedBody(req, "capsuleExport");
|
|
60522
|
+
this.ensureWriteRateLimitAvailable();
|
|
60523
|
+
const result = await this.service.capsuleExport({
|
|
60524
|
+
name: body.name,
|
|
60525
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
60526
|
+
principal: this.resolveRequestPrincipal(req),
|
|
60527
|
+
since: body.since,
|
|
60528
|
+
includeKinds: body.includeKinds,
|
|
60529
|
+
peerIds: body.peerIds,
|
|
60530
|
+
includeTranscripts: body.includeTranscripts,
|
|
60531
|
+
encrypt: body.encrypt
|
|
60532
|
+
});
|
|
60533
|
+
this.recordWriteRateLimitHit();
|
|
60534
|
+
this.respondJson(res, 200, result);
|
|
60535
|
+
return;
|
|
60536
|
+
}
|
|
60537
|
+
if (req.method === "POST" && (pathname === "/engram/v1/capsules/import" || pathname === "/remnic/v1/capsules/import")) {
|
|
60538
|
+
const body = await this.readValidatedBody(req, "capsuleImport");
|
|
60539
|
+
this.ensureWriteRateLimitAvailable();
|
|
60540
|
+
const result = await this.service.capsuleImport({
|
|
60541
|
+
archivePath: expandTildePath(body.archivePath),
|
|
60542
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
60543
|
+
principal: this.resolveRequestPrincipal(req),
|
|
60544
|
+
mode: body.mode
|
|
60545
|
+
});
|
|
60546
|
+
this.recordWriteRateLimitHit();
|
|
60547
|
+
this.respondJson(res, 200, result);
|
|
60548
|
+
return;
|
|
60549
|
+
}
|
|
59102
60550
|
if (req.method === "POST" && pathname === "/engram/v1/recall/explain") {
|
|
59103
60551
|
const body = await this.readValidatedBody(req, "recallExplain");
|
|
59104
60552
|
const response = await this.service.recallExplain({
|
|
@@ -59198,7 +60646,13 @@ var EngramAccessHttpServer = class {
|
|
|
59198
60646
|
this.ensureWriteRateLimitAvailable();
|
|
59199
60647
|
const response = await this.service.observe({
|
|
59200
60648
|
sessionKey: body.sessionKey,
|
|
59201
|
-
messages: body.messages
|
|
60649
|
+
messages: body.messages.map((message) => ({
|
|
60650
|
+
role: message.role,
|
|
60651
|
+
content: message.content,
|
|
60652
|
+
sourceFormat: message.sourceFormat ?? void 0,
|
|
60653
|
+
rawContent: message.rawContent ?? void 0,
|
|
60654
|
+
parts: message.parts ?? void 0
|
|
60655
|
+
})),
|
|
59202
60656
|
namespace: this.resolveNamespace(req, body.namespace),
|
|
59203
60657
|
authenticatedPrincipal: this.resolveRequestPrincipal(req),
|
|
59204
60658
|
skipExtraction: body.skipExtraction === true,
|
|
@@ -59882,7 +61336,8 @@ var EngramAccessHttpServer = class {
|
|
|
59882
61336
|
const toolName = typeof request.params?.name === "string" ? request.params.name : "";
|
|
59883
61337
|
const toolArgs = request.params?.arguments;
|
|
59884
61338
|
const dreamsRunDryRun = (toolName === "engram.dreams_run" || toolName === "remnic.dreams_run") && toolArgs !== null && typeof toolArgs === "object" && !Array.isArray(toolArgs) && toolArgs.dryRun === true;
|
|
59885
|
-
const
|
|
61339
|
+
const memoryActionApplyDryRun = (toolName === "engram.memory_action_apply" || toolName === "remnic.memory_action_apply") && toolArgs !== null && typeof toolArgs === "object" && !Array.isArray(toolArgs) && toolArgs.dryRun === true;
|
|
61340
|
+
const isMcpWrite = request.method === "tools/call" && (toolName === "engram.memory_store" || toolName === "remnic.memory_store" || toolName === "engram.suggestion_submit" || toolName === "remnic.suggestion_submit" || toolName === "engram.observe" || toolName === "remnic.observe" || toolName === "engram.capsule_export" || toolName === "remnic.capsule_export" || toolName === "engram.capsule_import" || toolName === "remnic.capsule_import" || !dreamsRunDryRun && (toolName === "engram.dreams_run" || toolName === "remnic.dreams_run") || !memoryActionApplyDryRun && (toolName === "engram.memory_action_apply" || toolName === "remnic.memory_action_apply"));
|
|
59886
61341
|
if (isMcpWrite) {
|
|
59887
61342
|
this.ensureWriteRateLimitAvailable();
|
|
59888
61343
|
}
|
|
@@ -59946,7 +61401,7 @@ var EngramAccessHttpServer = class {
|
|
|
59946
61401
|
}
|
|
59947
61402
|
async respondStatic(res, filePath, contentType) {
|
|
59948
61403
|
try {
|
|
59949
|
-
const body = await
|
|
61404
|
+
const body = await readFile44(filePath, "utf-8");
|
|
59950
61405
|
res.statusCode = 200;
|
|
59951
61406
|
res.setHeader("content-type", contentType);
|
|
59952
61407
|
res.setHeader("content-length", String(Buffer.byteLength(body)));
|
|
@@ -60121,7 +61576,7 @@ async function resolveAgentAccessAuthToken(value, options = {}) {
|
|
|
60121
61576
|
}
|
|
60122
61577
|
|
|
60123
61578
|
// ../remnic-core/src/compat/checks.ts
|
|
60124
|
-
import { access as
|
|
61579
|
+
import { access as access6, readFile as readFile45 } from "fs/promises";
|
|
60125
61580
|
import path71 from "path";
|
|
60126
61581
|
var REQUIRED_HOOKS_LEGACY = ["before_agent_start", "agent_end"];
|
|
60127
61582
|
var REQUIRED_HOOKS_NEW = ["before_prompt_build", "agent_end"];
|
|
@@ -60303,7 +61758,7 @@ async function runCompatChecks(options) {
|
|
|
60303
61758
|
let pluginRaw = "";
|
|
60304
61759
|
let pluginManifestPresent = false;
|
|
60305
61760
|
try {
|
|
60306
|
-
pluginRaw = await
|
|
61761
|
+
pluginRaw = await readFile45(pluginJsonPath, "utf-8");
|
|
60307
61762
|
pluginManifestPresent = true;
|
|
60308
61763
|
checks.push({
|
|
60309
61764
|
id: "plugin-manifest-present",
|
|
@@ -60353,7 +61808,7 @@ async function runCompatChecks(options) {
|
|
|
60353
61808
|
let packageRaw = "";
|
|
60354
61809
|
let packageJsonPresent = false;
|
|
60355
61810
|
try {
|
|
60356
|
-
packageRaw = await
|
|
61811
|
+
packageRaw = await readFile45(packageJsonPath, "utf-8");
|
|
60357
61812
|
packageJsonPresent = true;
|
|
60358
61813
|
} catch {
|
|
60359
61814
|
checks.push({
|
|
@@ -60423,8 +61878,8 @@ async function runCompatChecks(options) {
|
|
|
60423
61878
|
}
|
|
60424
61879
|
}
|
|
60425
61880
|
try {
|
|
60426
|
-
await
|
|
60427
|
-
const indexRaw = await
|
|
61881
|
+
await access6(indexPath);
|
|
61882
|
+
const indexRaw = await readFile45(indexPath, "utf-8");
|
|
60428
61883
|
const structuralSource = stripCommentsAndStrings(indexRaw);
|
|
60429
61884
|
const hooks = parseHookRegistrations(indexRaw);
|
|
60430
61885
|
const missingLegacy = REQUIRED_HOOKS_LEGACY.filter((hook) => !hooks.has(hook));
|
|
@@ -60849,7 +62304,7 @@ async function promoteSemanticRuleFromMemory(options) {
|
|
|
60849
62304
|
}
|
|
60850
62305
|
|
|
60851
62306
|
// ../remnic-core/src/training-export/converter.ts
|
|
60852
|
-
import { lstat as
|
|
62307
|
+
import { lstat as lstat3, readdir as readdir27, readFile as readFile46, realpath as realpath4 } from "fs/promises";
|
|
60853
62308
|
import path73 from "path";
|
|
60854
62309
|
|
|
60855
62310
|
// ../remnic-core/src/training-export/date-parse.ts
|
|
@@ -61455,7 +62910,7 @@ async function runRepairMemoryProjectionCliCommand(options) {
|
|
|
61455
62910
|
});
|
|
61456
62911
|
}
|
|
61457
62912
|
async function runMemoryTimelineCliCommand(options) {
|
|
61458
|
-
const storage = new (await import("./storage-
|
|
62913
|
+
const storage = new (await import("./storage-PTQ2H2YJ.js")).StorageManager(options.memoryDir);
|
|
61459
62914
|
return storage.getMemoryTimeline(options.memoryId, options.limit);
|
|
61460
62915
|
}
|
|
61461
62916
|
async function runMemoryGovernanceCliCommand(options) {
|
|
@@ -61483,7 +62938,7 @@ async function runMemoryGovernanceRestoreCliCommand(options) {
|
|
|
61483
62938
|
});
|
|
61484
62939
|
}
|
|
61485
62940
|
async function runMemoryReviewDispositionCliCommand(options) {
|
|
61486
|
-
const storage = new (await import("./storage-
|
|
62941
|
+
const storage = new (await import("./storage-PTQ2H2YJ.js")).StorageManager(options.memoryDir);
|
|
61487
62942
|
const memory = await storage.getMemoryById(options.memoryId);
|
|
61488
62943
|
if (!memory) throw new Error(`memory not found: ${options.memoryId}`);
|
|
61489
62944
|
const updated = await storage.writeMemoryFrontmatter(memory, {
|
|
@@ -61662,7 +63117,7 @@ async function runSemanticRulePromoteCliCommand(options) {
|
|
|
61662
63117
|
});
|
|
61663
63118
|
}
|
|
61664
63119
|
async function runCompoundingPromoteCliCommand(options) {
|
|
61665
|
-
const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-
|
|
63120
|
+
const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-BIYI3P4J.js");
|
|
61666
63121
|
const config = parseConfig({
|
|
61667
63122
|
memoryDir: options.memoryDir,
|
|
61668
63123
|
qmdEnabled: false,
|
|
@@ -62076,7 +63531,7 @@ function effectivePolicyValuesForVersion(values, config) {
|
|
|
62076
63531
|
}
|
|
62077
63532
|
function policyVersionForValues(values, config) {
|
|
62078
63533
|
const normalized = effectivePolicyValuesForVersion(values, config);
|
|
62079
|
-
return
|
|
63534
|
+
return createHash14("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
62080
63535
|
}
|
|
62081
63536
|
async function readRuntimePolicySnapshot2(config, fileName) {
|
|
62082
63537
|
const filePath = path74.join(config.memoryDir, "state", fileName);
|
|
@@ -62667,7 +64122,7 @@ async function withTimeout(promise, timeoutMs, timeoutMessage) {
|
|
|
62667
64122
|
}
|
|
62668
64123
|
async function runReplayCliCommand(orchestrator, options) {
|
|
62669
64124
|
const extractionIdleTimeoutMs = Number.isFinite(options.extractionIdleTimeoutMs) ? Math.max(1e3, Math.floor(options.extractionIdleTimeoutMs)) : 15 * 6e4;
|
|
62670
|
-
const inputRaw = await
|
|
64125
|
+
const inputRaw = await readFile47(options.inputPath, "utf-8");
|
|
62671
64126
|
const registry = buildReplayNormalizerRegistry([
|
|
62672
64127
|
openclawReplayNormalizer,
|
|
62673
64128
|
claudeReplayNormalizer,
|
|
@@ -62759,7 +64214,7 @@ async function runBulkImportCliCommand(opts) {
|
|
|
62759
64214
|
"Bulk import persistence is not wired: no ingestBatch callback was provided by the host CLI. Use --dry-run to validate without persisting, or invoke via `openclaw engram bulk-import` which supplies the orchestrator-backed ingestion path."
|
|
62760
64215
|
);
|
|
62761
64216
|
}
|
|
62762
|
-
const inputRaw = await
|
|
64217
|
+
const inputRaw = await readFile47(opts.file, "utf-8");
|
|
62763
64218
|
let inputParsed;
|
|
62764
64219
|
try {
|
|
62765
64220
|
inputParsed = JSON.parse(inputRaw);
|
|
@@ -62823,7 +64278,7 @@ async function runBulkImportCliCommand(opts) {
|
|
|
62823
64278
|
async function getPluginVersion() {
|
|
62824
64279
|
try {
|
|
62825
64280
|
const pkgPath = new URL("../package.json", import.meta.url);
|
|
62826
|
-
const raw = await
|
|
64281
|
+
const raw = await readFile47(pkgPath, "utf-8");
|
|
62827
64282
|
const parsed = JSON.parse(raw);
|
|
62828
64283
|
return parsed.version ?? "unknown";
|
|
62829
64284
|
} catch {
|
|
@@ -62832,7 +64287,7 @@ async function getPluginVersion() {
|
|
|
62832
64287
|
}
|
|
62833
64288
|
async function exists3(p) {
|
|
62834
64289
|
try {
|
|
62835
|
-
await
|
|
64290
|
+
await access7(p);
|
|
62836
64291
|
return true;
|
|
62837
64292
|
} catch {
|
|
62838
64293
|
return false;
|
|
@@ -62858,7 +64313,7 @@ async function walkMemoryMarkdownFiles(memoryDir, visit) {
|
|
|
62858
64313
|
const walk = async (dir) => {
|
|
62859
64314
|
let entries;
|
|
62860
64315
|
try {
|
|
62861
|
-
entries = await
|
|
64316
|
+
entries = await readdir28(dir, { withFileTypes: true });
|
|
62862
64317
|
} catch {
|
|
62863
64318
|
return;
|
|
62864
64319
|
}
|
|
@@ -62888,7 +64343,7 @@ async function readAllMemoryFiles(memoryDir) {
|
|
|
62888
64343
|
const out = [];
|
|
62889
64344
|
await walkMemoryMarkdownFiles(memoryDir, async (fullPath) => {
|
|
62890
64345
|
try {
|
|
62891
|
-
const raw = await
|
|
64346
|
+
const raw = await readFile47(fullPath, "utf-8");
|
|
62892
64347
|
const parsed = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
62893
64348
|
if (!parsed) return;
|
|
62894
64349
|
const fmRaw = parsed[1];
|
|
@@ -63634,8 +65089,8 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63634
65089
|
const memoryDir = await resolveMemoryDirForNamespace(orchestrator, namespace, {
|
|
63635
65090
|
rejectUnsupportedOverride: true
|
|
63636
65091
|
});
|
|
63637
|
-
const { exportCapsule } = await import("./capsule-export-
|
|
63638
|
-
const result = await
|
|
65092
|
+
const { exportCapsule: exportCapsule2 } = await import("./capsule-export-IXVERCQG.js");
|
|
65093
|
+
const result = await exportCapsule2({
|
|
63639
65094
|
name,
|
|
63640
65095
|
root: memoryDir,
|
|
63641
65096
|
since,
|
|
@@ -63680,7 +65135,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63680
65135
|
const memoryDir = await resolveMemoryDirForNamespace(orchestrator, namespace, {
|
|
63681
65136
|
rejectUnsupportedOverride: true
|
|
63682
65137
|
});
|
|
63683
|
-
const { importCapsule: importCapsule2 } = await import("./capsule-import-
|
|
65138
|
+
const { importCapsule: importCapsule2 } = await import("./capsule-import-IA6VIOPQ.js");
|
|
63684
65139
|
const result = await importCapsule2({
|
|
63685
65140
|
archivePath: expandTildePath(archivePath),
|
|
63686
65141
|
root: memoryDir,
|
|
@@ -63703,11 +65158,11 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63703
65158
|
const opts = args[1] ?? {};
|
|
63704
65159
|
const {
|
|
63705
65160
|
parseCapsuleMergeOptions,
|
|
63706
|
-
defaultCapsulesDir
|
|
63707
|
-
} = await import("./capsule-cli-
|
|
65161
|
+
defaultCapsulesDir: defaultCapsulesDir2
|
|
65162
|
+
} = await import("./capsule-cli-GBM3WPAM.js");
|
|
63708
65163
|
const parsed = parseCapsuleMergeOptions(archiveArg, opts);
|
|
63709
65164
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
63710
|
-
const capsulesDir =
|
|
65165
|
+
const capsulesDir = defaultCapsulesDir2(memoryDir);
|
|
63711
65166
|
const { stat: statMerge } = await import("fs/promises");
|
|
63712
65167
|
let sourceArchive = expandTildePath(parsed.archive);
|
|
63713
65168
|
const looksLikePath = sourceArchive.startsWith("/") || sourceArchive.startsWith("./") || sourceArchive.startsWith("../") || sourceArchive.includes(path74.sep);
|
|
@@ -63739,7 +65194,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63739
65194
|
);
|
|
63740
65195
|
}
|
|
63741
65196
|
}
|
|
63742
|
-
const { mergeCapsule } = await import("./capsule-merge-
|
|
65197
|
+
const { mergeCapsule } = await import("./capsule-merge-IWOQ34KL.js");
|
|
63743
65198
|
const result = await mergeCapsule({
|
|
63744
65199
|
sourceArchive,
|
|
63745
65200
|
targetRoot: memoryDir,
|
|
@@ -63769,17 +65224,17 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63769
65224
|
const {
|
|
63770
65225
|
parseCapsuleListOptions,
|
|
63771
65226
|
renderCapsuleList,
|
|
63772
|
-
defaultCapsulesDir
|
|
63773
|
-
} = await import("./capsule-cli-
|
|
65227
|
+
defaultCapsulesDir: defaultCapsulesDir2
|
|
65228
|
+
} = await import("./capsule-cli-GBM3WPAM.js");
|
|
63774
65229
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
63775
|
-
const defaultDir =
|
|
65230
|
+
const defaultDir = defaultCapsulesDir2(memoryDir);
|
|
63776
65231
|
const dirWasExplicit = typeof opts.dir === "string" && opts.dir.trim() !== "";
|
|
63777
65232
|
const parsed = parseCapsuleListOptions(opts, defaultDir);
|
|
63778
65233
|
const capsulesDir = expandTildePath(parsed.capsulesDir);
|
|
63779
|
-
const { readdir:
|
|
65234
|
+
const { readdir: readdir30, readFile: readFile54, stat: stat21 } = await import("fs/promises");
|
|
63780
65235
|
let dirEntries;
|
|
63781
65236
|
try {
|
|
63782
|
-
dirEntries = await
|
|
65237
|
+
dirEntries = await readdir30(capsulesDir);
|
|
63783
65238
|
} catch (err) {
|
|
63784
65239
|
const code = err.code;
|
|
63785
65240
|
if (dirWasExplicit) {
|
|
@@ -63815,7 +65270,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63815
65270
|
}
|
|
63816
65271
|
if (hasManifest) {
|
|
63817
65272
|
try {
|
|
63818
|
-
const raw = await
|
|
65273
|
+
const raw = await readFile54(manifestPath2, "utf-8");
|
|
63819
65274
|
const sidecar = JSON.parse(raw);
|
|
63820
65275
|
createdAt = typeof sidecar.createdAt === "string" ? sidecar.createdAt : null;
|
|
63821
65276
|
pluginVersion = typeof sidecar.pluginVersion === "string" ? sidecar.pluginVersion : null;
|
|
@@ -63850,10 +65305,10 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63850
65305
|
const {
|
|
63851
65306
|
parseCapsuleInspectOptions,
|
|
63852
65307
|
renderCapsuleInspect,
|
|
63853
|
-
defaultCapsulesDir
|
|
63854
|
-
} = await import("./capsule-cli-
|
|
65308
|
+
defaultCapsulesDir: defaultCapsulesDir2
|
|
65309
|
+
} = await import("./capsule-cli-GBM3WPAM.js");
|
|
63855
65310
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
63856
|
-
const capsulesDir =
|
|
65311
|
+
const capsulesDir = defaultCapsulesDir2(memoryDir);
|
|
63857
65312
|
const parsed = parseCapsuleInspectOptions(archiveArg, opts);
|
|
63858
65313
|
const { stat: stat21 } = await import("fs/promises");
|
|
63859
65314
|
let archivePath = expandTildePath(parsed.archive);
|
|
@@ -63881,8 +65336,8 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63881
65336
|
const sidecarPath = archivePath.replace(/\.enc$/, "").replace(/\.capsule\.json\.gz$/, ".manifest.json");
|
|
63882
65337
|
let sidecar = null;
|
|
63883
65338
|
try {
|
|
63884
|
-
const { readFile:
|
|
63885
|
-
const raw = await
|
|
65339
|
+
const { readFile: readFile54 } = await import("fs/promises");
|
|
65340
|
+
const raw = await readFile54(sidecarPath, "utf-8");
|
|
63886
65341
|
sidecar = JSON.parse(raw);
|
|
63887
65342
|
} catch {
|
|
63888
65343
|
}
|
|
@@ -63891,7 +65346,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63891
65346
|
manifest = sidecar;
|
|
63892
65347
|
} else if (isEncrypted) {
|
|
63893
65348
|
const { gunzipSync } = await import("zlib");
|
|
63894
|
-
const { parseExportBundle } = await import("./types-
|
|
65349
|
+
const { parseExportBundle } = await import("./types-R4DO7AKM.js");
|
|
63895
65350
|
let decryptedBuf;
|
|
63896
65351
|
try {
|
|
63897
65352
|
const { decryptCapsuleFileInMemory } = await import("./capsule-crypto-K3IRTKRH.js");
|
|
@@ -63919,10 +65374,10 @@ function registerCli(api, orchestrator, registerOptions = {}) {
|
|
|
63919
65374
|
}
|
|
63920
65375
|
manifest = parsed2.bundle.manifest;
|
|
63921
65376
|
} else {
|
|
63922
|
-
const { readFile:
|
|
65377
|
+
const { readFile: readFile54 } = await import("fs/promises");
|
|
63923
65378
|
const { gunzipSync } = await import("zlib");
|
|
63924
|
-
const { parseExportBundle } = await import("./types-
|
|
63925
|
-
const buf = await
|
|
65379
|
+
const { parseExportBundle } = await import("./types-R4DO7AKM.js");
|
|
65380
|
+
const buf = await readFile54(archivePath);
|
|
63926
65381
|
const json = gunzipSync(buf).toString("utf-8");
|
|
63927
65382
|
const parsed2 = parseExportBundle(JSON.parse(json));
|
|
63928
65383
|
if (parsed2.capsuleVersion !== 2) {
|
|
@@ -66689,7 +68144,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
|
|
|
66689
68144
|
runSecureStoreInit,
|
|
66690
68145
|
createPassphraseReader,
|
|
66691
68146
|
renderInitReport
|
|
66692
|
-
} = await import("./secure-store-
|
|
68147
|
+
} = await import("./secure-store-A4NGCNXV.js");
|
|
66693
68148
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
66694
68149
|
const kdf = typeof options.kdf === "string" ? options.kdf.trim() : "argon2id";
|
|
66695
68150
|
if (kdf !== "argon2id" && kdf !== "scrypt") {
|
|
@@ -66717,7 +68172,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
|
|
|
66717
68172
|
runSecureStoreUnlock,
|
|
66718
68173
|
createPassphraseReader,
|
|
66719
68174
|
renderUnlockReport
|
|
66720
|
-
} = await import("./secure-store-
|
|
68175
|
+
} = await import("./secure-store-A4NGCNXV.js");
|
|
66721
68176
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
66722
68177
|
const report = await runSecureStoreUnlock({
|
|
66723
68178
|
memoryDir,
|
|
@@ -66736,7 +68191,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
|
|
|
66736
68191
|
"Lock the secure-store. Clears the master key from the daemon's in-memory keyring. Idempotent \u2014 succeeds even if the store is already locked."
|
|
66737
68192
|
).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
|
|
66738
68193
|
const options = args[0] ?? {};
|
|
66739
|
-
const { runSecureStoreLock, renderLockReport } = await import("./secure-store-
|
|
68194
|
+
const { runSecureStoreLock, renderLockReport } = await import("./secure-store-A4NGCNXV.js");
|
|
66740
68195
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
66741
68196
|
const report = runSecureStoreLock({ memoryDir });
|
|
66742
68197
|
if (options.json === true) {
|
|
@@ -66749,7 +68204,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
|
|
|
66749
68204
|
"Encrypt existing plaintext storage-managed memory files in an initialized, unlocked secure-store. Idempotent; already-encrypted files are skipped."
|
|
66750
68205
|
).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
|
|
66751
68206
|
const options = args[0] ?? {};
|
|
66752
|
-
const { runSecureStoreMigrate, renderMigrateReport } = await import("./secure-store-
|
|
68207
|
+
const { runSecureStoreMigrate, renderMigrateReport } = await import("./secure-store-A4NGCNXV.js");
|
|
66753
68208
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
66754
68209
|
const report = await runSecureStoreMigrate({ memoryDir });
|
|
66755
68210
|
if (options.json === true) {
|
|
@@ -66761,11 +68216,34 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
|
|
|
66761
68216
|
process.exitCode = 1;
|
|
66762
68217
|
}
|
|
66763
68218
|
});
|
|
68219
|
+
async function runSecureStoreDisableCommand(options) {
|
|
68220
|
+
const { runSecureStoreDisable, renderDisableReport } = await import("./secure-store-A4NGCNXV.js");
|
|
68221
|
+
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
68222
|
+
const report = await runSecureStoreDisable({ memoryDir });
|
|
68223
|
+
if (options.json === true) {
|
|
68224
|
+
console.log(JSON.stringify(report, null, 2));
|
|
68225
|
+
} else {
|
|
68226
|
+
console.log(renderDisableReport(report));
|
|
68227
|
+
}
|
|
68228
|
+
if (!report.ok) {
|
|
68229
|
+
process.exitCode = 1;
|
|
68230
|
+
}
|
|
68231
|
+
}
|
|
68232
|
+
secureStoreCmd.command("disable").description(
|
|
68233
|
+
"Decrypt storage-managed secure-store files back to plaintext. Requires an initialized, unlocked secure-store and keeps .secure-store metadata in place."
|
|
68234
|
+
).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
|
|
68235
|
+
const options = args[0] ?? {};
|
|
68236
|
+
await runSecureStoreDisableCommand(options);
|
|
68237
|
+
});
|
|
68238
|
+
secureStoreCmd.command("decrypt").description("Alias for `secure-store disable`.").option("--json", "Emit machine-readable JSON only").action(async (...args) => {
|
|
68239
|
+
const options = args[0] ?? {};
|
|
68240
|
+
await runSecureStoreDisableCommand(options);
|
|
68241
|
+
});
|
|
66764
68242
|
secureStoreCmd.command("status").description(
|
|
66765
68243
|
"Report secure-store status: whether a header exists, whether the daemon currently holds the key, KDF parameters, and last-unlock timestamp."
|
|
66766
68244
|
).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
|
|
66767
68245
|
const options = args[0] ?? {};
|
|
66768
|
-
const { runSecureStoreStatus, renderStatusReport } = await import("./secure-store-
|
|
68246
|
+
const { runSecureStoreStatus, renderStatusReport } = await import("./secure-store-A4NGCNXV.js");
|
|
66769
68247
|
const memoryDir = expandTildePath(orchestrator.config.memoryDir);
|
|
66770
68248
|
const report = await runSecureStoreStatus({ memoryDir });
|
|
66771
68249
|
if (options.json === true) {
|
|
@@ -67112,7 +68590,7 @@ import crypto2 from "crypto";
|
|
|
67112
68590
|
function hashSha256(value) {
|
|
67113
68591
|
return crypto2.createHash("sha256").update(value).digest("hex");
|
|
67114
68592
|
}
|
|
67115
|
-
function
|
|
68593
|
+
function isRecord4(value) {
|
|
67116
68594
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
67117
68595
|
}
|
|
67118
68596
|
function optionalString2(value) {
|
|
@@ -67128,11 +68606,11 @@ function normalizedToolName(toolName) {
|
|
|
67128
68606
|
return toolNameTokens(toolName).join("_");
|
|
67129
68607
|
}
|
|
67130
68608
|
function parseToolArguments(value) {
|
|
67131
|
-
if (
|
|
68609
|
+
if (isRecord4(value)) return value;
|
|
67132
68610
|
if (typeof value !== "string") return void 0;
|
|
67133
68611
|
try {
|
|
67134
68612
|
const parsed = JSON.parse(value);
|
|
67135
|
-
return
|
|
68613
|
+
return isRecord4(parsed) ? parsed : void 0;
|
|
67136
68614
|
} catch {
|
|
67137
68615
|
return void 0;
|
|
67138
68616
|
}
|
|
@@ -67142,13 +68620,13 @@ function extractTextContent(value) {
|
|
|
67142
68620
|
if (Array.isArray(value)) {
|
|
67143
68621
|
return value.map((block) => {
|
|
67144
68622
|
if (typeof block === "string") return block.trim();
|
|
67145
|
-
if (
|
|
68623
|
+
if (isRecord4(block) && block.type === "text" && typeof block.text === "string") {
|
|
67146
68624
|
return block.text.trim();
|
|
67147
68625
|
}
|
|
67148
68626
|
return "";
|
|
67149
68627
|
}).filter((item) => item.length > 0).join("\n");
|
|
67150
68628
|
}
|
|
67151
|
-
if (
|
|
68629
|
+
if (isRecord4(value)) {
|
|
67152
68630
|
return JSON.stringify(value);
|
|
67153
68631
|
}
|
|
67154
68632
|
return "";
|
|
@@ -67175,10 +68653,10 @@ function getToolCallContexts(messages) {
|
|
|
67175
68653
|
const toolCalls = message.tool_calls ?? message.toolCalls;
|
|
67176
68654
|
if (!Array.isArray(toolCalls)) continue;
|
|
67177
68655
|
for (const call of toolCalls) {
|
|
67178
|
-
if (!
|
|
68656
|
+
if (!isRecord4(call)) continue;
|
|
67179
68657
|
const toolCallId = optionalString2(call.id) ?? optionalString2(call.toolCallId);
|
|
67180
68658
|
if (!toolCallId) continue;
|
|
67181
|
-
const fn =
|
|
68659
|
+
const fn = isRecord4(call.function) ? call.function : void 0;
|
|
67182
68660
|
const toolName = optionalString2(fn?.name) ?? optionalString2(call.name);
|
|
67183
68661
|
const args = parseToolArguments(fn?.arguments) ?? parseToolArguments(call.arguments) ?? parseToolArguments(call.args) ?? parseToolArguments(call.input);
|
|
67184
68662
|
contexts.set(toolCallId, { toolCallId, toolName, args });
|
|
@@ -67221,7 +68699,7 @@ function fileContentHash(args) {
|
|
|
67221
68699
|
}
|
|
67222
68700
|
function inferOutcome(message, parsedPayload) {
|
|
67223
68701
|
if (message.isError === true) return "failure";
|
|
67224
|
-
if (
|
|
68702
|
+
if (isRecord4(parsedPayload)) {
|
|
67225
68703
|
if (parsedPayload.partial === true || parsedPayload.status === "partial") return "partial";
|
|
67226
68704
|
if (parsedPayload.success === false || parsedPayload.ok === false) return "failure";
|
|
67227
68705
|
if (parsedPayload.success === true || parsedPayload.ok === true) return "success";
|
|
@@ -67425,13 +68903,13 @@ async function probeQmdAvailability(host) {
|
|
|
67425
68903
|
}
|
|
67426
68904
|
|
|
67427
68905
|
// ../../src/index.ts
|
|
67428
|
-
import { readFile as
|
|
68906
|
+
import { readFile as readFile53, realpath as realpath7, writeFile as writeFile44 } from "fs/promises";
|
|
67429
68907
|
import { existsSync as existsSync12, readFileSync as readFileSync6 } from "fs";
|
|
67430
68908
|
import path99 from "path";
|
|
67431
68909
|
import os7 from "os";
|
|
67432
68910
|
|
|
67433
68911
|
// ../remnic-core/src/opik-exporter.ts
|
|
67434
|
-
import { createHash as
|
|
68912
|
+
import { createHash as createHash15, randomBytes as randomBytes2 } from "crypto";
|
|
67435
68913
|
import { readFileSync as readFileSync4 } from "fs";
|
|
67436
68914
|
import path75 from "path";
|
|
67437
68915
|
var OPIK_EXPORTER_SLOT = "__openclawOpikExporter";
|
|
@@ -67752,7 +69230,7 @@ var OpikExporter = class _OpikExporter {
|
|
|
67752
69230
|
* the version/variant bits, not timestamp ordering.
|
|
67753
69231
|
*/
|
|
67754
69232
|
sessionToTraceId(sessionKey) {
|
|
67755
|
-
const digest =
|
|
69233
|
+
const digest = createHash15("sha256").update(sessionKey).digest();
|
|
67756
69234
|
digest[6] = digest[6] & 15 | 112;
|
|
67757
69235
|
digest[8] = digest[8] & 63 | 128;
|
|
67758
69236
|
const hex = digest.slice(0, 16).toString("hex");
|
|
@@ -67799,7 +69277,7 @@ function cleanUserMessage(content) {
|
|
|
67799
69277
|
}
|
|
67800
69278
|
|
|
67801
69279
|
// src/public-artifacts.ts
|
|
67802
|
-
import { readdir as
|
|
69280
|
+
import { readdir as readdir29, access as access8, stat as stat20, lstat as lstat4, realpath as realpath5 } from "fs/promises";
|
|
67803
69281
|
import path76 from "path";
|
|
67804
69282
|
var PUBLIC_DIRS = [
|
|
67805
69283
|
{ dir: "facts", kind: "fact", contentType: "markdown" },
|
|
@@ -67832,7 +69310,7 @@ async function listMarkdownFilesRecursive(rootDir, boundary, ancestorRealPaths)
|
|
|
67832
69310
|
nextAncestors.add(resolvedRoot);
|
|
67833
69311
|
let entries;
|
|
67834
69312
|
try {
|
|
67835
|
-
entries = await
|
|
69313
|
+
entries = await readdir29(rootDir, { withFileTypes: true });
|
|
67836
69314
|
} catch {
|
|
67837
69315
|
return [];
|
|
67838
69316
|
}
|
|
@@ -67843,7 +69321,7 @@ async function listMarkdownFilesRecursive(rootDir, boundary, ancestorRealPaths)
|
|
|
67843
69321
|
let isDir = entry.isDirectory();
|
|
67844
69322
|
let isFile = entry.isFile();
|
|
67845
69323
|
try {
|
|
67846
|
-
const linkStat = await
|
|
69324
|
+
const linkStat = await lstat4(fullPath);
|
|
67847
69325
|
if (linkStat.isSymbolicLink()) {
|
|
67848
69326
|
if (!await isContainedWithin(fullPath, boundaryDir)) {
|
|
67849
69327
|
continue;
|
|
@@ -67867,7 +69345,7 @@ async function listMarkdownFilesRecursive(rootDir, boundary, ancestorRealPaths)
|
|
|
67867
69345
|
}
|
|
67868
69346
|
async function pathExists2(inputPath) {
|
|
67869
69347
|
try {
|
|
67870
|
-
await
|
|
69348
|
+
await access8(inputPath);
|
|
67871
69349
|
return true;
|
|
67872
69350
|
} catch {
|
|
67873
69351
|
return false;
|
|
@@ -67907,7 +69385,7 @@ async function listRemnicPublicArtifacts(params) {
|
|
|
67907
69385
|
if (!await pathExists2(absolutePath)) continue;
|
|
67908
69386
|
if (!await isContainedWithin(absolutePath, memoryDir)) continue;
|
|
67909
69387
|
try {
|
|
67910
|
-
const linkStat = await
|
|
69388
|
+
const linkStat = await lstat4(absolutePath);
|
|
67911
69389
|
if (linkStat.isSymbolicLink()) {
|
|
67912
69390
|
const resolvedPath = await realpath5(absolutePath);
|
|
67913
69391
|
const expectedParent = await realpath5(memoryDir);
|
|
@@ -68158,12 +69636,12 @@ import os6 from "os";
|
|
|
68158
69636
|
import path92 from "path";
|
|
68159
69637
|
|
|
68160
69638
|
// ../remnic-core/src/enrichment/audit.ts
|
|
68161
|
-
import { mkdir as mkdir47, readFile as
|
|
69639
|
+
import { mkdir as mkdir47, readFile as readFile48, appendFile as appendFile5 } from "fs/promises";
|
|
68162
69640
|
import { existsSync as existsSync11 } from "fs";
|
|
68163
69641
|
import path93 from "path";
|
|
68164
69642
|
|
|
68165
69643
|
// ../remnic-core/src/transfer/capsule-fork.ts
|
|
68166
|
-
import { lstat as
|
|
69644
|
+
import { lstat as lstat5, mkdir as mkdir48, readFile as readFile49, realpath as realpath6, writeFile as writeFile41 } from "fs/promises";
|
|
68167
69645
|
import path94 from "path";
|
|
68168
69646
|
|
|
68169
69647
|
// src/openclaw-tools/shapes.ts
|
|
@@ -68943,7 +70421,7 @@ function validateSlotSelection(ctx) {
|
|
|
68943
70421
|
}
|
|
68944
70422
|
|
|
68945
70423
|
// ../remnic-core/src/session-toggles.ts
|
|
68946
|
-
import { mkdir as mkdir49, readFile as
|
|
70424
|
+
import { mkdir as mkdir49, readFile as readFile50, writeFile as writeFile42 } from "fs/promises";
|
|
68947
70425
|
import path95 from "path";
|
|
68948
70426
|
function encodeToggleKey(sessionKey, agentId) {
|
|
68949
70427
|
return `${encodeURIComponent(sessionKey)}::${encodeURIComponent(agentId)}`;
|
|
@@ -68958,7 +70436,7 @@ function decodeToggleKey(key) {
|
|
|
68958
70436
|
}
|
|
68959
70437
|
async function safeReadToggleFile(filePath) {
|
|
68960
70438
|
try {
|
|
68961
|
-
const raw = await
|
|
70439
|
+
const raw = await readFile50(filePath, "utf8");
|
|
68962
70440
|
const parsed = JSON.parse(raw);
|
|
68963
70441
|
if (!parsed || typeof parsed !== "object" || typeof parsed.entries !== "object") {
|
|
68964
70442
|
return { version: 1, entries: {} };
|
|
@@ -69441,14 +70919,14 @@ import {
|
|
|
69441
70919
|
} from "@remnic/core";
|
|
69442
70920
|
|
|
69443
70921
|
// ../remnic-core/src/surfaces/dreams.ts
|
|
69444
|
-
import { createHash as
|
|
70922
|
+
import { createHash as createHash16 } from "crypto";
|
|
69445
70923
|
import { statSync, watch as watch2 } from "fs";
|
|
69446
|
-
import { mkdir as mkdir51, readFile as
|
|
70924
|
+
import { mkdir as mkdir51, readFile as readFile51, writeFile as writeFile43 } from "fs/promises";
|
|
69447
70925
|
import path97 from "path";
|
|
69448
70926
|
var DIARY_START_MARKER = "<!-- openclaw:dreaming:diary:start -->";
|
|
69449
70927
|
var DIARY_END_MARKER = "<!-- openclaw:dreaming:diary:end -->";
|
|
69450
70928
|
function stableDreamId(params) {
|
|
69451
|
-
const digest =
|
|
70929
|
+
const digest = createHash16("sha1").update(
|
|
69452
70930
|
JSON.stringify({
|
|
69453
70931
|
timestamp: params.timestamp,
|
|
69454
70932
|
occurrence: params.occurrence
|
|
@@ -69609,7 +71087,7 @@ function createDreamsSurface() {
|
|
|
69609
71087
|
return {
|
|
69610
71088
|
async read(filePath) {
|
|
69611
71089
|
try {
|
|
69612
|
-
const content = await
|
|
71090
|
+
const content = await readFile51(filePath, "utf8");
|
|
69613
71091
|
return parseDreamEntries(content);
|
|
69614
71092
|
} catch (error) {
|
|
69615
71093
|
if (error.code === "ENOENT") {
|
|
@@ -69622,7 +71100,7 @@ function createDreamsSurface() {
|
|
|
69622
71100
|
await mkdir51(path97.dirname(filePath), { recursive: true });
|
|
69623
71101
|
let content = "";
|
|
69624
71102
|
try {
|
|
69625
|
-
content = await
|
|
71103
|
+
content = await readFile51(filePath, "utf8");
|
|
69626
71104
|
} catch (error) {
|
|
69627
71105
|
if (error.code !== "ENOENT") throw error;
|
|
69628
71106
|
}
|
|
@@ -69718,12 +71196,12 @@ ${ensured.slice(endIndex)}` : `${ensureDiary("")}${block}`;
|
|
|
69718
71196
|
}
|
|
69719
71197
|
|
|
69720
71198
|
// ../remnic-core/src/surfaces/heartbeat.ts
|
|
69721
|
-
import { createHash as
|
|
71199
|
+
import { createHash as createHash17 } from "crypto";
|
|
69722
71200
|
import { statSync as statSync2, watch as watch3 } from "fs";
|
|
69723
|
-
import { readFile as
|
|
71201
|
+
import { readFile as readFile52 } from "fs/promises";
|
|
69724
71202
|
import path98 from "path";
|
|
69725
71203
|
function stableHeartbeatId(params) {
|
|
69726
|
-
const digest =
|
|
71204
|
+
const digest = createHash17("sha1").update(
|
|
69727
71205
|
JSON.stringify({
|
|
69728
71206
|
sourceOffset: params.sourceOffset
|
|
69729
71207
|
})
|
|
@@ -69735,7 +71213,7 @@ function slugify(value) {
|
|
|
69735
71213
|
if (normalized.length > 0) return normalized;
|
|
69736
71214
|
const trimmed = value.trim();
|
|
69737
71215
|
if (trimmed.length === 0) return "heartbeat-untitled";
|
|
69738
|
-
return `heartbeat-${
|
|
71216
|
+
return `heartbeat-${createHash17("sha1").update(trimmed).digest("hex").slice(0, 8)}`;
|
|
69739
71217
|
}
|
|
69740
71218
|
function parseTags(line) {
|
|
69741
71219
|
const match = /^Tags:\s*(.*)$/i.exec(line.trim());
|
|
@@ -69884,7 +71362,7 @@ function createHeartbeatSurface() {
|
|
|
69884
71362
|
return {
|
|
69885
71363
|
async read(filePath) {
|
|
69886
71364
|
try {
|
|
69887
|
-
const content = await
|
|
71365
|
+
const content = await readFile52(filePath, "utf8");
|
|
69888
71366
|
return parseHeartbeatEntries(content);
|
|
69889
71367
|
} catch (error) {
|
|
69890
71368
|
if (error.code === "ENOENT") {
|
|
@@ -71562,7 +73040,7 @@ Keep the reflection grounded in the evidence below.
|
|
|
71562
73040
|
async readFile(params) {
|
|
71563
73041
|
const requestedPath = normalizeWorkspacePath(params.relPath);
|
|
71564
73042
|
const absolutePath = await resolveReadablePath(params.relPath);
|
|
71565
|
-
const text = await
|
|
73043
|
+
const text = await readFile53(absolutePath, "utf-8");
|
|
71566
73044
|
const allLines = text.split(/\r?\n/);
|
|
71567
73045
|
const from = typeof params.from === "number" ? Math.max(1, Math.floor(params.from)) : 1;
|
|
71568
73046
|
const lines = typeof params.lines === "number" && Number.isFinite(params.lines) ? Math.max(1, Math.floor(params.lines)) : void 0;
|
|
@@ -71813,7 +73291,12 @@ Keep the reflection grounded in the evidence below.
|
|
|
71813
73291
|
const lcmMessages = lastTurn.map((msg) => {
|
|
71814
73292
|
const rawRole = typeof msg.role === "string" ? msg.role : "";
|
|
71815
73293
|
const content = extractTextContent2(msg);
|
|
71816
|
-
return {
|
|
73294
|
+
return {
|
|
73295
|
+
role: rawRole,
|
|
73296
|
+
content,
|
|
73297
|
+
rawContent: msg,
|
|
73298
|
+
sourceFormat: "openclaw"
|
|
73299
|
+
};
|
|
71817
73300
|
}).filter((m) => m.content.length > 0);
|
|
71818
73301
|
if (lcmMessages.length > 0) {
|
|
71819
73302
|
orchestrator.lcmEngine.enqueueObserveMessages(
|
|
@@ -72218,7 +73701,7 @@ Keep the reflection grounded in the evidence below.
|
|
|
72218
73701
|
jobs: []
|
|
72219
73702
|
};
|
|
72220
73703
|
try {
|
|
72221
|
-
const content = await
|
|
73704
|
+
const content = await readFile53(cronFilePath, "utf-8");
|
|
72222
73705
|
jobsData = JSON.parse(content);
|
|
72223
73706
|
} catch {
|
|
72224
73707
|
}
|