@joshuaswarren/openclaw-engram 8.3.82 → 8.3.84
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/index.js +395 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3655,6 +3655,9 @@ function scoreImportance(content, category, tags = []) {
|
|
|
3655
3655
|
keywords
|
|
3656
3656
|
};
|
|
3657
3657
|
}
|
|
3658
|
+
function rescoreMemoryImportance(memory) {
|
|
3659
|
+
return scoreImportance(memory.content, memory.frontmatter.category, memory.frontmatter.tags ?? []);
|
|
3660
|
+
}
|
|
3658
3661
|
|
|
3659
3662
|
// src/qmd.ts
|
|
3660
3663
|
import { spawn } from "child_process";
|
|
@@ -6039,6 +6042,46 @@ ${memory.content}
|
|
|
6039
6042
|
await appendFile(this.behaviorSignalsPath, payload, "utf-8");
|
|
6040
6043
|
return deduped.length;
|
|
6041
6044
|
}
|
|
6045
|
+
async appendReextractJobs(events) {
|
|
6046
|
+
if (events.length === 0) return 0;
|
|
6047
|
+
await this.ensureDirectories();
|
|
6048
|
+
const filePath = path4.join(this.stateDir, "reextract-jobs.jsonl");
|
|
6049
|
+
const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
|
|
6050
|
+
try {
|
|
6051
|
+
await appendFile(filePath, lines, "utf-8");
|
|
6052
|
+
return events.length;
|
|
6053
|
+
} catch {
|
|
6054
|
+
return 0;
|
|
6055
|
+
}
|
|
6056
|
+
}
|
|
6057
|
+
async readReextractJobs(limit = 200) {
|
|
6058
|
+
const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
|
|
6059
|
+
const filePath = path4.join(this.stateDir, "reextract-jobs.jsonl");
|
|
6060
|
+
try {
|
|
6061
|
+
const raw = await readFile2(filePath, "utf-8");
|
|
6062
|
+
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
6063
|
+
const parsed = [];
|
|
6064
|
+
for (const line of lines) {
|
|
6065
|
+
try {
|
|
6066
|
+
const record = JSON.parse(line);
|
|
6067
|
+
if (typeof record.memoryId !== "string" || record.memoryId.length === 0 || typeof record.model !== "string" || record.model.length === 0 || typeof record.requestedAt !== "string" || record.requestedAt.length === 0 || record.source !== "cli-migrate") {
|
|
6068
|
+
continue;
|
|
6069
|
+
}
|
|
6070
|
+
parsed.push({
|
|
6071
|
+
memoryId: record.memoryId,
|
|
6072
|
+
model: record.model,
|
|
6073
|
+
requestedAt: record.requestedAt,
|
|
6074
|
+
source: "cli-migrate"
|
|
6075
|
+
});
|
|
6076
|
+
} catch {
|
|
6077
|
+
continue;
|
|
6078
|
+
}
|
|
6079
|
+
}
|
|
6080
|
+
return parsed.slice(-safeLimit);
|
|
6081
|
+
} catch {
|
|
6082
|
+
return [];
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6042
6085
|
async readBehaviorSignals(limit = 200) {
|
|
6043
6086
|
const cappedLimit = Math.max(0, Math.floor(limit));
|
|
6044
6087
|
if (cappedLimit === 0) return [];
|
|
@@ -12108,6 +12151,58 @@ function safeSlug(s) {
|
|
|
12108
12151
|
function ymd(d) {
|
|
12109
12152
|
return d.toISOString().slice(0, 10);
|
|
12110
12153
|
}
|
|
12154
|
+
var CROSS_SIGNAL_STOPWORDS = /* @__PURE__ */ new Set([
|
|
12155
|
+
"a",
|
|
12156
|
+
"an",
|
|
12157
|
+
"and",
|
|
12158
|
+
"are",
|
|
12159
|
+
"as",
|
|
12160
|
+
"at",
|
|
12161
|
+
"be",
|
|
12162
|
+
"by",
|
|
12163
|
+
"for",
|
|
12164
|
+
"from",
|
|
12165
|
+
"has",
|
|
12166
|
+
"have",
|
|
12167
|
+
"in",
|
|
12168
|
+
"is",
|
|
12169
|
+
"it",
|
|
12170
|
+
"of",
|
|
12171
|
+
"on",
|
|
12172
|
+
"or",
|
|
12173
|
+
"that",
|
|
12174
|
+
"the",
|
|
12175
|
+
"this",
|
|
12176
|
+
"to",
|
|
12177
|
+
"was",
|
|
12178
|
+
"were",
|
|
12179
|
+
"with",
|
|
12180
|
+
"agent",
|
|
12181
|
+
"output",
|
|
12182
|
+
"today",
|
|
12183
|
+
"daily",
|
|
12184
|
+
"notes",
|
|
12185
|
+
"note",
|
|
12186
|
+
"summary"
|
|
12187
|
+
]);
|
|
12188
|
+
function extractTopicTokens(text, maxTokens = 12) {
|
|
12189
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12190
|
+
const out = [];
|
|
12191
|
+
const tokens = text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).map((token) => token.trim()).filter((token) => token.length >= 4).filter((token) => !CROSS_SIGNAL_STOPWORDS.has(token));
|
|
12192
|
+
for (const token of tokens) {
|
|
12193
|
+
if (seen.has(token)) continue;
|
|
12194
|
+
seen.add(token);
|
|
12195
|
+
out.push(token);
|
|
12196
|
+
if (out.length >= maxTokens) break;
|
|
12197
|
+
}
|
|
12198
|
+
return out;
|
|
12199
|
+
}
|
|
12200
|
+
function stripYamlFrontmatter(text) {
|
|
12201
|
+
if (!text.startsWith("---\n")) return text;
|
|
12202
|
+
const closing = text.indexOf("\n---\n", 4);
|
|
12203
|
+
if (closing === -1) return text;
|
|
12204
|
+
return text.slice(closing + 5);
|
|
12205
|
+
}
|
|
12111
12206
|
var SharedContextManager = class {
|
|
12112
12207
|
constructor(config) {
|
|
12113
12208
|
this.config = config;
|
|
@@ -12238,7 +12333,7 @@ title: ${opts.title.replace(/\n/g, " ").slice(0, 200)}
|
|
|
12238
12333
|
const p = path22.join(dayDir, f);
|
|
12239
12334
|
const raw = await readFile15(p, "utf-8");
|
|
12240
12335
|
const title = (raw.match(/^title:\s*(.+)$/m)?.[1] ?? f).trim();
|
|
12241
|
-
outputs.push({ path: p, title });
|
|
12336
|
+
outputs.push({ agent: a.name, path: p, title, raw });
|
|
12242
12337
|
}
|
|
12243
12338
|
} catch {
|
|
12244
12339
|
}
|
|
@@ -12260,25 +12355,86 @@ title: ${opts.title.replace(/\n/g, " ").slice(0, 200)}
|
|
|
12260
12355
|
}
|
|
12261
12356
|
} catch {
|
|
12262
12357
|
}
|
|
12358
|
+
const sources = outputs.map((output) => {
|
|
12359
|
+
const body = stripYamlFrontmatter(output.raw);
|
|
12360
|
+
return {
|
|
12361
|
+
agent: output.agent,
|
|
12362
|
+
path: output.path,
|
|
12363
|
+
title: output.title,
|
|
12364
|
+
topics: extractTopicTokens(`${output.title}
|
|
12365
|
+
${body}`)
|
|
12366
|
+
};
|
|
12367
|
+
});
|
|
12368
|
+
const overlapMap = /* @__PURE__ */ new Map();
|
|
12369
|
+
for (const source of sources) {
|
|
12370
|
+
for (const token of source.topics) {
|
|
12371
|
+
const existing = overlapMap.get(token);
|
|
12372
|
+
if (existing) {
|
|
12373
|
+
existing.agents.add(source.agent);
|
|
12374
|
+
existing.sourcePaths.add(source.path);
|
|
12375
|
+
} else {
|
|
12376
|
+
overlapMap.set(token, {
|
|
12377
|
+
agents: /* @__PURE__ */ new Set([source.agent]),
|
|
12378
|
+
sourcePaths: /* @__PURE__ */ new Set([source.path])
|
|
12379
|
+
});
|
|
12380
|
+
}
|
|
12381
|
+
}
|
|
12382
|
+
}
|
|
12383
|
+
const overlaps = [...overlapMap.entries()].map(([token, v]) => ({
|
|
12384
|
+
token,
|
|
12385
|
+
agents: [...v.agents].sort(),
|
|
12386
|
+
sourcePaths: [...v.sourcePaths].sort(),
|
|
12387
|
+
agentCount: v.agents.size
|
|
12388
|
+
})).filter((entry) => entry.agentCount >= 2).sort((a, b) => b.agentCount - a.agentCount || a.token.localeCompare(b.token));
|
|
12389
|
+
const feedbackByDecision = {
|
|
12390
|
+
approved: 0,
|
|
12391
|
+
approved_with_feedback: 0,
|
|
12392
|
+
rejected: 0
|
|
12393
|
+
};
|
|
12394
|
+
for (const entry of feedback) {
|
|
12395
|
+
feedbackByDecision[entry.decision] += 1;
|
|
12396
|
+
}
|
|
12397
|
+
const crossSignalReport = {
|
|
12398
|
+
date,
|
|
12399
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12400
|
+
sourceCount: sources.length,
|
|
12401
|
+
feedbackCount: feedback.length,
|
|
12402
|
+
feedbackByDecision,
|
|
12403
|
+
sources,
|
|
12404
|
+
overlaps
|
|
12405
|
+
};
|
|
12406
|
+
const crossSignalsPath = path22.join(this.crossSignalsDir, `${date}.json`);
|
|
12407
|
+
await writeFile14(crossSignalsPath, `${JSON.stringify(crossSignalReport, null, 2)}
|
|
12408
|
+
`, "utf-8");
|
|
12409
|
+
const overlapBullets = overlaps.length === 0 ? ["- No multi-agent topic overlap detected."] : overlaps.slice(0, 8).map((entry) => `- \`${entry.token}\` (${entry.agentCount} agents: ${entry.agents.join(", ")})`);
|
|
12263
12410
|
const md = [
|
|
12264
12411
|
`# Roundtable \u2014 ${date}`,
|
|
12265
12412
|
"",
|
|
12266
12413
|
"## Notable Agent Outputs",
|
|
12267
|
-
...
|
|
12414
|
+
...sources.length === 0 ? ["- (none)"] : sources.map((o) => `- ${o.title} (${o.path})`),
|
|
12268
12415
|
"",
|
|
12269
12416
|
"## Feedback (Approve/Reject)",
|
|
12270
12417
|
...feedback.length === 0 ? ["- (none)"] : feedback.map((f) => `- [${f.agent}] ${f.decision}: ${f.reason}`),
|
|
12271
12418
|
"",
|
|
12272
12419
|
"## Cross-Signals",
|
|
12273
|
-
|
|
12420
|
+
`- Source outputs analyzed: ${sources.length}`,
|
|
12421
|
+
`- Feedback entries analyzed: ${feedback.length}`,
|
|
12422
|
+
`- Decision totals: approved=${feedbackByDecision.approved}, approved_with_feedback=${feedbackByDecision.approved_with_feedback}, rejected=${feedbackByDecision.rejected}`,
|
|
12423
|
+
`- Cross-signals file: ${crossSignalsPath}`,
|
|
12424
|
+
...overlapBullets,
|
|
12274
12425
|
""
|
|
12275
12426
|
];
|
|
12276
12427
|
const out = md.join("\n");
|
|
12277
12428
|
const trimmed = out.length > maxChars ? out.slice(0, maxChars) + "\n\n...(trimmed)\n" : out;
|
|
12278
|
-
const
|
|
12279
|
-
await writeFile14(
|
|
12280
|
-
log.info(`shared-context curated daily roundtable: ${
|
|
12281
|
-
return
|
|
12429
|
+
const roundtablePath = path22.join(this.roundtableDir, `${date}.md`);
|
|
12430
|
+
await writeFile14(roundtablePath, trimmed, "utf-8");
|
|
12431
|
+
log.info(`shared-context curated daily roundtable: ${roundtablePath}`);
|
|
12432
|
+
return {
|
|
12433
|
+
date,
|
|
12434
|
+
roundtablePath,
|
|
12435
|
+
crossSignalsPath,
|
|
12436
|
+
overlapCount: overlaps.length
|
|
12437
|
+
};
|
|
12282
12438
|
}
|
|
12283
12439
|
};
|
|
12284
12440
|
|
|
@@ -19790,8 +19946,14 @@ Best for:
|
|
|
19790
19946
|
);
|
|
19791
19947
|
}
|
|
19792
19948
|
const { date } = params;
|
|
19793
|
-
const
|
|
19794
|
-
return toolResult(
|
|
19949
|
+
const result = await orchestrator.sharedContext.curateDaily({ date });
|
|
19950
|
+
return toolResult(
|
|
19951
|
+
[
|
|
19952
|
+
`Roundtable: ${result.roundtablePath}`,
|
|
19953
|
+
`Cross-signals: ${result.crossSignalsPath}`,
|
|
19954
|
+
`Overlap count: ${result.overlapCount}`
|
|
19955
|
+
].join("\n")
|
|
19956
|
+
);
|
|
19795
19957
|
}
|
|
19796
19958
|
},
|
|
19797
19959
|
{ name: "shared_context_curate_daily" }
|
|
@@ -22122,6 +22284,187 @@ async function runTierMigrateCliCommand(orchestrator, options = {}) {
|
|
|
22122
22284
|
limit: options.limit
|
|
22123
22285
|
});
|
|
22124
22286
|
}
|
|
22287
|
+
var MIGRATE_LIMIT_CAP = 2e3;
|
|
22288
|
+
var REEXTRACT_LIMIT_CAP = 500;
|
|
22289
|
+
function clampMigrateLimit(limit, cap, fallback) {
|
|
22290
|
+
if (typeof limit !== "number" || !Number.isFinite(limit)) return fallback;
|
|
22291
|
+
return Math.max(1, Math.min(cap, Math.floor(limit)));
|
|
22292
|
+
}
|
|
22293
|
+
async function readMigrateCandidateMemories(storage, options) {
|
|
22294
|
+
const merged = /* @__PURE__ */ new Map();
|
|
22295
|
+
const addMany = (items) => {
|
|
22296
|
+
for (const item of items) {
|
|
22297
|
+
if (!item.frontmatter?.id) continue;
|
|
22298
|
+
merged.set(item.path, item);
|
|
22299
|
+
}
|
|
22300
|
+
};
|
|
22301
|
+
addMany(await storage.readAllMemories());
|
|
22302
|
+
if (options.includeArchived) {
|
|
22303
|
+
addMany(await storage.readArchivedMemories());
|
|
22304
|
+
}
|
|
22305
|
+
return [...merged.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
22306
|
+
}
|
|
22307
|
+
function sameImportance(a, b) {
|
|
22308
|
+
if (!a && !b) return true;
|
|
22309
|
+
if (!a || !b) return false;
|
|
22310
|
+
if (Math.abs(a.score - b.score) > 1e-6) return false;
|
|
22311
|
+
if (a.level !== b.level) return false;
|
|
22312
|
+
if (a.reasons.join("|") !== b.reasons.join("|")) return false;
|
|
22313
|
+
if (a.keywords.join("|") !== b.keywords.join("|")) return false;
|
|
22314
|
+
return true;
|
|
22315
|
+
}
|
|
22316
|
+
function sameChunkContent(existing, desired) {
|
|
22317
|
+
if (existing.length !== desired.length) return false;
|
|
22318
|
+
for (let i = 0; i < desired.length; i += 1) {
|
|
22319
|
+
const current = existing[i]?.content?.trim() ?? "";
|
|
22320
|
+
if (current !== desired[i]?.trim()) {
|
|
22321
|
+
return false;
|
|
22322
|
+
}
|
|
22323
|
+
}
|
|
22324
|
+
return true;
|
|
22325
|
+
}
|
|
22326
|
+
async function runMigrateNormalizeFrontmatterCliCommand(orchestrator, options = {}) {
|
|
22327
|
+
const limit = clampMigrateLimit(options.limit, MIGRATE_LIMIT_CAP, 200);
|
|
22328
|
+
const storage = await orchestrator.getStorage(orchestrator.config.defaultNamespace);
|
|
22329
|
+
const candidates = (await readMigrateCandidateMemories(storage, { includeArchived: true })).slice(0, limit);
|
|
22330
|
+
if (options.write === true) {
|
|
22331
|
+
for (const memory of candidates) {
|
|
22332
|
+
await storage.writeMemoryFrontmatter(memory, {});
|
|
22333
|
+
}
|
|
22334
|
+
}
|
|
22335
|
+
return {
|
|
22336
|
+
action: "normalize-frontmatter",
|
|
22337
|
+
dryRun: options.write !== true,
|
|
22338
|
+
scanned: candidates.length,
|
|
22339
|
+
changed: candidates.length,
|
|
22340
|
+
queued: 0,
|
|
22341
|
+
limit
|
|
22342
|
+
};
|
|
22343
|
+
}
|
|
22344
|
+
async function runMigrateRescoreImportanceCliCommand(orchestrator, options = {}) {
|
|
22345
|
+
const limit = clampMigrateLimit(options.limit, MIGRATE_LIMIT_CAP, 200);
|
|
22346
|
+
const storage = await orchestrator.getStorage(orchestrator.config.defaultNamespace);
|
|
22347
|
+
const candidates = (await readMigrateCandidateMemories(storage, { includeArchived: true })).slice(0, limit);
|
|
22348
|
+
let changed = 0;
|
|
22349
|
+
for (const memory of candidates) {
|
|
22350
|
+
const nextImportance = rescoreMemoryImportance(memory);
|
|
22351
|
+
if (sameImportance(memory.frontmatter.importance, nextImportance)) continue;
|
|
22352
|
+
changed += 1;
|
|
22353
|
+
if (options.write === true) {
|
|
22354
|
+
await storage.writeMemoryFrontmatter(memory, {
|
|
22355
|
+
importance: nextImportance,
|
|
22356
|
+
updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
22357
|
+
});
|
|
22358
|
+
}
|
|
22359
|
+
}
|
|
22360
|
+
return {
|
|
22361
|
+
action: "rescore-importance",
|
|
22362
|
+
dryRun: options.write !== true,
|
|
22363
|
+
scanned: candidates.length,
|
|
22364
|
+
changed,
|
|
22365
|
+
queued: 0,
|
|
22366
|
+
limit
|
|
22367
|
+
};
|
|
22368
|
+
}
|
|
22369
|
+
async function runMigrateRechunkCliCommand(orchestrator, options = {}) {
|
|
22370
|
+
const limit = clampMigrateLimit(options.limit, MIGRATE_LIMIT_CAP, 200);
|
|
22371
|
+
const storage = await orchestrator.getStorage(orchestrator.config.defaultNamespace);
|
|
22372
|
+
const candidates = (await readMigrateCandidateMemories(storage, { includeArchived: false })).filter((memory) => memory.frontmatter.parentId === void 0).slice(0, limit);
|
|
22373
|
+
let changed = 0;
|
|
22374
|
+
for (const memory of candidates) {
|
|
22375
|
+
const existing = await storage.getChunksForParent(memory.frontmatter.id);
|
|
22376
|
+
const chunked = chunkContent(memory.content);
|
|
22377
|
+
if (!chunked.chunked) {
|
|
22378
|
+
if (existing.length === 0) continue;
|
|
22379
|
+
changed += 1;
|
|
22380
|
+
if (options.write === true) {
|
|
22381
|
+
for (const stale of existing) {
|
|
22382
|
+
await storage.invalidateMemory(stale.frontmatter.id);
|
|
22383
|
+
}
|
|
22384
|
+
}
|
|
22385
|
+
continue;
|
|
22386
|
+
}
|
|
22387
|
+
const desired = chunked.chunks.map((chunk) => chunk.content);
|
|
22388
|
+
if (sameChunkContent(existing, desired)) continue;
|
|
22389
|
+
changed += 1;
|
|
22390
|
+
if (options.write !== true) continue;
|
|
22391
|
+
const total = chunked.chunks.length;
|
|
22392
|
+
for (const chunk of chunked.chunks) {
|
|
22393
|
+
const existingChunk = existing[chunk.index];
|
|
22394
|
+
if (existingChunk) {
|
|
22395
|
+
await storage.updateMemory(existingChunk.frontmatter.id, chunk.content);
|
|
22396
|
+
await storage.updateMemoryFrontmatter(existingChunk.frontmatter.id, {
|
|
22397
|
+
chunkIndex: chunk.index,
|
|
22398
|
+
chunkTotal: total,
|
|
22399
|
+
updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
22400
|
+
});
|
|
22401
|
+
continue;
|
|
22402
|
+
}
|
|
22403
|
+
await storage.writeChunk(
|
|
22404
|
+
memory.frontmatter.id,
|
|
22405
|
+
chunk.index,
|
|
22406
|
+
total,
|
|
22407
|
+
memory.frontmatter.category,
|
|
22408
|
+
chunk.content,
|
|
22409
|
+
{
|
|
22410
|
+
confidence: memory.frontmatter.confidence,
|
|
22411
|
+
tags: memory.frontmatter.tags,
|
|
22412
|
+
entityRef: memory.frontmatter.entityRef,
|
|
22413
|
+
source: "migration-rechunk",
|
|
22414
|
+
importance: memory.frontmatter.importance,
|
|
22415
|
+
intentGoal: memory.frontmatter.intentGoal,
|
|
22416
|
+
intentActionType: memory.frontmatter.intentActionType,
|
|
22417
|
+
intentEntityTypes: memory.frontmatter.intentEntityTypes,
|
|
22418
|
+
memoryKind: memory.frontmatter.memoryKind
|
|
22419
|
+
}
|
|
22420
|
+
);
|
|
22421
|
+
}
|
|
22422
|
+
for (let idx = total; idx < existing.length; idx += 1) {
|
|
22423
|
+
const stale = existing[idx];
|
|
22424
|
+
if (stale?.frontmatter?.id) {
|
|
22425
|
+
await storage.invalidateMemory(stale.frontmatter.id);
|
|
22426
|
+
}
|
|
22427
|
+
}
|
|
22428
|
+
}
|
|
22429
|
+
return {
|
|
22430
|
+
action: "rechunk",
|
|
22431
|
+
dryRun: options.write !== true,
|
|
22432
|
+
scanned: candidates.length,
|
|
22433
|
+
changed,
|
|
22434
|
+
queued: 0,
|
|
22435
|
+
limit
|
|
22436
|
+
};
|
|
22437
|
+
}
|
|
22438
|
+
async function runMigrateReextractCliCommand(orchestrator, options) {
|
|
22439
|
+
const model = options.model.trim();
|
|
22440
|
+
if (model.length === 0) {
|
|
22441
|
+
throw new Error("missing --model for migrate reextract");
|
|
22442
|
+
}
|
|
22443
|
+
const limit = clampMigrateLimit(options.limit, REEXTRACT_LIMIT_CAP, 100);
|
|
22444
|
+
const storage = await orchestrator.getStorage(orchestrator.config.defaultNamespace);
|
|
22445
|
+
const candidates = (await readMigrateCandidateMemories(storage, { includeArchived: false })).filter((memory) => memory.frontmatter.parentId === void 0);
|
|
22446
|
+
const selected = candidates.slice(0, limit);
|
|
22447
|
+
let queued = 0;
|
|
22448
|
+
if (options.write === true && selected.length > 0) {
|
|
22449
|
+
queued = await storage.appendReextractJobs(
|
|
22450
|
+
selected.map((memory) => ({
|
|
22451
|
+
memoryId: memory.frontmatter.id,
|
|
22452
|
+
model,
|
|
22453
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22454
|
+
source: "cli-migrate"
|
|
22455
|
+
}))
|
|
22456
|
+
);
|
|
22457
|
+
}
|
|
22458
|
+
return {
|
|
22459
|
+
action: "reextract",
|
|
22460
|
+
dryRun: options.write !== true,
|
|
22461
|
+
scanned: selected.length,
|
|
22462
|
+
changed: selected.length,
|
|
22463
|
+
queued,
|
|
22464
|
+
limit,
|
|
22465
|
+
model
|
|
22466
|
+
};
|
|
22467
|
+
}
|
|
22125
22468
|
function effectivePolicyValuesForVersion(values, config) {
|
|
22126
22469
|
const candidate = {
|
|
22127
22470
|
recencyWeight: values.recencyWeight ?? config.recencyWeight,
|
|
@@ -23023,6 +23366,49 @@ function registerCli(api, orchestrator) {
|
|
|
23023
23366
|
console.log(JSON.stringify(report, null, 2));
|
|
23024
23367
|
console.log("OK");
|
|
23025
23368
|
});
|
|
23369
|
+
const migrateCmd = cmd.command("migrate").description("Run memory migration helpers (dry-run by default)");
|
|
23370
|
+
migrateCmd.command("normalize-frontmatter").description("Normalize memory frontmatter serialization").option("--write", "Apply frontmatter rewrites (default: dry-run)").option("--limit <n>", "Maximum memories to scan", "200").action(async (...args) => {
|
|
23371
|
+
const options = args[0] ?? {};
|
|
23372
|
+
const limitRaw = parseInt(String(options.limit ?? "200"), 10);
|
|
23373
|
+
const report = await runMigrateNormalizeFrontmatterCliCommand(orchestrator, {
|
|
23374
|
+
write: options.write === true,
|
|
23375
|
+
limit: Number.isFinite(limitRaw) ? limitRaw : 200
|
|
23376
|
+
});
|
|
23377
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23378
|
+
console.log("OK");
|
|
23379
|
+
});
|
|
23380
|
+
migrateCmd.command("rescore-importance").description("Recompute memory importance scores using current local heuristics").option("--write", "Apply frontmatter updates (default: dry-run)").option("--limit <n>", "Maximum memories to scan", "200").action(async (...args) => {
|
|
23381
|
+
const options = args[0] ?? {};
|
|
23382
|
+
const limitRaw = parseInt(String(options.limit ?? "200"), 10);
|
|
23383
|
+
const report = await runMigrateRescoreImportanceCliCommand(orchestrator, {
|
|
23384
|
+
write: options.write === true,
|
|
23385
|
+
limit: Number.isFinite(limitRaw) ? limitRaw : 200
|
|
23386
|
+
});
|
|
23387
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23388
|
+
console.log("OK");
|
|
23389
|
+
});
|
|
23390
|
+
migrateCmd.command("rechunk").description("Rebuild chunk files from current chunking heuristics").option("--write", "Apply chunk rewrites (default: dry-run)").option("--limit <n>", "Maximum parent memories to scan", "200").action(async (...args) => {
|
|
23391
|
+
const options = args[0] ?? {};
|
|
23392
|
+
const limitRaw = parseInt(String(options.limit ?? "200"), 10);
|
|
23393
|
+
const report = await runMigrateRechunkCliCommand(orchestrator, {
|
|
23394
|
+
write: options.write === true,
|
|
23395
|
+
limit: Number.isFinite(limitRaw) ? limitRaw : 200
|
|
23396
|
+
});
|
|
23397
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23398
|
+
console.log("OK");
|
|
23399
|
+
});
|
|
23400
|
+
migrateCmd.command("reextract").description("Queue bounded memory re-extraction jobs for an explicit model").option("--model <id>", "Model id used for re-extraction request").option("--write", "Queue re-extraction jobs (default: dry-run)").option("--limit <n>", "Maximum memories to queue", "100").action(async (...args) => {
|
|
23401
|
+
const options = args[0] ?? {};
|
|
23402
|
+
const model = typeof options.model === "string" ? options.model : "";
|
|
23403
|
+
const limitRaw = parseInt(String(options.limit ?? "100"), 10);
|
|
23404
|
+
const report = await runMigrateReextractCliCommand(orchestrator, {
|
|
23405
|
+
model,
|
|
23406
|
+
write: options.write === true,
|
|
23407
|
+
limit: Number.isFinite(limitRaw) ? limitRaw : 100
|
|
23408
|
+
});
|
|
23409
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23410
|
+
console.log("OK");
|
|
23411
|
+
});
|
|
23026
23412
|
cmd.command("action-audit").description("Show namespace-aware memory action policy outcomes").option("--namespace <name>", "Filter to a single namespace").option("--limit <n>", "Max events to read per namespace", "200").action(async (...args) => {
|
|
23027
23413
|
const options = args[0] ?? {};
|
|
23028
23414
|
const limitRaw = parseInt(String(options.limit ?? "200"), 10);
|