@agenr/openclaw-plugin 0.12.1 → 0.12.2
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/CHANGELOG.md +23 -0
- package/README.md +2 -2
- package/dist/index.js +899 -234
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -693,6 +693,202 @@ var init_definitions = __esm({
|
|
|
693
693
|
}
|
|
694
694
|
});
|
|
695
695
|
|
|
696
|
+
// src/db/vector-index.ts
|
|
697
|
+
function toNumber(value) {
|
|
698
|
+
if (typeof value === "number") {
|
|
699
|
+
return value;
|
|
700
|
+
}
|
|
701
|
+
if (typeof value === "bigint") {
|
|
702
|
+
return Number(value);
|
|
703
|
+
}
|
|
704
|
+
if (typeof value === "string" && value.trim()) {
|
|
705
|
+
return Number(value);
|
|
706
|
+
}
|
|
707
|
+
return Number.NaN;
|
|
708
|
+
}
|
|
709
|
+
function toFiniteCount(value) {
|
|
710
|
+
const numeric = toNumber(value);
|
|
711
|
+
if (!Number.isFinite(numeric)) {
|
|
712
|
+
return 0;
|
|
713
|
+
}
|
|
714
|
+
return Math.max(0, Math.trunc(numeric));
|
|
715
|
+
}
|
|
716
|
+
function normalizeRowid(value) {
|
|
717
|
+
const numeric = toNumber(value);
|
|
718
|
+
if (!Number.isFinite(numeric)) {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
const rowid = Math.trunc(numeric);
|
|
722
|
+
return rowid > 0 ? rowid : null;
|
|
723
|
+
}
|
|
724
|
+
function formatShadowMismatch(stats) {
|
|
725
|
+
const details = [`active=${stats.embeddingCount}`, `shadow=${stats.shadowCount}`];
|
|
726
|
+
if (stats.missingRowids.length > 0) {
|
|
727
|
+
details.push(`missing=${stats.missingRowids.length}`);
|
|
728
|
+
}
|
|
729
|
+
return details.join(", ");
|
|
730
|
+
}
|
|
731
|
+
async function rollbackQuietly(db) {
|
|
732
|
+
try {
|
|
733
|
+
await db.execute("ROLLBACK");
|
|
734
|
+
} catch {
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
async function dropRepairTableQuietly(db) {
|
|
738
|
+
try {
|
|
739
|
+
await db.execute(`DROP TABLE IF EXISTS ${TEMP_REPAIR_TABLE}`);
|
|
740
|
+
} catch {
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
async function repairMissingRowids(db, missingRowids) {
|
|
744
|
+
if (missingRowids.length === 0) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
await db.execute(`DROP TABLE IF EXISTS ${TEMP_REPAIR_TABLE}`);
|
|
748
|
+
await db.execute(`
|
|
749
|
+
CREATE TEMP TABLE ${TEMP_REPAIR_TABLE} (
|
|
750
|
+
rid INTEGER PRIMARY KEY,
|
|
751
|
+
emb BLOB NOT NULL
|
|
752
|
+
)
|
|
753
|
+
`);
|
|
754
|
+
try {
|
|
755
|
+
for (let index = 0; index < missingRowids.length; index += REPAIR_CHUNK_SIZE) {
|
|
756
|
+
const chunk = missingRowids.slice(index, index + REPAIR_CHUNK_SIZE);
|
|
757
|
+
if (chunk.length === 0) {
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
const placeholders = chunk.map(() => "?").join(", ");
|
|
761
|
+
await db.execute(`DELETE FROM ${TEMP_REPAIR_TABLE}`);
|
|
762
|
+
await db.execute({
|
|
763
|
+
sql: `
|
|
764
|
+
INSERT INTO ${TEMP_REPAIR_TABLE} (rid, emb)
|
|
765
|
+
SELECT rowid, embedding
|
|
766
|
+
FROM entries
|
|
767
|
+
WHERE rowid IN (${placeholders})
|
|
768
|
+
`,
|
|
769
|
+
args: chunk
|
|
770
|
+
});
|
|
771
|
+
await db.execute({
|
|
772
|
+
sql: `
|
|
773
|
+
UPDATE entries
|
|
774
|
+
SET embedding = NULL
|
|
775
|
+
WHERE rowid IN (${placeholders})
|
|
776
|
+
`,
|
|
777
|
+
args: chunk
|
|
778
|
+
});
|
|
779
|
+
await db.execute({
|
|
780
|
+
sql: `
|
|
781
|
+
UPDATE entries
|
|
782
|
+
SET embedding = (
|
|
783
|
+
SELECT emb
|
|
784
|
+
FROM ${TEMP_REPAIR_TABLE}
|
|
785
|
+
WHERE rid = entries.rowid
|
|
786
|
+
)
|
|
787
|
+
WHERE rowid IN (${placeholders})
|
|
788
|
+
`,
|
|
789
|
+
args: chunk
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
} finally {
|
|
793
|
+
await dropRepairTableQuietly(db);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
async function getVectorIndexShadowStats(db) {
|
|
797
|
+
const countsResult = await db.execute(`
|
|
798
|
+
SELECT
|
|
799
|
+
(SELECT COUNT(*) FROM entries WHERE ${ACTIVE_EMBEDDED_WHERE_SQL}) AS embedding_count,
|
|
800
|
+
(SELECT COUNT(*) FROM idx_entries_embedding_shadow) AS shadow_count
|
|
801
|
+
`);
|
|
802
|
+
const countsRow = countsResult.rows[0];
|
|
803
|
+
const embeddingCount = toFiniteCount(countsRow?.embedding_count);
|
|
804
|
+
const shadowCount = toFiniteCount(countsRow?.shadow_count);
|
|
805
|
+
const missingResult = await db.execute(`
|
|
806
|
+
SELECT e.rowid AS rowid
|
|
807
|
+
FROM entries AS e
|
|
808
|
+
LEFT JOIN idx_entries_embedding_shadow AS s
|
|
809
|
+
ON s.index_key = e.rowid
|
|
810
|
+
WHERE e.embedding IS NOT NULL
|
|
811
|
+
AND e.retired = 0
|
|
812
|
+
AND e.superseded_by IS NULL
|
|
813
|
+
AND s.index_key IS NULL
|
|
814
|
+
ORDER BY e.rowid ASC
|
|
815
|
+
`);
|
|
816
|
+
const missingRowids = missingResult.rows.map((row) => normalizeRowid(row.rowid)).filter((rowid) => rowid !== null);
|
|
817
|
+
return {
|
|
818
|
+
embeddingCount,
|
|
819
|
+
shadowCount,
|
|
820
|
+
missingRowids
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
async function rebuildVectorIndex(db, options) {
|
|
824
|
+
const start = Date.now();
|
|
825
|
+
const onLog = options?.onLog ?? (() => void 0);
|
|
826
|
+
await db.execute("BEGIN IMMEDIATE");
|
|
827
|
+
try {
|
|
828
|
+
await db.execute("DROP INDEX IF EXISTS idx_entries_embedding");
|
|
829
|
+
await db.execute(CREATE_IDX_ENTRIES_EMBEDDING_SQL);
|
|
830
|
+
await db.execute(SELF_UPDATE_ACTIVE_EMBEDDINGS_SQL);
|
|
831
|
+
const beforeRepair = await getVectorIndexShadowStats(db);
|
|
832
|
+
let repairedCount = 0;
|
|
833
|
+
if (beforeRepair.missingRowids.length > 0) {
|
|
834
|
+
repairedCount = beforeRepair.missingRowids.length;
|
|
835
|
+
onLog(`[vector-index] repairing ${repairedCount} entries missing from shadow table`);
|
|
836
|
+
await repairMissingRowids(db, beforeRepair.missingRowids);
|
|
837
|
+
}
|
|
838
|
+
const afterRepair = await getVectorIndexShadowStats(db);
|
|
839
|
+
if (afterRepair.missingRowids.length > 0 || afterRepair.shadowCount !== afterRepair.embeddingCount) {
|
|
840
|
+
throw new Error(`Vector index shadow table desynced after rebuild (${formatShadowMismatch(afterRepair)})`);
|
|
841
|
+
}
|
|
842
|
+
if (afterRepair.embeddingCount > 0) {
|
|
843
|
+
const verify = await db.execute(`
|
|
844
|
+
SELECT count(*) AS count
|
|
845
|
+
FROM vector_top_k(
|
|
846
|
+
'idx_entries_embedding',
|
|
847
|
+
(SELECT embedding FROM entries WHERE ${ACTIVE_EMBEDDED_WHERE_SQL} LIMIT 1),
|
|
848
|
+
1
|
|
849
|
+
)
|
|
850
|
+
`);
|
|
851
|
+
const verifyCount = toFiniteCount(verify.rows[0]?.count);
|
|
852
|
+
if (verifyCount !== 1) {
|
|
853
|
+
throw new Error(`Vector index rebuild verification failed (expected 1, got ${verifyCount})`);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
await db.execute("COMMIT");
|
|
857
|
+
const durationMs = Date.now() - start;
|
|
858
|
+
onLog(
|
|
859
|
+
`[vector-index] rebuilt for ${afterRepair.embeddingCount} entries (${afterRepair.shadowCount} shadow rows, ${repairedCount} repaired, ${durationMs}ms)`
|
|
860
|
+
);
|
|
861
|
+
return {
|
|
862
|
+
embeddingCount: afterRepair.embeddingCount,
|
|
863
|
+
shadowCount: afterRepair.shadowCount,
|
|
864
|
+
repairedCount,
|
|
865
|
+
durationMs
|
|
866
|
+
};
|
|
867
|
+
} catch (error) {
|
|
868
|
+
await rollbackQuietly(db);
|
|
869
|
+
throw error;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
var ACTIVE_EMBEDDED_WHERE_SQL, SELF_UPDATE_ACTIVE_EMBEDDINGS_SQL, TEMP_REPAIR_TABLE, REPAIR_CHUNK_SIZE;
|
|
873
|
+
var init_vector_index = __esm({
|
|
874
|
+
"src/db/vector-index.ts"() {
|
|
875
|
+
"use strict";
|
|
876
|
+
init_definitions();
|
|
877
|
+
ACTIVE_EMBEDDED_WHERE_SQL = `
|
|
878
|
+
embedding IS NOT NULL
|
|
879
|
+
AND retired = 0
|
|
880
|
+
AND superseded_by IS NULL
|
|
881
|
+
`;
|
|
882
|
+
SELF_UPDATE_ACTIVE_EMBEDDINGS_SQL = `
|
|
883
|
+
UPDATE entries
|
|
884
|
+
SET embedding = embedding
|
|
885
|
+
WHERE ${ACTIVE_EMBEDDED_WHERE_SQL}
|
|
886
|
+
`;
|
|
887
|
+
TEMP_REPAIR_TABLE = "_vec_repair";
|
|
888
|
+
REPAIR_CHUNK_SIZE = 100;
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
|
|
696
892
|
// src/db/schema/fts.ts
|
|
697
893
|
async function rebuildEntriesFts(db) {
|
|
698
894
|
await db.execute("INSERT INTO entries_fts(entries_fts) VALUES('delete-all')");
|
|
@@ -727,31 +923,16 @@ async function rebuildFtsAndTriggers(db) {
|
|
|
727
923
|
throw error;
|
|
728
924
|
}
|
|
729
925
|
}
|
|
730
|
-
async function
|
|
926
|
+
async function rebuildVectorIndex2(db) {
|
|
731
927
|
try {
|
|
732
928
|
await db.execute("REINDEX idx_entries_embedding");
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
await db.execute("BEGIN IMMEDIATE");
|
|
737
|
-
try {
|
|
738
|
-
await db.execute("DROP INDEX IF EXISTS idx_entries_embedding");
|
|
739
|
-
await db.execute(CREATE_IDX_ENTRIES_EMBEDDING_SQL);
|
|
740
|
-
await db.execute(`
|
|
741
|
-
UPDATE entries
|
|
742
|
-
SET embedding = embedding
|
|
743
|
-
WHERE embedding IS NOT NULL
|
|
744
|
-
AND retired = 0
|
|
745
|
-
AND superseded_by IS NULL
|
|
746
|
-
`);
|
|
747
|
-
await db.execute("COMMIT");
|
|
748
|
-
} catch (fallbackError) {
|
|
749
|
-
try {
|
|
750
|
-
await db.execute("ROLLBACK");
|
|
751
|
-
} catch {
|
|
929
|
+
const stats = await getVectorIndexShadowStats(db);
|
|
930
|
+
if (stats.shadowCount === stats.embeddingCount && stats.missingRowids.length === 0) {
|
|
931
|
+
return;
|
|
752
932
|
}
|
|
753
|
-
|
|
933
|
+
} catch {
|
|
754
934
|
}
|
|
935
|
+
await rebuildVectorIndex(db);
|
|
755
936
|
}
|
|
756
937
|
async function clearBulkIngestMeta(db) {
|
|
757
938
|
await db.execute({ sql: "DELETE FROM _meta WHERE key = ?", args: [BULK_INGEST_META_KEY] });
|
|
@@ -777,6 +958,7 @@ var BULK_INGEST_META_KEY;
|
|
|
777
958
|
var init_bulk_ingest = __esm({
|
|
778
959
|
"src/db/schema/bulk-ingest.ts"() {
|
|
779
960
|
"use strict";
|
|
961
|
+
init_vector_index();
|
|
780
962
|
init_definitions();
|
|
781
963
|
init_fts();
|
|
782
964
|
BULK_INGEST_META_KEY = "bulk_ingest_state";
|
|
@@ -1358,15 +1540,10 @@ async function repairVectorIndexIfNeeded(client) {
|
|
|
1358
1540
|
if (probeCount > 0) {
|
|
1359
1541
|
return;
|
|
1360
1542
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
SET embedding = embedding
|
|
1366
|
-
WHERE embedding IS NOT NULL
|
|
1367
|
-
AND retired = 0
|
|
1368
|
-
AND superseded_by IS NULL
|
|
1369
|
-
`);
|
|
1543
|
+
} catch {
|
|
1544
|
+
}
|
|
1545
|
+
try {
|
|
1546
|
+
await rebuildVectorIndex(client);
|
|
1370
1547
|
} catch {
|
|
1371
1548
|
}
|
|
1372
1549
|
}
|
|
@@ -1395,6 +1572,7 @@ var init_init = __esm({
|
|
|
1395
1572
|
init_version();
|
|
1396
1573
|
init_reflection_importance_cap();
|
|
1397
1574
|
init_reflection_removal();
|
|
1575
|
+
init_vector_index();
|
|
1398
1576
|
init_definitions();
|
|
1399
1577
|
init_entry_provenance();
|
|
1400
1578
|
init_fts();
|
|
@@ -1596,7 +1774,7 @@ async function checkAndRecoverBulkIngest(client) {
|
|
|
1596
1774
|
}
|
|
1597
1775
|
}
|
|
1598
1776
|
if (indexCount < 1) {
|
|
1599
|
-
await
|
|
1777
|
+
await rebuildVectorIndex2(client);
|
|
1600
1778
|
}
|
|
1601
1779
|
try {
|
|
1602
1780
|
const integrityResult = await client.execute("PRAGMA integrity_check");
|
|
@@ -4428,7 +4606,7 @@ var init_source_classification = __esm({
|
|
|
4428
4606
|
});
|
|
4429
4607
|
|
|
4430
4608
|
// src/utils/entry-utils.ts
|
|
4431
|
-
function
|
|
4609
|
+
function toNumber2(value) {
|
|
4432
4610
|
if (typeof value === "number") {
|
|
4433
4611
|
return value;
|
|
4434
4612
|
}
|
|
@@ -4537,10 +4715,10 @@ function mapRawStoredEntry(row, options) {
|
|
|
4537
4715
|
const entryKind = toStringValue(row.entry_kind).trim();
|
|
4538
4716
|
const temporalClass = toStringValue(row.temporal_class).trim();
|
|
4539
4717
|
const scopeRaw = toStringValue(row.scope).trim();
|
|
4540
|
-
const importanceRaw =
|
|
4541
|
-
const confirmationsRaw =
|
|
4542
|
-
const contradictionsRaw =
|
|
4543
|
-
const qualityScoreRaw =
|
|
4718
|
+
const importanceRaw = toNumber2(row.importance);
|
|
4719
|
+
const confirmationsRaw = toNumber2(row.confirmations);
|
|
4720
|
+
const contradictionsRaw = toNumber2(row.contradictions);
|
|
4721
|
+
const qualityScoreRaw = toNumber2(row.quality_score);
|
|
4544
4722
|
const subjectEntity = toStringValue(row.subject_entity).trim();
|
|
4545
4723
|
const subjectAttribute = toStringValue(row.subject_attribute).trim();
|
|
4546
4724
|
const subjectKey2 = toStringValue(row.subject_key).trim();
|
|
@@ -4548,8 +4726,8 @@ function mapRawStoredEntry(row, options) {
|
|
|
4548
4726
|
const claimObject = toStringValue(row.claim_object).trim();
|
|
4549
4727
|
const claimRole = toStringValue(row.claim_role).trim();
|
|
4550
4728
|
const normalizedClaimRole = normalizeClaimRole2(claimRole);
|
|
4551
|
-
const claimConfidenceRaw =
|
|
4552
|
-
const retiredRaw =
|
|
4729
|
+
const claimConfidenceRaw = toNumber2(row.claim_confidence);
|
|
4730
|
+
const retiredRaw = toNumber2(row.retired);
|
|
4553
4731
|
const clusterId = toStringValue(row.cluster_id).trim();
|
|
4554
4732
|
const sourceClass = normalizeSourceClass(toStringValue(row.source_class));
|
|
4555
4733
|
const suppressedContextsRaw = toStringValue(row.suppressed_contexts);
|
|
@@ -4752,14 +4930,14 @@ function normalizeEntryIds(entryIds) {
|
|
|
4752
4930
|
);
|
|
4753
4931
|
}
|
|
4754
4932
|
function parseCount(value) {
|
|
4755
|
-
const parsed =
|
|
4933
|
+
const parsed = toNumber2(value);
|
|
4756
4934
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4757
4935
|
return 0;
|
|
4758
4936
|
}
|
|
4759
4937
|
return Math.floor(parsed);
|
|
4760
4938
|
}
|
|
4761
4939
|
function parseSignalTotal(value) {
|
|
4762
|
-
const parsed =
|
|
4940
|
+
const parsed = toNumber2(value);
|
|
4763
4941
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4764
4942
|
return 0;
|
|
4765
4943
|
}
|
|
@@ -4773,7 +4951,7 @@ function parseIsoTimestamp(value) {
|
|
|
4773
4951
|
return normalized.length > 0 ? normalized : null;
|
|
4774
4952
|
}
|
|
4775
4953
|
function parseGapDays(value) {
|
|
4776
|
-
const parsed =
|
|
4954
|
+
const parsed = toNumber2(value);
|
|
4777
4955
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4778
4956
|
return 0;
|
|
4779
4957
|
}
|
|
@@ -4979,7 +5157,7 @@ async function getStoredEntryById(db, id) {
|
|
|
4979
5157
|
}
|
|
4980
5158
|
async function getTotalEntries(db) {
|
|
4981
5159
|
const result = await db.execute("SELECT COUNT(*) AS count FROM entries");
|
|
4982
|
-
const count =
|
|
5160
|
+
const count = toNumber2(result.rows[0]?.count);
|
|
4983
5161
|
return Number.isFinite(count) ? count : 0;
|
|
4984
5162
|
}
|
|
4985
5163
|
async function hasContentHash(db, contentHash) {
|
|
@@ -5344,7 +5522,7 @@ async function findRecentEntriesBySubjectTypeAndSourceFile(db, requests) {
|
|
|
5344
5522
|
normalizedSubject: toStringValue(row.lookup_normalized_subject),
|
|
5345
5523
|
type: toStringValue(row.lookup_type),
|
|
5346
5524
|
sourceFile: toStringValue(row.lookup_source_file),
|
|
5347
|
-
withinHours:
|
|
5525
|
+
withinHours: toNumber2(row.lookup_within_hours),
|
|
5348
5526
|
entry: mapEntryRow(row, { tags: tagsById.get(entryId) ?? [], includeEmbedding: true })
|
|
5349
5527
|
});
|
|
5350
5528
|
}
|
|
@@ -5879,6 +6057,10 @@ var init_similarity = __esm({
|
|
|
5879
6057
|
|
|
5880
6058
|
// src/utils/content-fingerprint.ts
|
|
5881
6059
|
import { createHash as createHash3 } from "crypto";
|
|
6060
|
+
function computeNormContentHash(content) {
|
|
6061
|
+
const normalized = content.toLowerCase().replace(/\s+/g, " ").trim().replace(/[^\w\s]/g, "");
|
|
6062
|
+
return createHash3("sha256").update(normalized).digest("hex");
|
|
6063
|
+
}
|
|
5882
6064
|
var init_content_fingerprint = __esm({
|
|
5883
6065
|
"src/utils/content-fingerprint.ts"() {
|
|
5884
6066
|
"use strict";
|
|
@@ -6278,12 +6460,12 @@ async function getConflictShadowSummary(db) {
|
|
|
6278
6460
|
continue;
|
|
6279
6461
|
}
|
|
6280
6462
|
const relationSummary = {
|
|
6281
|
-
totalEvaluated: Number.isFinite(
|
|
6282
|
-
blockedAtCurrent: Number.isFinite(
|
|
6283
|
-
currentOnlyBand: Number.isFinite(
|
|
6284
|
-
wouldStillBlockAt090: Number.isFinite(
|
|
6285
|
-
wouldStillBlockAt095: Number.isFinite(
|
|
6286
|
-
silentCoexistBand: Number.isFinite(
|
|
6463
|
+
totalEvaluated: Number.isFinite(toNumber2(record.total)) ? toNumber2(record.total) : 0,
|
|
6464
|
+
blockedAtCurrent: Number.isFinite(toNumber2(record.blocked_current)) ? toNumber2(record.blocked_current) : 0,
|
|
6465
|
+
currentOnlyBand: Number.isFinite(toNumber2(record.current_only)) ? toNumber2(record.current_only) : 0,
|
|
6466
|
+
wouldStillBlockAt090: Number.isFinite(toNumber2(record.still_block_090)) ? toNumber2(record.still_block_090) : 0,
|
|
6467
|
+
wouldStillBlockAt095: Number.isFinite(toNumber2(record.still_block_095)) ? toNumber2(record.still_block_095) : 0,
|
|
6468
|
+
silentCoexistBand: Number.isFinite(toNumber2(record.silent_coexist)) ? toNumber2(record.silent_coexist) : 0
|
|
6287
6469
|
};
|
|
6288
6470
|
byRelation[relation] = relationSummary;
|
|
6289
6471
|
totalEvaluated += relationSummary.totalEvaluated;
|
|
@@ -6732,7 +6914,7 @@ async function getCoRecallEdgeCounts(db) {
|
|
|
6732
6914
|
if (!entryId) {
|
|
6733
6915
|
continue;
|
|
6734
6916
|
}
|
|
6735
|
-
counts.set(entryId, Math.max(0,
|
|
6917
|
+
counts.set(entryId, Math.max(0, toNumber2(row.edge_count)));
|
|
6736
6918
|
}
|
|
6737
6919
|
return counts;
|
|
6738
6920
|
}
|
|
@@ -7042,10 +7224,10 @@ async function evolveQualityScores(db, options = {}, config) {
|
|
|
7042
7224
|
return {
|
|
7043
7225
|
id,
|
|
7044
7226
|
type: toStringValue(row.type),
|
|
7045
|
-
importance: Math.max(0,
|
|
7227
|
+
importance: Math.max(0, toNumber2(row.importance)),
|
|
7046
7228
|
recallCount: Math.max(0, metrics?.totalCount ?? 0),
|
|
7047
|
-
confirmations: Math.max(0,
|
|
7048
|
-
qualityScore:
|
|
7229
|
+
confirmations: Math.max(0, toNumber2(row.confirmations)),
|
|
7230
|
+
qualityScore: toNumber2(row.quality_score),
|
|
7049
7231
|
lastRecalledAt: metrics?.lastLiveRecalledAt ?? metrics?.lastAnyRecalledAt ?? "",
|
|
7050
7232
|
createdAt: toStringValue(row.created_at)
|
|
7051
7233
|
};
|
|
@@ -7402,8 +7584,8 @@ async function fetchRecalledEntryMetrics(db, entryIds) {
|
|
|
7402
7584
|
});
|
|
7403
7585
|
return result.rows.map((row) => ({
|
|
7404
7586
|
id: toStringValue(row.id),
|
|
7405
|
-
qualityScore:
|
|
7406
|
-
recallEventsCount:
|
|
7587
|
+
qualityScore: toNumber2(row.quality_score),
|
|
7588
|
+
recallEventsCount: toNumber2(row.recall_events_count)
|
|
7407
7589
|
}));
|
|
7408
7590
|
}
|
|
7409
7591
|
async function processBeforeResetRecallFeedback(request, deps) {
|
|
@@ -7481,66 +7663,6 @@ var init_watcher_demotion = __esm({
|
|
|
7481
7663
|
}
|
|
7482
7664
|
});
|
|
7483
7665
|
|
|
7484
|
-
// src/db/vector-index.ts
|
|
7485
|
-
function toNumber2(value) {
|
|
7486
|
-
if (typeof value === "number") {
|
|
7487
|
-
return value;
|
|
7488
|
-
}
|
|
7489
|
-
if (typeof value === "bigint") {
|
|
7490
|
-
return Number(value);
|
|
7491
|
-
}
|
|
7492
|
-
if (typeof value === "string" && value.trim()) {
|
|
7493
|
-
return Number(value);
|
|
7494
|
-
}
|
|
7495
|
-
return Number.NaN;
|
|
7496
|
-
}
|
|
7497
|
-
async function rebuildVectorIndex2(db, options) {
|
|
7498
|
-
const start = Date.now();
|
|
7499
|
-
const onLog = options?.onLog ?? (() => void 0);
|
|
7500
|
-
await db.execute("DROP INDEX IF EXISTS idx_entries_embedding");
|
|
7501
|
-
await db.execute(CREATE_IDX_ENTRIES_EMBEDDING_SQL);
|
|
7502
|
-
await db.execute(`
|
|
7503
|
-
UPDATE entries
|
|
7504
|
-
SET embedding = embedding
|
|
7505
|
-
WHERE embedding IS NOT NULL
|
|
7506
|
-
AND retired = 0
|
|
7507
|
-
AND superseded_by IS NULL
|
|
7508
|
-
`);
|
|
7509
|
-
const result = await db.execute(`
|
|
7510
|
-
SELECT COUNT(*) AS count
|
|
7511
|
-
FROM entries
|
|
7512
|
-
WHERE embedding IS NOT NULL
|
|
7513
|
-
AND retired = 0
|
|
7514
|
-
AND superseded_by IS NULL
|
|
7515
|
-
`);
|
|
7516
|
-
const embeddingCountRaw = result.rows[0]?.count;
|
|
7517
|
-
const embeddingCount = Number.isFinite(toNumber2(embeddingCountRaw)) ? toNumber2(embeddingCountRaw) : 0;
|
|
7518
|
-
if (embeddingCount > 0) {
|
|
7519
|
-
const verify = await db.execute(`
|
|
7520
|
-
SELECT count(*) AS count
|
|
7521
|
-
FROM vector_top_k(
|
|
7522
|
-
'idx_entries_embedding',
|
|
7523
|
-
(SELECT embedding FROM entries WHERE embedding IS NOT NULL AND retired = 0 AND superseded_by IS NULL LIMIT 1),
|
|
7524
|
-
1
|
|
7525
|
-
)
|
|
7526
|
-
`);
|
|
7527
|
-
const verifyCountRaw = verify.rows[0]?.count;
|
|
7528
|
-
const verifyCount = Number.isFinite(toNumber2(verifyCountRaw)) ? toNumber2(verifyCountRaw) : 0;
|
|
7529
|
-
if (verifyCount !== 1) {
|
|
7530
|
-
throw new Error(`Vector index rebuild verification failed (expected 1, got ${verifyCount})`);
|
|
7531
|
-
}
|
|
7532
|
-
}
|
|
7533
|
-
const durationMs = Date.now() - start;
|
|
7534
|
-
onLog(`[vector-index] rebuilt for ${embeddingCount} entries (${durationMs}ms)`);
|
|
7535
|
-
return { embeddingCount, durationMs };
|
|
7536
|
-
}
|
|
7537
|
-
var init_vector_index = __esm({
|
|
7538
|
-
"src/db/vector-index.ts"() {
|
|
7539
|
-
"use strict";
|
|
7540
|
-
init_schema();
|
|
7541
|
-
}
|
|
7542
|
-
});
|
|
7543
|
-
|
|
7544
7666
|
// src/runtime/db-command-defaults.ts
|
|
7545
7667
|
function resolveDbCommandDefaults() {
|
|
7546
7668
|
const shared = resolveDefaultAppRuntimeDeps();
|
|
@@ -7553,7 +7675,7 @@ function resolveDbCommandDefaults() {
|
|
|
7553
7675
|
getConflictShadowSummary,
|
|
7554
7676
|
resetDb,
|
|
7555
7677
|
walCheckpoint,
|
|
7556
|
-
rebuildVectorIndex
|
|
7678
|
+
rebuildVectorIndex,
|
|
7557
7679
|
evolveQualityScores
|
|
7558
7680
|
};
|
|
7559
7681
|
}
|
|
@@ -8882,6 +9004,47 @@ async function finalizeRecallResults(params) {
|
|
|
8882
9004
|
return results;
|
|
8883
9005
|
}
|
|
8884
9006
|
|
|
9007
|
+
// src/domain/recall/browse-selection.ts
|
|
9008
|
+
var DEFAULT_BROWSE_DIVERSITY_TARGET = 4;
|
|
9009
|
+
function normalizeEntryType(result) {
|
|
9010
|
+
const rawType = result.entry.type;
|
|
9011
|
+
return typeof rawType === "string" ? rawType.trim().toLowerCase() : "";
|
|
9012
|
+
}
|
|
9013
|
+
function diversifyBrowseResults(results, limit, diversityTarget = DEFAULT_BROWSE_DIVERSITY_TARGET) {
|
|
9014
|
+
const normalizedLimit = Math.max(0, Math.floor(limit));
|
|
9015
|
+
if (normalizedLimit === 0 || results.length === 0) {
|
|
9016
|
+
return [];
|
|
9017
|
+
}
|
|
9018
|
+
const normalizedDiversityTarget = Math.max(0, Math.floor(diversityTarget));
|
|
9019
|
+
const seedTarget = Math.min(normalizedLimit, normalizedDiversityTarget);
|
|
9020
|
+
const selected = [];
|
|
9021
|
+
const selectedIds = /* @__PURE__ */ new Set();
|
|
9022
|
+
const admittedTypes = /* @__PURE__ */ new Set();
|
|
9023
|
+
for (const result of results) {
|
|
9024
|
+
if (selected.length >= seedTarget) {
|
|
9025
|
+
break;
|
|
9026
|
+
}
|
|
9027
|
+
const normalizedType = normalizeEntryType(result);
|
|
9028
|
+
if (!normalizedType || admittedTypes.has(normalizedType)) {
|
|
9029
|
+
continue;
|
|
9030
|
+
}
|
|
9031
|
+
selected.push(result);
|
|
9032
|
+
selectedIds.add(result.entry.id);
|
|
9033
|
+
admittedTypes.add(normalizedType);
|
|
9034
|
+
}
|
|
9035
|
+
for (const result of results) {
|
|
9036
|
+
if (selected.length >= normalizedLimit) {
|
|
9037
|
+
break;
|
|
9038
|
+
}
|
|
9039
|
+
if (selectedIds.has(result.entry.id)) {
|
|
9040
|
+
continue;
|
|
9041
|
+
}
|
|
9042
|
+
selected.push(result);
|
|
9043
|
+
selectedIds.add(result.entry.id);
|
|
9044
|
+
}
|
|
9045
|
+
return selected;
|
|
9046
|
+
}
|
|
9047
|
+
|
|
8885
9048
|
// src/db/recall/pipeline/retrieval.ts
|
|
8886
9049
|
init_client2();
|
|
8887
9050
|
|
|
@@ -9045,6 +9208,8 @@ var DEFAULT_RECALL_SATURATION = 10;
|
|
|
9045
9208
|
var DEFAULT_WARM_START_THRESHOLD = 3;
|
|
9046
9209
|
var DEFAULT_SYNTHETIC_FLOOR = 0.1;
|
|
9047
9210
|
var DEFAULT_AGENT_SOURCE_BONUS = 0.05;
|
|
9211
|
+
var BROWSE_RECENCY_WEIGHT = 0.8;
|
|
9212
|
+
var BROWSE_IMPORTANCE_WEIGHT = 0.2;
|
|
9048
9213
|
var MISSING_RECALL_DAYS = 99999;
|
|
9049
9214
|
var EMPTY_RECALL_METRICS = {
|
|
9050
9215
|
totalCount: 0,
|
|
@@ -9166,7 +9331,9 @@ function browseRecencyFactor(entry, now, aroundDate, aroundRadius = DEFAULT_AROU
|
|
|
9166
9331
|
return resolveRecallRecency(entry, now, aroundDate, aroundRadius);
|
|
9167
9332
|
}
|
|
9168
9333
|
function scoreBrowseEntry(entry, now, aroundDate, aroundRadius = DEFAULT_AROUND_RADIUS_DAYS) {
|
|
9169
|
-
|
|
9334
|
+
const recency2 = browseRecencyFactor(entry, now, aroundDate, aroundRadius);
|
|
9335
|
+
const importance = importanceScore(entry.importance);
|
|
9336
|
+
return clamp01(recency2 * BROWSE_RECENCY_WEIGHT + importance * BROWSE_IMPORTANCE_WEIGHT);
|
|
9170
9337
|
}
|
|
9171
9338
|
function scoreSessionEntry(entry, effectiveNow, freshnessNow, metricsMap, aroundDate, aroundRadius = DEFAULT_AROUND_RADIUS_DAYS, config) {
|
|
9172
9339
|
return scoreEntryWithBreakdown(
|
|
@@ -9702,8 +9869,21 @@ async function fetchBrowseCandidates(params) {
|
|
|
9702
9869
|
whereClauses.push("platform = ?");
|
|
9703
9870
|
args.push(params.query.platform);
|
|
9704
9871
|
}
|
|
9705
|
-
args.push(params.limit);
|
|
9706
9872
|
const whereClause = whereClauses.length > 0 ? "WHERE " + whereClauses.join(" AND ") : "";
|
|
9873
|
+
const orderBy = params.aroundDate ? `
|
|
9874
|
+
ORDER BY
|
|
9875
|
+
ABS(julianday(created_at) - julianday(?)) ASC,
|
|
9876
|
+
importance DESC,
|
|
9877
|
+
created_at DESC
|
|
9878
|
+
` : `
|
|
9879
|
+
ORDER BY
|
|
9880
|
+
created_at DESC,
|
|
9881
|
+
importance DESC
|
|
9882
|
+
`;
|
|
9883
|
+
if (params.aroundDate) {
|
|
9884
|
+
args.push(params.aroundDate.toISOString());
|
|
9885
|
+
}
|
|
9886
|
+
args.push(params.limit);
|
|
9707
9887
|
const result = await params.db.execute({
|
|
9708
9888
|
sql: `
|
|
9709
9889
|
SELECT
|
|
@@ -9711,10 +9891,10 @@ async function fetchBrowseCandidates(params) {
|
|
|
9711
9891
|
FROM entries
|
|
9712
9892
|
${whereClause}
|
|
9713
9893
|
-- SQL pre-sort is a best-effort approximation only.
|
|
9714
|
-
-- Final order is determined by
|
|
9715
|
-
--
|
|
9894
|
+
-- Final order is determined by recency-first browse scoring and a post-score
|
|
9895
|
+
-- diversity pass. The over-fetch buffer (limit*3, min 50)
|
|
9716
9896
|
-- ensures the final top-N are present in the candidate pool.
|
|
9717
|
-
|
|
9897
|
+
${orderBy}
|
|
9718
9898
|
LIMIT ?
|
|
9719
9899
|
`,
|
|
9720
9900
|
args
|
|
@@ -9947,6 +10127,7 @@ async function recallBrowseMode(params) {
|
|
|
9947
10127
|
query: browseQuery,
|
|
9948
10128
|
limit: browseLimit,
|
|
9949
10129
|
now: params.now,
|
|
10130
|
+
aroundDate: params.prepared.temporal.aroundDate,
|
|
9950
10131
|
projectFilter: params.prepared.scope.resolution.primaryFilter
|
|
9951
10132
|
});
|
|
9952
10133
|
const filtered = browseCandidates.filter(
|
|
@@ -9967,7 +10148,11 @@ async function recallBrowseMode(params) {
|
|
|
9967
10148
|
aroundRadiusDays: params.prepared.temporal.aroundRadiusDays
|
|
9968
10149
|
});
|
|
9969
10150
|
scored.sort((left, right) => right.score - left.score);
|
|
9970
|
-
|
|
10151
|
+
const results = diversifyBrowseResults(scored, requestedLimit, DEFAULT_BROWSE_DIVERSITY_TARGET);
|
|
10152
|
+
if (params.trace) {
|
|
10153
|
+
params.trace.finalResultIds = results.map((result) => result.entry.subject ?? result.entry.id);
|
|
10154
|
+
}
|
|
10155
|
+
return results;
|
|
9971
10156
|
}
|
|
9972
10157
|
async function retrieveCandidates(params) {
|
|
9973
10158
|
if (!params.prepared.retrievalSearchText) {
|
|
@@ -10377,11 +10562,12 @@ function resolvePreparedRecallScope(query, normalizedQuery) {
|
|
|
10377
10562
|
const explicitWildcardProject = hasWildcardProjectOverride(query.project);
|
|
10378
10563
|
const explicitProjects = explicitWildcardProject ? [] : parseProjectList(query.project);
|
|
10379
10564
|
const explicitExcludedProjects = parseProjectList(query.excludeProject);
|
|
10380
|
-
const inferredProjectHints = deriveRecallProjectScopeHints({
|
|
10565
|
+
const inferredProjectHints = explicitWildcardProject ? [] : deriveRecallProjectScopeHints({
|
|
10381
10566
|
queryText: normalizedQuery?.searchText ?? query.text ?? "",
|
|
10382
10567
|
explicitProjects
|
|
10383
10568
|
});
|
|
10384
|
-
const
|
|
10569
|
+
const callerProjectHints = explicitProjects.length > 0 || explicitWildcardProject ? [] : parseProjectList(query.projectHints).filter((projectHint) => projectHint !== "*");
|
|
10570
|
+
const projectHints = explicitProjects.length > 0 ? explicitProjects : Array.from(/* @__PURE__ */ new Set([...inferredProjectHints, ...callerProjectHints]));
|
|
10385
10571
|
const intent = projectHints.length > 0 ? "project" : normalizedQuery?.scopeIntent ?? "ambiguous";
|
|
10386
10572
|
if (query.universalOnly === true) {
|
|
10387
10573
|
return {
|
|
@@ -12126,6 +12312,7 @@ function buildRecallQuery(request, options) {
|
|
|
12126
12312
|
scope: request.scope ?? "private",
|
|
12127
12313
|
platform: request.platform,
|
|
12128
12314
|
project: request.project,
|
|
12315
|
+
projectHints: request.projectHints,
|
|
12129
12316
|
excludeProject: request.excludeProject,
|
|
12130
12317
|
projectStrict: request.projectStrict,
|
|
12131
12318
|
universalOnly: request.universalOnly,
|
|
@@ -12454,6 +12641,9 @@ async function sessionStartRecall2(request, deps) {
|
|
|
12454
12641
|
});
|
|
12455
12642
|
}
|
|
12456
12643
|
|
|
12644
|
+
// src/openclaw-plugin/recall.ts
|
|
12645
|
+
init_project();
|
|
12646
|
+
|
|
12457
12647
|
// src/openclaw-plugin/memory-index.ts
|
|
12458
12648
|
init_errors();
|
|
12459
12649
|
var MEMORY_INDEX_TIMEOUT_MS = 1e4;
|
|
@@ -12587,18 +12777,23 @@ function buildRecallRequest(budget, project, query, options) {
|
|
|
12587
12777
|
const queryText = trimmedQuery.length > RECALL_QUERY_MAX_CHARS ? trimmedQuery.slice(0, RECALL_QUERY_MAX_CHARS) : trimmedQuery;
|
|
12588
12778
|
const inferredSessionStart = isSessionStart || queryText.length === 0;
|
|
12589
12779
|
const universalOnly = options?.nullProjectOnly === true || options?.universalOnly === true;
|
|
12590
|
-
const
|
|
12780
|
+
const explicitWildcardProject = (options?.project ?? []).some(
|
|
12781
|
+
(candidate) => candidate.split(",").some((part) => part.trim() === "*")
|
|
12782
|
+
);
|
|
12591
12783
|
const normalizedProjects = Array.from(new Set(
|
|
12592
12784
|
(options?.project ?? []).map((candidate) => candidate.trim()).filter((candidate) => candidate.length > 0)
|
|
12593
12785
|
));
|
|
12594
|
-
const
|
|
12595
|
-
const
|
|
12786
|
+
const explicitProjectSelection = explicitWildcardProject || normalizedProjects.length > 0;
|
|
12787
|
+
const normalizedProjectHints = parseProjectList(options?.projectHints).filter((projectHint) => projectHint !== "*");
|
|
12788
|
+
const resolvedProject = universalOnly ? void 0 : explicitProjectSelection ? normalizedProjects.length > 0 ? normalizedProjects : void 0 : !project ? void 0 : [project];
|
|
12789
|
+
const resolvedProjectStrict = universalOnly ? void 0 : explicitProjectSelection ? options?.projectStrict ? true : void 0 : project && !universalOnly ? true : void 0;
|
|
12790
|
+
const resolvedProjectHints = universalOnly || explicitProjectSelection || explicitWildcardProject ? void 0 : normalizedProjectHints.length > 0 ? normalizedProjectHints : void 0;
|
|
12596
12791
|
return {
|
|
12597
12792
|
isBrowse,
|
|
12598
12793
|
isSessionStart: !isBrowse && inferredSessionStart,
|
|
12599
12794
|
limit: options?.limit ?? DEFAULT_LIMIT2,
|
|
12600
12795
|
queryText,
|
|
12601
|
-
since:
|
|
12796
|
+
since: options?.since,
|
|
12602
12797
|
types: options?.types,
|
|
12603
12798
|
until: options?.until,
|
|
12604
12799
|
around: options?.around,
|
|
@@ -12609,6 +12804,7 @@ function buildRecallRequest(budget, project, query, options) {
|
|
|
12609
12804
|
universalOnly,
|
|
12610
12805
|
project: resolvedProject,
|
|
12611
12806
|
projectStrict: resolvedProjectStrict,
|
|
12807
|
+
projectHints: resolvedProjectHints,
|
|
12612
12808
|
budget: isBrowse ? void 0 : options?.budget === null ? void 0 : options?.budget ?? budget
|
|
12613
12809
|
};
|
|
12614
12810
|
}
|
|
@@ -12658,6 +12854,7 @@ async function executeRecallRequest(budget, project, query, options, dbPath, exe
|
|
|
12658
12854
|
expiry: request.expiry,
|
|
12659
12855
|
project: request.project,
|
|
12660
12856
|
projectStrict: request.projectStrict,
|
|
12857
|
+
projectHints: request.projectHints,
|
|
12661
12858
|
universalOnly: request.universalOnly,
|
|
12662
12859
|
includeRecallCounts: false
|
|
12663
12860
|
},
|
|
@@ -12678,6 +12875,7 @@ async function executeRecallRequest(budget, project, query, options, dbPath, exe
|
|
|
12678
12875
|
expiry: request.expiry,
|
|
12679
12876
|
project: request.project,
|
|
12680
12877
|
projectStrict: request.projectStrict,
|
|
12878
|
+
projectHints: request.projectHints,
|
|
12681
12879
|
universalOnly: request.universalOnly,
|
|
12682
12880
|
updateMetadata,
|
|
12683
12881
|
includeRecallCounts: false
|
|
@@ -12701,6 +12899,7 @@ async function executeRecallRequest(budget, project, query, options, dbPath, exe
|
|
|
12701
12899
|
expiry: request.expiry,
|
|
12702
12900
|
project: request.project,
|
|
12703
12901
|
projectStrict: request.projectStrict,
|
|
12902
|
+
projectHints: request.projectHints,
|
|
12704
12903
|
universalOnly: request.universalOnly,
|
|
12705
12904
|
updateMetadata,
|
|
12706
12905
|
includeRecallCounts: false
|
|
@@ -14923,6 +15122,31 @@ var genericJsonlAdapter = {
|
|
|
14923
15122
|
|
|
14924
15123
|
// src/adapters/openclaw.ts
|
|
14925
15124
|
import fs13 from "fs/promises";
|
|
15125
|
+
init_content_fingerprint();
|
|
15126
|
+
|
|
15127
|
+
// src/utils/expiry.ts
|
|
15128
|
+
init_types();
|
|
15129
|
+
var EXPIRY_SET = new Set(EXPIRY_LEVELS);
|
|
15130
|
+
var EXPIRY_PRIORITY = {
|
|
15131
|
+
temporary: 0,
|
|
15132
|
+
permanent: 1,
|
|
15133
|
+
core: 2
|
|
15134
|
+
};
|
|
15135
|
+
function normalizeExpiry(value) {
|
|
15136
|
+
if (typeof value !== "string") {
|
|
15137
|
+
return void 0;
|
|
15138
|
+
}
|
|
15139
|
+
const normalized = value.trim().toLowerCase();
|
|
15140
|
+
if (!normalized) {
|
|
15141
|
+
return void 0;
|
|
15142
|
+
}
|
|
15143
|
+
return EXPIRY_SET.has(normalized) ? normalized : void 0;
|
|
15144
|
+
}
|
|
15145
|
+
function resolveHigherExpiry(a, b) {
|
|
15146
|
+
return EXPIRY_PRIORITY[a] >= EXPIRY_PRIORITY[b] ? a : b;
|
|
15147
|
+
}
|
|
15148
|
+
|
|
15149
|
+
// src/adapters/openclaw.ts
|
|
14926
15150
|
init_string();
|
|
14927
15151
|
function normalizeOpenClawRole(value) {
|
|
14928
15152
|
if (typeof value !== "string") {
|
|
@@ -14968,10 +15192,120 @@ function getStringArray(value) {
|
|
|
14968
15192
|
const values = value.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
14969
15193
|
return values.length > 0 ? values : void 0;
|
|
14970
15194
|
}
|
|
15195
|
+
function parseJsonRecord(value) {
|
|
15196
|
+
try {
|
|
15197
|
+
return asRecord4(JSON.parse(value));
|
|
15198
|
+
} catch {
|
|
15199
|
+
return null;
|
|
15200
|
+
}
|
|
15201
|
+
}
|
|
15202
|
+
function normalizeProjectValue(value) {
|
|
15203
|
+
const trimmed = value?.trim();
|
|
15204
|
+
return trimmed ? trimmed.toLowerCase() : void 0;
|
|
15205
|
+
}
|
|
14971
15206
|
function normalizeSessionLabel(value) {
|
|
14972
15207
|
const normalized = normalizeLabel(value);
|
|
14973
15208
|
return normalized.length > 0 ? normalized : void 0;
|
|
14974
15209
|
}
|
|
15210
|
+
function normalizeHintSubject(subject) {
|
|
15211
|
+
const trimmed = subject?.trim().toLowerCase();
|
|
15212
|
+
return trimmed ? trimmed : void 0;
|
|
15213
|
+
}
|
|
15214
|
+
function extractRecallResultsPayload(message, toolText) {
|
|
15215
|
+
const details = asRecord4(message.details);
|
|
15216
|
+
if (Array.isArray(details?.results)) {
|
|
15217
|
+
return details.results;
|
|
15218
|
+
}
|
|
15219
|
+
const parsedPayload = parseJsonRecord(toolText);
|
|
15220
|
+
if (Array.isArray(parsedPayload?.results)) {
|
|
15221
|
+
return parsedPayload.results;
|
|
15222
|
+
}
|
|
15223
|
+
return [];
|
|
15224
|
+
}
|
|
15225
|
+
function extractRecallTargetHints(message, toolText) {
|
|
15226
|
+
const hints = [];
|
|
15227
|
+
for (const result of extractRecallResultsPayload(message, toolText)) {
|
|
15228
|
+
const resultRecord = asRecord4(result);
|
|
15229
|
+
const entryRecord = asRecord4(resultRecord?.entry);
|
|
15230
|
+
const recalledEntryId = getString4(entryRecord?.id);
|
|
15231
|
+
const type = getString4(entryRecord?.type);
|
|
15232
|
+
const subject = getString4(entryRecord?.subject);
|
|
15233
|
+
const content = getString4(entryRecord?.content);
|
|
15234
|
+
if (!recalledEntryId || !type || !subject || !content) {
|
|
15235
|
+
continue;
|
|
15236
|
+
}
|
|
15237
|
+
const source = asRecord4(entryRecord?.source);
|
|
15238
|
+
hints.push({
|
|
15239
|
+
recalledEntryId,
|
|
15240
|
+
type,
|
|
15241
|
+
subject,
|
|
15242
|
+
normContentHash: computeNormContentHash(content),
|
|
15243
|
+
project: normalizeProjectValue(getString4(entryRecord?.project)),
|
|
15244
|
+
sourceFile: getString4(source?.file),
|
|
15245
|
+
sourceContext: getString4(source?.context)
|
|
15246
|
+
});
|
|
15247
|
+
}
|
|
15248
|
+
return hints;
|
|
15249
|
+
}
|
|
15250
|
+
function isRetireSuccessText(toolText) {
|
|
15251
|
+
const entryLabelPattern = '\\S+(?:\\s+\\("(?:\\\\.|[^"])*"\\))?';
|
|
15252
|
+
return new RegExp(`^Retired entry\\s+${entryLabelPattern}\\.\\s*$`, "i").test(toolText.trim());
|
|
15253
|
+
}
|
|
15254
|
+
function isUpdateSuccessText(toolText) {
|
|
15255
|
+
const trimmed = toolText.trim();
|
|
15256
|
+
const entryLabelPattern = '\\S+(?:\\s+\\("(?:\\\\.|[^"])*"\\))?';
|
|
15257
|
+
const updatePart = "(?:importance\\s+\\d+\\s+(?:->|\u2192)\\s+\\d+|expiry\\s+(?:core|permanent|temporary)\\s+(?:->|\u2192)\\s+(?:core|permanent|temporary))";
|
|
15258
|
+
return new RegExp(`^Updated entry\\s+${entryLabelPattern}\\s+importance:\\s+\\d+\\s+->\\s+\\d+\\.\\s*$`, "i").test(trimmed) || new RegExp(`^Entry\\s+${entryLabelPattern}\\s+already has importance\\s+\\d+\\.\\s*$`, "i").test(trimmed) || new RegExp(`^Updated entry\\s+${entryLabelPattern}:\\s+importance\\s+\u2192\\s+\\d+\\.\\s*$`, "i").test(trimmed) || new RegExp(`^Updated entry\\s+${entryLabelPattern}:\\s+${updatePart}(?:,\\s+${updatePart})*\\.\\s*$`, "i").test(trimmed) || new RegExp(`^Entry\\s+${entryLabelPattern}\\s+already has expiry\\s+(?:core|permanent|temporary)\\.\\s*$`, "i").test(trimmed) || new RegExp(`^Entry\\s+${entryLabelPattern}\\s+already has importance\\s+\\d+\\s+and\\s+expiry\\s+(?:core|permanent|temporary)\\.\\s*$`, "i").test(trimmed);
|
|
15259
|
+
}
|
|
15260
|
+
function isInactiveUpdateText(toolText) {
|
|
15261
|
+
const entryLabelPattern = '\\S+(?:\\s+\\("(?:\\\\.|[^"])*"\\))?';
|
|
15262
|
+
return new RegExp(
|
|
15263
|
+
`^Entry\\s+${entryLabelPattern}\\s+was not updated because it is no longer active\\.\\s*$`,
|
|
15264
|
+
"i"
|
|
15265
|
+
).test(toolText.trim());
|
|
15266
|
+
}
|
|
15267
|
+
function parseQuotedSubject(subjectToken) {
|
|
15268
|
+
if (!subjectToken) {
|
|
15269
|
+
return void 0;
|
|
15270
|
+
}
|
|
15271
|
+
try {
|
|
15272
|
+
const parsed = JSON.parse(subjectToken);
|
|
15273
|
+
return typeof parsed === "string" ? parsed : void 0;
|
|
15274
|
+
} catch {
|
|
15275
|
+
return void 0;
|
|
15276
|
+
}
|
|
15277
|
+
}
|
|
15278
|
+
function parseRetireSuccessReceipt(toolText) {
|
|
15279
|
+
const match = toolText.trim().match(
|
|
15280
|
+
/^Retired entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\.\s*$/i
|
|
15281
|
+
);
|
|
15282
|
+
if (!match) {
|
|
15283
|
+
return null;
|
|
15284
|
+
}
|
|
15285
|
+
return {
|
|
15286
|
+
entryId: match[1],
|
|
15287
|
+
subject: parseQuotedSubject(match[2])
|
|
15288
|
+
};
|
|
15289
|
+
}
|
|
15290
|
+
function parseUpdateReceiptEntry(toolText) {
|
|
15291
|
+
const matchers = [
|
|
15292
|
+
/^Updated entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\s+importance:/i,
|
|
15293
|
+
/^Updated entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?:/i,
|
|
15294
|
+
/^Entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\s+already has/i,
|
|
15295
|
+
/^Entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\s+was not updated because/i
|
|
15296
|
+
];
|
|
15297
|
+
for (const matcher of matchers) {
|
|
15298
|
+
const match = toolText.trim().match(matcher);
|
|
15299
|
+
if (!match) {
|
|
15300
|
+
continue;
|
|
15301
|
+
}
|
|
15302
|
+
return {
|
|
15303
|
+
entryId: match[1],
|
|
15304
|
+
subject: parseQuotedSubject(match[2])
|
|
15305
|
+
};
|
|
15306
|
+
}
|
|
15307
|
+
return null;
|
|
15308
|
+
}
|
|
14975
15309
|
function parsePendingAgentStoreEntry(value, defaultProject) {
|
|
14976
15310
|
const record = asRecord4(value);
|
|
14977
15311
|
if (!record) {
|
|
@@ -15125,11 +15459,43 @@ var openClawAdapter = {
|
|
|
15125
15459
|
const modelsUsed = [];
|
|
15126
15460
|
const modelsUsedSet = /* @__PURE__ */ new Set();
|
|
15127
15461
|
const successfulAgentStoredEntries = [];
|
|
15462
|
+
const successfulAgentRetires = [];
|
|
15463
|
+
const successfulAgentUpdates = [];
|
|
15128
15464
|
const agentStoreProjects = /* @__PURE__ */ new Set();
|
|
15465
|
+
const recalledEntryHintsById = /* @__PURE__ */ new Map();
|
|
15466
|
+
const recalledEntryHintsBySubject = /* @__PURE__ */ new Map();
|
|
15129
15467
|
const pendingToolCalls = [];
|
|
15130
15468
|
const pendingToolCallsById = /* @__PURE__ */ new Map();
|
|
15131
15469
|
const pendingAgentStores = /* @__PURE__ */ new Map();
|
|
15132
15470
|
const pendingAgentStoreQueue = [];
|
|
15471
|
+
const pendingAgentRetires = /* @__PURE__ */ new Map();
|
|
15472
|
+
const pendingAgentRetireQueue = [];
|
|
15473
|
+
const pendingAgentUpdates = /* @__PURE__ */ new Map();
|
|
15474
|
+
const pendingAgentUpdateQueue = [];
|
|
15475
|
+
const appendRecalledEntryHint = (hint) => {
|
|
15476
|
+
recalledEntryHintsById.set(hint.recalledEntryId, hint);
|
|
15477
|
+
const subjectKey2 = normalizeHintSubject(hint.subject);
|
|
15478
|
+
if (!subjectKey2) {
|
|
15479
|
+
return;
|
|
15480
|
+
}
|
|
15481
|
+
const existing = recalledEntryHintsBySubject.get(subjectKey2) ?? [];
|
|
15482
|
+
existing.push(hint);
|
|
15483
|
+
recalledEntryHintsBySubject.set(subjectKey2, existing);
|
|
15484
|
+
};
|
|
15485
|
+
const resolveRecalledEntryHint = (entryId, subject) => {
|
|
15486
|
+
if (entryId) {
|
|
15487
|
+
const byId = recalledEntryHintsById.get(entryId);
|
|
15488
|
+
if (byId) {
|
|
15489
|
+
return byId;
|
|
15490
|
+
}
|
|
15491
|
+
}
|
|
15492
|
+
const subjectKey2 = normalizeHintSubject(subject);
|
|
15493
|
+
if (!subjectKey2) {
|
|
15494
|
+
return void 0;
|
|
15495
|
+
}
|
|
15496
|
+
const bySubject = recalledEntryHintsBySubject.get(subjectKey2) ?? [];
|
|
15497
|
+
return bySubject.length === 1 ? bySubject[0] : void 0;
|
|
15498
|
+
};
|
|
15133
15499
|
const addModelUsed = (value) => {
|
|
15134
15500
|
const modelId = typeof value === "string" ? value.trim() : "";
|
|
15135
15501
|
if (!modelId || modelsUsedSet.has(modelId)) {
|
|
@@ -15167,7 +15533,7 @@ var openClawAdapter = {
|
|
|
15167
15533
|
}
|
|
15168
15534
|
return pendingToolCalls.shift() ?? null;
|
|
15169
15535
|
};
|
|
15170
|
-
const
|
|
15536
|
+
const resolvePendingAction = (message, byId, queue, toolCallIdHint) => {
|
|
15171
15537
|
const candidateIds = [
|
|
15172
15538
|
toolCallIdHint,
|
|
15173
15539
|
getString4(message.toolCallId),
|
|
@@ -15176,14 +15542,23 @@ var openClawAdapter = {
|
|
|
15176
15542
|
getString4(message.id)
|
|
15177
15543
|
].filter((value, index, all) => Boolean(value) && all.indexOf(value) === index);
|
|
15178
15544
|
for (const id of candidateIds) {
|
|
15179
|
-
const pending =
|
|
15545
|
+
const pending = byId.get(id);
|
|
15180
15546
|
if (!pending) {
|
|
15181
15547
|
continue;
|
|
15182
15548
|
}
|
|
15183
|
-
|
|
15549
|
+
byId.delete(id);
|
|
15184
15550
|
return pending;
|
|
15185
15551
|
}
|
|
15186
|
-
return
|
|
15552
|
+
return queue.shift() ?? null;
|
|
15553
|
+
};
|
|
15554
|
+
const resolvePendingAgentStore = (message, toolCallIdHint) => {
|
|
15555
|
+
return resolvePendingAction(message, pendingAgentStores, pendingAgentStoreQueue, toolCallIdHint);
|
|
15556
|
+
};
|
|
15557
|
+
const resolvePendingAgentRetire = (message, toolCallIdHint) => {
|
|
15558
|
+
return resolvePendingAction(message, pendingAgentRetires, pendingAgentRetireQueue, toolCallIdHint);
|
|
15559
|
+
};
|
|
15560
|
+
const resolvePendingAgentUpdate = (message, toolCallIdHint) => {
|
|
15561
|
+
return resolvePendingAction(message, pendingAgentUpdates, pendingAgentUpdateQueue, toolCallIdHint);
|
|
15187
15562
|
};
|
|
15188
15563
|
parseJsonlLines(raw, warnings, (record) => {
|
|
15189
15564
|
if (record.type === "session") {
|
|
@@ -15249,28 +15624,75 @@ var openClawAdapter = {
|
|
|
15249
15624
|
const toolCalls = extractToolCallBlocks(content);
|
|
15250
15625
|
const assistantMessageIndex = messages.length;
|
|
15251
15626
|
for (const call of toolCalls) {
|
|
15627
|
+
const normalizedToolName = call.name.trim().toLowerCase();
|
|
15252
15628
|
pendingToolCalls.push(call);
|
|
15253
15629
|
if (call.id) {
|
|
15254
15630
|
pendingToolCallsById.set(call.id, call);
|
|
15255
15631
|
}
|
|
15256
|
-
if (
|
|
15632
|
+
if (normalizedToolName === "agenr_store" && Array.isArray(call.args.entries)) {
|
|
15633
|
+
const defaultProject = getString4(call.args.project);
|
|
15634
|
+
const entries = call.args.entries.map((entry) => parsePendingAgentStoreEntry(entry, defaultProject)).filter((entry) => entry !== null);
|
|
15635
|
+
if (entries.length === 0) {
|
|
15636
|
+
continue;
|
|
15637
|
+
}
|
|
15638
|
+
const pending = {
|
|
15639
|
+
entries,
|
|
15640
|
+
toolCallId: call.id,
|
|
15641
|
+
assistantMessageIndex,
|
|
15642
|
+
timestamp: timestamp2
|
|
15643
|
+
};
|
|
15644
|
+
if (call.id) {
|
|
15645
|
+
pendingAgentStores.set(call.id, pending);
|
|
15646
|
+
} else {
|
|
15647
|
+
pendingAgentStoreQueue.push(pending);
|
|
15648
|
+
}
|
|
15257
15649
|
continue;
|
|
15258
15650
|
}
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15651
|
+
if (normalizedToolName === "agenr_retire") {
|
|
15652
|
+
const entryId = getString4(call.args.entry_id);
|
|
15653
|
+
const subject = getString4(call.args.subject);
|
|
15654
|
+
if (!entryId && !subject || entryId && subject) {
|
|
15655
|
+
continue;
|
|
15656
|
+
}
|
|
15657
|
+
const pending = {
|
|
15658
|
+
...entryId ? { entryId } : {},
|
|
15659
|
+
...subject ? { subject } : {},
|
|
15660
|
+
reason: getString4(call.args.reason),
|
|
15661
|
+
toolCallId: call.id,
|
|
15662
|
+
assistantMessageIndex,
|
|
15663
|
+
timestamp: timestamp2,
|
|
15664
|
+
targetHint: resolveRecalledEntryHint(entryId, subject)
|
|
15665
|
+
};
|
|
15666
|
+
if (call.id) {
|
|
15667
|
+
pendingAgentRetires.set(call.id, pending);
|
|
15668
|
+
} else {
|
|
15669
|
+
pendingAgentRetireQueue.push(pending);
|
|
15670
|
+
}
|
|
15262
15671
|
continue;
|
|
15263
15672
|
}
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
|
|
15269
|
-
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
|
|
15673
|
+
if (normalizedToolName === "agenr_update") {
|
|
15674
|
+
const entryId = getString4(call.args.entry_id);
|
|
15675
|
+
const subject = getString4(call.args.subject);
|
|
15676
|
+
const importance = getNumber(call.args.importance);
|
|
15677
|
+
const expiry = normalizeExpiry(getString4(call.args.expiry));
|
|
15678
|
+
if (!entryId && !subject || entryId && subject || importance === void 0 && expiry === void 0) {
|
|
15679
|
+
continue;
|
|
15680
|
+
}
|
|
15681
|
+
const pending = {
|
|
15682
|
+
...entryId ? { entryId } : {},
|
|
15683
|
+
...subject ? { subject } : {},
|
|
15684
|
+
...importance !== void 0 ? { importance } : {},
|
|
15685
|
+
...expiry !== void 0 ? { expiry } : {},
|
|
15686
|
+
toolCallId: call.id,
|
|
15687
|
+
assistantMessageIndex,
|
|
15688
|
+
timestamp: timestamp2,
|
|
15689
|
+
targetHint: resolveRecalledEntryHint(entryId, subject)
|
|
15690
|
+
};
|
|
15691
|
+
if (call.id) {
|
|
15692
|
+
pendingAgentUpdates.set(call.id, pending);
|
|
15693
|
+
} else {
|
|
15694
|
+
pendingAgentUpdateQueue.push(pending);
|
|
15695
|
+
}
|
|
15274
15696
|
}
|
|
15275
15697
|
}
|
|
15276
15698
|
let text;
|
|
@@ -15308,8 +15730,17 @@ var openClawAdapter = {
|
|
|
15308
15730
|
const normalizedToolName = toolName?.trim().toLowerCase();
|
|
15309
15731
|
const args = ctx?.args ?? {};
|
|
15310
15732
|
const toolText = normalizeMessageText(content);
|
|
15733
|
+
const trimmedToolText = toolText.trim();
|
|
15734
|
+
if (normalizedToolName === "agenr_recall") {
|
|
15735
|
+
const recallFailed = message.isError === true || message.is_error === true || /^agenr_recall failed:/i.test(trimmedToolText);
|
|
15736
|
+
if (!recallFailed) {
|
|
15737
|
+
for (const hint of extractRecallTargetHints(message, toolText)) {
|
|
15738
|
+
appendRecalledEntryHint(hint);
|
|
15739
|
+
}
|
|
15740
|
+
}
|
|
15741
|
+
}
|
|
15311
15742
|
if (normalizedToolName === "agenr_store") {
|
|
15312
|
-
const storeFailed = message.isError === true || message.is_error === true || /^validation failed\b/i.test(
|
|
15743
|
+
const storeFailed = message.isError === true || message.is_error === true || /^validation failed\b/i.test(trimmedToolText);
|
|
15313
15744
|
const pending = resolvePendingAgentStore(message, ctx?.id);
|
|
15314
15745
|
if (pending && !storeFailed) {
|
|
15315
15746
|
const toolResultMessageIndex = messages.length;
|
|
@@ -15331,6 +15762,39 @@ var openClawAdapter = {
|
|
|
15331
15762
|
}
|
|
15332
15763
|
}
|
|
15333
15764
|
}
|
|
15765
|
+
if (normalizedToolName === "agenr_retire") {
|
|
15766
|
+
const retireFailed = message.isError === true || message.is_error === true || /^agenr_retire failed:/i.test(trimmedToolText);
|
|
15767
|
+
const pending = resolvePendingAgentRetire(message, ctx?.id);
|
|
15768
|
+
const receipt = parseRetireSuccessReceipt(toolText);
|
|
15769
|
+
if (pending && !retireFailed && receipt && isRetireSuccessText(toolText)) {
|
|
15770
|
+
const targetHint = pending.targetHint ?? resolveRecalledEntryHint(void 0, receipt.subject);
|
|
15771
|
+
successfulAgentRetires.push({
|
|
15772
|
+
entryId: receipt.entryId,
|
|
15773
|
+
reason: pending.reason,
|
|
15774
|
+
toolCallId: pending.toolCallId,
|
|
15775
|
+
assistantMessageIndex: pending.assistantMessageIndex,
|
|
15776
|
+
timestamp: pending.timestamp,
|
|
15777
|
+
...targetHint ? { targetHint } : {}
|
|
15778
|
+
});
|
|
15779
|
+
}
|
|
15780
|
+
}
|
|
15781
|
+
if (normalizedToolName === "agenr_update") {
|
|
15782
|
+
const updateFailed = message.isError === true || message.is_error === true || /^agenr_update failed:/i.test(trimmedToolText) || isInactiveUpdateText(trimmedToolText);
|
|
15783
|
+
const pending = resolvePendingAgentUpdate(message, ctx?.id);
|
|
15784
|
+
const receipt = parseUpdateReceiptEntry(toolText);
|
|
15785
|
+
if (pending && !updateFailed && receipt && isUpdateSuccessText(toolText)) {
|
|
15786
|
+
const targetHint = pending.targetHint ?? resolveRecalledEntryHint(void 0, receipt.subject);
|
|
15787
|
+
successfulAgentUpdates.push({
|
|
15788
|
+
entryId: receipt.entryId,
|
|
15789
|
+
...pending.importance !== void 0 ? { importance: pending.importance } : {},
|
|
15790
|
+
...pending.expiry !== void 0 ? { expiry: pending.expiry } : {},
|
|
15791
|
+
toolCallId: pending.toolCallId,
|
|
15792
|
+
assistantMessageIndex: pending.assistantMessageIndex,
|
|
15793
|
+
timestamp: pending.timestamp,
|
|
15794
|
+
...targetHint ? { targetHint } : {}
|
|
15795
|
+
});
|
|
15796
|
+
}
|
|
15797
|
+
}
|
|
15334
15798
|
if (!toolText) {
|
|
15335
15799
|
return;
|
|
15336
15800
|
}
|
|
@@ -15388,7 +15852,9 @@ var openClawAdapter = {
|
|
|
15388
15852
|
startedAt: sessionTimestamp ?? messages[0]?.timestamp ?? fallbackTimestamp,
|
|
15389
15853
|
agentStoreProjects: agentStoreProjects.size > 0 ? Array.from(agentStoreProjects) : void 0
|
|
15390
15854
|
},
|
|
15391
|
-
successfulAgentStoredEntries: successfulAgentStoredEntries.length > 0 ? successfulAgentStoredEntries : void 0
|
|
15855
|
+
successfulAgentStoredEntries: successfulAgentStoredEntries.length > 0 ? successfulAgentStoredEntries : void 0,
|
|
15856
|
+
successfulAgentRetires: successfulAgentRetires.length > 0 ? successfulAgentRetires : void 0,
|
|
15857
|
+
successfulAgentUpdates: successfulAgentUpdates.length > 0 ? successfulAgentUpdates : void 0
|
|
15392
15858
|
};
|
|
15393
15859
|
}
|
|
15394
15860
|
};
|
|
@@ -15853,7 +16319,9 @@ async function parseTranscriptFile(filePath, options) {
|
|
|
15853
16319
|
chunks,
|
|
15854
16320
|
warnings: result.warnings,
|
|
15855
16321
|
metadata: result.metadata,
|
|
15856
|
-
successfulAgentStoredEntries: result.successfulAgentStoredEntries
|
|
16322
|
+
successfulAgentStoredEntries: result.successfulAgentStoredEntries,
|
|
16323
|
+
successfulAgentRetires: result.successfulAgentRetires,
|
|
16324
|
+
successfulAgentUpdates: result.successfulAgentUpdates
|
|
15857
16325
|
};
|
|
15858
16326
|
}
|
|
15859
16327
|
|
|
@@ -20281,18 +20749,6 @@ async function extractKnowledgeFromChunks(params) {
|
|
|
20281
20749
|
};
|
|
20282
20750
|
}
|
|
20283
20751
|
|
|
20284
|
-
// src/utils/expiry.ts
|
|
20285
|
-
init_types();
|
|
20286
|
-
var EXPIRY_SET = new Set(EXPIRY_LEVELS);
|
|
20287
|
-
var EXPIRY_PRIORITY = {
|
|
20288
|
-
temporary: 0,
|
|
20289
|
-
permanent: 1,
|
|
20290
|
-
core: 2
|
|
20291
|
-
};
|
|
20292
|
-
function resolveHigherExpiry(a, b) {
|
|
20293
|
-
return EXPIRY_PRIORITY[a] >= EXPIRY_PRIORITY[b] ? a : b;
|
|
20294
|
-
}
|
|
20295
|
-
|
|
20296
20752
|
// src/app/ingest/trigram-dedup.ts
|
|
20297
20753
|
function normalize3(value) {
|
|
20298
20754
|
return value.toLowerCase().replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -20660,8 +21116,8 @@ function createContradictionRepository(db) {
|
|
|
20660
21116
|
});
|
|
20661
21117
|
return result.rows.map((row) => {
|
|
20662
21118
|
const record = row;
|
|
20663
|
-
const importance =
|
|
20664
|
-
const claimConfidence =
|
|
21119
|
+
const importance = toNumber2(record.importance);
|
|
21120
|
+
const claimConfidence = toNumber2(record.claim_confidence);
|
|
20665
21121
|
const claimRole = toStringValue(record.claim_role);
|
|
20666
21122
|
return {
|
|
20667
21123
|
id: toStringValue(record.id),
|
|
@@ -25108,7 +25564,7 @@ async function queryCandidates(db, subject, contains) {
|
|
|
25108
25564
|
id: toStringValue(row.id),
|
|
25109
25565
|
type: toStringValue(row.type),
|
|
25110
25566
|
subject: toStringValue(row.subject),
|
|
25111
|
-
importance:
|
|
25567
|
+
importance: toNumber2(row.importance),
|
|
25112
25568
|
content: toStringValue(row.content)
|
|
25113
25569
|
}));
|
|
25114
25570
|
}
|
|
@@ -25125,7 +25581,7 @@ async function queryById(db, id) {
|
|
|
25125
25581
|
id: toStringValue(row.id),
|
|
25126
25582
|
type: toStringValue(row.type),
|
|
25127
25583
|
subject: toStringValue(row.subject),
|
|
25128
|
-
importance:
|
|
25584
|
+
importance: toNumber2(row.importance),
|
|
25129
25585
|
content: toStringValue(row.content)
|
|
25130
25586
|
}));
|
|
25131
25587
|
}
|
|
@@ -25201,12 +25657,16 @@ init_runtime2();
|
|
|
25201
25657
|
function resolveUpdateServiceDeps(deps) {
|
|
25202
25658
|
return resolveAppRuntimeDeps(deps);
|
|
25203
25659
|
}
|
|
25204
|
-
function
|
|
25205
|
-
const
|
|
25206
|
-
|
|
25207
|
-
|
|
25660
|
+
function validateSelector2(request) {
|
|
25661
|
+
const queryId = request.id?.trim() ?? "";
|
|
25662
|
+
const querySubject = request.subject?.trim() ?? "";
|
|
25663
|
+
if (!queryId && !querySubject) {
|
|
25664
|
+
throw new Error("entry_id or subject is required");
|
|
25665
|
+
}
|
|
25666
|
+
if (queryId && querySubject) {
|
|
25667
|
+
throw new Error("entry_id and subject are mutually exclusive");
|
|
25208
25668
|
}
|
|
25209
|
-
return
|
|
25669
|
+
return { queryId, querySubject };
|
|
25210
25670
|
}
|
|
25211
25671
|
function normalizeImportance3(value) {
|
|
25212
25672
|
const parsed = typeof value === "number" ? value : Number(value);
|
|
@@ -25215,10 +25675,26 @@ function normalizeImportance3(value) {
|
|
|
25215
25675
|
}
|
|
25216
25676
|
return parsed;
|
|
25217
25677
|
}
|
|
25678
|
+
function normalizeOptionalImportance(value) {
|
|
25679
|
+
if (value === void 0) {
|
|
25680
|
+
return void 0;
|
|
25681
|
+
}
|
|
25682
|
+
return normalizeImportance3(value);
|
|
25683
|
+
}
|
|
25684
|
+
function normalizeOptionalExpiry(value) {
|
|
25685
|
+
if (value === void 0) {
|
|
25686
|
+
return void 0;
|
|
25687
|
+
}
|
|
25688
|
+
const normalized = normalizeExpiry(value);
|
|
25689
|
+
if (!normalized) {
|
|
25690
|
+
throw new Error(`expiry must be one of: ${EXPIRY_LEVELS.join(", ")}`);
|
|
25691
|
+
}
|
|
25692
|
+
return normalized;
|
|
25693
|
+
}
|
|
25218
25694
|
async function queryById2(db, id) {
|
|
25219
25695
|
const result = await db.execute({
|
|
25220
25696
|
sql: `
|
|
25221
|
-
SELECT id, type, subject, importance, content
|
|
25697
|
+
SELECT id, type, subject, importance, expiry, content
|
|
25222
25698
|
FROM entries
|
|
25223
25699
|
WHERE retired = 0 AND id = ?
|
|
25224
25700
|
LIMIT 1
|
|
@@ -25229,11 +25705,39 @@ async function queryById2(db, id) {
|
|
|
25229
25705
|
if (!row) {
|
|
25230
25706
|
return null;
|
|
25231
25707
|
}
|
|
25708
|
+
const expiry = normalizeExpiry(row.expiry) ?? "temporary";
|
|
25232
25709
|
return {
|
|
25233
25710
|
id: toStringValue(row.id),
|
|
25234
25711
|
type: toStringValue(row.type),
|
|
25235
25712
|
subject: toStringValue(row.subject),
|
|
25236
|
-
importance:
|
|
25713
|
+
importance: toNumber2(row.importance),
|
|
25714
|
+
expiry,
|
|
25715
|
+
content: toStringValue(row.content)
|
|
25716
|
+
};
|
|
25717
|
+
}
|
|
25718
|
+
async function queryBySubject(db, subject) {
|
|
25719
|
+
const result = await db.execute({
|
|
25720
|
+
sql: `
|
|
25721
|
+
SELECT id, type, subject, importance, expiry, content
|
|
25722
|
+
FROM entries
|
|
25723
|
+
WHERE retired = 0
|
|
25724
|
+
AND LOWER(subject) = LOWER(?)
|
|
25725
|
+
ORDER BY updated_at DESC
|
|
25726
|
+
LIMIT 1
|
|
25727
|
+
`,
|
|
25728
|
+
args: [subject]
|
|
25729
|
+
});
|
|
25730
|
+
const row = result.rows[0];
|
|
25731
|
+
if (!row) {
|
|
25732
|
+
return null;
|
|
25733
|
+
}
|
|
25734
|
+
const expiry = normalizeExpiry(row.expiry) ?? "temporary";
|
|
25735
|
+
return {
|
|
25736
|
+
id: toStringValue(row.id),
|
|
25737
|
+
type: toStringValue(row.type),
|
|
25738
|
+
subject: toStringValue(row.subject),
|
|
25739
|
+
importance: toNumber2(row.importance),
|
|
25740
|
+
expiry,
|
|
25237
25741
|
content: toStringValue(row.content)
|
|
25238
25742
|
};
|
|
25239
25743
|
}
|
|
@@ -25245,7 +25749,7 @@ async function lookupUpdateCandidate(request, deps) {
|
|
|
25245
25749
|
}
|
|
25246
25750
|
async function runUpdateService(request, deps) {
|
|
25247
25751
|
const resolvedDeps = resolveUpdateServiceDeps(deps);
|
|
25248
|
-
const
|
|
25752
|
+
const { queryId, querySubject } = validateSelector2(request);
|
|
25249
25753
|
return withAppDb(
|
|
25250
25754
|
{
|
|
25251
25755
|
env: request.env,
|
|
@@ -25256,53 +25760,81 @@ async function runUpdateService(request, deps) {
|
|
|
25256
25760
|
if (request.action === "lookup") {
|
|
25257
25761
|
return {
|
|
25258
25762
|
action: "lookup",
|
|
25259
|
-
candidate: await queryById2(db,
|
|
25763
|
+
candidate: queryId ? await queryById2(db, queryId) : await queryBySubject(db, querySubject)
|
|
25260
25764
|
};
|
|
25261
25765
|
}
|
|
25262
|
-
const importance =
|
|
25263
|
-
const
|
|
25766
|
+
const importance = normalizeOptionalImportance(request.importance);
|
|
25767
|
+
const expiry = normalizeOptionalExpiry(request.expiry);
|
|
25768
|
+
if (importance === void 0 && expiry === void 0) {
|
|
25769
|
+
throw new Error("at least one of importance or expiry is required");
|
|
25770
|
+
}
|
|
25771
|
+
const existing = queryId ? await queryById2(db, queryId) : await queryBySubject(db, querySubject);
|
|
25772
|
+
const targetId = existing?.id ?? queryId ?? querySubject;
|
|
25264
25773
|
if (!existing) {
|
|
25265
25774
|
return {
|
|
25266
25775
|
action: "execute",
|
|
25267
|
-
id,
|
|
25268
|
-
previousImportance: importance,
|
|
25269
|
-
importance,
|
|
25776
|
+
id: targetId,
|
|
25777
|
+
previousImportance: importance ?? IMPORTANCE_MIN,
|
|
25778
|
+
importance: importance ?? IMPORTANCE_MIN,
|
|
25779
|
+
previousExpiry: expiry ?? "temporary",
|
|
25780
|
+
expiry: expiry ?? "temporary",
|
|
25270
25781
|
updated: false
|
|
25271
25782
|
};
|
|
25272
25783
|
}
|
|
25273
|
-
|
|
25784
|
+
const nextImportance = importance ?? existing.importance;
|
|
25785
|
+
const nextExpiry = expiry ?? existing.expiry;
|
|
25786
|
+
const importanceChanged = existing.importance !== nextImportance;
|
|
25787
|
+
const expiryChanged = existing.expiry !== nextExpiry;
|
|
25788
|
+
if (!importanceChanged && !expiryChanged) {
|
|
25274
25789
|
return {
|
|
25275
25790
|
action: "execute",
|
|
25276
|
-
id,
|
|
25791
|
+
id: existing.id,
|
|
25277
25792
|
previousImportance: existing.importance,
|
|
25278
|
-
importance,
|
|
25793
|
+
importance: existing.importance,
|
|
25794
|
+
previousExpiry: existing.expiry,
|
|
25795
|
+
expiry: existing.expiry,
|
|
25279
25796
|
updated: true
|
|
25280
25797
|
};
|
|
25281
25798
|
}
|
|
25799
|
+
const setClauses = [];
|
|
25800
|
+
const setArgs = [];
|
|
25801
|
+
if (importanceChanged) {
|
|
25802
|
+
setClauses.push("importance = ?");
|
|
25803
|
+
setArgs.push(nextImportance);
|
|
25804
|
+
}
|
|
25805
|
+
if (expiryChanged) {
|
|
25806
|
+
setClauses.push("expiry = ?");
|
|
25807
|
+
setArgs.push(nextExpiry);
|
|
25808
|
+
}
|
|
25809
|
+
setClauses.push("updated_at = ?");
|
|
25810
|
+
setArgs.push(runtime.now.toISOString());
|
|
25282
25811
|
const result = await db.execute({
|
|
25283
25812
|
sql: `
|
|
25284
25813
|
UPDATE entries
|
|
25285
|
-
SET
|
|
25286
|
-
updated_at = ?
|
|
25814
|
+
SET ${setClauses.join(", ")}
|
|
25287
25815
|
WHERE id = ?
|
|
25288
25816
|
AND retired = 0
|
|
25289
25817
|
`,
|
|
25290
|
-
args: [
|
|
25818
|
+
args: [...setArgs, existing.id]
|
|
25291
25819
|
});
|
|
25292
25820
|
if (toRowsAffected(result.rowsAffected) === 0) {
|
|
25293
25821
|
return {
|
|
25294
25822
|
action: "execute",
|
|
25295
|
-
id,
|
|
25823
|
+
id: existing.id,
|
|
25296
25824
|
previousImportance: existing.importance,
|
|
25297
25825
|
importance: existing.importance,
|
|
25826
|
+
previousExpiry: existing.expiry,
|
|
25827
|
+
expiry: existing.expiry,
|
|
25298
25828
|
updated: false
|
|
25299
25829
|
};
|
|
25300
25830
|
}
|
|
25301
25831
|
return {
|
|
25302
25832
|
action: "execute",
|
|
25303
|
-
id,
|
|
25833
|
+
id: existing.id,
|
|
25304
25834
|
previousImportance: existing.importance,
|
|
25305
|
-
importance,
|
|
25835
|
+
importance: nextImportance,
|
|
25836
|
+
previousExpiry: existing.expiry,
|
|
25837
|
+
expiry: nextExpiry,
|
|
25306
25838
|
updated: true
|
|
25307
25839
|
};
|
|
25308
25840
|
}
|
|
@@ -25314,6 +25846,8 @@ async function executeUpdate(request, deps) {
|
|
|
25314
25846
|
id: result.id,
|
|
25315
25847
|
previousImportance: result.previousImportance,
|
|
25316
25848
|
importance: result.importance,
|
|
25849
|
+
previousExpiry: result.previousExpiry,
|
|
25850
|
+
expiry: result.expiry,
|
|
25317
25851
|
updated: result.updated
|
|
25318
25852
|
};
|
|
25319
25853
|
}
|
|
@@ -25325,8 +25859,8 @@ init_client();
|
|
|
25325
25859
|
// src/db/provenance.ts
|
|
25326
25860
|
init_entry_utils();
|
|
25327
25861
|
function mapProvenanceEntry(row, tags) {
|
|
25328
|
-
const importance =
|
|
25329
|
-
const retired =
|
|
25862
|
+
const importance = toNumber2(row.importance);
|
|
25863
|
+
const retired = toNumber2(row.retired);
|
|
25330
25864
|
return {
|
|
25331
25865
|
id: toStringValue(row.id),
|
|
25332
25866
|
subject: toStringValue(row.subject),
|
|
@@ -25349,7 +25883,7 @@ function mapProvenanceRelated(row, tags) {
|
|
|
25349
25883
|
};
|
|
25350
25884
|
}
|
|
25351
25885
|
function mapProvenanceSupport(row) {
|
|
25352
|
-
const claimConfidence =
|
|
25886
|
+
const claimConfidence = toNumber2(row.claim_confidence);
|
|
25353
25887
|
const sourceFile = toStringValue(row.source_file).trim();
|
|
25354
25888
|
const sourceContext = toStringValue(row.source_context).trim();
|
|
25355
25889
|
const sourceCreatedAt = toStringValue(row.source_created_at).trim();
|
|
@@ -26643,6 +27177,7 @@ function resolveOpenClawBridgeStoreProjectAttribution(params) {
|
|
|
26643
27177
|
|
|
26644
27178
|
// src/openclaw-plugin/tools.ts
|
|
26645
27179
|
init_types();
|
|
27180
|
+
init_project();
|
|
26646
27181
|
var KNOWN_PLATFORMS = /* @__PURE__ */ new Set(["openclaw", "codex", "claude-code", "plaud"]);
|
|
26647
27182
|
var log7 = createLogger("tools");
|
|
26648
27183
|
var SUCCESSFUL_STORE_ACTIONS = /* @__PURE__ */ new Set([
|
|
@@ -26657,10 +27192,31 @@ function asString2(value) {
|
|
|
26657
27192
|
const trimmed = value.trim();
|
|
26658
27193
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
26659
27194
|
}
|
|
27195
|
+
function validateExclusiveSelector(params) {
|
|
27196
|
+
const entryId = asString2(params.entry_id);
|
|
27197
|
+
const subject = asString2(params.subject);
|
|
27198
|
+
if (entryId && subject || !entryId && !subject) {
|
|
27199
|
+
throw new Error("exactly one of entry_id or subject is required");
|
|
27200
|
+
}
|
|
27201
|
+
return { entryId, subject };
|
|
27202
|
+
}
|
|
27203
|
+
function formatQuotedSubject(subject) {
|
|
27204
|
+
return JSON.stringify(subject);
|
|
27205
|
+
}
|
|
27206
|
+
function formatEntryLabel(id, subject) {
|
|
27207
|
+
return subject ? `${id} (${formatQuotedSubject(subject)})` : id;
|
|
27208
|
+
}
|
|
27209
|
+
function formatMissingEntryError(selector) {
|
|
27210
|
+
if (selector.subject) {
|
|
27211
|
+
return `No active entry found matching subject: ${formatQuotedSubject(selector.subject)}`;
|
|
27212
|
+
}
|
|
27213
|
+
return `No active entry found with id: ${selector.entryId}`;
|
|
27214
|
+
}
|
|
26660
27215
|
function resolveStoreCandidateProject(explicitProject, sessionProject, defaultProject) {
|
|
26661
27216
|
return asString2(explicitProject) ?? asString2(sessionProject) ?? asString2(defaultProject);
|
|
26662
27217
|
}
|
|
26663
27218
|
function createAgentToolRecallScopeDiagnostic(scope, defaultProjectPresent) {
|
|
27219
|
+
const diagnosticProjects = scope.projects.length > 0 ? scope.projects : scope.projectHints ?? [];
|
|
26664
27220
|
return createProjectScopeResolutionDiagnostic({
|
|
26665
27221
|
surface: "agent-tool-recall",
|
|
26666
27222
|
inputs: {
|
|
@@ -26674,8 +27230,8 @@ function createAgentToolRecallScopeDiagnostic(scope, defaultProjectPresent) {
|
|
|
26674
27230
|
outcome: {
|
|
26675
27231
|
projectSource: scope.projectSource,
|
|
26676
27232
|
reason: scope.reason,
|
|
26677
|
-
projects:
|
|
26678
|
-
primaryProject:
|
|
27233
|
+
projects: diagnosticProjects,
|
|
27234
|
+
primaryProject: diagnosticProjects[0],
|
|
26679
27235
|
recallProjectArg: scope.recallProjectArg,
|
|
26680
27236
|
strictScope: scope.projectStrict,
|
|
26681
27237
|
dependencyExpansionApplied: false,
|
|
@@ -26685,7 +27241,9 @@ function createAgentToolRecallScopeDiagnostic(scope, defaultProjectPresent) {
|
|
|
26685
27241
|
}
|
|
26686
27242
|
function resolveAgentToolRecallScope(explicitProject, defaultProject) {
|
|
26687
27243
|
const normalizedExplicitProject = explicitProject?.trim();
|
|
26688
|
-
const
|
|
27244
|
+
const normalizedDefaultProjects = parseProjectList(defaultProject).filter((project) => project !== "*");
|
|
27245
|
+
const normalizedDefaultProject = normalizedDefaultProjects[0];
|
|
27246
|
+
const defaultProjectPresent = normalizedDefaultProjects.length > 0;
|
|
26689
27247
|
if (normalizedExplicitProject === "*") {
|
|
26690
27248
|
const scope2 = {
|
|
26691
27249
|
surface: "agent-tool-recall",
|
|
@@ -26693,8 +27251,8 @@ function resolveAgentToolRecallScope(explicitProject, defaultProject) {
|
|
|
26693
27251
|
projectSource: "unscoped",
|
|
26694
27252
|
projectArgumentState: "wildcard",
|
|
26695
27253
|
reason: "explicit-tool-project-bypass",
|
|
26696
|
-
projects: [],
|
|
26697
|
-
recallProjectArg:
|
|
27254
|
+
projects: ["*"],
|
|
27255
|
+
recallProjectArg: "*",
|
|
26698
27256
|
projectStrict: false
|
|
26699
27257
|
};
|
|
26700
27258
|
return {
|
|
@@ -26706,14 +27264,34 @@ function resolveAgentToolRecallScope(explicitProject, defaultProject) {
|
|
|
26706
27264
|
};
|
|
26707
27265
|
}
|
|
26708
27266
|
if (!normalizedExplicitProject) {
|
|
27267
|
+
if (normalizedDefaultProject) {
|
|
27268
|
+
const scope3 = {
|
|
27269
|
+
surface: "agent-tool-recall",
|
|
27270
|
+
projectResolutionMode: "explicit-tool-project-only",
|
|
27271
|
+
projectSource: "plugin-default-project",
|
|
27272
|
+
projectArgumentState: "omitted",
|
|
27273
|
+
reason: "plugin-default-project",
|
|
27274
|
+
projects: [],
|
|
27275
|
+
projectHints: [normalizedDefaultProject],
|
|
27276
|
+
recallProjectArg: void 0,
|
|
27277
|
+
projectStrict: false
|
|
27278
|
+
};
|
|
27279
|
+
return {
|
|
27280
|
+
...scope3,
|
|
27281
|
+
memoryReliabilityDiagnostic: createAgentToolRecallScopeDiagnostic(
|
|
27282
|
+
scope3,
|
|
27283
|
+
defaultProjectPresent
|
|
27284
|
+
)
|
|
27285
|
+
};
|
|
27286
|
+
}
|
|
26709
27287
|
const scope2 = {
|
|
26710
27288
|
surface: "agent-tool-recall",
|
|
26711
27289
|
projectResolutionMode: "explicit-tool-project-only",
|
|
26712
27290
|
projectSource: "unscoped",
|
|
26713
27291
|
projectArgumentState: "omitted",
|
|
26714
27292
|
reason: "no-project-candidate",
|
|
26715
|
-
projects: [],
|
|
26716
|
-
recallProjectArg:
|
|
27293
|
+
projects: ["*"],
|
|
27294
|
+
recallProjectArg: "*",
|
|
26717
27295
|
projectStrict: false
|
|
26718
27296
|
};
|
|
26719
27297
|
return {
|
|
@@ -26755,6 +27333,36 @@ function asNumber(value) {
|
|
|
26755
27333
|
}
|
|
26756
27334
|
return void 0;
|
|
26757
27335
|
}
|
|
27336
|
+
function normalizeOptionalUpdateExpiry(value) {
|
|
27337
|
+
if (value === void 0) {
|
|
27338
|
+
return void 0;
|
|
27339
|
+
}
|
|
27340
|
+
const expiry = normalizeExpiry(value);
|
|
27341
|
+
if (!expiry) {
|
|
27342
|
+
throw new Error(`expiry must be one of: ${EXPIRY_LEVELS.join(", ")}`);
|
|
27343
|
+
}
|
|
27344
|
+
return expiry;
|
|
27345
|
+
}
|
|
27346
|
+
function buildChangedUpdateParts(request, result) {
|
|
27347
|
+
const parts = [];
|
|
27348
|
+
if (request.importance !== void 0 && result.previousImportance !== result.importance) {
|
|
27349
|
+
parts.push(`importance ${result.previousImportance} \u2192 ${result.importance}`);
|
|
27350
|
+
}
|
|
27351
|
+
if (request.expiry !== void 0 && result.previousExpiry !== result.expiry) {
|
|
27352
|
+
parts.push(`expiry ${result.previousExpiry} \u2192 ${result.expiry}`);
|
|
27353
|
+
}
|
|
27354
|
+
return parts;
|
|
27355
|
+
}
|
|
27356
|
+
function buildRequestedUpdateParts(request, result) {
|
|
27357
|
+
const parts = [];
|
|
27358
|
+
if (request.importance !== void 0) {
|
|
27359
|
+
parts.push(`importance ${result.importance}`);
|
|
27360
|
+
}
|
|
27361
|
+
if (request.expiry !== void 0) {
|
|
27362
|
+
parts.push(`expiry ${result.expiry}`);
|
|
27363
|
+
}
|
|
27364
|
+
return parts;
|
|
27365
|
+
}
|
|
26758
27366
|
function parseOptionalPositiveInt(value, label) {
|
|
26759
27367
|
if (value === void 0) {
|
|
26760
27368
|
return void 0;
|
|
@@ -26879,6 +27487,7 @@ async function runRecallTool(params, defaultProject, dbPath) {
|
|
|
26879
27487
|
platform: normalizeRecallPlatform(asString2(params.platform)),
|
|
26880
27488
|
project: recallScope.projects,
|
|
26881
27489
|
projectStrict: recallScope.projectStrict,
|
|
27490
|
+
projectHints: recallScope.projectHints,
|
|
26882
27491
|
budget: null
|
|
26883
27492
|
},
|
|
26884
27493
|
dbPath,
|
|
@@ -27069,34 +27678,34 @@ async function runExtractTool(params, dbPath) {
|
|
|
27069
27678
|
}
|
|
27070
27679
|
async function runRetireTool(params, dbPath) {
|
|
27071
27680
|
try {
|
|
27072
|
-
const
|
|
27073
|
-
if (!entryId) {
|
|
27074
|
-
return {
|
|
27075
|
-
content: [{ type: "text", text: "agenr_retire failed: entry_id is required" }]
|
|
27076
|
-
};
|
|
27077
|
-
}
|
|
27681
|
+
const selector = validateExclusiveSelector(params);
|
|
27078
27682
|
const lookup = await lookupRetireCandidates({
|
|
27079
|
-
id: entryId,
|
|
27683
|
+
id: selector.entryId,
|
|
27684
|
+
subject: selector.subject,
|
|
27080
27685
|
dbPath
|
|
27081
27686
|
});
|
|
27082
|
-
|
|
27687
|
+
const candidate = lookup.candidates[0];
|
|
27688
|
+
if (!candidate) {
|
|
27083
27689
|
return {
|
|
27084
|
-
content: [{ type: "text", text: `agenr_retire failed:
|
|
27690
|
+
content: [{ type: "text", text: `agenr_retire failed: ${formatMissingEntryError(selector)}` }]
|
|
27085
27691
|
};
|
|
27086
27692
|
}
|
|
27087
27693
|
const retired = await executeRetire({
|
|
27088
|
-
id:
|
|
27694
|
+
id: candidate.id,
|
|
27089
27695
|
reason: asString2(params.reason),
|
|
27090
27696
|
persist: params.persist === true,
|
|
27091
27697
|
dbPath
|
|
27092
27698
|
});
|
|
27093
27699
|
if (retired.retiredCount === 0) {
|
|
27094
27700
|
return {
|
|
27095
|
-
content: [{ type: "text", text: `agenr_retire failed:
|
|
27701
|
+
content: [{ type: "text", text: `agenr_retire failed: ${formatMissingEntryError(selector)}` }]
|
|
27096
27702
|
};
|
|
27097
27703
|
}
|
|
27098
27704
|
return {
|
|
27099
|
-
content: [{
|
|
27705
|
+
content: [{
|
|
27706
|
+
type: "text",
|
|
27707
|
+
text: `Retired entry ${formatEntryLabel(candidate.id, selector.subject ? candidate.subject : void 0)}.`
|
|
27708
|
+
}]
|
|
27100
27709
|
};
|
|
27101
27710
|
} catch (error) {
|
|
27102
27711
|
return {
|
|
@@ -27106,42 +27715,60 @@ async function runRetireTool(params, dbPath) {
|
|
|
27106
27715
|
}
|
|
27107
27716
|
async function runUpdateTool(params, dbPath) {
|
|
27108
27717
|
try {
|
|
27109
|
-
const
|
|
27718
|
+
const selector = validateExclusiveSelector(params);
|
|
27719
|
+
const importanceProvided = Object.prototype.hasOwnProperty.call(params, "importance");
|
|
27110
27720
|
const importance = asNumber(params.importance);
|
|
27111
|
-
if (!
|
|
27721
|
+
if (importanceProvided && (importance === void 0 || !Number.isInteger(importance) || importance < 1 || importance > 10)) {
|
|
27112
27722
|
return {
|
|
27113
|
-
content: [{ type: "text", text: "agenr_update failed:
|
|
27723
|
+
content: [{ type: "text", text: "agenr_update failed: importance must be an integer between 1 and 10" }]
|
|
27114
27724
|
};
|
|
27115
27725
|
}
|
|
27116
|
-
|
|
27726
|
+
const expiry = normalizeOptionalUpdateExpiry(params.expiry);
|
|
27727
|
+
if (importance === void 0 && expiry === void 0) {
|
|
27117
27728
|
return {
|
|
27118
|
-
content: [{ type: "text", text: "agenr_update failed:
|
|
27729
|
+
content: [{ type: "text", text: "agenr_update failed: at least one of importance or expiry is required" }]
|
|
27119
27730
|
};
|
|
27120
27731
|
}
|
|
27121
27732
|
const lookup = await lookupUpdateCandidate({
|
|
27122
|
-
id: entryId,
|
|
27733
|
+
id: selector.entryId,
|
|
27734
|
+
subject: selector.subject,
|
|
27123
27735
|
dbPath
|
|
27124
27736
|
});
|
|
27125
|
-
|
|
27737
|
+
const candidate = lookup.candidate;
|
|
27738
|
+
if (!candidate) {
|
|
27126
27739
|
return {
|
|
27127
|
-
content: [{ type: "text", text: `agenr_update failed:
|
|
27740
|
+
content: [{ type: "text", text: `agenr_update failed: ${formatMissingEntryError(selector)}` }]
|
|
27128
27741
|
};
|
|
27129
27742
|
}
|
|
27130
27743
|
const updated = await executeUpdate({
|
|
27131
|
-
id:
|
|
27132
|
-
importance,
|
|
27744
|
+
id: candidate.id,
|
|
27745
|
+
...importance !== void 0 ? { importance } : {},
|
|
27746
|
+
...expiry !== void 0 ? { expiry } : {},
|
|
27133
27747
|
dbPath
|
|
27134
27748
|
});
|
|
27749
|
+
const entryLabel = formatEntryLabel(candidate.id, selector.subject ? candidate.subject : void 0);
|
|
27135
27750
|
if (!updated.updated) {
|
|
27136
27751
|
return {
|
|
27137
|
-
content: [{ type: "text", text: `Entry ${
|
|
27752
|
+
content: [{ type: "text", text: `Entry ${entryLabel} was not updated because it is no longer active.` }]
|
|
27138
27753
|
};
|
|
27139
27754
|
}
|
|
27755
|
+
const changedParts = buildChangedUpdateParts({ importance, expiry }, updated);
|
|
27756
|
+
if (changedParts.length > 0) {
|
|
27757
|
+
return {
|
|
27758
|
+
content: [
|
|
27759
|
+
{
|
|
27760
|
+
type: "text",
|
|
27761
|
+
text: `Updated entry ${entryLabel}: ${changedParts.join(", ")}.`
|
|
27762
|
+
}
|
|
27763
|
+
]
|
|
27764
|
+
};
|
|
27765
|
+
}
|
|
27766
|
+
const requestedParts = buildRequestedUpdateParts({ importance, expiry }, updated);
|
|
27140
27767
|
return {
|
|
27141
27768
|
content: [
|
|
27142
27769
|
{
|
|
27143
27770
|
type: "text",
|
|
27144
|
-
text:
|
|
27771
|
+
text: requestedParts.length === 1 ? `Entry ${entryLabel} already has ${requestedParts[0]}.` : `Entry ${entryLabel} already has ${requestedParts.join(" and ")}.`
|
|
27145
27772
|
}
|
|
27146
27773
|
]
|
|
27147
27774
|
};
|
|
@@ -32774,7 +33401,7 @@ function registerAgenrTools(api, params) {
|
|
|
32774
33401
|
Type6.Union(
|
|
32775
33402
|
[Type6.Literal("default"), Type6.Literal("session-start"), Type6.Literal("browse")],
|
|
32776
33403
|
{
|
|
32777
|
-
description: "Use session-start for fast bootstrap without embedding. Use browse for temporal browsing
|
|
33404
|
+
description: "Use session-start for fast bootstrap without embedding. Use browse for recency-dominant temporal browsing with secondary importance tie-breaking (no query needed, no semantic search)."
|
|
32778
33405
|
}
|
|
32779
33406
|
)
|
|
32780
33407
|
),
|
|
@@ -32803,7 +33430,8 @@ function registerAgenrTools(api, params) {
|
|
|
32803
33430
|
return makeDisabledToolResult();
|
|
32804
33431
|
}
|
|
32805
33432
|
const dbPath = runtimeConfig?.dbPath;
|
|
32806
|
-
const
|
|
33433
|
+
const defaultProject = runtimeConfig?.project?.trim() || void 0;
|
|
33434
|
+
const result = await runRecallTool(toolParams, defaultProject, dbPath);
|
|
32807
33435
|
const sessionKey = sessionRef.current;
|
|
32808
33436
|
if (sessionKey && result.agentToolRecallSurface) {
|
|
32809
33437
|
const addedCount = createSessionSurfacedMemoryService(sessionKey).recordByIntent(
|
|
@@ -32992,11 +33620,22 @@ function registerAgenrTools(api, params) {
|
|
|
32992
33620
|
name: "agenr_retire",
|
|
32993
33621
|
label: "Agenr Retire",
|
|
32994
33622
|
description: "Mark a memory entry as retired (soft delete). Retired entries are excluded from all recall.",
|
|
32995
|
-
parameters: Type6.Object(
|
|
32996
|
-
|
|
32997
|
-
|
|
32998
|
-
|
|
32999
|
-
|
|
33623
|
+
parameters: Type6.Object(
|
|
33624
|
+
{
|
|
33625
|
+
entry_id: Type6.Optional(Type6.String({ description: "Entry ID to retire." })),
|
|
33626
|
+
subject: Type6.Optional(
|
|
33627
|
+
Type6.String({ description: "Subject string to match. Mutually exclusive with entry_id." })
|
|
33628
|
+
),
|
|
33629
|
+
reason: Type6.Optional(Type6.String({ description: "Retirement reason." })),
|
|
33630
|
+
persist: Type6.Optional(Type6.Boolean({ description: "Persist retirement to ledger." }))
|
|
33631
|
+
},
|
|
33632
|
+
{
|
|
33633
|
+
anyOf: [
|
|
33634
|
+
{ required: ["entry_id"] },
|
|
33635
|
+
{ required: ["subject"] }
|
|
33636
|
+
]
|
|
33637
|
+
}
|
|
33638
|
+
),
|
|
33000
33639
|
async execute(_toolCallId, toolParams) {
|
|
33001
33640
|
const runtimeConfig = api.pluginConfig;
|
|
33002
33641
|
if (runtimeConfig?.enabled === false) {
|
|
@@ -33011,11 +33650,37 @@ function registerAgenrTools(api, params) {
|
|
|
33011
33650
|
{
|
|
33012
33651
|
name: "agenr_update",
|
|
33013
33652
|
label: "Agenr Update",
|
|
33014
|
-
description: "Update an existing memory entry in place. Currently supports importance
|
|
33015
|
-
parameters: Type6.Object(
|
|
33016
|
-
|
|
33017
|
-
|
|
33018
|
-
|
|
33653
|
+
description: "Update an existing memory entry in place. Currently supports importance and expiry.",
|
|
33654
|
+
parameters: Type6.Object(
|
|
33655
|
+
{
|
|
33656
|
+
entry_id: Type6.Optional(Type6.String({ description: "Entry ID to update." })),
|
|
33657
|
+
subject: Type6.Optional(
|
|
33658
|
+
Type6.String({
|
|
33659
|
+
description: "Subject string to match. Mutually exclusive with entry_id."
|
|
33660
|
+
})
|
|
33661
|
+
),
|
|
33662
|
+
importance: Type6.Optional(
|
|
33663
|
+
Type6.Integer({ minimum: 1, maximum: 10, description: "New importance score." })
|
|
33664
|
+
),
|
|
33665
|
+
expiry: optionalExpirySchema("New expiry tier: core, permanent, or temporary.")
|
|
33666
|
+
},
|
|
33667
|
+
{
|
|
33668
|
+
allOf: [
|
|
33669
|
+
{
|
|
33670
|
+
anyOf: [
|
|
33671
|
+
{ required: ["entry_id"] },
|
|
33672
|
+
{ required: ["subject"] }
|
|
33673
|
+
]
|
|
33674
|
+
},
|
|
33675
|
+
{
|
|
33676
|
+
anyOf: [
|
|
33677
|
+
{ required: ["importance"] },
|
|
33678
|
+
{ required: ["expiry"] }
|
|
33679
|
+
]
|
|
33680
|
+
}
|
|
33681
|
+
]
|
|
33682
|
+
}
|
|
33683
|
+
),
|
|
33019
33684
|
async execute(_toolCallId, toolParams) {
|
|
33020
33685
|
const runtimeConfig = api.pluginConfig;
|
|
33021
33686
|
if (runtimeConfig?.enabled === false) {
|