@remnic/plugin-openclaw 1.0.13 → 1.0.14
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 +670 -3
- package/openclaw.plugin.json +17 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -601,6 +601,9 @@ var MEMORY_OS_PRESETS = {
|
|
|
601
601
|
contextCompressionActionsEnabled: true,
|
|
602
602
|
compressionGuidelineLearningEnabled: true,
|
|
603
603
|
compressionGuidelineSemanticRefinementEnabled: true,
|
|
604
|
+
explicitCueRecallEnabled: true,
|
|
605
|
+
explicitCueRecallMaxChars: 3200,
|
|
606
|
+
lcmEnabled: true,
|
|
604
607
|
maxProactiveQuestionsPerExtraction: 4,
|
|
605
608
|
maxCompressionTokensPerHour: 3e3,
|
|
606
609
|
behaviorLoopAutoTuneEnabled: true
|
|
@@ -1897,6 +1900,9 @@ function parseConfig(raw) {
|
|
|
1897
1900
|
temporalMemoryTreeEnabled: cfg.temporalMemoryTreeEnabled === true,
|
|
1898
1901
|
tmtHourlyMinMemories: typeof cfg.tmtHourlyMinMemories === "number" ? cfg.tmtHourlyMinMemories : 3,
|
|
1899
1902
|
tmtSummaryMaxTokens: typeof cfg.tmtSummaryMaxTokens === "number" ? cfg.tmtSummaryMaxTokens : 300,
|
|
1903
|
+
explicitCueRecallEnabled: coerceBool(cfg.explicitCueRecallEnabled) === true,
|
|
1904
|
+
explicitCueRecallMaxChars: coerceNumber(cfg.explicitCueRecallMaxChars) !== void 0 ? Math.max(0, Math.floor(coerceNumber(cfg.explicitCueRecallMaxChars))) : 2400,
|
|
1905
|
+
explicitCueRecallMaxReferences: coerceNumber(cfg.explicitCueRecallMaxReferences) !== void 0 ? Math.max(0, Math.floor(coerceNumber(cfg.explicitCueRecallMaxReferences))) : 24,
|
|
1900
1906
|
// Lossless Context Management (LCM)
|
|
1901
1907
|
lcmEnabled: cfg.lcmEnabled === true,
|
|
1902
1908
|
lcmLeafBatchSize: typeof cfg.lcmLeafBatchSize === "number" ? Math.max(2, Math.floor(cfg.lcmLeafBatchSize)) : 8,
|
|
@@ -2254,6 +2260,12 @@ function buildDefaultRecallPipeline(cfg) {
|
|
|
2254
2260
|
enabled: cfg.sharedContextEnabled === true,
|
|
2255
2261
|
maxChars: typeof cfg.sharedContextMaxInjectChars === "number" ? Math.max(0, Math.floor(cfg.sharedContextMaxInjectChars)) : 4e3
|
|
2256
2262
|
},
|
|
2263
|
+
{
|
|
2264
|
+
id: "explicit-cue",
|
|
2265
|
+
enabled: coerceBool(cfg.explicitCueRecallEnabled) === true,
|
|
2266
|
+
maxChars: coerceNumber(cfg.explicitCueRecallMaxChars) !== void 0 ? Math.max(0, Math.floor(coerceNumber(cfg.explicitCueRecallMaxChars))) : 2400,
|
|
2267
|
+
maxResults: coerceNumber(cfg.explicitCueRecallMaxReferences) !== void 0 ? Math.max(0, Math.floor(coerceNumber(cfg.explicitCueRecallMaxReferences))) : 24
|
|
2268
|
+
},
|
|
2257
2269
|
{
|
|
2258
2270
|
id: "profile",
|
|
2259
2271
|
enabled: true,
|
|
@@ -23087,6 +23099,630 @@ async function readRecentEntityTranscriptEntries(transcriptEntriesPromise, recen
|
|
|
23087
23099
|
}
|
|
23088
23100
|
var entityRecentTranscriptLookbackHours = RECENT_TRANSCRIPT_LOOKBACK_HOURS;
|
|
23089
23101
|
|
|
23102
|
+
// ../remnic-core/src/evidence-pack.ts
|
|
23103
|
+
var DEFAULT_MAX_ITEM_CHARS = 1200;
|
|
23104
|
+
function buildEvidencePack(items, options) {
|
|
23105
|
+
const budget = normalizePositiveInteger(options.maxChars);
|
|
23106
|
+
if (budget <= 0 || items.length === 0) {
|
|
23107
|
+
return "";
|
|
23108
|
+
}
|
|
23109
|
+
const maxItemChars = normalizePositiveInteger(
|
|
23110
|
+
options.maxItemChars ?? DEFAULT_MAX_ITEM_CHARS
|
|
23111
|
+
);
|
|
23112
|
+
if (maxItemChars <= 0) {
|
|
23113
|
+
return "";
|
|
23114
|
+
}
|
|
23115
|
+
const title = options.title ?? "Evidence";
|
|
23116
|
+
const lines = [`## ${title}`];
|
|
23117
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
23118
|
+
const seenContent = /* @__PURE__ */ new Set();
|
|
23119
|
+
let used = lines[0].length;
|
|
23120
|
+
for (const item of items) {
|
|
23121
|
+
const content = item.content.trim();
|
|
23122
|
+
if (!content) continue;
|
|
23123
|
+
const id = item.id ?? evidenceItemFallbackId(item);
|
|
23124
|
+
if (id && seenIds.has(id)) continue;
|
|
23125
|
+
const contentKey = normalizeEvidenceContent(content);
|
|
23126
|
+
if (seenContent.has(contentKey)) continue;
|
|
23127
|
+
const label = formatEvidenceLabel(item);
|
|
23128
|
+
const clipped = clipText(content, maxItemChars);
|
|
23129
|
+
const block = `${label}: ${clipped}`;
|
|
23130
|
+
const separatorLength = lines.length > 0 ? 2 : 0;
|
|
23131
|
+
const remaining = budget - used - separatorLength;
|
|
23132
|
+
if (remaining <= 0) break;
|
|
23133
|
+
const finalBlock = block.length > remaining ? clipText(block, remaining) : block;
|
|
23134
|
+
if (!finalBlock.trim()) break;
|
|
23135
|
+
lines.push(finalBlock);
|
|
23136
|
+
used += separatorLength + finalBlock.length;
|
|
23137
|
+
if (id) seenIds.add(id);
|
|
23138
|
+
seenContent.add(contentKey);
|
|
23139
|
+
}
|
|
23140
|
+
return lines.length === 1 ? "" : lines.join("\n\n");
|
|
23141
|
+
}
|
|
23142
|
+
function normalizePositiveInteger(value) {
|
|
23143
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
23144
|
+
return 0;
|
|
23145
|
+
}
|
|
23146
|
+
return Math.floor(value);
|
|
23147
|
+
}
|
|
23148
|
+
function evidenceItemFallbackId(item) {
|
|
23149
|
+
if (item.sessionId && typeof item.turnIndex === "number") {
|
|
23150
|
+
return `${item.sessionId}:${item.turnIndex}`;
|
|
23151
|
+
}
|
|
23152
|
+
return void 0;
|
|
23153
|
+
}
|
|
23154
|
+
function normalizeEvidenceContent(content) {
|
|
23155
|
+
return content.toLowerCase().replace(/\s+/g, " ").trim();
|
|
23156
|
+
}
|
|
23157
|
+
function formatEvidenceLabel(item) {
|
|
23158
|
+
const parts = [];
|
|
23159
|
+
if (item.sessionId) parts.push(item.sessionId);
|
|
23160
|
+
if (typeof item.turnIndex === "number") parts.push(`turn ${item.turnIndex}`);
|
|
23161
|
+
if (item.role) parts.push(item.role);
|
|
23162
|
+
if (typeof item.score === "number" && Number.isFinite(item.score)) {
|
|
23163
|
+
parts.push(`score ${item.score.toFixed(3)}`);
|
|
23164
|
+
}
|
|
23165
|
+
return parts.length > 0 ? `[${parts.join(", ")}]` : "[evidence]";
|
|
23166
|
+
}
|
|
23167
|
+
function clipText(text, maxChars) {
|
|
23168
|
+
if (text.length <= maxChars) {
|
|
23169
|
+
return text;
|
|
23170
|
+
}
|
|
23171
|
+
if (maxChars <= 1) {
|
|
23172
|
+
return text.slice(0, maxChars);
|
|
23173
|
+
}
|
|
23174
|
+
if (maxChars <= 3) {
|
|
23175
|
+
return text.slice(0, maxChars);
|
|
23176
|
+
}
|
|
23177
|
+
return `${text.slice(0, maxChars - 3).trimEnd()}...`;
|
|
23178
|
+
}
|
|
23179
|
+
|
|
23180
|
+
// ../remnic-core/src/explicit-cue-recall.ts
|
|
23181
|
+
var DEFAULT_MAX_CHARS = 2400;
|
|
23182
|
+
var DEFAULT_MAX_ITEM_CHARS2 = 1200;
|
|
23183
|
+
var DEFAULT_MAX_REFERENCES = 24;
|
|
23184
|
+
var REFERENCE_SCAN_TOKEN_FACTOR = 3;
|
|
23185
|
+
var TURN_REFERENCE_WINDOW_RADIUS = 0;
|
|
23186
|
+
var LEXICAL_CUE_WINDOW_RADIUS = 1;
|
|
23187
|
+
var LEXICAL_CUE_SEARCH_LIMIT = 3;
|
|
23188
|
+
var LEXICAL_CUE_MAX_TOKENS = 400;
|
|
23189
|
+
var LATEST_STATE_CUES = /* @__PURE__ */ new Set([
|
|
23190
|
+
"as of",
|
|
23191
|
+
"currently",
|
|
23192
|
+
"latest",
|
|
23193
|
+
"most recent",
|
|
23194
|
+
"newest",
|
|
23195
|
+
"now",
|
|
23196
|
+
"updated",
|
|
23197
|
+
"changed",
|
|
23198
|
+
"change"
|
|
23199
|
+
]);
|
|
23200
|
+
var RELATIVE_TEMPORAL_CUES = [
|
|
23201
|
+
"as of",
|
|
23202
|
+
"most recent",
|
|
23203
|
+
"last time",
|
|
23204
|
+
"last week",
|
|
23205
|
+
"last month",
|
|
23206
|
+
"last year",
|
|
23207
|
+
"last session",
|
|
23208
|
+
"last conversation",
|
|
23209
|
+
"next time",
|
|
23210
|
+
"next week",
|
|
23211
|
+
"next month",
|
|
23212
|
+
"next year",
|
|
23213
|
+
"next session",
|
|
23214
|
+
"next conversation",
|
|
23215
|
+
"previous time",
|
|
23216
|
+
"previous week",
|
|
23217
|
+
"previous month",
|
|
23218
|
+
"previous year",
|
|
23219
|
+
"previous session",
|
|
23220
|
+
"previous conversation",
|
|
23221
|
+
"prior time",
|
|
23222
|
+
"prior week",
|
|
23223
|
+
"prior month",
|
|
23224
|
+
"prior year",
|
|
23225
|
+
"prior session",
|
|
23226
|
+
"prior conversation",
|
|
23227
|
+
"today",
|
|
23228
|
+
"yesterday",
|
|
23229
|
+
"tomorrow",
|
|
23230
|
+
"tonight",
|
|
23231
|
+
"earlier",
|
|
23232
|
+
"later",
|
|
23233
|
+
"recently",
|
|
23234
|
+
"previously",
|
|
23235
|
+
"currently",
|
|
23236
|
+
"now",
|
|
23237
|
+
"latest",
|
|
23238
|
+
"newest",
|
|
23239
|
+
"oldest",
|
|
23240
|
+
"earliest",
|
|
23241
|
+
"before",
|
|
23242
|
+
"after",
|
|
23243
|
+
"since",
|
|
23244
|
+
"updated",
|
|
23245
|
+
"changed",
|
|
23246
|
+
"change"
|
|
23247
|
+
];
|
|
23248
|
+
var SPEAKER_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
23249
|
+
"A",
|
|
23250
|
+
"According",
|
|
23251
|
+
"An",
|
|
23252
|
+
"And",
|
|
23253
|
+
"Are",
|
|
23254
|
+
"As",
|
|
23255
|
+
"At",
|
|
23256
|
+
"Before",
|
|
23257
|
+
"Can",
|
|
23258
|
+
"Compare",
|
|
23259
|
+
"Could",
|
|
23260
|
+
"Did",
|
|
23261
|
+
"Do",
|
|
23262
|
+
"Does",
|
|
23263
|
+
"For",
|
|
23264
|
+
"From",
|
|
23265
|
+
"Had",
|
|
23266
|
+
"Has",
|
|
23267
|
+
"Have",
|
|
23268
|
+
"How",
|
|
23269
|
+
"In",
|
|
23270
|
+
"Is",
|
|
23271
|
+
"It",
|
|
23272
|
+
"Of",
|
|
23273
|
+
"On",
|
|
23274
|
+
"Or",
|
|
23275
|
+
"Please",
|
|
23276
|
+
"Review",
|
|
23277
|
+
"Step",
|
|
23278
|
+
"Tell",
|
|
23279
|
+
"The",
|
|
23280
|
+
"To",
|
|
23281
|
+
"Turn",
|
|
23282
|
+
"Use",
|
|
23283
|
+
"Was",
|
|
23284
|
+
"Were",
|
|
23285
|
+
"What",
|
|
23286
|
+
"When",
|
|
23287
|
+
"Where",
|
|
23288
|
+
"Which",
|
|
23289
|
+
"Who",
|
|
23290
|
+
"Why",
|
|
23291
|
+
"Will",
|
|
23292
|
+
"Would"
|
|
23293
|
+
]);
|
|
23294
|
+
var QUESTION_SLOT_STOPWORDS = /* @__PURE__ */ new Set([
|
|
23295
|
+
"answer",
|
|
23296
|
+
"choice",
|
|
23297
|
+
"did",
|
|
23298
|
+
"does",
|
|
23299
|
+
"do",
|
|
23300
|
+
"is",
|
|
23301
|
+
"should",
|
|
23302
|
+
"single",
|
|
23303
|
+
"the",
|
|
23304
|
+
"user",
|
|
23305
|
+
"was",
|
|
23306
|
+
"were"
|
|
23307
|
+
]);
|
|
23308
|
+
async function buildExplicitCueRecallSection(options) {
|
|
23309
|
+
const engine = options.engine;
|
|
23310
|
+
const query = options.query.trim();
|
|
23311
|
+
const maxChars = normalizePositiveInteger2(options.maxChars, DEFAULT_MAX_CHARS);
|
|
23312
|
+
if (!engine || query.length === 0 || maxChars <= 0) {
|
|
23313
|
+
return "";
|
|
23314
|
+
}
|
|
23315
|
+
const maxReferences = normalizePositiveInteger2(
|
|
23316
|
+
options.maxReferences,
|
|
23317
|
+
DEFAULT_MAX_REFERENCES
|
|
23318
|
+
);
|
|
23319
|
+
if (maxReferences <= 0) {
|
|
23320
|
+
return "";
|
|
23321
|
+
}
|
|
23322
|
+
const evidenceItems = [];
|
|
23323
|
+
const seenTurns = /* @__PURE__ */ new Set();
|
|
23324
|
+
await collectTurnReferenceEvidence({
|
|
23325
|
+
engine,
|
|
23326
|
+
sessionId: options.sessionId,
|
|
23327
|
+
query,
|
|
23328
|
+
maxReferences,
|
|
23329
|
+
evidenceItems,
|
|
23330
|
+
seenTurns
|
|
23331
|
+
});
|
|
23332
|
+
await collectLexicalCueEvidence({
|
|
23333
|
+
engine,
|
|
23334
|
+
sessionId: options.sessionId,
|
|
23335
|
+
query,
|
|
23336
|
+
maxReferences,
|
|
23337
|
+
evidenceItems,
|
|
23338
|
+
seenTurns
|
|
23339
|
+
});
|
|
23340
|
+
return buildEvidencePack(evidenceItems, {
|
|
23341
|
+
title: "Explicit Cue Evidence",
|
|
23342
|
+
maxChars,
|
|
23343
|
+
maxItemChars: normalizePositiveInteger2(
|
|
23344
|
+
options.maxItemChars,
|
|
23345
|
+
DEFAULT_MAX_ITEM_CHARS2
|
|
23346
|
+
)
|
|
23347
|
+
});
|
|
23348
|
+
}
|
|
23349
|
+
async function collectTurnReferenceEvidence(options) {
|
|
23350
|
+
if (!options.sessionId) {
|
|
23351
|
+
return;
|
|
23352
|
+
}
|
|
23353
|
+
const references = collectExplicitTurnReferences(options.query).slice(
|
|
23354
|
+
0,
|
|
23355
|
+
options.maxReferences
|
|
23356
|
+
);
|
|
23357
|
+
if (references.length === 0) {
|
|
23358
|
+
return;
|
|
23359
|
+
}
|
|
23360
|
+
const windows = /* @__PURE__ */ new Map();
|
|
23361
|
+
for (const reference of references) {
|
|
23362
|
+
for (const center of candidateTurnIndexesForReference(reference)) {
|
|
23363
|
+
if (center < 0) {
|
|
23364
|
+
continue;
|
|
23365
|
+
}
|
|
23366
|
+
const fromTurn = Math.max(0, center - TURN_REFERENCE_WINDOW_RADIUS);
|
|
23367
|
+
const toTurn = center + TURN_REFERENCE_WINDOW_RADIUS;
|
|
23368
|
+
windows.set(`${fromTurn}:${toTurn}`, { fromTurn, toTurn });
|
|
23369
|
+
}
|
|
23370
|
+
}
|
|
23371
|
+
for (const window of [...windows.values()].sort(
|
|
23372
|
+
(left, right) => left.fromTurn - right.fromTurn || left.toTurn - right.toTurn
|
|
23373
|
+
)) {
|
|
23374
|
+
const expanded = await options.engine.expandContext(
|
|
23375
|
+
options.sessionId,
|
|
23376
|
+
window.fromTurn,
|
|
23377
|
+
window.toTurn,
|
|
23378
|
+
2e3
|
|
23379
|
+
);
|
|
23380
|
+
appendExpandedEvidence(
|
|
23381
|
+
options.evidenceItems,
|
|
23382
|
+
options.seenTurns,
|
|
23383
|
+
options.sessionId,
|
|
23384
|
+
expanded
|
|
23385
|
+
);
|
|
23386
|
+
}
|
|
23387
|
+
}
|
|
23388
|
+
async function collectLexicalCueEvidence(options) {
|
|
23389
|
+
const cues = collectLexicalCues(options.query).slice(0, options.maxReferences);
|
|
23390
|
+
const preferLatest = hasLatestStateIntent(options.query);
|
|
23391
|
+
for (const cue of cues) {
|
|
23392
|
+
const results = sortLexicalCueResults(
|
|
23393
|
+
await options.engine.searchContextFull(
|
|
23394
|
+
cue,
|
|
23395
|
+
LEXICAL_CUE_SEARCH_LIMIT,
|
|
23396
|
+
options.sessionId
|
|
23397
|
+
),
|
|
23398
|
+
preferLatest
|
|
23399
|
+
);
|
|
23400
|
+
for (const result of results) {
|
|
23401
|
+
const windowRadius = preferLatest ? 0 : LEXICAL_CUE_WINDOW_RADIUS;
|
|
23402
|
+
const fromTurn = Math.max(0, result.turn_index - windowRadius);
|
|
23403
|
+
const toTurn = result.turn_index + windowRadius;
|
|
23404
|
+
const expanded = await options.engine.expandContext(
|
|
23405
|
+
result.session_id,
|
|
23406
|
+
fromTurn,
|
|
23407
|
+
toTurn,
|
|
23408
|
+
LEXICAL_CUE_MAX_TOKENS
|
|
23409
|
+
);
|
|
23410
|
+
if (expanded.length === 0) {
|
|
23411
|
+
appendEvidenceItem(options.evidenceItems, options.seenTurns, {
|
|
23412
|
+
id: `${result.session_id}:${result.turn_index}`,
|
|
23413
|
+
sessionId: result.session_id,
|
|
23414
|
+
turnIndex: result.turn_index,
|
|
23415
|
+
role: result.role,
|
|
23416
|
+
content: result.content,
|
|
23417
|
+
...typeof result.score === "number" ? { score: result.score } : {}
|
|
23418
|
+
});
|
|
23419
|
+
continue;
|
|
23420
|
+
}
|
|
23421
|
+
appendExpandedEvidence(
|
|
23422
|
+
options.evidenceItems,
|
|
23423
|
+
options.seenTurns,
|
|
23424
|
+
result.session_id,
|
|
23425
|
+
expanded
|
|
23426
|
+
);
|
|
23427
|
+
}
|
|
23428
|
+
}
|
|
23429
|
+
}
|
|
23430
|
+
function appendExpandedEvidence(evidenceItems, seenTurns, sessionId, expanded) {
|
|
23431
|
+
for (const message of expanded) {
|
|
23432
|
+
appendEvidenceItem(evidenceItems, seenTurns, {
|
|
23433
|
+
id: `${sessionId}:${message.turn_index}`,
|
|
23434
|
+
sessionId,
|
|
23435
|
+
turnIndex: message.turn_index,
|
|
23436
|
+
role: message.role,
|
|
23437
|
+
content: message.content
|
|
23438
|
+
});
|
|
23439
|
+
}
|
|
23440
|
+
}
|
|
23441
|
+
function appendEvidenceItem(evidenceItems, seenTurns, item) {
|
|
23442
|
+
if (seenTurns.has(item.id)) {
|
|
23443
|
+
return;
|
|
23444
|
+
}
|
|
23445
|
+
seenTurns.add(item.id);
|
|
23446
|
+
evidenceItems.push(item);
|
|
23447
|
+
}
|
|
23448
|
+
function collectExplicitTurnReferences(query) {
|
|
23449
|
+
const references = /* @__PURE__ */ new Map();
|
|
23450
|
+
const addReference = (value, label) => {
|
|
23451
|
+
const existing = references.get(String(value));
|
|
23452
|
+
references.set(String(value), {
|
|
23453
|
+
number: value,
|
|
23454
|
+
includeDirectTurn: (existing?.includeDirectTurn ?? false) || label === "turn"
|
|
23455
|
+
});
|
|
23456
|
+
};
|
|
23457
|
+
const tokens = tokenizeReferenceQuery(query);
|
|
23458
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
23459
|
+
const label = normalizeReferenceLabel(tokens[index]);
|
|
23460
|
+
if (!label) {
|
|
23461
|
+
continue;
|
|
23462
|
+
}
|
|
23463
|
+
const parsed = parseReferenceNumbers(tokens, index + 1);
|
|
23464
|
+
for (const number of parsed.numbers) {
|
|
23465
|
+
addReference(number, label);
|
|
23466
|
+
}
|
|
23467
|
+
index = Math.max(index, parsed.nextIndex - 1);
|
|
23468
|
+
}
|
|
23469
|
+
return [...references.values()].sort((left, right) => left.number - right.number);
|
|
23470
|
+
}
|
|
23471
|
+
function collectLexicalCues(query) {
|
|
23472
|
+
const cues = /* @__PURE__ */ new Set();
|
|
23473
|
+
for (const match of query.matchAll(/\b[A-Za-z][A-Za-z0-9]{0,12}\d+:\d+\b/g)) {
|
|
23474
|
+
cues.add(match[0]);
|
|
23475
|
+
}
|
|
23476
|
+
for (const match of query.matchAll(/\b\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2})?Z?)?\b/g)) {
|
|
23477
|
+
cues.add(match[0]);
|
|
23478
|
+
}
|
|
23479
|
+
for (const cue of collectTemporalLexicalCues(query)) {
|
|
23480
|
+
cues.add(cue);
|
|
23481
|
+
}
|
|
23482
|
+
for (const cue of collectQuestionSlotCues(query)) {
|
|
23483
|
+
cues.add(cue);
|
|
23484
|
+
}
|
|
23485
|
+
for (const match of query.matchAll(/\b(?:session|source|chat|plan|task|event|file|tool)[_-][A-Za-z0-9][A-Za-z0-9_.:-]{0,80}\b/gi)) {
|
|
23486
|
+
cues.add(match[0]);
|
|
23487
|
+
}
|
|
23488
|
+
for (const match of query.matchAll(/\b[A-Z][a-z]{1,30}(?:\s+[A-Z][a-z]{1,30}){0,2}\b/g)) {
|
|
23489
|
+
const value = normalizeSpeakerNameCue(match[0]);
|
|
23490
|
+
if (value) {
|
|
23491
|
+
cues.add(value);
|
|
23492
|
+
}
|
|
23493
|
+
}
|
|
23494
|
+
for (const match of query.matchAll(/\[([A-Za-z0-9][A-Za-z0-9_.:/ -]{1,80})\]/g)) {
|
|
23495
|
+
const value = match[1]?.trim();
|
|
23496
|
+
if (value) {
|
|
23497
|
+
cues.add(value);
|
|
23498
|
+
}
|
|
23499
|
+
}
|
|
23500
|
+
return [...cues].sort((left, right) => left.localeCompare(right));
|
|
23501
|
+
}
|
|
23502
|
+
function collectQuestionSlotCues(query) {
|
|
23503
|
+
const cues = /* @__PURE__ */ new Set();
|
|
23504
|
+
for (const match of query.matchAll(
|
|
23505
|
+
/\b(?:what|which)\s+([a-z][a-z0-9_-]{2,30})\s+(?:does|do|did|is|are|was|were|should|would|could|can|will)\b/gi
|
|
23506
|
+
)) {
|
|
23507
|
+
const value = match[1]?.toLowerCase();
|
|
23508
|
+
if (value && !QUESTION_SLOT_STOPWORDS.has(value)) {
|
|
23509
|
+
cues.add(value);
|
|
23510
|
+
}
|
|
23511
|
+
}
|
|
23512
|
+
return [...cues].sort((left, right) => left.localeCompare(right));
|
|
23513
|
+
}
|
|
23514
|
+
function collectTemporalLexicalCues(query) {
|
|
23515
|
+
const cues = /* @__PURE__ */ new Set();
|
|
23516
|
+
const normalizedQuery = query.toLowerCase().replace(/\s+/g, " ");
|
|
23517
|
+
for (const cue of RELATIVE_TEMPORAL_CUES) {
|
|
23518
|
+
let searchFrom = 0;
|
|
23519
|
+
while (searchFrom < normalizedQuery.length) {
|
|
23520
|
+
const index = normalizedQuery.indexOf(cue, searchFrom);
|
|
23521
|
+
if (index < 0) {
|
|
23522
|
+
break;
|
|
23523
|
+
}
|
|
23524
|
+
const afterIndex = index + cue.length;
|
|
23525
|
+
if (isTemporalCueBoundary(normalizedQuery[index - 1]) && isTemporalCueBoundary(normalizedQuery[afterIndex])) {
|
|
23526
|
+
cues.add(cue);
|
|
23527
|
+
break;
|
|
23528
|
+
}
|
|
23529
|
+
searchFrom = afterIndex;
|
|
23530
|
+
}
|
|
23531
|
+
}
|
|
23532
|
+
return [...cues].sort((left, right) => left.localeCompare(right));
|
|
23533
|
+
}
|
|
23534
|
+
function hasLatestStateIntent(query) {
|
|
23535
|
+
return collectTemporalLexicalCues(query).some(
|
|
23536
|
+
(cue) => LATEST_STATE_CUES.has(cue)
|
|
23537
|
+
);
|
|
23538
|
+
}
|
|
23539
|
+
function sortLexicalCueResults(results, preferLatest) {
|
|
23540
|
+
return [...results].sort((left, right) => {
|
|
23541
|
+
if (preferLatest) {
|
|
23542
|
+
const sessionOrder2 = left.session_id.localeCompare(right.session_id);
|
|
23543
|
+
if (sessionOrder2 !== 0) {
|
|
23544
|
+
return sessionOrder2;
|
|
23545
|
+
}
|
|
23546
|
+
const turnOrder = right.turn_index - left.turn_index;
|
|
23547
|
+
if (turnOrder !== 0) {
|
|
23548
|
+
return turnOrder;
|
|
23549
|
+
}
|
|
23550
|
+
return (right.score ?? 0) - (left.score ?? 0);
|
|
23551
|
+
}
|
|
23552
|
+
const scoreDelta = (right.score ?? 0) - (left.score ?? 0);
|
|
23553
|
+
if (scoreDelta !== 0) {
|
|
23554
|
+
return scoreDelta;
|
|
23555
|
+
}
|
|
23556
|
+
const sessionOrder = left.session_id.localeCompare(right.session_id);
|
|
23557
|
+
if (sessionOrder !== 0) {
|
|
23558
|
+
return sessionOrder;
|
|
23559
|
+
}
|
|
23560
|
+
return left.turn_index - right.turn_index;
|
|
23561
|
+
});
|
|
23562
|
+
}
|
|
23563
|
+
function normalizeSpeakerNameCue(value) {
|
|
23564
|
+
const words = value.trim().split(/\s+/).filter(Boolean);
|
|
23565
|
+
while (words.length > 0 && SPEAKER_NAME_STOPWORDS.has(words[0])) {
|
|
23566
|
+
words.shift();
|
|
23567
|
+
}
|
|
23568
|
+
while (words.length > 0 && SPEAKER_NAME_STOPWORDS.has(words[words.length - 1])) {
|
|
23569
|
+
words.pop();
|
|
23570
|
+
}
|
|
23571
|
+
return words.length > 0 ? words.join(" ") : void 0;
|
|
23572
|
+
}
|
|
23573
|
+
function isTemporalCueBoundary(char) {
|
|
23574
|
+
if (!char) {
|
|
23575
|
+
return true;
|
|
23576
|
+
}
|
|
23577
|
+
return !isAsciiLetterOrDigit(char);
|
|
23578
|
+
}
|
|
23579
|
+
function tokenizeReferenceQuery(query) {
|
|
23580
|
+
const tokens = [];
|
|
23581
|
+
let current = "";
|
|
23582
|
+
const flushCurrent = () => {
|
|
23583
|
+
if (current) {
|
|
23584
|
+
tokens.push(current);
|
|
23585
|
+
current = "";
|
|
23586
|
+
}
|
|
23587
|
+
};
|
|
23588
|
+
for (const char of query) {
|
|
23589
|
+
if (isAsciiLetterOrDigit(char)) {
|
|
23590
|
+
current += char;
|
|
23591
|
+
continue;
|
|
23592
|
+
}
|
|
23593
|
+
flushCurrent();
|
|
23594
|
+
if (char === "#" || char === ",") {
|
|
23595
|
+
tokens.push(char);
|
|
23596
|
+
} else if (isReferenceDash(char)) {
|
|
23597
|
+
tokens.push("-");
|
|
23598
|
+
}
|
|
23599
|
+
}
|
|
23600
|
+
flushCurrent();
|
|
23601
|
+
return tokens;
|
|
23602
|
+
}
|
|
23603
|
+
function parseReferenceNumbers(tokens, startIndex) {
|
|
23604
|
+
const numbers = [];
|
|
23605
|
+
let lastNumber;
|
|
23606
|
+
let pendingRangeStart;
|
|
23607
|
+
let index = startIndex;
|
|
23608
|
+
const scanEnd = Math.min(
|
|
23609
|
+
tokens.length,
|
|
23610
|
+
startIndex + DEFAULT_MAX_REFERENCES * REFERENCE_SCAN_TOKEN_FACTOR
|
|
23611
|
+
);
|
|
23612
|
+
for (; index < scanEnd; index += 1) {
|
|
23613
|
+
const token = tokens[index];
|
|
23614
|
+
const normalized = token.toLowerCase();
|
|
23615
|
+
const value = parseNonNegativeIntegerToken(token);
|
|
23616
|
+
if (value !== void 0) {
|
|
23617
|
+
if (pendingRangeStart !== void 0) {
|
|
23618
|
+
numbers.push(...expandReferenceRange(pendingRangeStart, value));
|
|
23619
|
+
pendingRangeStart = void 0;
|
|
23620
|
+
} else {
|
|
23621
|
+
numbers.push(value);
|
|
23622
|
+
}
|
|
23623
|
+
lastNumber = value;
|
|
23624
|
+
continue;
|
|
23625
|
+
}
|
|
23626
|
+
if (normalized === "#" || normalized === "number" || normalized === ",") {
|
|
23627
|
+
continue;
|
|
23628
|
+
}
|
|
23629
|
+
if (normalized === "-" || normalized === "to" || normalized === "through" || normalized === "thru") {
|
|
23630
|
+
if (lastNumber !== void 0) {
|
|
23631
|
+
if (numbers[numbers.length - 1] === lastNumber) {
|
|
23632
|
+
numbers.pop();
|
|
23633
|
+
}
|
|
23634
|
+
pendingRangeStart = lastNumber;
|
|
23635
|
+
}
|
|
23636
|
+
continue;
|
|
23637
|
+
}
|
|
23638
|
+
if (normalized === "and" && numbers.length > 0) {
|
|
23639
|
+
continue;
|
|
23640
|
+
}
|
|
23641
|
+
if (normalizeReferenceLabel(token)) {
|
|
23642
|
+
break;
|
|
23643
|
+
}
|
|
23644
|
+
break;
|
|
23645
|
+
}
|
|
23646
|
+
if (pendingRangeStart !== void 0) {
|
|
23647
|
+
numbers.push(pendingRangeStart);
|
|
23648
|
+
}
|
|
23649
|
+
return {
|
|
23650
|
+
numbers: [...new Set(numbers)],
|
|
23651
|
+
nextIndex: index
|
|
23652
|
+
};
|
|
23653
|
+
}
|
|
23654
|
+
function expandReferenceRange(start, end) {
|
|
23655
|
+
const low = Math.min(start, end);
|
|
23656
|
+
const high = Math.max(start, end);
|
|
23657
|
+
if (high - low + 1 > DEFAULT_MAX_REFERENCES) {
|
|
23658
|
+
return [start, end];
|
|
23659
|
+
}
|
|
23660
|
+
const values = [];
|
|
23661
|
+
for (let value = low; value <= high; value += 1) {
|
|
23662
|
+
values.push(value);
|
|
23663
|
+
}
|
|
23664
|
+
return values;
|
|
23665
|
+
}
|
|
23666
|
+
function normalizeReferenceLabel(token) {
|
|
23667
|
+
const normalized = token?.toLowerCase();
|
|
23668
|
+
switch (normalized) {
|
|
23669
|
+
case "step":
|
|
23670
|
+
case "steps":
|
|
23671
|
+
return "step";
|
|
23672
|
+
case "turn":
|
|
23673
|
+
case "turns":
|
|
23674
|
+
return "turn";
|
|
23675
|
+
case "action":
|
|
23676
|
+
case "actions":
|
|
23677
|
+
return "action";
|
|
23678
|
+
case "observation":
|
|
23679
|
+
case "observations":
|
|
23680
|
+
return "observation";
|
|
23681
|
+
default:
|
|
23682
|
+
return void 0;
|
|
23683
|
+
}
|
|
23684
|
+
}
|
|
23685
|
+
function candidateTurnIndexesForReference(reference) {
|
|
23686
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
23687
|
+
if (reference.includeDirectTurn) {
|
|
23688
|
+
for (let offset = -1; offset <= 1; offset += 1) {
|
|
23689
|
+
candidates.add(reference.number + offset);
|
|
23690
|
+
}
|
|
23691
|
+
}
|
|
23692
|
+
const pairedBase = reference.number * 2;
|
|
23693
|
+
for (let offset = -2; offset <= 3; offset += 1) {
|
|
23694
|
+
candidates.add(pairedBase + offset);
|
|
23695
|
+
}
|
|
23696
|
+
return [...candidates].sort((left, right) => left - right);
|
|
23697
|
+
}
|
|
23698
|
+
function parseNonNegativeIntegerToken(token) {
|
|
23699
|
+
if (token.length === 0) {
|
|
23700
|
+
return void 0;
|
|
23701
|
+
}
|
|
23702
|
+
let value = 0;
|
|
23703
|
+
for (const char of token) {
|
|
23704
|
+
const code = char.charCodeAt(0);
|
|
23705
|
+
if (code < 48 || code > 57) {
|
|
23706
|
+
return void 0;
|
|
23707
|
+
}
|
|
23708
|
+
value = value * 10 + (code - 48);
|
|
23709
|
+
}
|
|
23710
|
+
return value;
|
|
23711
|
+
}
|
|
23712
|
+
function normalizePositiveInteger2(value, fallback) {
|
|
23713
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
23714
|
+
return fallback;
|
|
23715
|
+
}
|
|
23716
|
+
return Math.max(0, Math.floor(value));
|
|
23717
|
+
}
|
|
23718
|
+
function isAsciiLetterOrDigit(char) {
|
|
23719
|
+
const code = char.charCodeAt(0);
|
|
23720
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
23721
|
+
}
|
|
23722
|
+
function isReferenceDash(char) {
|
|
23723
|
+
return char === "-" || char === "\u2010" || char === "\u2011" || char === "\u2012" || char === "\u2013" || char === "\u2014" || char === "\u2015";
|
|
23724
|
+
}
|
|
23725
|
+
|
|
23090
23726
|
// ../remnic-core/src/recall-query-policy.ts
|
|
23091
23727
|
var DEFAULT_STOPWORDS = /* @__PURE__ */ new Set([
|
|
23092
23728
|
"the",
|
|
@@ -37930,6 +38566,27 @@ ${formatted}`;
|
|
|
37930
38566
|
this.profiler.startSpan("assembly", profileTraceId);
|
|
37931
38567
|
if (sharedCtx)
|
|
37932
38568
|
this.appendRecallSection(sectionBuckets, "shared-context", sharedCtx);
|
|
38569
|
+
const explicitCueMaxChars = this.getRecallSectionMaxChars("explicit-cue") ?? this.config.explicitCueRecallMaxChars;
|
|
38570
|
+
if (this.config.explicitCueRecallEnabled && this.isRecallSectionEnabled("explicit-cue") && explicitCueMaxChars !== 0 && this.lcmEngine?.enabled && recallMode !== "no_recall") {
|
|
38571
|
+
try {
|
|
38572
|
+
const explicitCueSection = await buildExplicitCueRecallSection({
|
|
38573
|
+
engine: this.lcmEngine,
|
|
38574
|
+
sessionId: sessionKey,
|
|
38575
|
+
query: retrievalQuery,
|
|
38576
|
+
maxChars: explicitCueMaxChars,
|
|
38577
|
+
maxReferences: this.getRecallSectionNumber("explicit-cue", "maxResults") ?? this.config.explicitCueRecallMaxReferences
|
|
38578
|
+
});
|
|
38579
|
+
if (explicitCueSection) {
|
|
38580
|
+
this.appendRecallSection(
|
|
38581
|
+
sectionBuckets,
|
|
38582
|
+
"explicit-cue",
|
|
38583
|
+
explicitCueSection
|
|
38584
|
+
);
|
|
38585
|
+
}
|
|
38586
|
+
} catch (err) {
|
|
38587
|
+
log.debug(`Explicit cue recall assembly error: ${err}`);
|
|
38588
|
+
}
|
|
38589
|
+
}
|
|
37933
38590
|
if (profile)
|
|
37934
38591
|
this.appendRecallSection(
|
|
37935
38592
|
sectionBuckets,
|
|
@@ -70914,8 +71571,7 @@ function buildTurnFingerprint(input) {
|
|
|
70914
71571
|
// ../../src/index.ts
|
|
70915
71572
|
import {
|
|
70916
71573
|
resolvePrincipal as resolvePrincipal2,
|
|
70917
|
-
resolveAgentAccessAuthToken as resolveAgentAccessAuthToken2
|
|
70918
|
-
hasEnabledLiveConnector as hasEnabledLiveConnector2
|
|
71574
|
+
resolveAgentAccessAuthToken as resolveAgentAccessAuthToken2
|
|
70919
71575
|
} from "@remnic/core";
|
|
70920
71576
|
|
|
70921
71577
|
// ../remnic-core/src/surfaces/dreams.ts
|
|
@@ -71494,6 +72150,17 @@ function liveConnectorCronExprForConfig(connectors) {
|
|
|
71494
72150
|
return hasEnabledConnector ? ENABLED_LIVE_CONNECTOR_CRON_EXPR : DEFAULT_LIVE_CONNECTOR_CRON_EXPR;
|
|
71495
72151
|
}
|
|
71496
72152
|
|
|
72153
|
+
// ../../src/openclaw-live-connector-config.ts
|
|
72154
|
+
function hasEnabledLiveConnectorConfig(config) {
|
|
72155
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) return false;
|
|
72156
|
+
return Object.values(config).some((connector) => {
|
|
72157
|
+
if (!connector || typeof connector !== "object" || Array.isArray(connector)) {
|
|
72158
|
+
return false;
|
|
72159
|
+
}
|
|
72160
|
+
return connector.enabled === true;
|
|
72161
|
+
});
|
|
72162
|
+
}
|
|
72163
|
+
|
|
71497
72164
|
// ../../src/index.ts
|
|
71498
72165
|
var ENGRAM_MIGRATION_PROMISE = "__openclawEngramMigrationPromise";
|
|
71499
72166
|
var CLI_REGISTERED_GUARD = "__openclawEngramCliRegistered";
|
|
@@ -71605,7 +72272,7 @@ function readPluginHooksPolicy(apiConfig, pluginId) {
|
|
|
71605
72272
|
return loadPluginEntryFromFile(pluginId)?.["hooks"];
|
|
71606
72273
|
}
|
|
71607
72274
|
async function maybeRegisterLiveConnectorCron(orchestrator) {
|
|
71608
|
-
if (!
|
|
72275
|
+
if (!hasEnabledLiveConnectorConfig(orchestrator.config.connectors)) return;
|
|
71609
72276
|
const jobsPath = path99.join(resolveHomeDir(), ".openclaw", "cron", "jobs.json");
|
|
71610
72277
|
try {
|
|
71611
72278
|
if (!existsSync12(jobsPath)) {
|
package/openclaw.plugin.json
CHANGED
|
@@ -2192,6 +2192,23 @@
|
|
|
2192
2192
|
"default": 300,
|
|
2193
2193
|
"description": "Max tokens for each TMT summary node. Default: 300."
|
|
2194
2194
|
},
|
|
2195
|
+
"explicitCueRecallEnabled": {
|
|
2196
|
+
"type": "boolean",
|
|
2197
|
+
"default": false,
|
|
2198
|
+
"description": "Front-load exact LCM evidence for query-visible cues such as turns, dates, ids, files, and tools."
|
|
2199
|
+
},
|
|
2200
|
+
"explicitCueRecallMaxChars": {
|
|
2201
|
+
"type": "number",
|
|
2202
|
+
"default": 2400,
|
|
2203
|
+
"minimum": 0,
|
|
2204
|
+
"description": "Character budget for the explicit cue evidence recall section."
|
|
2205
|
+
},
|
|
2206
|
+
"explicitCueRecallMaxReferences": {
|
|
2207
|
+
"type": "number",
|
|
2208
|
+
"default": 24,
|
|
2209
|
+
"minimum": 0,
|
|
2210
|
+
"description": "Maximum query-visible cues expanded by explicit cue recall."
|
|
2211
|
+
},
|
|
2195
2212
|
"queryExpansionEnabled": {
|
|
2196
2213
|
"type": "boolean",
|
|
2197
2214
|
"default": false,
|