@agenr/agenr-plugin 1.7.4 → 1.8.1
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/chunk-GUDCFFRV.js +1517 -0
- package/dist/chunk-LVDQXSHP.js +5122 -0
- package/dist/{chunk-NXCCTZ4G.js → chunk-O45JQ6O3.js} +2212 -544
- package/dist/index.js +334 -261
- package/openclaw.plugin.json +31 -8
- package/package.json +2 -2
- package/dist/chunk-7WL5EAQZ.js +0 -758
- package/dist/chunk-IZDGXMTQ.js +0 -839
- package/dist/chunk-NIQKTINU.js +0 -2545
package/dist/index.js
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OpenClawTranscriptParser,
|
|
3
|
+
createOpenClawRepository,
|
|
3
4
|
deriveOpenClawSessionIdFromFilePath,
|
|
4
5
|
ingestEpisodeTranscript,
|
|
5
|
-
normalizeClaimKey,
|
|
6
6
|
openClawTranscriptParser,
|
|
7
7
|
parseTuiSessionKey,
|
|
8
8
|
readOpenClawSessionsStore,
|
|
9
9
|
storeEntriesDetailed
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import {
|
|
12
|
-
runUnifiedRecall
|
|
13
|
-
} from "./chunk-IZDGXMTQ.js";
|
|
10
|
+
} from "./chunk-O45JQ6O3.js";
|
|
14
11
|
import {
|
|
15
12
|
EMBEDDING_DIMENSIONS,
|
|
16
13
|
ENTRY_TYPES,
|
|
17
14
|
EXPIRY_LEVELS,
|
|
18
|
-
VECTOR_INDEX_NAME,
|
|
19
|
-
buildActiveEntryClause,
|
|
20
15
|
createDatabase,
|
|
21
16
|
createEmbeddingClient,
|
|
22
17
|
createRecallAdapter,
|
|
23
|
-
|
|
18
|
+
normalizeManualClaimKeyUpdate,
|
|
24
19
|
readConfig,
|
|
25
|
-
readNumber,
|
|
26
|
-
readOptionalString,
|
|
27
|
-
readRequiredString,
|
|
28
20
|
resolveClaimExtractionConfig,
|
|
29
21
|
resolveConfigPath,
|
|
30
22
|
resolveDbPath,
|
|
31
23
|
resolveEmbeddingApiKey,
|
|
32
|
-
resolveEmbeddingModel
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
resolveEmbeddingModel,
|
|
25
|
+
runUnifiedRecall,
|
|
26
|
+
validateTemporalValidityRange
|
|
27
|
+
} from "./chunk-LVDQXSHP.js";
|
|
28
|
+
import {
|
|
29
|
+
resolveClaimSlotPolicy
|
|
30
|
+
} from "./chunk-GUDCFFRV.js";
|
|
35
31
|
|
|
36
32
|
// src/adapters/openclaw/index.ts
|
|
37
33
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
@@ -123,6 +119,14 @@ function buildSessionSourceFile(ctx) {
|
|
|
123
119
|
const target = ctx.sessionKey ?? ctx.sessionId ?? ctx.agentId ?? "unknown";
|
|
124
120
|
return `openclaw-session:${target}`;
|
|
125
121
|
}
|
|
122
|
+
function buildToolCallClaimSupport(ctx, toolName, observedAt) {
|
|
123
|
+
return {
|
|
124
|
+
claim_support_source_kind: "tool_call",
|
|
125
|
+
claim_support_locator: `${buildSessionSourceFile(ctx)}#${toolName}`,
|
|
126
|
+
claim_support_observed_at: observedAt,
|
|
127
|
+
claim_support_mode: "explicit"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
126
130
|
function logToolCall(logger, toolName, ctx, summary, sanitizedParams) {
|
|
127
131
|
logger.info(`[agenr] tool=${toolName} ${formatToolSessionContext(ctx)} ${summary}`);
|
|
128
132
|
logger.info(`[agenr] tool=${toolName} ${formatToolSessionContext(ctx)} params=${JSON.stringify(sanitizedParams)}`);
|
|
@@ -171,6 +175,9 @@ function formatRecallToolSummary(params) {
|
|
|
171
175
|
if (params.tags.length > 0) {
|
|
172
176
|
parts.push(`tags=${JSON.stringify(params.tags)}`);
|
|
173
177
|
}
|
|
178
|
+
if (params.asOf) {
|
|
179
|
+
parts.push(`as_of=${JSON.stringify(params.asOf)}`);
|
|
180
|
+
}
|
|
174
181
|
return parts.join(" ");
|
|
175
182
|
}
|
|
176
183
|
function sanitizeRecallToolParams(params) {
|
|
@@ -180,7 +187,8 @@ function sanitizeRecallToolParams(params) {
|
|
|
180
187
|
...params.limit !== void 0 ? { limit: params.limit } : {},
|
|
181
188
|
...params.threshold !== void 0 ? { threshold: params.threshold } : {},
|
|
182
189
|
...params.types.length > 0 ? { types: params.types } : {},
|
|
183
|
-
...params.tags.length > 0 ? { tags: params.tags } : {}
|
|
190
|
+
...params.tags.length > 0 ? { tags: params.tags } : {},
|
|
191
|
+
...params.asOf ? { asOf: params.asOf } : {}
|
|
184
192
|
};
|
|
185
193
|
}
|
|
186
194
|
function sanitizeRetireToolParams(params) {
|
|
@@ -220,15 +228,24 @@ function formatUnifiedRecallResults(result) {
|
|
|
220
228
|
lines.push(`${result.timeWindow.start} -> ${result.timeWindow.end} (${result.timeWindow.timezone}) from ${JSON.stringify(result.timeWindow.resolvedFrom)}`);
|
|
221
229
|
lines.push("");
|
|
222
230
|
}
|
|
231
|
+
if (result.asOf) {
|
|
232
|
+
lines.push("As Of");
|
|
233
|
+
lines.push(result.asOf);
|
|
234
|
+
lines.push("");
|
|
235
|
+
}
|
|
223
236
|
const renderEntriesFirst = result.routing.detectedIntent === "historical_state";
|
|
224
237
|
if (renderEntriesFirst) {
|
|
225
238
|
appendEntryMatches(lines, result);
|
|
226
239
|
lines.push("");
|
|
240
|
+
appendClaimTransitions(lines, result);
|
|
241
|
+
lines.push("");
|
|
227
242
|
appendEpisodeMatches(lines, result);
|
|
228
243
|
} else {
|
|
229
244
|
appendEpisodeMatches(lines, result);
|
|
230
245
|
lines.push("");
|
|
231
246
|
appendEntryMatches(lines, result);
|
|
247
|
+
lines.push("");
|
|
248
|
+
appendClaimTransitions(lines, result);
|
|
232
249
|
}
|
|
233
250
|
if (result.notices.length > 0) {
|
|
234
251
|
lines.push("");
|
|
@@ -241,15 +258,26 @@ function formatUnifiedRecallResults(result) {
|
|
|
241
258
|
}
|
|
242
259
|
function appendEntryMatches(lines, result) {
|
|
243
260
|
lines.push("Entry Matches");
|
|
244
|
-
if (result.
|
|
261
|
+
if (result.projectedEntries.length === 0) {
|
|
245
262
|
lines.push("None.");
|
|
246
263
|
return;
|
|
247
264
|
}
|
|
248
|
-
for (const [
|
|
265
|
+
for (const [familyIndex, family] of result.entryFamilies.entries()) {
|
|
249
266
|
lines.push(
|
|
250
|
-
|
|
267
|
+
family.claimKey ? `Family ${familyIndex + 1}. claim_key=${family.claimKey} | slot_policy=${family.slotPolicy} | primary=${family.primary.entryId} | subject=${family.subject}` : `Standalone ${familyIndex + 1}. ${family.primary.entryId} | subject=${family.subject}`
|
|
251
268
|
);
|
|
252
|
-
|
|
269
|
+
for (const [entryIndex, entry] of family.entries.entries()) {
|
|
270
|
+
lines.push(
|
|
271
|
+
` ${entryIndex + 1}. ${entry.entryId} | ${entry.recall.entry.type} | ${entry.recall.entry.subject} | score ${entry.recall.score.toFixed(2)} | state=${entry.memoryState} | claim_status=${formatClaimStatus(entry.claimStatus)}`
|
|
272
|
+
);
|
|
273
|
+
lines.push(` ${truncate(entry.recall.entry.content, 220)}`);
|
|
274
|
+
lines.push(` freshness=${entry.freshness.label}`);
|
|
275
|
+
const provenance = formatProjectedEntryProvenance(entry);
|
|
276
|
+
if (provenance) {
|
|
277
|
+
lines.push(` provenance=${provenance}`);
|
|
278
|
+
}
|
|
279
|
+
lines.push(` why_surfaced=${entry.whySurfaced.summary}`);
|
|
280
|
+
}
|
|
253
281
|
}
|
|
254
282
|
}
|
|
255
283
|
function appendEpisodeMatches(lines, result) {
|
|
@@ -266,6 +294,25 @@ function appendEpisodeMatches(lines, result) {
|
|
|
266
294
|
lines.push(` why_matched=${describeEpisodeMatch(episode)}`);
|
|
267
295
|
}
|
|
268
296
|
}
|
|
297
|
+
function appendClaimTransitions(lines, result) {
|
|
298
|
+
lines.push("Claim Transitions");
|
|
299
|
+
if (result.claimTransitions.length === 0) {
|
|
300
|
+
lines.push("None.");
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
for (const [index, transition] of result.claimTransitions.entries()) {
|
|
304
|
+
lines.push(
|
|
305
|
+
`${index + 1}. family=${transition.claimKey ?? transition.familyKey} | slot_policy=${transition.slotPolicy}${transition.currentEntryId ? ` | current=${transition.currentEntryId}` : ""}${transition.priorEntryId ? ` | prior=${transition.priorEntryId}` : ""}`
|
|
306
|
+
);
|
|
307
|
+
lines.push(` ${transition.summary}`);
|
|
308
|
+
if (transition.episodeContext) {
|
|
309
|
+
lines.push(
|
|
310
|
+
` episode=${transition.episodeContext.episodeId} | ${transition.episodeContext.startedAt} -> ${transition.episodeContext.endedAt ?? transition.episodeContext.startedAt}`
|
|
311
|
+
);
|
|
312
|
+
lines.push(` ${truncate(transition.episodeContext.summary.trim(), 220)}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
269
316
|
function formatUnifiedRecallLogSummary(result) {
|
|
270
317
|
const entrySubjects = result.entries.map((entry) => entry.entry.subject.trim()).filter((subject) => subject.length > 0);
|
|
271
318
|
const displayed = entrySubjects.slice(0, RESULT_SUBJECT_LOG_LIMIT).map((subject) => JSON.stringify(truncate(subject, 80)));
|
|
@@ -273,7 +320,11 @@ function formatUnifiedRecallLogSummary(result) {
|
|
|
273
320
|
const suffix = displayed.length === 0 ? "" : ` [entry subjects: ${displayed.join(", ")}${remaining > 0 ? `, ... and ${remaining} more` : ""}]`;
|
|
274
321
|
return `${result.episodes.length} episode${result.episodes.length === 1 ? "" : "s"}, ${result.entries.length} entr${result.entries.length === 1 ? "y" : "ies"}${suffix}`;
|
|
275
322
|
}
|
|
276
|
-
function formatTrace(entry, supersededBy, supersedes, recallEvents) {
|
|
323
|
+
function formatTrace(entry, supersededBy, supersedes, claimFamily, recallEvents) {
|
|
324
|
+
const slotPolicy = entry.claim_key ? claimFamily ? {
|
|
325
|
+
policy: claimFamily.slotPolicy ?? resolveClaimSlotPolicy(claimFamily.claimKey).policy,
|
|
326
|
+
reason: claimFamily.slotPolicyReason ?? resolveClaimSlotPolicy(claimFamily.claimKey).reason
|
|
327
|
+
} : resolveClaimSlotPolicy(entry.claim_key) : void 0;
|
|
277
328
|
const lines = [
|
|
278
329
|
`Trace for ${entry.id} | ${entry.subject}`,
|
|
279
330
|
`type=${entry.type} expiry=${entry.expiry} importance=${entry.importance} retired=${entry.retired}`,
|
|
@@ -287,6 +338,22 @@ function formatTrace(entry, supersededBy, supersedes, recallEvents) {
|
|
|
287
338
|
}
|
|
288
339
|
if (entry.claim_key) {
|
|
289
340
|
lines.push(`claim_key=${entry.claim_key}`);
|
|
341
|
+
if (slotPolicy) {
|
|
342
|
+
lines.push(`slot_policy=${slotPolicy.policy}`);
|
|
343
|
+
lines.push(`slot_policy_reason=${slotPolicy.reason}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (claimFamily && claimFamily.entries.length > 0) {
|
|
347
|
+
lines.push(
|
|
348
|
+
`claim_family=${claimFamily.claimKey} | slot_policy=${slotPolicy?.policy ?? "exclusive"} | ${claimFamily.entries.map((item) => `${item.id}:${describeTraceEntryState(item)}:${formatClaimLifecycleLabel(item)}`).join(", ")}`
|
|
349
|
+
);
|
|
350
|
+
if (slotPolicy) {
|
|
351
|
+
lines.push(`claim_family_policy_reason=${slotPolicy.reason}`);
|
|
352
|
+
}
|
|
353
|
+
const transitionSummary = summarizeTraceClaimFamilyTransition(claimFamily.entries);
|
|
354
|
+
if (transitionSummary) {
|
|
355
|
+
lines.push(`transition=${transitionSummary}`);
|
|
356
|
+
}
|
|
290
357
|
}
|
|
291
358
|
if (entry.valid_from || entry.valid_to) {
|
|
292
359
|
lines.push(`validity=${entry.valid_from ?? "?"} -> ${entry.valid_to ?? "ongoing"}`);
|
|
@@ -350,6 +417,50 @@ function describeEpisodeMatch(result) {
|
|
|
350
417
|
}
|
|
351
418
|
return "Matched episodic recall ranking.";
|
|
352
419
|
}
|
|
420
|
+
function formatClaimStatus(status) {
|
|
421
|
+
return status === "no_key" ? "no-key" : status;
|
|
422
|
+
}
|
|
423
|
+
function formatProjectedEntryProvenance(entry) {
|
|
424
|
+
const parts = [
|
|
425
|
+
entry.provenance.supersededById ? `superseded_by=${entry.provenance.supersededById}` : void 0,
|
|
426
|
+
entry.provenance.supersessionKind ? `kind=${entry.provenance.supersessionKind}` : void 0,
|
|
427
|
+
entry.provenance.supersessionReason ? `reason=${truncate(entry.provenance.supersessionReason, 120)}` : void 0,
|
|
428
|
+
entry.provenance.supportSourceKind ? `support=${entry.provenance.supportSourceKind}` : void 0,
|
|
429
|
+
entry.provenance.supportMode ? `support_mode=${entry.provenance.supportMode}` : void 0,
|
|
430
|
+
entry.provenance.supportObservedAt ? `observed=${entry.provenance.supportObservedAt}` : void 0,
|
|
431
|
+
entry.provenance.supportLocator ? `locator=${truncate(entry.provenance.supportLocator, 120)}` : void 0
|
|
432
|
+
].filter((value) => value !== void 0);
|
|
433
|
+
return parts.join(" | ");
|
|
434
|
+
}
|
|
435
|
+
function describeTraceEntryState(entry) {
|
|
436
|
+
if (entry.superseded_by) {
|
|
437
|
+
return "superseded";
|
|
438
|
+
}
|
|
439
|
+
if (entry.retired || entry.valid_to) {
|
|
440
|
+
return "historical";
|
|
441
|
+
}
|
|
442
|
+
return "current";
|
|
443
|
+
}
|
|
444
|
+
function formatClaimLifecycleLabel(entry) {
|
|
445
|
+
if (!entry.claim_key) {
|
|
446
|
+
return "no-key";
|
|
447
|
+
}
|
|
448
|
+
return entry.claim_key_status ?? "legacy";
|
|
449
|
+
}
|
|
450
|
+
function summarizeTraceClaimFamilyTransition(entries) {
|
|
451
|
+
const current = entries.find((entry) => !entry.retired && !entry.superseded_by);
|
|
452
|
+
const prior = [...entries].reverse().find((entry) => entry.id !== current?.id && (entry.superseded_by !== void 0 || entry.retired || entry.valid_to !== void 0));
|
|
453
|
+
if (current && prior) {
|
|
454
|
+
return `${prior.id} -> ${current.id}`;
|
|
455
|
+
}
|
|
456
|
+
if (prior) {
|
|
457
|
+
return `${prior.id} is historical with no current sibling in the traced family`;
|
|
458
|
+
}
|
|
459
|
+
if (current) {
|
|
460
|
+
return `${current.id} is the only current sibling in the traced family`;
|
|
461
|
+
}
|
|
462
|
+
return void 0;
|
|
463
|
+
}
|
|
353
464
|
|
|
354
465
|
// src/adapters/openclaw/tools/recall.ts
|
|
355
466
|
var RECALL_TOOL_PARAMETERS = {
|
|
@@ -389,6 +500,10 @@ var RECALL_TOOL_PARAMETERS = {
|
|
|
389
500
|
type: "array",
|
|
390
501
|
items: { type: "string" },
|
|
391
502
|
description: "Optional tags to filter by once you already know the relevant entity, system, or theme."
|
|
503
|
+
},
|
|
504
|
+
asOf: {
|
|
505
|
+
type: "string",
|
|
506
|
+
description: "Optional reference time for current-vs-prior resolution. Supports ISO timestamps and the same natural-language date phrases used elsewhere in recall."
|
|
392
507
|
}
|
|
393
508
|
},
|
|
394
509
|
required: ["query"]
|
|
@@ -409,6 +524,7 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
409
524
|
const services = await servicesPromise;
|
|
410
525
|
const types = parseEntryTypes(readStringArrayParam(params, "types"));
|
|
411
526
|
const tags = normalizeStringArray(readStringArrayParam(params, "tags"));
|
|
527
|
+
const asOf = readStringParam2(params, "asOf");
|
|
412
528
|
const request = {
|
|
413
529
|
text: query,
|
|
414
530
|
...mode ? { mode } : {},
|
|
@@ -416,6 +532,7 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
416
532
|
...threshold !== void 0 ? { threshold } : {},
|
|
417
533
|
...types.length > 0 ? { types } : {},
|
|
418
534
|
...tags.length > 0 ? { tags } : {},
|
|
535
|
+
...asOf ? { asOf } : {},
|
|
419
536
|
sessionKey: ctx.sessionKey
|
|
420
537
|
};
|
|
421
538
|
logToolCall(
|
|
@@ -427,7 +544,8 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
427
544
|
mode,
|
|
428
545
|
limit,
|
|
429
546
|
types,
|
|
430
|
-
tags
|
|
547
|
+
tags,
|
|
548
|
+
...asOf ? { asOf } : {}
|
|
431
549
|
}),
|
|
432
550
|
sanitizeRecallToolParams({
|
|
433
551
|
query,
|
|
@@ -435,7 +553,8 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
435
553
|
limit,
|
|
436
554
|
threshold,
|
|
437
555
|
types,
|
|
438
|
-
tags
|
|
556
|
+
tags,
|
|
557
|
+
...asOf ? { asOf } : {}
|
|
439
558
|
})
|
|
440
559
|
);
|
|
441
560
|
const result = await runUnifiedRecall(request, {
|
|
@@ -443,13 +562,17 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
443
562
|
recall: services.recall,
|
|
444
563
|
embeddingAvailable: services.embeddingStatus.available,
|
|
445
564
|
embeddingError: services.embeddingStatus.error,
|
|
565
|
+
claimSlotPolicyConfig: services.pluginConfig.memoryPolicy?.slotPolicies,
|
|
446
566
|
debugLog: (message) => {
|
|
447
567
|
logger.debug?.(message);
|
|
448
568
|
},
|
|
449
569
|
embedQuery: services.embeddingStatus.available ? async (text) => {
|
|
450
570
|
const vectors = await services.embedding.embed([text]);
|
|
451
571
|
return vectors[0] ?? [];
|
|
452
|
-
} : void 0
|
|
572
|
+
} : void 0,
|
|
573
|
+
recallOptions: {
|
|
574
|
+
slotPolicyConfig: services.pluginConfig.memoryPolicy?.slotPolicies
|
|
575
|
+
}
|
|
453
576
|
});
|
|
454
577
|
logger.info(
|
|
455
578
|
`[agenr] tool=agenr_recall session=${ctx.sessionId ?? "unknown"} key=${ctx.sessionKey ?? "unknown"} result: ${formatUnifiedRecallLogSummary(result)}`
|
|
@@ -463,6 +586,7 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
463
586
|
queried: result.routing.queried,
|
|
464
587
|
reason: result.routing.reason
|
|
465
588
|
},
|
|
589
|
+
...result.asOf ? { asOf: result.asOf } : {},
|
|
466
590
|
...result.timeWindow ? { timeWindow: result.timeWindow } : {},
|
|
467
591
|
episodes: result.episodes.map((episode) => ({
|
|
468
592
|
id: episode.episode.id,
|
|
@@ -486,6 +610,30 @@ function createAgenrRecallTool(ctx, servicesPromise, logger) {
|
|
|
486
610
|
tags: entry.entry.tags,
|
|
487
611
|
content: entry.entry.content
|
|
488
612
|
})),
|
|
613
|
+
projectedEntries: result.projectedEntries.map((entry) => ({
|
|
614
|
+
id: entry.entryId,
|
|
615
|
+
familyKey: entry.familyKey,
|
|
616
|
+
claimKey: entry.claimKey,
|
|
617
|
+
slotPolicy: entry.slotPolicy,
|
|
618
|
+
memoryState: entry.memoryState,
|
|
619
|
+
claimStatus: entry.claimStatus,
|
|
620
|
+
freshness: entry.freshness,
|
|
621
|
+
provenance: entry.provenance,
|
|
622
|
+
whySurfaced: entry.whySurfaced
|
|
623
|
+
})),
|
|
624
|
+
entryFamilies: result.entryFamilies.map((family) => ({
|
|
625
|
+
familyKey: family.familyKey,
|
|
626
|
+
claimKey: family.claimKey,
|
|
627
|
+
slotPolicy: family.slotPolicy,
|
|
628
|
+
subject: family.subject,
|
|
629
|
+
primaryEntryId: family.primary.entryId,
|
|
630
|
+
entries: family.entries.map((entry) => ({
|
|
631
|
+
id: entry.entryId,
|
|
632
|
+
memoryState: entry.memoryState,
|
|
633
|
+
claimStatus: entry.claimStatus
|
|
634
|
+
}))
|
|
635
|
+
})),
|
|
636
|
+
claimTransitions: result.claimTransitions,
|
|
489
637
|
notices: result.notices
|
|
490
638
|
});
|
|
491
639
|
} catch (error) {
|
|
@@ -627,9 +775,10 @@ function createAgenrStoreTool(ctx, servicesPromise, logger) {
|
|
|
627
775
|
const tags = normalizeStringArray(readStringArrayParam2(params, "tags"));
|
|
628
776
|
const sourceContext = readStringParam4(params, "sourceContext");
|
|
629
777
|
const supersedes = readStringParam4(params, "supersedes");
|
|
630
|
-
const claimKey = readStringParam4(params, "claimKey");
|
|
778
|
+
const claimKey = readStringParam4(params, "claimKey", { trim: false });
|
|
631
779
|
const validFrom = readStringParam4(params, "validFrom");
|
|
632
780
|
const validTo = readStringParam4(params, "validTo");
|
|
781
|
+
const claimSupportObservedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
633
782
|
logToolCall(
|
|
634
783
|
logger,
|
|
635
784
|
"agenr_store",
|
|
@@ -660,7 +809,11 @@ function createAgenrStoreTool(ctx, servicesPromise, logger) {
|
|
|
660
809
|
...expiry !== void 0 ? { expiry } : {},
|
|
661
810
|
...tags.length > 0 ? { tags } : {},
|
|
662
811
|
...supersedes ? { supersedes } : {},
|
|
663
|
-
...claimKey ? {
|
|
812
|
+
...claimKey ? {
|
|
813
|
+
claim_key: claimKey,
|
|
814
|
+
claim_key_raw: claimKey,
|
|
815
|
+
...buildToolCallClaimSupport(ctx, "agenr_store", claimSupportObservedAt)
|
|
816
|
+
} : {},
|
|
664
817
|
...validFrom ? { valid_from: validFrom } : {},
|
|
665
818
|
...validTo ? { valid_to: validTo } : {},
|
|
666
819
|
source_file: buildSessionSourceFile(ctx),
|
|
@@ -752,13 +905,14 @@ function createAgenrTraceTool(ctx, servicesPromise, logger) {
|
|
|
752
905
|
entryId: entry.id
|
|
753
906
|
});
|
|
754
907
|
}
|
|
755
|
-
return textResult4(formatTrace(trace.entry, trace.supersededBy, trace.supersedes, trace.recallEvents), {
|
|
908
|
+
return textResult4(formatTrace(trace.entry, trace.supersededBy, trace.supersedes, trace.claimFamily, trace.recallEvents), {
|
|
756
909
|
status: "ok",
|
|
757
910
|
sessionKey: ctx.sessionKey,
|
|
758
911
|
trace: {
|
|
759
912
|
entry: trace.entry,
|
|
760
913
|
supersededBy: trace.supersededBy,
|
|
761
914
|
supersedes: trace.supersedes,
|
|
915
|
+
claimFamily: trace.claimFamily,
|
|
762
916
|
recallEvents: trace.recallEvents
|
|
763
917
|
}
|
|
764
918
|
});
|
|
@@ -819,34 +973,49 @@ function createAgenrUpdateTool(ctx, servicesPromise, logger) {
|
|
|
819
973
|
const subject = readStringParam6(params, "subject");
|
|
820
974
|
const importance = readNumberParam3(params, "importance", { integer: true, strict: true });
|
|
821
975
|
const expiry = parseExpiry(readStringParam6(params, "expiry"));
|
|
822
|
-
const claimKeyInput = readStringParam6(params, "claimKey");
|
|
976
|
+
const claimKeyInput = readStringParam6(params, "claimKey", { trim: false });
|
|
823
977
|
const validFrom = readStringParam6(params, "validFrom");
|
|
824
978
|
const validTo = readStringParam6(params, "validTo");
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
|
|
979
|
+
const claimSupportObservedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
980
|
+
const claimSupport = claimKeyInput === void 0 ? void 0 : buildToolCallClaimSupport(ctx, "agenr_update", claimSupportObservedAt);
|
|
981
|
+
const normalizedClaimKeyUpdate = claimKeyInput === void 0 ? void 0 : (() => {
|
|
982
|
+
try {
|
|
983
|
+
return normalizeManualClaimKeyUpdate({
|
|
984
|
+
claimKey: claimKeyInput,
|
|
985
|
+
rawClaimKey: claimKeyInput,
|
|
986
|
+
supportSourceKind: claimSupport?.claim_support_source_kind,
|
|
987
|
+
supportLocator: claimSupport?.claim_support_locator,
|
|
988
|
+
supportObservedAt: claimSupport?.claim_support_observed_at,
|
|
989
|
+
supportMode: claimSupport?.claim_support_mode
|
|
990
|
+
});
|
|
991
|
+
} catch {
|
|
828
992
|
throw new Error("claimKey must use canonical entity/attribute format.");
|
|
829
993
|
}
|
|
830
|
-
return claimKey.value.claimKey;
|
|
831
994
|
})();
|
|
832
995
|
logToolCall(
|
|
833
996
|
logger,
|
|
834
997
|
"agenr_update",
|
|
835
998
|
ctx,
|
|
836
999
|
`target=${formatTargetSelector(id, subject)}${importance !== void 0 ? ` importance=${importance}` : ""}${expiry !== void 0 ? ` expiry=${expiry}` : ""}`,
|
|
837
|
-
sanitizeUpdateToolParams({ id, subject, importance, expiry, claimKey:
|
|
1000
|
+
sanitizeUpdateToolParams({ id, subject, importance, expiry, claimKey: normalizedClaimKeyUpdate?.claimKey, validFrom, validTo })
|
|
838
1001
|
);
|
|
839
1002
|
const services = await servicesPromise;
|
|
840
1003
|
const entry = await resolveTargetEntry(services, params);
|
|
841
|
-
if (importance === void 0 && expiry === void 0 &&
|
|
1004
|
+
if (importance === void 0 && expiry === void 0 && normalizedClaimKeyUpdate === void 0 && validFrom === void 0 && validTo === void 0) {
|
|
842
1005
|
throw new Error("Provide at least one update field: importance, expiry, claimKey, validFrom, or validTo.");
|
|
843
1006
|
}
|
|
1007
|
+
const mergedValidity = validateTemporalValidityRange(validFrom ?? entry.valid_from, validTo ?? entry.valid_to);
|
|
1008
|
+
if (!mergedValidity.ok) {
|
|
1009
|
+
throw new Error(mergedValidity.message);
|
|
1010
|
+
}
|
|
1011
|
+
const normalizedValidFrom = validFrom !== void 0 ? mergedValidity.value.validFrom : void 0;
|
|
1012
|
+
const normalizedValidTo = validTo !== void 0 ? mergedValidity.value.validTo : void 0;
|
|
844
1013
|
const updated = await services.entries.updateEntry(entry.id, {
|
|
845
1014
|
...importance !== void 0 ? { importance } : {},
|
|
846
1015
|
...expiry !== void 0 ? { expiry } : {},
|
|
847
|
-
...
|
|
848
|
-
...validFrom !== void 0 ? { valid_from:
|
|
849
|
-
...validTo !== void 0 ? { valid_to:
|
|
1016
|
+
...normalizedClaimKeyUpdate?.updateFields ?? {},
|
|
1017
|
+
...validFrom !== void 0 ? { valid_from: normalizedValidFrom } : {},
|
|
1018
|
+
...validTo !== void 0 ? { valid_to: normalizedValidTo } : {}
|
|
850
1019
|
});
|
|
851
1020
|
if (!updated) {
|
|
852
1021
|
return failedTextResult5(`Entry ${entry.id} is not active, so it could not be updated.`, {
|
|
@@ -861,9 +1030,9 @@ function createAgenrUpdateTool(ctx, servicesPromise, logger) {
|
|
|
861
1030
|
sessionKey: ctx.sessionKey,
|
|
862
1031
|
...importance !== void 0 ? { importance } : {},
|
|
863
1032
|
...expiry !== void 0 ? { expiry } : {},
|
|
864
|
-
...
|
|
865
|
-
...validFrom !== void 0 ? { validFrom } : {},
|
|
866
|
-
...validTo !== void 0 ? { validTo } : {}
|
|
1033
|
+
...normalizedClaimKeyUpdate !== void 0 ? { claimKey: normalizedClaimKeyUpdate.claimKey } : {},
|
|
1034
|
+
...validFrom !== void 0 ? { validFrom: normalizedValidFrom } : {},
|
|
1035
|
+
...validTo !== void 0 ? { validTo: normalizedValidTo } : {}
|
|
867
1036
|
});
|
|
868
1037
|
} catch (error) {
|
|
869
1038
|
logToolFailure(logger, "agenr_update", ctx, error);
|
|
@@ -886,17 +1055,11 @@ function registerAgenrOpenClawTools(api, servicesPromise, logger) {
|
|
|
886
1055
|
var openclaw_plugin_default = {
|
|
887
1056
|
id: "agenr",
|
|
888
1057
|
name: "agenr",
|
|
889
|
-
version: "1.
|
|
1058
|
+
version: "1.8.1",
|
|
890
1059
|
description: "agenr memory plugin for OpenClaw",
|
|
891
1060
|
kind: "memory",
|
|
892
1061
|
contracts: {
|
|
893
|
-
tools: [
|
|
894
|
-
"agenr_store",
|
|
895
|
-
"agenr_recall",
|
|
896
|
-
"agenr_retire",
|
|
897
|
-
"agenr_update",
|
|
898
|
-
"agenr_trace"
|
|
899
|
-
]
|
|
1062
|
+
tools: ["agenr_store", "agenr_recall", "agenr_retire", "agenr_update", "agenr_trace"]
|
|
900
1063
|
},
|
|
901
1064
|
uiHints: {
|
|
902
1065
|
dbPath: {
|
|
@@ -922,6 +1085,10 @@ var openclaw_plugin_default = {
|
|
|
922
1085
|
storeNudge: {
|
|
923
1086
|
label: "Store nudge",
|
|
924
1087
|
help: "Optional mid-session reminder settings for prompting durable memory storage after several turns of memory silence."
|
|
1088
|
+
},
|
|
1089
|
+
memoryPolicy: {
|
|
1090
|
+
label: "Memory policy",
|
|
1091
|
+
help: "Optional runtime overrides for claim-aware read behavior such as slot-policy classes."
|
|
925
1092
|
}
|
|
926
1093
|
},
|
|
927
1094
|
configSchema: {
|
|
@@ -971,6 +1138,31 @@ var openclaw_plugin_default = {
|
|
|
971
1138
|
description: "Maximum nudges injected during one session lifetime. Defaults to 5."
|
|
972
1139
|
}
|
|
973
1140
|
}
|
|
1141
|
+
},
|
|
1142
|
+
memoryPolicy: {
|
|
1143
|
+
type: "object",
|
|
1144
|
+
additionalProperties: false,
|
|
1145
|
+
description: "Optional runtime overrides for claim-aware read behavior exposed by the OpenClaw adapter.",
|
|
1146
|
+
properties: {
|
|
1147
|
+
slotPolicies: {
|
|
1148
|
+
type: "object",
|
|
1149
|
+
additionalProperties: false,
|
|
1150
|
+
description: "Claim-slot policy overrides keyed by canonical claim-key attribute head.",
|
|
1151
|
+
properties: {
|
|
1152
|
+
attributeHeads: {
|
|
1153
|
+
type: "object",
|
|
1154
|
+
description: "Map canonical attribute heads such as `integration` or `preference` to `exclusive` or `multivalued` read-time slot behavior.",
|
|
1155
|
+
propertyNames: {
|
|
1156
|
+
pattern: "^[A-Za-z0-9][A-Za-z0-9_-]*$"
|
|
1157
|
+
},
|
|
1158
|
+
additionalProperties: {
|
|
1159
|
+
type: "string",
|
|
1160
|
+
enum: ["exclusive", "multivalued"]
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
974
1166
|
}
|
|
975
1167
|
}
|
|
976
1168
|
}
|
|
@@ -1023,7 +1215,11 @@ function normalizeAgenrOpenClawPluginConfig(value) {
|
|
|
1023
1215
|
if (!storeNudgeResult.ok) {
|
|
1024
1216
|
errors.push(...storeNudgeResult.errors);
|
|
1025
1217
|
}
|
|
1026
|
-
const
|
|
1218
|
+
const memoryPolicyResult = normalizeMemoryPolicyConfig(value.memoryPolicy);
|
|
1219
|
+
if (!memoryPolicyResult.ok) {
|
|
1220
|
+
errors.push(...memoryPolicyResult.errors);
|
|
1221
|
+
}
|
|
1222
|
+
const allowedKeys = /* @__PURE__ */ new Set(["dbPath", "configPath", "continuityModel", "episodeModel", "claimExtractionModel", "storeNudge", "memoryPolicy"]);
|
|
1027
1223
|
for (const key of Object.keys(value)) {
|
|
1028
1224
|
if (!allowedKeys.has(key)) {
|
|
1029
1225
|
errors.push(`unknown config field: ${key}`);
|
|
@@ -1040,7 +1236,8 @@ function normalizeAgenrOpenClawPluginConfig(value) {
|
|
|
1040
1236
|
...continuityModel ? { continuityModel } : {},
|
|
1041
1237
|
...episodeModel ? { episodeModel } : {},
|
|
1042
1238
|
...claimExtractionModel ? { claimExtractionModel } : {},
|
|
1043
|
-
...storeNudgeResult.ok && storeNudgeResult.value ? { storeNudge: storeNudgeResult.value } : {}
|
|
1239
|
+
...storeNudgeResult.ok && storeNudgeResult.value ? { storeNudge: storeNudgeResult.value } : {},
|
|
1240
|
+
...memoryPolicyResult.ok && memoryPolicyResult.value ? { memoryPolicy: memoryPolicyResult.value } : {}
|
|
1044
1241
|
}
|
|
1045
1242
|
};
|
|
1046
1243
|
}
|
|
@@ -1101,6 +1298,80 @@ function normalizeStoreNudgeConfig(value) {
|
|
|
1101
1298
|
value: Object.keys(normalizedValue).length > 0 ? resolveStoreNudgeConfig(normalizedValue) : void 0
|
|
1102
1299
|
};
|
|
1103
1300
|
}
|
|
1301
|
+
function normalizeMemoryPolicyConfig(value) {
|
|
1302
|
+
if (value === void 0) {
|
|
1303
|
+
return { ok: true, value: void 0 };
|
|
1304
|
+
}
|
|
1305
|
+
if (!isRecord(value)) {
|
|
1306
|
+
return { ok: false, errors: ["memoryPolicy must be an object when provided"] };
|
|
1307
|
+
}
|
|
1308
|
+
const errors = [];
|
|
1309
|
+
const slotPoliciesResult = normalizeClaimSlotPolicyConfig(value.slotPolicies);
|
|
1310
|
+
if (!slotPoliciesResult.ok) {
|
|
1311
|
+
errors.push(...slotPoliciesResult.errors);
|
|
1312
|
+
}
|
|
1313
|
+
const allowedKeys = /* @__PURE__ */ new Set(["slotPolicies"]);
|
|
1314
|
+
for (const key of Object.keys(value)) {
|
|
1315
|
+
if (!allowedKeys.has(key)) {
|
|
1316
|
+
errors.push(`unknown config field: memoryPolicy.${key}`);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (errors.length > 0) {
|
|
1320
|
+
return { ok: false, errors };
|
|
1321
|
+
}
|
|
1322
|
+
return {
|
|
1323
|
+
ok: true,
|
|
1324
|
+
value: slotPoliciesResult.ok && slotPoliciesResult.value ? {
|
|
1325
|
+
slotPolicies: slotPoliciesResult.value
|
|
1326
|
+
} : void 0
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
function normalizeClaimSlotPolicyConfig(value) {
|
|
1330
|
+
if (value === void 0) {
|
|
1331
|
+
return { ok: true, value: void 0 };
|
|
1332
|
+
}
|
|
1333
|
+
if (!isRecord(value)) {
|
|
1334
|
+
return { ok: false, errors: ["memoryPolicy.slotPolicies must be an object when provided"] };
|
|
1335
|
+
}
|
|
1336
|
+
const errors = [];
|
|
1337
|
+
const attributeHeads = normalizeClaimSlotPolicyAttributeHeads(value.attributeHeads, errors);
|
|
1338
|
+
const allowedKeys = /* @__PURE__ */ new Set(["attributeHeads"]);
|
|
1339
|
+
for (const key of Object.keys(value)) {
|
|
1340
|
+
if (!allowedKeys.has(key)) {
|
|
1341
|
+
errors.push(`unknown config field: memoryPolicy.slotPolicies.${key}`);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
if (errors.length > 0) {
|
|
1345
|
+
return { ok: false, errors };
|
|
1346
|
+
}
|
|
1347
|
+
return {
|
|
1348
|
+
ok: true,
|
|
1349
|
+
value: attributeHeads ? { attributeHeads } : void 0
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
function normalizeClaimSlotPolicyAttributeHeads(value, errors) {
|
|
1353
|
+
if (value === void 0) {
|
|
1354
|
+
return void 0;
|
|
1355
|
+
}
|
|
1356
|
+
if (!isRecord(value)) {
|
|
1357
|
+
errors.push("memoryPolicy.slotPolicies.attributeHeads must be an object when provided");
|
|
1358
|
+
return void 0;
|
|
1359
|
+
}
|
|
1360
|
+
const normalized = {};
|
|
1361
|
+
for (const [rawKey, rawPolicy] of Object.entries(value)) {
|
|
1362
|
+
const attributeHead = rawKey.trim().toLowerCase();
|
|
1363
|
+
if (!/^[a-z0-9][a-z0-9_-]*$/.test(attributeHead)) {
|
|
1364
|
+
errors.push(`memoryPolicy.slotPolicies.attributeHeads.${rawKey} must use a canonical attribute-head label`);
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
if (rawPolicy !== "exclusive" && rawPolicy !== "multivalued") {
|
|
1368
|
+
errors.push(`memoryPolicy.slotPolicies.attributeHeads.${attributeHead} must be "exclusive" or "multivalued"`);
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1371
|
+
normalized[attributeHead] = rawPolicy;
|
|
1372
|
+
}
|
|
1373
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
1374
|
+
}
|
|
1104
1375
|
function normalizeOptionalBoolean(value, label, errors) {
|
|
1105
1376
|
if (value === void 0) {
|
|
1106
1377
|
return void 0;
|
|
@@ -2868,6 +3139,12 @@ function createAgenrMemoryRuntime(servicesPromise) {
|
|
|
2868
3139
|
};
|
|
2869
3140
|
return {
|
|
2870
3141
|
manager: {
|
|
3142
|
+
async search() {
|
|
3143
|
+
return [];
|
|
3144
|
+
},
|
|
3145
|
+
async readFile({ relPath }) {
|
|
3146
|
+
throw new Error(`[agenr] memory file reads are not supported for "${relPath}"`);
|
|
3147
|
+
},
|
|
2871
3148
|
status() {
|
|
2872
3149
|
return status;
|
|
2873
3150
|
},
|
|
@@ -2896,213 +3173,6 @@ function createAgenrMemoryRuntime(servicesPromise) {
|
|
|
2896
3173
|
};
|
|
2897
3174
|
}
|
|
2898
3175
|
|
|
2899
|
-
// src/adapters/db/openclaw-repository.ts
|
|
2900
|
-
var ZERO_VECTOR = JSON.stringify(Array.from({ length: EMBEDDING_DIMENSIONS }, () => 0));
|
|
2901
|
-
var ENTRY_SELECT_COLUMNS = `
|
|
2902
|
-
id,
|
|
2903
|
-
type,
|
|
2904
|
-
subject,
|
|
2905
|
-
content,
|
|
2906
|
-
importance,
|
|
2907
|
-
expiry,
|
|
2908
|
-
tags,
|
|
2909
|
-
source_file,
|
|
2910
|
-
source_context,
|
|
2911
|
-
embedding,
|
|
2912
|
-
content_hash,
|
|
2913
|
-
norm_content_hash,
|
|
2914
|
-
quality_score,
|
|
2915
|
-
recall_count,
|
|
2916
|
-
last_recalled_at,
|
|
2917
|
-
superseded_by,
|
|
2918
|
-
valid_from,
|
|
2919
|
-
valid_to,
|
|
2920
|
-
claim_key,
|
|
2921
|
-
supersession_kind,
|
|
2922
|
-
supersession_reason,
|
|
2923
|
-
cluster_id,
|
|
2924
|
-
user_id,
|
|
2925
|
-
project,
|
|
2926
|
-
retired,
|
|
2927
|
-
retired_at,
|
|
2928
|
-
retired_reason,
|
|
2929
|
-
created_at,
|
|
2930
|
-
updated_at
|
|
2931
|
-
`;
|
|
2932
|
-
function createOpenClawRepository(executor) {
|
|
2933
|
-
return {
|
|
2934
|
-
listCoreEntries: async (limit) => listCoreEntries(executor, limit),
|
|
2935
|
-
findEntryBySubject: async (subject) => findEntryBySubject(executor, subject),
|
|
2936
|
-
findMostRecentEntry: async () => findMostRecentEntry(executor),
|
|
2937
|
-
getEntryTrace: async (entryId) => getEntryTrace(executor, entryId),
|
|
2938
|
-
getMemoryStatusSnapshot: async () => getMemoryStatusSnapshot(executor),
|
|
2939
|
-
probeVectorAvailability: async () => probeVectorAvailability(executor)
|
|
2940
|
-
};
|
|
2941
|
-
}
|
|
2942
|
-
async function listCoreEntries(executor, limit) {
|
|
2943
|
-
if (limit <= 0) {
|
|
2944
|
-
return [];
|
|
2945
|
-
}
|
|
2946
|
-
const result = await executor.execute({
|
|
2947
|
-
sql: `
|
|
2948
|
-
SELECT
|
|
2949
|
-
${ENTRY_SELECT_COLUMNS}
|
|
2950
|
-
FROM entries
|
|
2951
|
-
WHERE ${buildActiveEntryClause()}
|
|
2952
|
-
AND expiry = 'core'
|
|
2953
|
-
ORDER BY importance DESC, created_at DESC
|
|
2954
|
-
LIMIT ?
|
|
2955
|
-
`,
|
|
2956
|
-
args: [limit]
|
|
2957
|
-
});
|
|
2958
|
-
return result.rows.map((row) => mapEntryRow(row));
|
|
2959
|
-
}
|
|
2960
|
-
async function findEntryBySubject(executor, subject) {
|
|
2961
|
-
const normalizedSubject = subject.trim();
|
|
2962
|
-
if (normalizedSubject.length === 0) {
|
|
2963
|
-
return null;
|
|
2964
|
-
}
|
|
2965
|
-
const result = await executor.execute({
|
|
2966
|
-
sql: `
|
|
2967
|
-
SELECT
|
|
2968
|
-
${ENTRY_SELECT_COLUMNS},
|
|
2969
|
-
CASE
|
|
2970
|
-
WHEN lower(subject) = lower(?) THEN 0
|
|
2971
|
-
WHEN lower(subject) LIKE lower(?) THEN 1
|
|
2972
|
-
ELSE 2
|
|
2973
|
-
END AS match_rank
|
|
2974
|
-
FROM entries
|
|
2975
|
-
WHERE lower(subject) = lower(?)
|
|
2976
|
-
OR lower(subject) LIKE lower(?)
|
|
2977
|
-
ORDER BY match_rank ASC, created_at DESC
|
|
2978
|
-
LIMIT 1
|
|
2979
|
-
`,
|
|
2980
|
-
args: [normalizedSubject, `%${normalizedSubject}%`, normalizedSubject, `%${normalizedSubject}%`]
|
|
2981
|
-
});
|
|
2982
|
-
const row = result.rows[0];
|
|
2983
|
-
return row ? mapEntryRow(row) : null;
|
|
2984
|
-
}
|
|
2985
|
-
async function findMostRecentEntry(executor) {
|
|
2986
|
-
const result = await executor.execute({
|
|
2987
|
-
sql: `
|
|
2988
|
-
SELECT
|
|
2989
|
-
${ENTRY_SELECT_COLUMNS}
|
|
2990
|
-
FROM entries
|
|
2991
|
-
ORDER BY created_at DESC
|
|
2992
|
-
LIMIT 1
|
|
2993
|
-
`
|
|
2994
|
-
});
|
|
2995
|
-
const row = result.rows[0];
|
|
2996
|
-
return row ? mapEntryRow(row) : null;
|
|
2997
|
-
}
|
|
2998
|
-
async function getEntryTrace(executor, entryId) {
|
|
2999
|
-
const entry = await getEntryByIdIncludingInactive(executor, entryId);
|
|
3000
|
-
if (!entry) {
|
|
3001
|
-
return null;
|
|
3002
|
-
}
|
|
3003
|
-
const [supersededBy, supersedes, recallEvents] = await Promise.all([
|
|
3004
|
-
entry.superseded_by ? getEntryByIdIncludingInactive(executor, entry.superseded_by) : Promise.resolve(null),
|
|
3005
|
-
listSupersededEntries(executor, entry.id),
|
|
3006
|
-
listRecallEvents(executor, entry.id)
|
|
3007
|
-
]);
|
|
3008
|
-
return {
|
|
3009
|
-
entry,
|
|
3010
|
-
...supersededBy ? { supersededBy } : {},
|
|
3011
|
-
supersedes,
|
|
3012
|
-
recallEvents
|
|
3013
|
-
};
|
|
3014
|
-
}
|
|
3015
|
-
async function getMemoryStatusSnapshot(executor) {
|
|
3016
|
-
const result = await executor.execute({
|
|
3017
|
-
sql: `
|
|
3018
|
-
SELECT
|
|
3019
|
-
COUNT(*) AS active_entries,
|
|
3020
|
-
SUM(CASE WHEN expiry = 'core' THEN 1 ELSE 0 END) AS core_entries,
|
|
3021
|
-
COUNT(DISTINCT source_file) AS source_files
|
|
3022
|
-
FROM entries
|
|
3023
|
-
WHERE ${buildActiveEntryClause()}
|
|
3024
|
-
`
|
|
3025
|
-
});
|
|
3026
|
-
const row = result.rows[0];
|
|
3027
|
-
if (!row) {
|
|
3028
|
-
return {
|
|
3029
|
-
activeEntries: 0,
|
|
3030
|
-
coreEntries: 0,
|
|
3031
|
-
sourceFiles: 0
|
|
3032
|
-
};
|
|
3033
|
-
}
|
|
3034
|
-
return {
|
|
3035
|
-
activeEntries: readNumber(row, "active_entries", 0),
|
|
3036
|
-
coreEntries: readNumber(row, "core_entries", 0),
|
|
3037
|
-
sourceFiles: readNumber(row, "source_files", 0)
|
|
3038
|
-
};
|
|
3039
|
-
}
|
|
3040
|
-
async function probeVectorAvailability(executor) {
|
|
3041
|
-
try {
|
|
3042
|
-
await executor.execute({
|
|
3043
|
-
sql: `
|
|
3044
|
-
SELECT COUNT(*) AS matches
|
|
3045
|
-
FROM vector_top_k('${VECTOR_INDEX_NAME}', vector32(?), ?) AS matches
|
|
3046
|
-
`,
|
|
3047
|
-
args: [ZERO_VECTOR, 1]
|
|
3048
|
-
});
|
|
3049
|
-
return true;
|
|
3050
|
-
} catch {
|
|
3051
|
-
return false;
|
|
3052
|
-
}
|
|
3053
|
-
}
|
|
3054
|
-
async function getEntryByIdIncludingInactive(executor, entryId) {
|
|
3055
|
-
const normalizedId = entryId.trim();
|
|
3056
|
-
if (normalizedId.length === 0) {
|
|
3057
|
-
return null;
|
|
3058
|
-
}
|
|
3059
|
-
const result = await executor.execute({
|
|
3060
|
-
sql: `
|
|
3061
|
-
SELECT
|
|
3062
|
-
${ENTRY_SELECT_COLUMNS}
|
|
3063
|
-
FROM entries
|
|
3064
|
-
WHERE id = ?
|
|
3065
|
-
LIMIT 1
|
|
3066
|
-
`,
|
|
3067
|
-
args: [normalizedId]
|
|
3068
|
-
});
|
|
3069
|
-
const row = result.rows[0];
|
|
3070
|
-
return row ? mapEntryRow(row) : null;
|
|
3071
|
-
}
|
|
3072
|
-
async function listSupersededEntries(executor, entryId) {
|
|
3073
|
-
const result = await executor.execute({
|
|
3074
|
-
sql: `
|
|
3075
|
-
SELECT
|
|
3076
|
-
${ENTRY_SELECT_COLUMNS}
|
|
3077
|
-
FROM entries
|
|
3078
|
-
WHERE superseded_by = ?
|
|
3079
|
-
ORDER BY created_at DESC
|
|
3080
|
-
`,
|
|
3081
|
-
args: [entryId]
|
|
3082
|
-
});
|
|
3083
|
-
return result.rows.map((row) => mapEntryRow(row));
|
|
3084
|
-
}
|
|
3085
|
-
async function listRecallEvents(executor, entryId) {
|
|
3086
|
-
const result = await executor.execute({
|
|
3087
|
-
sql: `
|
|
3088
|
-
SELECT
|
|
3089
|
-
query,
|
|
3090
|
-
session_key,
|
|
3091
|
-
recalled_at
|
|
3092
|
-
FROM recall_events
|
|
3093
|
-
WHERE entry_id = ?
|
|
3094
|
-
ORDER BY recalled_at DESC
|
|
3095
|
-
LIMIT 10
|
|
3096
|
-
`,
|
|
3097
|
-
args: [entryId]
|
|
3098
|
-
});
|
|
3099
|
-
return result.rows.map((row) => ({
|
|
3100
|
-
query: readOptionalString(row, "query"),
|
|
3101
|
-
sessionKey: readOptionalString(row, "session_key"),
|
|
3102
|
-
recalledAt: readRequiredString(row, "recalled_at")
|
|
3103
|
-
}));
|
|
3104
|
-
}
|
|
3105
|
-
|
|
3106
3176
|
// src/app/openclaw/runtime.ts
|
|
3107
3177
|
async function createAgenrOpenClawServices(config, options) {
|
|
3108
3178
|
const { resolvedConfig, agenrConfig: loadedAgenrConfig } = resolveRuntimeConfig(config, options.resolvePath);
|
|
@@ -3159,7 +3229,9 @@ async function createRuntimeServices(dbPath, config, embeddingStatus, openClawCo
|
|
|
3159
3229
|
return {
|
|
3160
3230
|
entries: database,
|
|
3161
3231
|
episodes: database,
|
|
3162
|
-
memory: createOpenClawRepository(database
|
|
3232
|
+
memory: createOpenClawRepository(database, {
|
|
3233
|
+
claimSlotPolicyConfig: openClawContext.pluginConfig.memoryPolicy?.slotPolicies
|
|
3234
|
+
}),
|
|
3163
3235
|
embedding,
|
|
3164
3236
|
recall: createRecallAdapter(database, embedding),
|
|
3165
3237
|
claimExtraction,
|
|
@@ -3244,7 +3316,6 @@ var openclaw_default = definePluginEntry({
|
|
|
3244
3316
|
kind: "memory",
|
|
3245
3317
|
configSchema: createAgenrOpenClawPluginConfigSchema(),
|
|
3246
3318
|
register(api) {
|
|
3247
|
-
const memoryApi = api;
|
|
3248
3319
|
const sessionStartTracker = createSessionStartTracker();
|
|
3249
3320
|
const midSessionTracker = createMidSessionTracker();
|
|
3250
3321
|
const pluginConfig = coerceAgenrOpenClawPluginConfig(api.pluginConfig);
|
|
@@ -3260,9 +3331,11 @@ var openclaw_default = definePluginEntry({
|
|
|
3260
3331
|
},
|
|
3261
3332
|
resolvePath: api.resolvePath
|
|
3262
3333
|
});
|
|
3263
|
-
api.
|
|
3264
|
-
|
|
3265
|
-
|
|
3334
|
+
api.registerMemoryCapability({
|
|
3335
|
+
promptBuilder: buildAgenrMemoryPromptSection,
|
|
3336
|
+
flushPlanResolver: (params) => buildAgenrMemoryFlushPlan(params, api.logger),
|
|
3337
|
+
runtime: createAgenrMemoryRuntime(servicesPromise)
|
|
3338
|
+
});
|
|
3266
3339
|
registerAgenrOpenClawTools(api, servicesPromise, api.logger);
|
|
3267
3340
|
api.on(
|
|
3268
3341
|
"before_prompt_build",
|