@agenr/openclaw-plugin 0.12.1 → 0.12.3
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 +31 -0
- package/README.md +2 -2
- package/dist/index.js +978 -299
- package/package.json +1 -1
- package/skills/skills/SKILL.md +77 -0
package/dist/index.js
CHANGED
|
@@ -107,7 +107,7 @@ var init_logger = __esm({
|
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
// src/db/schema/definitions.ts
|
|
110
|
-
var CREATE_IDX_ENTRIES_EMBEDDING_SQL, CREATE_ENTRIES_FTS_TABLE_SQL, CREATE_ENTRIES_FTS_TRIGGER_AI_SQL, CREATE_ENTRIES_FTS_TRIGGER_AD_SQL, CREATE_ENTRIES_FTS_TRIGGER_AU_SQL, CREATE_TABLE_AND_TRIGGER_STATEMENTS, COLUMN_MIGRATIONS, CREATE_INDEX_STATEMENTS;
|
|
110
|
+
var CREATE_IDX_ENTRIES_EMBEDDING_SQL, CREATE_ENTRIES_FTS_TABLE_SQL, CREATE_ENTRIES_FTS_TRIGGER_AI_SQL, CREATE_ENTRIES_FTS_TRIGGER_AD_SQL, CREATE_ENTRIES_FTS_TRIGGER_AU_SQL, CREATE_SEEN_SESSIONS_TABLE_SQL, CREATE_SEEN_SESSIONS_SEEN_AT_INDEX_SQL, CREATE_SESSION_PROJECTS_TABLE_SQL, CREATE_SESSION_IDENTITY_BREADCRUMBS_TABLE_SQL, CREATE_SESSION_IDENTITY_BREADCRUMBS_UPDATED_AT_INDEX_SQL, ADD_SESSION_PROJECT_STATE_COLUMN_SQL, OPENCLAW_PLUGIN_SCHEMA_STATEMENTS, OPENCLAW_PLUGIN_COLUMN_MIGRATIONS, CREATE_TABLE_AND_TRIGGER_STATEMENTS, COLUMN_MIGRATIONS, CREATE_INDEX_STATEMENTS;
|
|
111
111
|
var init_definitions = __esm({
|
|
112
112
|
"src/db/schema/definitions.ts"() {
|
|
113
113
|
"use strict";
|
|
@@ -146,6 +146,60 @@ var init_definitions = __esm({
|
|
|
146
146
|
WHERE new.retired = 0 AND new.superseded_by IS NULL;
|
|
147
147
|
END
|
|
148
148
|
`;
|
|
149
|
+
CREATE_SEEN_SESSIONS_TABLE_SQL = `
|
|
150
|
+
CREATE TABLE IF NOT EXISTS seen_sessions (
|
|
151
|
+
dedupe_key TEXT PRIMARY KEY,
|
|
152
|
+
seen_at INTEGER NOT NULL
|
|
153
|
+
)
|
|
154
|
+
`;
|
|
155
|
+
CREATE_SEEN_SESSIONS_SEEN_AT_INDEX_SQL = `
|
|
156
|
+
CREATE INDEX IF NOT EXISTS idx_seen_sessions_seen_at
|
|
157
|
+
ON seen_sessions(seen_at)
|
|
158
|
+
`;
|
|
159
|
+
CREATE_SESSION_PROJECTS_TABLE_SQL = `
|
|
160
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
161
|
+
session_key TEXT PRIMARY KEY,
|
|
162
|
+
project TEXT NOT NULL,
|
|
163
|
+
state TEXT NOT NULL DEFAULT 'set',
|
|
164
|
+
updated_at TEXT NOT NULL
|
|
165
|
+
)
|
|
166
|
+
`;
|
|
167
|
+
CREATE_SESSION_IDENTITY_BREADCRUMBS_TABLE_SQL = `
|
|
168
|
+
CREATE TABLE IF NOT EXISTS session_identity_breadcrumbs (
|
|
169
|
+
session_id TEXT PRIMARY KEY,
|
|
170
|
+
session_key TEXT,
|
|
171
|
+
family TEXT NOT NULL,
|
|
172
|
+
lane_id TEXT,
|
|
173
|
+
origin_surface TEXT,
|
|
174
|
+
delivery_channel TEXT,
|
|
175
|
+
family_source TEXT,
|
|
176
|
+
lane_source TEXT,
|
|
177
|
+
created_at TEXT NOT NULL,
|
|
178
|
+
updated_at TEXT NOT NULL
|
|
179
|
+
)
|
|
180
|
+
`;
|
|
181
|
+
CREATE_SESSION_IDENTITY_BREADCRUMBS_UPDATED_AT_INDEX_SQL = `
|
|
182
|
+
CREATE INDEX IF NOT EXISTS idx_session_identity_breadcrumbs_updated_at
|
|
183
|
+
ON session_identity_breadcrumbs(updated_at)
|
|
184
|
+
`;
|
|
185
|
+
ADD_SESSION_PROJECT_STATE_COLUMN_SQL = `
|
|
186
|
+
ALTER TABLE session_projects
|
|
187
|
+
ADD COLUMN state TEXT NOT NULL DEFAULT 'set'
|
|
188
|
+
`;
|
|
189
|
+
OPENCLAW_PLUGIN_SCHEMA_STATEMENTS = [
|
|
190
|
+
CREATE_SEEN_SESSIONS_TABLE_SQL,
|
|
191
|
+
CREATE_SEEN_SESSIONS_SEEN_AT_INDEX_SQL,
|
|
192
|
+
CREATE_SESSION_PROJECTS_TABLE_SQL,
|
|
193
|
+
CREATE_SESSION_IDENTITY_BREADCRUMBS_TABLE_SQL,
|
|
194
|
+
CREATE_SESSION_IDENTITY_BREADCRUMBS_UPDATED_AT_INDEX_SQL
|
|
195
|
+
];
|
|
196
|
+
OPENCLAW_PLUGIN_COLUMN_MIGRATIONS = [
|
|
197
|
+
{
|
|
198
|
+
table: "session_projects",
|
|
199
|
+
column: "state",
|
|
200
|
+
sql: ADD_SESSION_PROJECT_STATE_COLUMN_SQL
|
|
201
|
+
}
|
|
202
|
+
];
|
|
149
203
|
CREATE_TABLE_AND_TRIGGER_STATEMENTS = [
|
|
150
204
|
`
|
|
151
205
|
CREATE TABLE IF NOT EXISTS _meta (
|
|
@@ -419,9 +473,11 @@ var init_definitions = __esm({
|
|
|
419
473
|
CREATE_ENTRIES_FTS_TABLE_SQL,
|
|
420
474
|
CREATE_ENTRIES_FTS_TRIGGER_AI_SQL,
|
|
421
475
|
CREATE_ENTRIES_FTS_TRIGGER_AD_SQL,
|
|
422
|
-
CREATE_ENTRIES_FTS_TRIGGER_AU_SQL
|
|
476
|
+
CREATE_ENTRIES_FTS_TRIGGER_AU_SQL,
|
|
477
|
+
...OPENCLAW_PLUGIN_SCHEMA_STATEMENTS
|
|
423
478
|
];
|
|
424
479
|
COLUMN_MIGRATIONS = [
|
|
480
|
+
...OPENCLAW_PLUGIN_COLUMN_MIGRATIONS,
|
|
425
481
|
{
|
|
426
482
|
table: "co_recall_edges",
|
|
427
483
|
column: "edge_type",
|
|
@@ -693,6 +749,202 @@ var init_definitions = __esm({
|
|
|
693
749
|
}
|
|
694
750
|
});
|
|
695
751
|
|
|
752
|
+
// src/db/vector-index.ts
|
|
753
|
+
function toNumber(value) {
|
|
754
|
+
if (typeof value === "number") {
|
|
755
|
+
return value;
|
|
756
|
+
}
|
|
757
|
+
if (typeof value === "bigint") {
|
|
758
|
+
return Number(value);
|
|
759
|
+
}
|
|
760
|
+
if (typeof value === "string" && value.trim()) {
|
|
761
|
+
return Number(value);
|
|
762
|
+
}
|
|
763
|
+
return Number.NaN;
|
|
764
|
+
}
|
|
765
|
+
function toFiniteCount(value) {
|
|
766
|
+
const numeric = toNumber(value);
|
|
767
|
+
if (!Number.isFinite(numeric)) {
|
|
768
|
+
return 0;
|
|
769
|
+
}
|
|
770
|
+
return Math.max(0, Math.trunc(numeric));
|
|
771
|
+
}
|
|
772
|
+
function normalizeRowid(value) {
|
|
773
|
+
const numeric = toNumber(value);
|
|
774
|
+
if (!Number.isFinite(numeric)) {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
const rowid = Math.trunc(numeric);
|
|
778
|
+
return rowid > 0 ? rowid : null;
|
|
779
|
+
}
|
|
780
|
+
function formatShadowMismatch(stats) {
|
|
781
|
+
const details = [`active=${stats.embeddingCount}`, `shadow=${stats.shadowCount}`];
|
|
782
|
+
if (stats.missingRowids.length > 0) {
|
|
783
|
+
details.push(`missing=${stats.missingRowids.length}`);
|
|
784
|
+
}
|
|
785
|
+
return details.join(", ");
|
|
786
|
+
}
|
|
787
|
+
async function rollbackQuietly(db) {
|
|
788
|
+
try {
|
|
789
|
+
await db.execute("ROLLBACK");
|
|
790
|
+
} catch {
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
async function dropRepairTableQuietly(db) {
|
|
794
|
+
try {
|
|
795
|
+
await db.execute(`DROP TABLE IF EXISTS ${TEMP_REPAIR_TABLE}`);
|
|
796
|
+
} catch {
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
async function repairMissingRowids(db, missingRowids) {
|
|
800
|
+
if (missingRowids.length === 0) {
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
await db.execute(`DROP TABLE IF EXISTS ${TEMP_REPAIR_TABLE}`);
|
|
804
|
+
await db.execute(`
|
|
805
|
+
CREATE TEMP TABLE ${TEMP_REPAIR_TABLE} (
|
|
806
|
+
rid INTEGER PRIMARY KEY,
|
|
807
|
+
emb BLOB NOT NULL
|
|
808
|
+
)
|
|
809
|
+
`);
|
|
810
|
+
try {
|
|
811
|
+
for (let index = 0; index < missingRowids.length; index += REPAIR_CHUNK_SIZE) {
|
|
812
|
+
const chunk = missingRowids.slice(index, index + REPAIR_CHUNK_SIZE);
|
|
813
|
+
if (chunk.length === 0) {
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
const placeholders = chunk.map(() => "?").join(", ");
|
|
817
|
+
await db.execute(`DELETE FROM ${TEMP_REPAIR_TABLE}`);
|
|
818
|
+
await db.execute({
|
|
819
|
+
sql: `
|
|
820
|
+
INSERT INTO ${TEMP_REPAIR_TABLE} (rid, emb)
|
|
821
|
+
SELECT rowid, embedding
|
|
822
|
+
FROM entries
|
|
823
|
+
WHERE rowid IN (${placeholders})
|
|
824
|
+
`,
|
|
825
|
+
args: chunk
|
|
826
|
+
});
|
|
827
|
+
await db.execute({
|
|
828
|
+
sql: `
|
|
829
|
+
UPDATE entries
|
|
830
|
+
SET embedding = NULL
|
|
831
|
+
WHERE rowid IN (${placeholders})
|
|
832
|
+
`,
|
|
833
|
+
args: chunk
|
|
834
|
+
});
|
|
835
|
+
await db.execute({
|
|
836
|
+
sql: `
|
|
837
|
+
UPDATE entries
|
|
838
|
+
SET embedding = (
|
|
839
|
+
SELECT emb
|
|
840
|
+
FROM ${TEMP_REPAIR_TABLE}
|
|
841
|
+
WHERE rid = entries.rowid
|
|
842
|
+
)
|
|
843
|
+
WHERE rowid IN (${placeholders})
|
|
844
|
+
`,
|
|
845
|
+
args: chunk
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
} finally {
|
|
849
|
+
await dropRepairTableQuietly(db);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
async function getVectorIndexShadowStats(db) {
|
|
853
|
+
const countsResult = await db.execute(`
|
|
854
|
+
SELECT
|
|
855
|
+
(SELECT COUNT(*) FROM entries WHERE ${ACTIVE_EMBEDDED_WHERE_SQL}) AS embedding_count,
|
|
856
|
+
(SELECT COUNT(*) FROM idx_entries_embedding_shadow) AS shadow_count
|
|
857
|
+
`);
|
|
858
|
+
const countsRow = countsResult.rows[0];
|
|
859
|
+
const embeddingCount = toFiniteCount(countsRow?.embedding_count);
|
|
860
|
+
const shadowCount = toFiniteCount(countsRow?.shadow_count);
|
|
861
|
+
const missingResult = await db.execute(`
|
|
862
|
+
SELECT e.rowid AS rowid
|
|
863
|
+
FROM entries AS e
|
|
864
|
+
LEFT JOIN idx_entries_embedding_shadow AS s
|
|
865
|
+
ON s.index_key = e.rowid
|
|
866
|
+
WHERE e.embedding IS NOT NULL
|
|
867
|
+
AND e.retired = 0
|
|
868
|
+
AND e.superseded_by IS NULL
|
|
869
|
+
AND s.index_key IS NULL
|
|
870
|
+
ORDER BY e.rowid ASC
|
|
871
|
+
`);
|
|
872
|
+
const missingRowids = missingResult.rows.map((row) => normalizeRowid(row.rowid)).filter((rowid) => rowid !== null);
|
|
873
|
+
return {
|
|
874
|
+
embeddingCount,
|
|
875
|
+
shadowCount,
|
|
876
|
+
missingRowids
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
async function rebuildVectorIndex(db, options) {
|
|
880
|
+
const start = Date.now();
|
|
881
|
+
const onLog = options?.onLog ?? (() => void 0);
|
|
882
|
+
await db.execute("BEGIN IMMEDIATE");
|
|
883
|
+
try {
|
|
884
|
+
await db.execute("DROP INDEX IF EXISTS idx_entries_embedding");
|
|
885
|
+
await db.execute(CREATE_IDX_ENTRIES_EMBEDDING_SQL);
|
|
886
|
+
await db.execute(SELF_UPDATE_ACTIVE_EMBEDDINGS_SQL);
|
|
887
|
+
const beforeRepair = await getVectorIndexShadowStats(db);
|
|
888
|
+
let repairedCount = 0;
|
|
889
|
+
if (beforeRepair.missingRowids.length > 0) {
|
|
890
|
+
repairedCount = beforeRepair.missingRowids.length;
|
|
891
|
+
onLog(`[vector-index] repairing ${repairedCount} entries missing from shadow table`);
|
|
892
|
+
await repairMissingRowids(db, beforeRepair.missingRowids);
|
|
893
|
+
}
|
|
894
|
+
const afterRepair = await getVectorIndexShadowStats(db);
|
|
895
|
+
if (afterRepair.missingRowids.length > 0 || afterRepair.shadowCount !== afterRepair.embeddingCount) {
|
|
896
|
+
throw new Error(`Vector index shadow table desynced after rebuild (${formatShadowMismatch(afterRepair)})`);
|
|
897
|
+
}
|
|
898
|
+
if (afterRepair.embeddingCount > 0) {
|
|
899
|
+
const verify = await db.execute(`
|
|
900
|
+
SELECT count(*) AS count
|
|
901
|
+
FROM vector_top_k(
|
|
902
|
+
'idx_entries_embedding',
|
|
903
|
+
(SELECT embedding FROM entries WHERE ${ACTIVE_EMBEDDED_WHERE_SQL} LIMIT 1),
|
|
904
|
+
1
|
|
905
|
+
)
|
|
906
|
+
`);
|
|
907
|
+
const verifyCount = toFiniteCount(verify.rows[0]?.count);
|
|
908
|
+
if (verifyCount !== 1) {
|
|
909
|
+
throw new Error(`Vector index rebuild verification failed (expected 1, got ${verifyCount})`);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
await db.execute("COMMIT");
|
|
913
|
+
const durationMs = Date.now() - start;
|
|
914
|
+
onLog(
|
|
915
|
+
`[vector-index] rebuilt for ${afterRepair.embeddingCount} entries (${afterRepair.shadowCount} shadow rows, ${repairedCount} repaired, ${durationMs}ms)`
|
|
916
|
+
);
|
|
917
|
+
return {
|
|
918
|
+
embeddingCount: afterRepair.embeddingCount,
|
|
919
|
+
shadowCount: afterRepair.shadowCount,
|
|
920
|
+
repairedCount,
|
|
921
|
+
durationMs
|
|
922
|
+
};
|
|
923
|
+
} catch (error) {
|
|
924
|
+
await rollbackQuietly(db);
|
|
925
|
+
throw error;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
var ACTIVE_EMBEDDED_WHERE_SQL, SELF_UPDATE_ACTIVE_EMBEDDINGS_SQL, TEMP_REPAIR_TABLE, REPAIR_CHUNK_SIZE;
|
|
929
|
+
var init_vector_index = __esm({
|
|
930
|
+
"src/db/vector-index.ts"() {
|
|
931
|
+
"use strict";
|
|
932
|
+
init_definitions();
|
|
933
|
+
ACTIVE_EMBEDDED_WHERE_SQL = `
|
|
934
|
+
embedding IS NOT NULL
|
|
935
|
+
AND retired = 0
|
|
936
|
+
AND superseded_by IS NULL
|
|
937
|
+
`;
|
|
938
|
+
SELF_UPDATE_ACTIVE_EMBEDDINGS_SQL = `
|
|
939
|
+
UPDATE entries
|
|
940
|
+
SET embedding = embedding
|
|
941
|
+
WHERE ${ACTIVE_EMBEDDED_WHERE_SQL}
|
|
942
|
+
`;
|
|
943
|
+
TEMP_REPAIR_TABLE = "_vec_repair";
|
|
944
|
+
REPAIR_CHUNK_SIZE = 100;
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
|
|
696
948
|
// src/db/schema/fts.ts
|
|
697
949
|
async function rebuildEntriesFts(db) {
|
|
698
950
|
await db.execute("INSERT INTO entries_fts(entries_fts) VALUES('delete-all')");
|
|
@@ -727,31 +979,16 @@ async function rebuildFtsAndTriggers(db) {
|
|
|
727
979
|
throw error;
|
|
728
980
|
}
|
|
729
981
|
}
|
|
730
|
-
async function
|
|
982
|
+
async function rebuildVectorIndex2(db) {
|
|
731
983
|
try {
|
|
732
984
|
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 {
|
|
985
|
+
const stats = await getVectorIndexShadowStats(db);
|
|
986
|
+
if (stats.shadowCount === stats.embeddingCount && stats.missingRowids.length === 0) {
|
|
987
|
+
return;
|
|
752
988
|
}
|
|
753
|
-
|
|
989
|
+
} catch {
|
|
754
990
|
}
|
|
991
|
+
await rebuildVectorIndex(db);
|
|
755
992
|
}
|
|
756
993
|
async function clearBulkIngestMeta(db) {
|
|
757
994
|
await db.execute({ sql: "DELETE FROM _meta WHERE key = ?", args: [BULK_INGEST_META_KEY] });
|
|
@@ -777,6 +1014,7 @@ var BULK_INGEST_META_KEY;
|
|
|
777
1014
|
var init_bulk_ingest = __esm({
|
|
778
1015
|
"src/db/schema/bulk-ingest.ts"() {
|
|
779
1016
|
"use strict";
|
|
1017
|
+
init_vector_index();
|
|
780
1018
|
init_definitions();
|
|
781
1019
|
init_fts();
|
|
782
1020
|
BULK_INGEST_META_KEY = "bulk_ingest_state";
|
|
@@ -1358,15 +1596,10 @@ async function repairVectorIndexIfNeeded(client) {
|
|
|
1358
1596
|
if (probeCount > 0) {
|
|
1359
1597
|
return;
|
|
1360
1598
|
}
|
|
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
|
-
`);
|
|
1599
|
+
} catch {
|
|
1600
|
+
}
|
|
1601
|
+
try {
|
|
1602
|
+
await rebuildVectorIndex(client);
|
|
1370
1603
|
} catch {
|
|
1371
1604
|
}
|
|
1372
1605
|
}
|
|
@@ -1395,6 +1628,7 @@ var init_init = __esm({
|
|
|
1395
1628
|
init_version();
|
|
1396
1629
|
init_reflection_importance_cap();
|
|
1397
1630
|
init_reflection_removal();
|
|
1631
|
+
init_vector_index();
|
|
1398
1632
|
init_definitions();
|
|
1399
1633
|
init_entry_provenance();
|
|
1400
1634
|
init_fts();
|
|
@@ -1596,7 +1830,7 @@ async function checkAndRecoverBulkIngest(client) {
|
|
|
1596
1830
|
}
|
|
1597
1831
|
}
|
|
1598
1832
|
if (indexCount < 1) {
|
|
1599
|
-
await
|
|
1833
|
+
await rebuildVectorIndex2(client);
|
|
1600
1834
|
}
|
|
1601
1835
|
try {
|
|
1602
1836
|
const integrityResult = await client.execute("PRAGMA integrity_check");
|
|
@@ -4428,7 +4662,7 @@ var init_source_classification = __esm({
|
|
|
4428
4662
|
});
|
|
4429
4663
|
|
|
4430
4664
|
// src/utils/entry-utils.ts
|
|
4431
|
-
function
|
|
4665
|
+
function toNumber2(value) {
|
|
4432
4666
|
if (typeof value === "number") {
|
|
4433
4667
|
return value;
|
|
4434
4668
|
}
|
|
@@ -4537,10 +4771,10 @@ function mapRawStoredEntry(row, options) {
|
|
|
4537
4771
|
const entryKind = toStringValue(row.entry_kind).trim();
|
|
4538
4772
|
const temporalClass = toStringValue(row.temporal_class).trim();
|
|
4539
4773
|
const scopeRaw = toStringValue(row.scope).trim();
|
|
4540
|
-
const importanceRaw =
|
|
4541
|
-
const confirmationsRaw =
|
|
4542
|
-
const contradictionsRaw =
|
|
4543
|
-
const qualityScoreRaw =
|
|
4774
|
+
const importanceRaw = toNumber2(row.importance);
|
|
4775
|
+
const confirmationsRaw = toNumber2(row.confirmations);
|
|
4776
|
+
const contradictionsRaw = toNumber2(row.contradictions);
|
|
4777
|
+
const qualityScoreRaw = toNumber2(row.quality_score);
|
|
4544
4778
|
const subjectEntity = toStringValue(row.subject_entity).trim();
|
|
4545
4779
|
const subjectAttribute = toStringValue(row.subject_attribute).trim();
|
|
4546
4780
|
const subjectKey2 = toStringValue(row.subject_key).trim();
|
|
@@ -4548,8 +4782,8 @@ function mapRawStoredEntry(row, options) {
|
|
|
4548
4782
|
const claimObject = toStringValue(row.claim_object).trim();
|
|
4549
4783
|
const claimRole = toStringValue(row.claim_role).trim();
|
|
4550
4784
|
const normalizedClaimRole = normalizeClaimRole2(claimRole);
|
|
4551
|
-
const claimConfidenceRaw =
|
|
4552
|
-
const retiredRaw =
|
|
4785
|
+
const claimConfidenceRaw = toNumber2(row.claim_confidence);
|
|
4786
|
+
const retiredRaw = toNumber2(row.retired);
|
|
4553
4787
|
const clusterId = toStringValue(row.cluster_id).trim();
|
|
4554
4788
|
const sourceClass = normalizeSourceClass(toStringValue(row.source_class));
|
|
4555
4789
|
const suppressedContextsRaw = toStringValue(row.suppressed_contexts);
|
|
@@ -4752,14 +4986,14 @@ function normalizeEntryIds(entryIds) {
|
|
|
4752
4986
|
);
|
|
4753
4987
|
}
|
|
4754
4988
|
function parseCount(value) {
|
|
4755
|
-
const parsed =
|
|
4989
|
+
const parsed = toNumber2(value);
|
|
4756
4990
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4757
4991
|
return 0;
|
|
4758
4992
|
}
|
|
4759
4993
|
return Math.floor(parsed);
|
|
4760
4994
|
}
|
|
4761
4995
|
function parseSignalTotal(value) {
|
|
4762
|
-
const parsed =
|
|
4996
|
+
const parsed = toNumber2(value);
|
|
4763
4997
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4764
4998
|
return 0;
|
|
4765
4999
|
}
|
|
@@ -4773,7 +5007,7 @@ function parseIsoTimestamp(value) {
|
|
|
4773
5007
|
return normalized.length > 0 ? normalized : null;
|
|
4774
5008
|
}
|
|
4775
5009
|
function parseGapDays(value) {
|
|
4776
|
-
const parsed =
|
|
5010
|
+
const parsed = toNumber2(value);
|
|
4777
5011
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4778
5012
|
return 0;
|
|
4779
5013
|
}
|
|
@@ -4979,7 +5213,7 @@ async function getStoredEntryById(db, id) {
|
|
|
4979
5213
|
}
|
|
4980
5214
|
async function getTotalEntries(db) {
|
|
4981
5215
|
const result = await db.execute("SELECT COUNT(*) AS count FROM entries");
|
|
4982
|
-
const count =
|
|
5216
|
+
const count = toNumber2(result.rows[0]?.count);
|
|
4983
5217
|
return Number.isFinite(count) ? count : 0;
|
|
4984
5218
|
}
|
|
4985
5219
|
async function hasContentHash(db, contentHash) {
|
|
@@ -5344,7 +5578,7 @@ async function findRecentEntriesBySubjectTypeAndSourceFile(db, requests) {
|
|
|
5344
5578
|
normalizedSubject: toStringValue(row.lookup_normalized_subject),
|
|
5345
5579
|
type: toStringValue(row.lookup_type),
|
|
5346
5580
|
sourceFile: toStringValue(row.lookup_source_file),
|
|
5347
|
-
withinHours:
|
|
5581
|
+
withinHours: toNumber2(row.lookup_within_hours),
|
|
5348
5582
|
entry: mapEntryRow(row, { tags: tagsById.get(entryId) ?? [], includeEmbedding: true })
|
|
5349
5583
|
});
|
|
5350
5584
|
}
|
|
@@ -5879,6 +6113,10 @@ var init_similarity = __esm({
|
|
|
5879
6113
|
|
|
5880
6114
|
// src/utils/content-fingerprint.ts
|
|
5881
6115
|
import { createHash as createHash3 } from "crypto";
|
|
6116
|
+
function computeNormContentHash(content) {
|
|
6117
|
+
const normalized = content.toLowerCase().replace(/\s+/g, " ").trim().replace(/[^\w\s]/g, "");
|
|
6118
|
+
return createHash3("sha256").update(normalized).digest("hex");
|
|
6119
|
+
}
|
|
5882
6120
|
var init_content_fingerprint = __esm({
|
|
5883
6121
|
"src/utils/content-fingerprint.ts"() {
|
|
5884
6122
|
"use strict";
|
|
@@ -6278,12 +6516,12 @@ async function getConflictShadowSummary(db) {
|
|
|
6278
6516
|
continue;
|
|
6279
6517
|
}
|
|
6280
6518
|
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(
|
|
6519
|
+
totalEvaluated: Number.isFinite(toNumber2(record.total)) ? toNumber2(record.total) : 0,
|
|
6520
|
+
blockedAtCurrent: Number.isFinite(toNumber2(record.blocked_current)) ? toNumber2(record.blocked_current) : 0,
|
|
6521
|
+
currentOnlyBand: Number.isFinite(toNumber2(record.current_only)) ? toNumber2(record.current_only) : 0,
|
|
6522
|
+
wouldStillBlockAt090: Number.isFinite(toNumber2(record.still_block_090)) ? toNumber2(record.still_block_090) : 0,
|
|
6523
|
+
wouldStillBlockAt095: Number.isFinite(toNumber2(record.still_block_095)) ? toNumber2(record.still_block_095) : 0,
|
|
6524
|
+
silentCoexistBand: Number.isFinite(toNumber2(record.silent_coexist)) ? toNumber2(record.silent_coexist) : 0
|
|
6287
6525
|
};
|
|
6288
6526
|
byRelation[relation] = relationSummary;
|
|
6289
6527
|
totalEvaluated += relationSummary.totalEvaluated;
|
|
@@ -6732,7 +6970,7 @@ async function getCoRecallEdgeCounts(db) {
|
|
|
6732
6970
|
if (!entryId) {
|
|
6733
6971
|
continue;
|
|
6734
6972
|
}
|
|
6735
|
-
counts.set(entryId, Math.max(0,
|
|
6973
|
+
counts.set(entryId, Math.max(0, toNumber2(row.edge_count)));
|
|
6736
6974
|
}
|
|
6737
6975
|
return counts;
|
|
6738
6976
|
}
|
|
@@ -7042,10 +7280,10 @@ async function evolveQualityScores(db, options = {}, config) {
|
|
|
7042
7280
|
return {
|
|
7043
7281
|
id,
|
|
7044
7282
|
type: toStringValue(row.type),
|
|
7045
|
-
importance: Math.max(0,
|
|
7283
|
+
importance: Math.max(0, toNumber2(row.importance)),
|
|
7046
7284
|
recallCount: Math.max(0, metrics?.totalCount ?? 0),
|
|
7047
|
-
confirmations: Math.max(0,
|
|
7048
|
-
qualityScore:
|
|
7285
|
+
confirmations: Math.max(0, toNumber2(row.confirmations)),
|
|
7286
|
+
qualityScore: toNumber2(row.quality_score),
|
|
7049
7287
|
lastRecalledAt: metrics?.lastLiveRecalledAt ?? metrics?.lastAnyRecalledAt ?? "",
|
|
7050
7288
|
createdAt: toStringValue(row.created_at)
|
|
7051
7289
|
};
|
|
@@ -7402,8 +7640,8 @@ async function fetchRecalledEntryMetrics(db, entryIds) {
|
|
|
7402
7640
|
});
|
|
7403
7641
|
return result.rows.map((row) => ({
|
|
7404
7642
|
id: toStringValue(row.id),
|
|
7405
|
-
qualityScore:
|
|
7406
|
-
recallEventsCount:
|
|
7643
|
+
qualityScore: toNumber2(row.quality_score),
|
|
7644
|
+
recallEventsCount: toNumber2(row.recall_events_count)
|
|
7407
7645
|
}));
|
|
7408
7646
|
}
|
|
7409
7647
|
async function processBeforeResetRecallFeedback(request, deps) {
|
|
@@ -7481,66 +7719,6 @@ var init_watcher_demotion = __esm({
|
|
|
7481
7719
|
}
|
|
7482
7720
|
});
|
|
7483
7721
|
|
|
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
7722
|
// src/runtime/db-command-defaults.ts
|
|
7545
7723
|
function resolveDbCommandDefaults() {
|
|
7546
7724
|
const shared = resolveDefaultAppRuntimeDeps();
|
|
@@ -7553,7 +7731,7 @@ function resolveDbCommandDefaults() {
|
|
|
7553
7731
|
getConflictShadowSummary,
|
|
7554
7732
|
resetDb,
|
|
7555
7733
|
walCheckpoint,
|
|
7556
|
-
rebuildVectorIndex
|
|
7734
|
+
rebuildVectorIndex,
|
|
7557
7735
|
evolveQualityScores
|
|
7558
7736
|
};
|
|
7559
7737
|
}
|
|
@@ -8430,6 +8608,7 @@ function formatMidSessionRecall(results, options = {}) {
|
|
|
8430
8608
|
|
|
8431
8609
|
// src/runtime/openclaw-defaults.ts
|
|
8432
8610
|
init_client();
|
|
8611
|
+
init_schema();
|
|
8433
8612
|
|
|
8434
8613
|
// src/db/signals.ts
|
|
8435
8614
|
async function fetchNewSignalEntries(db, sinceSeq, minImportance, limit, maxAgeSec = 0) {
|
|
@@ -8546,7 +8725,9 @@ function resolveOpenClawPluginDbDefaults() {
|
|
|
8546
8725
|
return {
|
|
8547
8726
|
getDb: shared.getDbFn,
|
|
8548
8727
|
initDb: shared.initDbFn,
|
|
8549
|
-
closeDb: shared.closeDbFn
|
|
8728
|
+
closeDb: shared.closeDbFn,
|
|
8729
|
+
pluginSchemaStatements: OPENCLAW_PLUGIN_SCHEMA_STATEMENTS,
|
|
8730
|
+
pluginColumnMigrations: OPENCLAW_PLUGIN_COLUMN_MIGRATIONS
|
|
8550
8731
|
};
|
|
8551
8732
|
}
|
|
8552
8733
|
function resolveOpenClawSignalDefaults() {
|
|
@@ -8566,46 +8747,6 @@ function resolveOpenClawHandoffDefaults() {
|
|
|
8566
8747
|
}
|
|
8567
8748
|
|
|
8568
8749
|
// src/openclaw-plugin/plugin-db.ts
|
|
8569
|
-
var CREATE_SEEN_SESSIONS_TABLE_SQL = `
|
|
8570
|
-
CREATE TABLE IF NOT EXISTS seen_sessions (
|
|
8571
|
-
dedupe_key TEXT PRIMARY KEY,
|
|
8572
|
-
seen_at INTEGER NOT NULL
|
|
8573
|
-
)
|
|
8574
|
-
`;
|
|
8575
|
-
var CREATE_SEEN_SESSIONS_SEEN_AT_INDEX_SQL = `
|
|
8576
|
-
CREATE INDEX IF NOT EXISTS idx_seen_sessions_seen_at
|
|
8577
|
-
ON seen_sessions(seen_at)
|
|
8578
|
-
`;
|
|
8579
|
-
var CREATE_SESSION_PROJECTS_TABLE_SQL = `
|
|
8580
|
-
CREATE TABLE IF NOT EXISTS session_projects (
|
|
8581
|
-
session_key TEXT PRIMARY KEY,
|
|
8582
|
-
project TEXT NOT NULL,
|
|
8583
|
-
state TEXT NOT NULL DEFAULT 'set',
|
|
8584
|
-
updated_at TEXT NOT NULL
|
|
8585
|
-
)
|
|
8586
|
-
`;
|
|
8587
|
-
var CREATE_SESSION_IDENTITY_BREADCRUMBS_TABLE_SQL = `
|
|
8588
|
-
CREATE TABLE IF NOT EXISTS session_identity_breadcrumbs (
|
|
8589
|
-
session_id TEXT PRIMARY KEY,
|
|
8590
|
-
session_key TEXT,
|
|
8591
|
-
family TEXT NOT NULL,
|
|
8592
|
-
lane_id TEXT,
|
|
8593
|
-
origin_surface TEXT,
|
|
8594
|
-
delivery_channel TEXT,
|
|
8595
|
-
family_source TEXT,
|
|
8596
|
-
lane_source TEXT,
|
|
8597
|
-
created_at TEXT NOT NULL,
|
|
8598
|
-
updated_at TEXT NOT NULL
|
|
8599
|
-
)
|
|
8600
|
-
`;
|
|
8601
|
-
var CREATE_SESSION_IDENTITY_BREADCRUMBS_UPDATED_AT_INDEX_SQL = `
|
|
8602
|
-
CREATE INDEX IF NOT EXISTS idx_session_identity_breadcrumbs_updated_at
|
|
8603
|
-
ON session_identity_breadcrumbs(updated_at)
|
|
8604
|
-
`;
|
|
8605
|
-
var ADD_SESSION_PROJECT_STATE_COLUMN_SQL = `
|
|
8606
|
-
ALTER TABLE session_projects
|
|
8607
|
-
ADD COLUMN state TEXT NOT NULL DEFAULT 'set'
|
|
8608
|
-
`;
|
|
8609
8750
|
var PLUGIN_DB_STATE_KEY = "__agenrOpenClawPluginDbState";
|
|
8610
8751
|
function getPluginDbState() {
|
|
8611
8752
|
const globalState = globalThis;
|
|
@@ -8625,18 +8766,19 @@ function closePluginDbState(state) {
|
|
|
8625
8766
|
state.init = null;
|
|
8626
8767
|
}
|
|
8627
8768
|
async function ensurePluginDbTables(client) {
|
|
8628
|
-
|
|
8629
|
-
await
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8769
|
+
const defaults = resolveOpenClawPluginDbDefaults();
|
|
8770
|
+
await defaults.initDb(client);
|
|
8771
|
+
for (const statement of defaults.pluginSchemaStatements) {
|
|
8772
|
+
await client.execute(statement);
|
|
8773
|
+
}
|
|
8774
|
+
for (const migration of defaults.pluginColumnMigrations) {
|
|
8775
|
+
const tableInfo = await client.execute(`PRAGMA table_info(${migration.table})`);
|
|
8776
|
+
const hasColumn2 = tableInfo.rows.some(
|
|
8777
|
+
(row) => String(row.name) === migration.column
|
|
8778
|
+
);
|
|
8779
|
+
if (!hasColumn2) {
|
|
8780
|
+
await client.execute(migration.sql);
|
|
8781
|
+
}
|
|
8640
8782
|
}
|
|
8641
8783
|
}
|
|
8642
8784
|
function registerDbShutdown(state) {
|
|
@@ -8882,6 +9024,47 @@ async function finalizeRecallResults(params) {
|
|
|
8882
9024
|
return results;
|
|
8883
9025
|
}
|
|
8884
9026
|
|
|
9027
|
+
// src/domain/recall/browse-selection.ts
|
|
9028
|
+
var DEFAULT_BROWSE_DIVERSITY_TARGET = 4;
|
|
9029
|
+
function normalizeEntryType(result) {
|
|
9030
|
+
const rawType = result.entry.type;
|
|
9031
|
+
return typeof rawType === "string" ? rawType.trim().toLowerCase() : "";
|
|
9032
|
+
}
|
|
9033
|
+
function diversifyBrowseResults(results, limit, diversityTarget = DEFAULT_BROWSE_DIVERSITY_TARGET) {
|
|
9034
|
+
const normalizedLimit = Math.max(0, Math.floor(limit));
|
|
9035
|
+
if (normalizedLimit === 0 || results.length === 0) {
|
|
9036
|
+
return [];
|
|
9037
|
+
}
|
|
9038
|
+
const normalizedDiversityTarget = Math.max(0, Math.floor(diversityTarget));
|
|
9039
|
+
const seedTarget = Math.min(normalizedLimit, normalizedDiversityTarget);
|
|
9040
|
+
const selected = [];
|
|
9041
|
+
const selectedIds = /* @__PURE__ */ new Set();
|
|
9042
|
+
const admittedTypes = /* @__PURE__ */ new Set();
|
|
9043
|
+
for (const result of results) {
|
|
9044
|
+
if (selected.length >= seedTarget) {
|
|
9045
|
+
break;
|
|
9046
|
+
}
|
|
9047
|
+
const normalizedType = normalizeEntryType(result);
|
|
9048
|
+
if (!normalizedType || admittedTypes.has(normalizedType)) {
|
|
9049
|
+
continue;
|
|
9050
|
+
}
|
|
9051
|
+
selected.push(result);
|
|
9052
|
+
selectedIds.add(result.entry.id);
|
|
9053
|
+
admittedTypes.add(normalizedType);
|
|
9054
|
+
}
|
|
9055
|
+
for (const result of results) {
|
|
9056
|
+
if (selected.length >= normalizedLimit) {
|
|
9057
|
+
break;
|
|
9058
|
+
}
|
|
9059
|
+
if (selectedIds.has(result.entry.id)) {
|
|
9060
|
+
continue;
|
|
9061
|
+
}
|
|
9062
|
+
selected.push(result);
|
|
9063
|
+
selectedIds.add(result.entry.id);
|
|
9064
|
+
}
|
|
9065
|
+
return selected;
|
|
9066
|
+
}
|
|
9067
|
+
|
|
8885
9068
|
// src/db/recall/pipeline/retrieval.ts
|
|
8886
9069
|
init_client2();
|
|
8887
9070
|
|
|
@@ -9045,6 +9228,8 @@ var DEFAULT_RECALL_SATURATION = 10;
|
|
|
9045
9228
|
var DEFAULT_WARM_START_THRESHOLD = 3;
|
|
9046
9229
|
var DEFAULT_SYNTHETIC_FLOOR = 0.1;
|
|
9047
9230
|
var DEFAULT_AGENT_SOURCE_BONUS = 0.05;
|
|
9231
|
+
var BROWSE_RECENCY_WEIGHT = 0.8;
|
|
9232
|
+
var BROWSE_IMPORTANCE_WEIGHT = 0.2;
|
|
9048
9233
|
var MISSING_RECALL_DAYS = 99999;
|
|
9049
9234
|
var EMPTY_RECALL_METRICS = {
|
|
9050
9235
|
totalCount: 0,
|
|
@@ -9166,7 +9351,9 @@ function browseRecencyFactor(entry, now, aroundDate, aroundRadius = DEFAULT_AROU
|
|
|
9166
9351
|
return resolveRecallRecency(entry, now, aroundDate, aroundRadius);
|
|
9167
9352
|
}
|
|
9168
9353
|
function scoreBrowseEntry(entry, now, aroundDate, aroundRadius = DEFAULT_AROUND_RADIUS_DAYS) {
|
|
9169
|
-
|
|
9354
|
+
const recency2 = browseRecencyFactor(entry, now, aroundDate, aroundRadius);
|
|
9355
|
+
const importance = importanceScore(entry.importance);
|
|
9356
|
+
return clamp01(recency2 * BROWSE_RECENCY_WEIGHT + importance * BROWSE_IMPORTANCE_WEIGHT);
|
|
9170
9357
|
}
|
|
9171
9358
|
function scoreSessionEntry(entry, effectiveNow, freshnessNow, metricsMap, aroundDate, aroundRadius = DEFAULT_AROUND_RADIUS_DAYS, config) {
|
|
9172
9359
|
return scoreEntryWithBreakdown(
|
|
@@ -9702,8 +9889,21 @@ async function fetchBrowseCandidates(params) {
|
|
|
9702
9889
|
whereClauses.push("platform = ?");
|
|
9703
9890
|
args.push(params.query.platform);
|
|
9704
9891
|
}
|
|
9705
|
-
args.push(params.limit);
|
|
9706
9892
|
const whereClause = whereClauses.length > 0 ? "WHERE " + whereClauses.join(" AND ") : "";
|
|
9893
|
+
const orderBy = params.aroundDate ? `
|
|
9894
|
+
ORDER BY
|
|
9895
|
+
ABS(julianday(created_at) - julianday(?)) ASC,
|
|
9896
|
+
importance DESC,
|
|
9897
|
+
created_at DESC
|
|
9898
|
+
` : `
|
|
9899
|
+
ORDER BY
|
|
9900
|
+
created_at DESC,
|
|
9901
|
+
importance DESC
|
|
9902
|
+
`;
|
|
9903
|
+
if (params.aroundDate) {
|
|
9904
|
+
args.push(params.aroundDate.toISOString());
|
|
9905
|
+
}
|
|
9906
|
+
args.push(params.limit);
|
|
9707
9907
|
const result = await params.db.execute({
|
|
9708
9908
|
sql: `
|
|
9709
9909
|
SELECT
|
|
@@ -9711,10 +9911,10 @@ async function fetchBrowseCandidates(params) {
|
|
|
9711
9911
|
FROM entries
|
|
9712
9912
|
${whereClause}
|
|
9713
9913
|
-- SQL pre-sort is a best-effort approximation only.
|
|
9714
|
-
-- Final order is determined by
|
|
9715
|
-
--
|
|
9914
|
+
-- Final order is determined by recency-first browse scoring and a post-score
|
|
9915
|
+
-- diversity pass. The over-fetch buffer (limit*3, min 50)
|
|
9716
9916
|
-- ensures the final top-N are present in the candidate pool.
|
|
9717
|
-
|
|
9917
|
+
${orderBy}
|
|
9718
9918
|
LIMIT ?
|
|
9719
9919
|
`,
|
|
9720
9920
|
args
|
|
@@ -9947,6 +10147,7 @@ async function recallBrowseMode(params) {
|
|
|
9947
10147
|
query: browseQuery,
|
|
9948
10148
|
limit: browseLimit,
|
|
9949
10149
|
now: params.now,
|
|
10150
|
+
aroundDate: params.prepared.temporal.aroundDate,
|
|
9950
10151
|
projectFilter: params.prepared.scope.resolution.primaryFilter
|
|
9951
10152
|
});
|
|
9952
10153
|
const filtered = browseCandidates.filter(
|
|
@@ -9967,7 +10168,11 @@ async function recallBrowseMode(params) {
|
|
|
9967
10168
|
aroundRadiusDays: params.prepared.temporal.aroundRadiusDays
|
|
9968
10169
|
});
|
|
9969
10170
|
scored.sort((left, right) => right.score - left.score);
|
|
9970
|
-
|
|
10171
|
+
const results = diversifyBrowseResults(scored, requestedLimit, DEFAULT_BROWSE_DIVERSITY_TARGET);
|
|
10172
|
+
if (params.trace) {
|
|
10173
|
+
params.trace.finalResultIds = results.map((result) => result.entry.subject ?? result.entry.id);
|
|
10174
|
+
}
|
|
10175
|
+
return results;
|
|
9971
10176
|
}
|
|
9972
10177
|
async function retrieveCandidates(params) {
|
|
9973
10178
|
if (!params.prepared.retrievalSearchText) {
|
|
@@ -10377,11 +10582,12 @@ function resolvePreparedRecallScope(query, normalizedQuery) {
|
|
|
10377
10582
|
const explicitWildcardProject = hasWildcardProjectOverride(query.project);
|
|
10378
10583
|
const explicitProjects = explicitWildcardProject ? [] : parseProjectList(query.project);
|
|
10379
10584
|
const explicitExcludedProjects = parseProjectList(query.excludeProject);
|
|
10380
|
-
const inferredProjectHints = deriveRecallProjectScopeHints({
|
|
10585
|
+
const inferredProjectHints = explicitWildcardProject ? [] : deriveRecallProjectScopeHints({
|
|
10381
10586
|
queryText: normalizedQuery?.searchText ?? query.text ?? "",
|
|
10382
10587
|
explicitProjects
|
|
10383
10588
|
});
|
|
10384
|
-
const
|
|
10589
|
+
const callerProjectHints = explicitProjects.length > 0 || explicitWildcardProject ? [] : parseProjectList(query.projectHints).filter((projectHint) => projectHint !== "*");
|
|
10590
|
+
const projectHints = explicitProjects.length > 0 ? explicitProjects : Array.from(/* @__PURE__ */ new Set([...inferredProjectHints, ...callerProjectHints]));
|
|
10385
10591
|
const intent = projectHints.length > 0 ? "project" : normalizedQuery?.scopeIntent ?? "ambiguous";
|
|
10386
10592
|
if (query.universalOnly === true) {
|
|
10387
10593
|
return {
|
|
@@ -12126,6 +12332,7 @@ function buildRecallQuery(request, options) {
|
|
|
12126
12332
|
scope: request.scope ?? "private",
|
|
12127
12333
|
platform: request.platform,
|
|
12128
12334
|
project: request.project,
|
|
12335
|
+
projectHints: request.projectHints,
|
|
12129
12336
|
excludeProject: request.excludeProject,
|
|
12130
12337
|
projectStrict: request.projectStrict,
|
|
12131
12338
|
universalOnly: request.universalOnly,
|
|
@@ -12454,6 +12661,9 @@ async function sessionStartRecall2(request, deps) {
|
|
|
12454
12661
|
});
|
|
12455
12662
|
}
|
|
12456
12663
|
|
|
12664
|
+
// src/openclaw-plugin/recall.ts
|
|
12665
|
+
init_project();
|
|
12666
|
+
|
|
12457
12667
|
// src/openclaw-plugin/memory-index.ts
|
|
12458
12668
|
init_errors();
|
|
12459
12669
|
var MEMORY_INDEX_TIMEOUT_MS = 1e4;
|
|
@@ -12587,18 +12797,23 @@ function buildRecallRequest(budget, project, query, options) {
|
|
|
12587
12797
|
const queryText = trimmedQuery.length > RECALL_QUERY_MAX_CHARS ? trimmedQuery.slice(0, RECALL_QUERY_MAX_CHARS) : trimmedQuery;
|
|
12588
12798
|
const inferredSessionStart = isSessionStart || queryText.length === 0;
|
|
12589
12799
|
const universalOnly = options?.nullProjectOnly === true || options?.universalOnly === true;
|
|
12590
|
-
const
|
|
12800
|
+
const explicitWildcardProject = (options?.project ?? []).some(
|
|
12801
|
+
(candidate) => candidate.split(",").some((part) => part.trim() === "*")
|
|
12802
|
+
);
|
|
12591
12803
|
const normalizedProjects = Array.from(new Set(
|
|
12592
12804
|
(options?.project ?? []).map((candidate) => candidate.trim()).filter((candidate) => candidate.length > 0)
|
|
12593
12805
|
));
|
|
12594
|
-
const
|
|
12595
|
-
const
|
|
12806
|
+
const explicitProjectSelection = explicitWildcardProject || normalizedProjects.length > 0;
|
|
12807
|
+
const normalizedProjectHints = parseProjectList(options?.projectHints).filter((projectHint) => projectHint !== "*");
|
|
12808
|
+
const resolvedProject = universalOnly ? void 0 : explicitProjectSelection ? normalizedProjects.length > 0 ? normalizedProjects : void 0 : !project ? void 0 : [project];
|
|
12809
|
+
const resolvedProjectStrict = universalOnly ? void 0 : explicitProjectSelection ? options?.projectStrict ? true : void 0 : project && !universalOnly ? true : void 0;
|
|
12810
|
+
const resolvedProjectHints = universalOnly || explicitProjectSelection || explicitWildcardProject ? void 0 : normalizedProjectHints.length > 0 ? normalizedProjectHints : void 0;
|
|
12596
12811
|
return {
|
|
12597
12812
|
isBrowse,
|
|
12598
12813
|
isSessionStart: !isBrowse && inferredSessionStart,
|
|
12599
12814
|
limit: options?.limit ?? DEFAULT_LIMIT2,
|
|
12600
12815
|
queryText,
|
|
12601
|
-
since:
|
|
12816
|
+
since: options?.since,
|
|
12602
12817
|
types: options?.types,
|
|
12603
12818
|
until: options?.until,
|
|
12604
12819
|
around: options?.around,
|
|
@@ -12609,6 +12824,7 @@ function buildRecallRequest(budget, project, query, options) {
|
|
|
12609
12824
|
universalOnly,
|
|
12610
12825
|
project: resolvedProject,
|
|
12611
12826
|
projectStrict: resolvedProjectStrict,
|
|
12827
|
+
projectHints: resolvedProjectHints,
|
|
12612
12828
|
budget: isBrowse ? void 0 : options?.budget === null ? void 0 : options?.budget ?? budget
|
|
12613
12829
|
};
|
|
12614
12830
|
}
|
|
@@ -12658,6 +12874,7 @@ async function executeRecallRequest(budget, project, query, options, dbPath, exe
|
|
|
12658
12874
|
expiry: request.expiry,
|
|
12659
12875
|
project: request.project,
|
|
12660
12876
|
projectStrict: request.projectStrict,
|
|
12877
|
+
projectHints: request.projectHints,
|
|
12661
12878
|
universalOnly: request.universalOnly,
|
|
12662
12879
|
includeRecallCounts: false
|
|
12663
12880
|
},
|
|
@@ -12678,6 +12895,7 @@ async function executeRecallRequest(budget, project, query, options, dbPath, exe
|
|
|
12678
12895
|
expiry: request.expiry,
|
|
12679
12896
|
project: request.project,
|
|
12680
12897
|
projectStrict: request.projectStrict,
|
|
12898
|
+
projectHints: request.projectHints,
|
|
12681
12899
|
universalOnly: request.universalOnly,
|
|
12682
12900
|
updateMetadata,
|
|
12683
12901
|
includeRecallCounts: false
|
|
@@ -12701,6 +12919,7 @@ async function executeRecallRequest(budget, project, query, options, dbPath, exe
|
|
|
12701
12919
|
expiry: request.expiry,
|
|
12702
12920
|
project: request.project,
|
|
12703
12921
|
projectStrict: request.projectStrict,
|
|
12922
|
+
projectHints: request.projectHints,
|
|
12704
12923
|
universalOnly: request.universalOnly,
|
|
12705
12924
|
updateMetadata,
|
|
12706
12925
|
includeRecallCounts: false
|
|
@@ -14923,6 +15142,31 @@ var genericJsonlAdapter = {
|
|
|
14923
15142
|
|
|
14924
15143
|
// src/adapters/openclaw.ts
|
|
14925
15144
|
import fs13 from "fs/promises";
|
|
15145
|
+
init_content_fingerprint();
|
|
15146
|
+
|
|
15147
|
+
// src/utils/expiry.ts
|
|
15148
|
+
init_types();
|
|
15149
|
+
var EXPIRY_SET = new Set(EXPIRY_LEVELS);
|
|
15150
|
+
var EXPIRY_PRIORITY = {
|
|
15151
|
+
temporary: 0,
|
|
15152
|
+
permanent: 1,
|
|
15153
|
+
core: 2
|
|
15154
|
+
};
|
|
15155
|
+
function normalizeExpiry(value) {
|
|
15156
|
+
if (typeof value !== "string") {
|
|
15157
|
+
return void 0;
|
|
15158
|
+
}
|
|
15159
|
+
const normalized = value.trim().toLowerCase();
|
|
15160
|
+
if (!normalized) {
|
|
15161
|
+
return void 0;
|
|
15162
|
+
}
|
|
15163
|
+
return EXPIRY_SET.has(normalized) ? normalized : void 0;
|
|
15164
|
+
}
|
|
15165
|
+
function resolveHigherExpiry(a, b) {
|
|
15166
|
+
return EXPIRY_PRIORITY[a] >= EXPIRY_PRIORITY[b] ? a : b;
|
|
15167
|
+
}
|
|
15168
|
+
|
|
15169
|
+
// src/adapters/openclaw.ts
|
|
14926
15170
|
init_string();
|
|
14927
15171
|
function normalizeOpenClawRole(value) {
|
|
14928
15172
|
if (typeof value !== "string") {
|
|
@@ -14968,10 +15212,120 @@ function getStringArray(value) {
|
|
|
14968
15212
|
const values = value.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
14969
15213
|
return values.length > 0 ? values : void 0;
|
|
14970
15214
|
}
|
|
15215
|
+
function parseJsonRecord(value) {
|
|
15216
|
+
try {
|
|
15217
|
+
return asRecord4(JSON.parse(value));
|
|
15218
|
+
} catch {
|
|
15219
|
+
return null;
|
|
15220
|
+
}
|
|
15221
|
+
}
|
|
15222
|
+
function normalizeProjectValue(value) {
|
|
15223
|
+
const trimmed = value?.trim();
|
|
15224
|
+
return trimmed ? trimmed.toLowerCase() : void 0;
|
|
15225
|
+
}
|
|
14971
15226
|
function normalizeSessionLabel(value) {
|
|
14972
15227
|
const normalized = normalizeLabel(value);
|
|
14973
15228
|
return normalized.length > 0 ? normalized : void 0;
|
|
14974
15229
|
}
|
|
15230
|
+
function normalizeHintSubject(subject) {
|
|
15231
|
+
const trimmed = subject?.trim().toLowerCase();
|
|
15232
|
+
return trimmed ? trimmed : void 0;
|
|
15233
|
+
}
|
|
15234
|
+
function extractRecallResultsPayload(message, toolText) {
|
|
15235
|
+
const details = asRecord4(message.details);
|
|
15236
|
+
if (Array.isArray(details?.results)) {
|
|
15237
|
+
return details.results;
|
|
15238
|
+
}
|
|
15239
|
+
const parsedPayload = parseJsonRecord(toolText);
|
|
15240
|
+
if (Array.isArray(parsedPayload?.results)) {
|
|
15241
|
+
return parsedPayload.results;
|
|
15242
|
+
}
|
|
15243
|
+
return [];
|
|
15244
|
+
}
|
|
15245
|
+
function extractRecallTargetHints(message, toolText) {
|
|
15246
|
+
const hints = [];
|
|
15247
|
+
for (const result of extractRecallResultsPayload(message, toolText)) {
|
|
15248
|
+
const resultRecord = asRecord4(result);
|
|
15249
|
+
const entryRecord = asRecord4(resultRecord?.entry);
|
|
15250
|
+
const recalledEntryId = getString4(entryRecord?.id);
|
|
15251
|
+
const type = getString4(entryRecord?.type);
|
|
15252
|
+
const subject = getString4(entryRecord?.subject);
|
|
15253
|
+
const content = getString4(entryRecord?.content);
|
|
15254
|
+
if (!recalledEntryId || !type || !subject || !content) {
|
|
15255
|
+
continue;
|
|
15256
|
+
}
|
|
15257
|
+
const source = asRecord4(entryRecord?.source);
|
|
15258
|
+
hints.push({
|
|
15259
|
+
recalledEntryId,
|
|
15260
|
+
type,
|
|
15261
|
+
subject,
|
|
15262
|
+
normContentHash: computeNormContentHash(content),
|
|
15263
|
+
project: normalizeProjectValue(getString4(entryRecord?.project)),
|
|
15264
|
+
sourceFile: getString4(source?.file),
|
|
15265
|
+
sourceContext: getString4(source?.context)
|
|
15266
|
+
});
|
|
15267
|
+
}
|
|
15268
|
+
return hints;
|
|
15269
|
+
}
|
|
15270
|
+
function isRetireSuccessText(toolText) {
|
|
15271
|
+
const entryLabelPattern = '\\S+(?:\\s+\\("(?:\\\\.|[^"])*"\\))?';
|
|
15272
|
+
return new RegExp(`^Retired entry\\s+${entryLabelPattern}\\.\\s*$`, "i").test(toolText.trim());
|
|
15273
|
+
}
|
|
15274
|
+
function isUpdateSuccessText(toolText) {
|
|
15275
|
+
const trimmed = toolText.trim();
|
|
15276
|
+
const entryLabelPattern = '\\S+(?:\\s+\\("(?:\\\\.|[^"])*"\\))?';
|
|
15277
|
+
const updatePart = "(?:importance\\s+\\d+\\s+(?:->|\u2192)\\s+\\d+|expiry\\s+(?:core|permanent|temporary)\\s+(?:->|\u2192)\\s+(?:core|permanent|temporary))";
|
|
15278
|
+
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);
|
|
15279
|
+
}
|
|
15280
|
+
function isInactiveUpdateText(toolText) {
|
|
15281
|
+
const entryLabelPattern = '\\S+(?:\\s+\\("(?:\\\\.|[^"])*"\\))?';
|
|
15282
|
+
return new RegExp(
|
|
15283
|
+
`^Entry\\s+${entryLabelPattern}\\s+was not updated because it is no longer active\\.\\s*$`,
|
|
15284
|
+
"i"
|
|
15285
|
+
).test(toolText.trim());
|
|
15286
|
+
}
|
|
15287
|
+
function parseQuotedSubject(subjectToken) {
|
|
15288
|
+
if (!subjectToken) {
|
|
15289
|
+
return void 0;
|
|
15290
|
+
}
|
|
15291
|
+
try {
|
|
15292
|
+
const parsed = JSON.parse(subjectToken);
|
|
15293
|
+
return typeof parsed === "string" ? parsed : void 0;
|
|
15294
|
+
} catch {
|
|
15295
|
+
return void 0;
|
|
15296
|
+
}
|
|
15297
|
+
}
|
|
15298
|
+
function parseRetireSuccessReceipt(toolText) {
|
|
15299
|
+
const match = toolText.trim().match(
|
|
15300
|
+
/^Retired entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\.\s*$/i
|
|
15301
|
+
);
|
|
15302
|
+
if (!match) {
|
|
15303
|
+
return null;
|
|
15304
|
+
}
|
|
15305
|
+
return {
|
|
15306
|
+
entryId: match[1],
|
|
15307
|
+
subject: parseQuotedSubject(match[2])
|
|
15308
|
+
};
|
|
15309
|
+
}
|
|
15310
|
+
function parseUpdateReceiptEntry(toolText) {
|
|
15311
|
+
const matchers = [
|
|
15312
|
+
/^Updated entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\s+importance:/i,
|
|
15313
|
+
/^Updated entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?:/i,
|
|
15314
|
+
/^Entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\s+already has/i,
|
|
15315
|
+
/^Entry\s+(\S+)(?:\s+\(("(?:(?:\\.)|[^"])*")\))?\s+was not updated because/i
|
|
15316
|
+
];
|
|
15317
|
+
for (const matcher of matchers) {
|
|
15318
|
+
const match = toolText.trim().match(matcher);
|
|
15319
|
+
if (!match) {
|
|
15320
|
+
continue;
|
|
15321
|
+
}
|
|
15322
|
+
return {
|
|
15323
|
+
entryId: match[1],
|
|
15324
|
+
subject: parseQuotedSubject(match[2])
|
|
15325
|
+
};
|
|
15326
|
+
}
|
|
15327
|
+
return null;
|
|
15328
|
+
}
|
|
14975
15329
|
function parsePendingAgentStoreEntry(value, defaultProject) {
|
|
14976
15330
|
const record = asRecord4(value);
|
|
14977
15331
|
if (!record) {
|
|
@@ -15125,11 +15479,43 @@ var openClawAdapter = {
|
|
|
15125
15479
|
const modelsUsed = [];
|
|
15126
15480
|
const modelsUsedSet = /* @__PURE__ */ new Set();
|
|
15127
15481
|
const successfulAgentStoredEntries = [];
|
|
15482
|
+
const successfulAgentRetires = [];
|
|
15483
|
+
const successfulAgentUpdates = [];
|
|
15128
15484
|
const agentStoreProjects = /* @__PURE__ */ new Set();
|
|
15485
|
+
const recalledEntryHintsById = /* @__PURE__ */ new Map();
|
|
15486
|
+
const recalledEntryHintsBySubject = /* @__PURE__ */ new Map();
|
|
15129
15487
|
const pendingToolCalls = [];
|
|
15130
15488
|
const pendingToolCallsById = /* @__PURE__ */ new Map();
|
|
15131
15489
|
const pendingAgentStores = /* @__PURE__ */ new Map();
|
|
15132
15490
|
const pendingAgentStoreQueue = [];
|
|
15491
|
+
const pendingAgentRetires = /* @__PURE__ */ new Map();
|
|
15492
|
+
const pendingAgentRetireQueue = [];
|
|
15493
|
+
const pendingAgentUpdates = /* @__PURE__ */ new Map();
|
|
15494
|
+
const pendingAgentUpdateQueue = [];
|
|
15495
|
+
const appendRecalledEntryHint = (hint) => {
|
|
15496
|
+
recalledEntryHintsById.set(hint.recalledEntryId, hint);
|
|
15497
|
+
const subjectKey2 = normalizeHintSubject(hint.subject);
|
|
15498
|
+
if (!subjectKey2) {
|
|
15499
|
+
return;
|
|
15500
|
+
}
|
|
15501
|
+
const existing = recalledEntryHintsBySubject.get(subjectKey2) ?? [];
|
|
15502
|
+
existing.push(hint);
|
|
15503
|
+
recalledEntryHintsBySubject.set(subjectKey2, existing);
|
|
15504
|
+
};
|
|
15505
|
+
const resolveRecalledEntryHint = (entryId, subject) => {
|
|
15506
|
+
if (entryId) {
|
|
15507
|
+
const byId = recalledEntryHintsById.get(entryId);
|
|
15508
|
+
if (byId) {
|
|
15509
|
+
return byId;
|
|
15510
|
+
}
|
|
15511
|
+
}
|
|
15512
|
+
const subjectKey2 = normalizeHintSubject(subject);
|
|
15513
|
+
if (!subjectKey2) {
|
|
15514
|
+
return void 0;
|
|
15515
|
+
}
|
|
15516
|
+
const bySubject = recalledEntryHintsBySubject.get(subjectKey2) ?? [];
|
|
15517
|
+
return bySubject.length === 1 ? bySubject[0] : void 0;
|
|
15518
|
+
};
|
|
15133
15519
|
const addModelUsed = (value) => {
|
|
15134
15520
|
const modelId = typeof value === "string" ? value.trim() : "";
|
|
15135
15521
|
if (!modelId || modelsUsedSet.has(modelId)) {
|
|
@@ -15167,7 +15553,7 @@ var openClawAdapter = {
|
|
|
15167
15553
|
}
|
|
15168
15554
|
return pendingToolCalls.shift() ?? null;
|
|
15169
15555
|
};
|
|
15170
|
-
const
|
|
15556
|
+
const resolvePendingAction = (message, byId, queue, toolCallIdHint) => {
|
|
15171
15557
|
const candidateIds = [
|
|
15172
15558
|
toolCallIdHint,
|
|
15173
15559
|
getString4(message.toolCallId),
|
|
@@ -15176,14 +15562,23 @@ var openClawAdapter = {
|
|
|
15176
15562
|
getString4(message.id)
|
|
15177
15563
|
].filter((value, index, all) => Boolean(value) && all.indexOf(value) === index);
|
|
15178
15564
|
for (const id of candidateIds) {
|
|
15179
|
-
const pending =
|
|
15565
|
+
const pending = byId.get(id);
|
|
15180
15566
|
if (!pending) {
|
|
15181
15567
|
continue;
|
|
15182
15568
|
}
|
|
15183
|
-
|
|
15569
|
+
byId.delete(id);
|
|
15184
15570
|
return pending;
|
|
15185
15571
|
}
|
|
15186
|
-
return
|
|
15572
|
+
return queue.shift() ?? null;
|
|
15573
|
+
};
|
|
15574
|
+
const resolvePendingAgentStore = (message, toolCallIdHint) => {
|
|
15575
|
+
return resolvePendingAction(message, pendingAgentStores, pendingAgentStoreQueue, toolCallIdHint);
|
|
15576
|
+
};
|
|
15577
|
+
const resolvePendingAgentRetire = (message, toolCallIdHint) => {
|
|
15578
|
+
return resolvePendingAction(message, pendingAgentRetires, pendingAgentRetireQueue, toolCallIdHint);
|
|
15579
|
+
};
|
|
15580
|
+
const resolvePendingAgentUpdate = (message, toolCallIdHint) => {
|
|
15581
|
+
return resolvePendingAction(message, pendingAgentUpdates, pendingAgentUpdateQueue, toolCallIdHint);
|
|
15187
15582
|
};
|
|
15188
15583
|
parseJsonlLines(raw, warnings, (record) => {
|
|
15189
15584
|
if (record.type === "session") {
|
|
@@ -15249,28 +15644,75 @@ var openClawAdapter = {
|
|
|
15249
15644
|
const toolCalls = extractToolCallBlocks(content);
|
|
15250
15645
|
const assistantMessageIndex = messages.length;
|
|
15251
15646
|
for (const call of toolCalls) {
|
|
15647
|
+
const normalizedToolName = call.name.trim().toLowerCase();
|
|
15252
15648
|
pendingToolCalls.push(call);
|
|
15253
15649
|
if (call.id) {
|
|
15254
15650
|
pendingToolCallsById.set(call.id, call);
|
|
15255
15651
|
}
|
|
15256
|
-
if (
|
|
15652
|
+
if (normalizedToolName === "agenr_store" && Array.isArray(call.args.entries)) {
|
|
15653
|
+
const defaultProject = getString4(call.args.project);
|
|
15654
|
+
const entries = call.args.entries.map((entry) => parsePendingAgentStoreEntry(entry, defaultProject)).filter((entry) => entry !== null);
|
|
15655
|
+
if (entries.length === 0) {
|
|
15656
|
+
continue;
|
|
15657
|
+
}
|
|
15658
|
+
const pending = {
|
|
15659
|
+
entries,
|
|
15660
|
+
toolCallId: call.id,
|
|
15661
|
+
assistantMessageIndex,
|
|
15662
|
+
timestamp: timestamp2
|
|
15663
|
+
};
|
|
15664
|
+
if (call.id) {
|
|
15665
|
+
pendingAgentStores.set(call.id, pending);
|
|
15666
|
+
} else {
|
|
15667
|
+
pendingAgentStoreQueue.push(pending);
|
|
15668
|
+
}
|
|
15257
15669
|
continue;
|
|
15258
15670
|
}
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15671
|
+
if (normalizedToolName === "agenr_retire") {
|
|
15672
|
+
const entryId = getString4(call.args.entry_id);
|
|
15673
|
+
const subject = getString4(call.args.subject);
|
|
15674
|
+
if (!entryId && !subject || entryId && subject) {
|
|
15675
|
+
continue;
|
|
15676
|
+
}
|
|
15677
|
+
const pending = {
|
|
15678
|
+
...entryId ? { entryId } : {},
|
|
15679
|
+
...subject ? { subject } : {},
|
|
15680
|
+
reason: getString4(call.args.reason),
|
|
15681
|
+
toolCallId: call.id,
|
|
15682
|
+
assistantMessageIndex,
|
|
15683
|
+
timestamp: timestamp2,
|
|
15684
|
+
targetHint: resolveRecalledEntryHint(entryId, subject)
|
|
15685
|
+
};
|
|
15686
|
+
if (call.id) {
|
|
15687
|
+
pendingAgentRetires.set(call.id, pending);
|
|
15688
|
+
} else {
|
|
15689
|
+
pendingAgentRetireQueue.push(pending);
|
|
15690
|
+
}
|
|
15262
15691
|
continue;
|
|
15263
15692
|
}
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
|
|
15269
|
-
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
|
|
15693
|
+
if (normalizedToolName === "agenr_update") {
|
|
15694
|
+
const entryId = getString4(call.args.entry_id);
|
|
15695
|
+
const subject = getString4(call.args.subject);
|
|
15696
|
+
const importance = getNumber(call.args.importance);
|
|
15697
|
+
const expiry = normalizeExpiry(getString4(call.args.expiry));
|
|
15698
|
+
if (!entryId && !subject || entryId && subject || importance === void 0 && expiry === void 0) {
|
|
15699
|
+
continue;
|
|
15700
|
+
}
|
|
15701
|
+
const pending = {
|
|
15702
|
+
...entryId ? { entryId } : {},
|
|
15703
|
+
...subject ? { subject } : {},
|
|
15704
|
+
...importance !== void 0 ? { importance } : {},
|
|
15705
|
+
...expiry !== void 0 ? { expiry } : {},
|
|
15706
|
+
toolCallId: call.id,
|
|
15707
|
+
assistantMessageIndex,
|
|
15708
|
+
timestamp: timestamp2,
|
|
15709
|
+
targetHint: resolveRecalledEntryHint(entryId, subject)
|
|
15710
|
+
};
|
|
15711
|
+
if (call.id) {
|
|
15712
|
+
pendingAgentUpdates.set(call.id, pending);
|
|
15713
|
+
} else {
|
|
15714
|
+
pendingAgentUpdateQueue.push(pending);
|
|
15715
|
+
}
|
|
15274
15716
|
}
|
|
15275
15717
|
}
|
|
15276
15718
|
let text;
|
|
@@ -15308,8 +15750,17 @@ var openClawAdapter = {
|
|
|
15308
15750
|
const normalizedToolName = toolName?.trim().toLowerCase();
|
|
15309
15751
|
const args = ctx?.args ?? {};
|
|
15310
15752
|
const toolText = normalizeMessageText(content);
|
|
15753
|
+
const trimmedToolText = toolText.trim();
|
|
15754
|
+
if (normalizedToolName === "agenr_recall") {
|
|
15755
|
+
const recallFailed = message.isError === true || message.is_error === true || /^agenr_recall failed:/i.test(trimmedToolText);
|
|
15756
|
+
if (!recallFailed) {
|
|
15757
|
+
for (const hint of extractRecallTargetHints(message, toolText)) {
|
|
15758
|
+
appendRecalledEntryHint(hint);
|
|
15759
|
+
}
|
|
15760
|
+
}
|
|
15761
|
+
}
|
|
15311
15762
|
if (normalizedToolName === "agenr_store") {
|
|
15312
|
-
const storeFailed = message.isError === true || message.is_error === true || /^validation failed\b/i.test(
|
|
15763
|
+
const storeFailed = message.isError === true || message.is_error === true || /^validation failed\b/i.test(trimmedToolText);
|
|
15313
15764
|
const pending = resolvePendingAgentStore(message, ctx?.id);
|
|
15314
15765
|
if (pending && !storeFailed) {
|
|
15315
15766
|
const toolResultMessageIndex = messages.length;
|
|
@@ -15331,6 +15782,39 @@ var openClawAdapter = {
|
|
|
15331
15782
|
}
|
|
15332
15783
|
}
|
|
15333
15784
|
}
|
|
15785
|
+
if (normalizedToolName === "agenr_retire") {
|
|
15786
|
+
const retireFailed = message.isError === true || message.is_error === true || /^agenr_retire failed:/i.test(trimmedToolText);
|
|
15787
|
+
const pending = resolvePendingAgentRetire(message, ctx?.id);
|
|
15788
|
+
const receipt = parseRetireSuccessReceipt(toolText);
|
|
15789
|
+
if (pending && !retireFailed && receipt && isRetireSuccessText(toolText)) {
|
|
15790
|
+
const targetHint = pending.targetHint ?? resolveRecalledEntryHint(void 0, receipt.subject);
|
|
15791
|
+
successfulAgentRetires.push({
|
|
15792
|
+
entryId: receipt.entryId,
|
|
15793
|
+
reason: pending.reason,
|
|
15794
|
+
toolCallId: pending.toolCallId,
|
|
15795
|
+
assistantMessageIndex: pending.assistantMessageIndex,
|
|
15796
|
+
timestamp: pending.timestamp,
|
|
15797
|
+
...targetHint ? { targetHint } : {}
|
|
15798
|
+
});
|
|
15799
|
+
}
|
|
15800
|
+
}
|
|
15801
|
+
if (normalizedToolName === "agenr_update") {
|
|
15802
|
+
const updateFailed = message.isError === true || message.is_error === true || /^agenr_update failed:/i.test(trimmedToolText) || isInactiveUpdateText(trimmedToolText);
|
|
15803
|
+
const pending = resolvePendingAgentUpdate(message, ctx?.id);
|
|
15804
|
+
const receipt = parseUpdateReceiptEntry(toolText);
|
|
15805
|
+
if (pending && !updateFailed && receipt && isUpdateSuccessText(toolText)) {
|
|
15806
|
+
const targetHint = pending.targetHint ?? resolveRecalledEntryHint(void 0, receipt.subject);
|
|
15807
|
+
successfulAgentUpdates.push({
|
|
15808
|
+
entryId: receipt.entryId,
|
|
15809
|
+
...pending.importance !== void 0 ? { importance: pending.importance } : {},
|
|
15810
|
+
...pending.expiry !== void 0 ? { expiry: pending.expiry } : {},
|
|
15811
|
+
toolCallId: pending.toolCallId,
|
|
15812
|
+
assistantMessageIndex: pending.assistantMessageIndex,
|
|
15813
|
+
timestamp: pending.timestamp,
|
|
15814
|
+
...targetHint ? { targetHint } : {}
|
|
15815
|
+
});
|
|
15816
|
+
}
|
|
15817
|
+
}
|
|
15334
15818
|
if (!toolText) {
|
|
15335
15819
|
return;
|
|
15336
15820
|
}
|
|
@@ -15388,7 +15872,9 @@ var openClawAdapter = {
|
|
|
15388
15872
|
startedAt: sessionTimestamp ?? messages[0]?.timestamp ?? fallbackTimestamp,
|
|
15389
15873
|
agentStoreProjects: agentStoreProjects.size > 0 ? Array.from(agentStoreProjects) : void 0
|
|
15390
15874
|
},
|
|
15391
|
-
successfulAgentStoredEntries: successfulAgentStoredEntries.length > 0 ? successfulAgentStoredEntries : void 0
|
|
15875
|
+
successfulAgentStoredEntries: successfulAgentStoredEntries.length > 0 ? successfulAgentStoredEntries : void 0,
|
|
15876
|
+
successfulAgentRetires: successfulAgentRetires.length > 0 ? successfulAgentRetires : void 0,
|
|
15877
|
+
successfulAgentUpdates: successfulAgentUpdates.length > 0 ? successfulAgentUpdates : void 0
|
|
15392
15878
|
};
|
|
15393
15879
|
}
|
|
15394
15880
|
};
|
|
@@ -15853,7 +16339,9 @@ async function parseTranscriptFile(filePath, options) {
|
|
|
15853
16339
|
chunks,
|
|
15854
16340
|
warnings: result.warnings,
|
|
15855
16341
|
metadata: result.metadata,
|
|
15856
|
-
successfulAgentStoredEntries: result.successfulAgentStoredEntries
|
|
16342
|
+
successfulAgentStoredEntries: result.successfulAgentStoredEntries,
|
|
16343
|
+
successfulAgentRetires: result.successfulAgentRetires,
|
|
16344
|
+
successfulAgentUpdates: result.successfulAgentUpdates
|
|
15857
16345
|
};
|
|
15858
16346
|
}
|
|
15859
16347
|
|
|
@@ -20281,18 +20769,6 @@ async function extractKnowledgeFromChunks(params) {
|
|
|
20281
20769
|
};
|
|
20282
20770
|
}
|
|
20283
20771
|
|
|
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
20772
|
// src/app/ingest/trigram-dedup.ts
|
|
20297
20773
|
function normalize3(value) {
|
|
20298
20774
|
return value.toLowerCase().replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -20660,8 +21136,8 @@ function createContradictionRepository(db) {
|
|
|
20660
21136
|
});
|
|
20661
21137
|
return result.rows.map((row) => {
|
|
20662
21138
|
const record = row;
|
|
20663
|
-
const importance =
|
|
20664
|
-
const claimConfidence =
|
|
21139
|
+
const importance = toNumber2(record.importance);
|
|
21140
|
+
const claimConfidence = toNumber2(record.claim_confidence);
|
|
20665
21141
|
const claimRole = toStringValue(record.claim_role);
|
|
20666
21142
|
return {
|
|
20667
21143
|
id: toStringValue(record.id),
|
|
@@ -25108,7 +25584,7 @@ async function queryCandidates(db, subject, contains) {
|
|
|
25108
25584
|
id: toStringValue(row.id),
|
|
25109
25585
|
type: toStringValue(row.type),
|
|
25110
25586
|
subject: toStringValue(row.subject),
|
|
25111
|
-
importance:
|
|
25587
|
+
importance: toNumber2(row.importance),
|
|
25112
25588
|
content: toStringValue(row.content)
|
|
25113
25589
|
}));
|
|
25114
25590
|
}
|
|
@@ -25125,7 +25601,7 @@ async function queryById(db, id) {
|
|
|
25125
25601
|
id: toStringValue(row.id),
|
|
25126
25602
|
type: toStringValue(row.type),
|
|
25127
25603
|
subject: toStringValue(row.subject),
|
|
25128
|
-
importance:
|
|
25604
|
+
importance: toNumber2(row.importance),
|
|
25129
25605
|
content: toStringValue(row.content)
|
|
25130
25606
|
}));
|
|
25131
25607
|
}
|
|
@@ -25201,12 +25677,16 @@ init_runtime2();
|
|
|
25201
25677
|
function resolveUpdateServiceDeps(deps) {
|
|
25202
25678
|
return resolveAppRuntimeDeps(deps);
|
|
25203
25679
|
}
|
|
25204
|
-
function
|
|
25205
|
-
const
|
|
25206
|
-
|
|
25207
|
-
|
|
25680
|
+
function validateSelector2(request) {
|
|
25681
|
+
const queryId = request.id?.trim() ?? "";
|
|
25682
|
+
const querySubject = request.subject?.trim() ?? "";
|
|
25683
|
+
if (!queryId && !querySubject) {
|
|
25684
|
+
throw new Error("entry_id or subject is required");
|
|
25208
25685
|
}
|
|
25209
|
-
|
|
25686
|
+
if (queryId && querySubject) {
|
|
25687
|
+
throw new Error("entry_id and subject are mutually exclusive");
|
|
25688
|
+
}
|
|
25689
|
+
return { queryId, querySubject };
|
|
25210
25690
|
}
|
|
25211
25691
|
function normalizeImportance3(value) {
|
|
25212
25692
|
const parsed = typeof value === "number" ? value : Number(value);
|
|
@@ -25215,10 +25695,26 @@ function normalizeImportance3(value) {
|
|
|
25215
25695
|
}
|
|
25216
25696
|
return parsed;
|
|
25217
25697
|
}
|
|
25698
|
+
function normalizeOptionalImportance(value) {
|
|
25699
|
+
if (value === void 0) {
|
|
25700
|
+
return void 0;
|
|
25701
|
+
}
|
|
25702
|
+
return normalizeImportance3(value);
|
|
25703
|
+
}
|
|
25704
|
+
function normalizeOptionalExpiry(value) {
|
|
25705
|
+
if (value === void 0) {
|
|
25706
|
+
return void 0;
|
|
25707
|
+
}
|
|
25708
|
+
const normalized = normalizeExpiry(value);
|
|
25709
|
+
if (!normalized) {
|
|
25710
|
+
throw new Error(`expiry must be one of: ${EXPIRY_LEVELS.join(", ")}`);
|
|
25711
|
+
}
|
|
25712
|
+
return normalized;
|
|
25713
|
+
}
|
|
25218
25714
|
async function queryById2(db, id) {
|
|
25219
25715
|
const result = await db.execute({
|
|
25220
25716
|
sql: `
|
|
25221
|
-
SELECT id, type, subject, importance, content
|
|
25717
|
+
SELECT id, type, subject, importance, expiry, content
|
|
25222
25718
|
FROM entries
|
|
25223
25719
|
WHERE retired = 0 AND id = ?
|
|
25224
25720
|
LIMIT 1
|
|
@@ -25229,11 +25725,39 @@ async function queryById2(db, id) {
|
|
|
25229
25725
|
if (!row) {
|
|
25230
25726
|
return null;
|
|
25231
25727
|
}
|
|
25728
|
+
const expiry = normalizeExpiry(row.expiry) ?? "temporary";
|
|
25232
25729
|
return {
|
|
25233
25730
|
id: toStringValue(row.id),
|
|
25234
25731
|
type: toStringValue(row.type),
|
|
25235
25732
|
subject: toStringValue(row.subject),
|
|
25236
|
-
importance:
|
|
25733
|
+
importance: toNumber2(row.importance),
|
|
25734
|
+
expiry,
|
|
25735
|
+
content: toStringValue(row.content)
|
|
25736
|
+
};
|
|
25737
|
+
}
|
|
25738
|
+
async function queryBySubject(db, subject) {
|
|
25739
|
+
const result = await db.execute({
|
|
25740
|
+
sql: `
|
|
25741
|
+
SELECT id, type, subject, importance, expiry, content
|
|
25742
|
+
FROM entries
|
|
25743
|
+
WHERE retired = 0
|
|
25744
|
+
AND LOWER(subject) = LOWER(?)
|
|
25745
|
+
ORDER BY updated_at DESC
|
|
25746
|
+
LIMIT 1
|
|
25747
|
+
`,
|
|
25748
|
+
args: [subject]
|
|
25749
|
+
});
|
|
25750
|
+
const row = result.rows[0];
|
|
25751
|
+
if (!row) {
|
|
25752
|
+
return null;
|
|
25753
|
+
}
|
|
25754
|
+
const expiry = normalizeExpiry(row.expiry) ?? "temporary";
|
|
25755
|
+
return {
|
|
25756
|
+
id: toStringValue(row.id),
|
|
25757
|
+
type: toStringValue(row.type),
|
|
25758
|
+
subject: toStringValue(row.subject),
|
|
25759
|
+
importance: toNumber2(row.importance),
|
|
25760
|
+
expiry,
|
|
25237
25761
|
content: toStringValue(row.content)
|
|
25238
25762
|
};
|
|
25239
25763
|
}
|
|
@@ -25245,7 +25769,7 @@ async function lookupUpdateCandidate(request, deps) {
|
|
|
25245
25769
|
}
|
|
25246
25770
|
async function runUpdateService(request, deps) {
|
|
25247
25771
|
const resolvedDeps = resolveUpdateServiceDeps(deps);
|
|
25248
|
-
const
|
|
25772
|
+
const { queryId, querySubject } = validateSelector2(request);
|
|
25249
25773
|
return withAppDb(
|
|
25250
25774
|
{
|
|
25251
25775
|
env: request.env,
|
|
@@ -25256,53 +25780,81 @@ async function runUpdateService(request, deps) {
|
|
|
25256
25780
|
if (request.action === "lookup") {
|
|
25257
25781
|
return {
|
|
25258
25782
|
action: "lookup",
|
|
25259
|
-
candidate: await queryById2(db,
|
|
25783
|
+
candidate: queryId ? await queryById2(db, queryId) : await queryBySubject(db, querySubject)
|
|
25260
25784
|
};
|
|
25261
25785
|
}
|
|
25262
|
-
const importance =
|
|
25263
|
-
const
|
|
25786
|
+
const importance = normalizeOptionalImportance(request.importance);
|
|
25787
|
+
const expiry = normalizeOptionalExpiry(request.expiry);
|
|
25788
|
+
if (importance === void 0 && expiry === void 0) {
|
|
25789
|
+
throw new Error("at least one of importance or expiry is required");
|
|
25790
|
+
}
|
|
25791
|
+
const existing = queryId ? await queryById2(db, queryId) : await queryBySubject(db, querySubject);
|
|
25792
|
+
const targetId = existing?.id ?? queryId ?? querySubject;
|
|
25264
25793
|
if (!existing) {
|
|
25265
25794
|
return {
|
|
25266
25795
|
action: "execute",
|
|
25267
|
-
id,
|
|
25268
|
-
previousImportance: importance,
|
|
25269
|
-
importance,
|
|
25796
|
+
id: targetId,
|
|
25797
|
+
previousImportance: importance ?? IMPORTANCE_MIN,
|
|
25798
|
+
importance: importance ?? IMPORTANCE_MIN,
|
|
25799
|
+
previousExpiry: expiry ?? "temporary",
|
|
25800
|
+
expiry: expiry ?? "temporary",
|
|
25270
25801
|
updated: false
|
|
25271
25802
|
};
|
|
25272
25803
|
}
|
|
25273
|
-
|
|
25804
|
+
const nextImportance = importance ?? existing.importance;
|
|
25805
|
+
const nextExpiry = expiry ?? existing.expiry;
|
|
25806
|
+
const importanceChanged = existing.importance !== nextImportance;
|
|
25807
|
+
const expiryChanged = existing.expiry !== nextExpiry;
|
|
25808
|
+
if (!importanceChanged && !expiryChanged) {
|
|
25274
25809
|
return {
|
|
25275
25810
|
action: "execute",
|
|
25276
|
-
id,
|
|
25811
|
+
id: existing.id,
|
|
25277
25812
|
previousImportance: existing.importance,
|
|
25278
|
-
importance,
|
|
25813
|
+
importance: existing.importance,
|
|
25814
|
+
previousExpiry: existing.expiry,
|
|
25815
|
+
expiry: existing.expiry,
|
|
25279
25816
|
updated: true
|
|
25280
25817
|
};
|
|
25281
25818
|
}
|
|
25819
|
+
const setClauses = [];
|
|
25820
|
+
const setArgs = [];
|
|
25821
|
+
if (importanceChanged) {
|
|
25822
|
+
setClauses.push("importance = ?");
|
|
25823
|
+
setArgs.push(nextImportance);
|
|
25824
|
+
}
|
|
25825
|
+
if (expiryChanged) {
|
|
25826
|
+
setClauses.push("expiry = ?");
|
|
25827
|
+
setArgs.push(nextExpiry);
|
|
25828
|
+
}
|
|
25829
|
+
setClauses.push("updated_at = ?");
|
|
25830
|
+
setArgs.push(runtime.now.toISOString());
|
|
25282
25831
|
const result = await db.execute({
|
|
25283
25832
|
sql: `
|
|
25284
25833
|
UPDATE entries
|
|
25285
|
-
SET
|
|
25286
|
-
updated_at = ?
|
|
25834
|
+
SET ${setClauses.join(", ")}
|
|
25287
25835
|
WHERE id = ?
|
|
25288
25836
|
AND retired = 0
|
|
25289
25837
|
`,
|
|
25290
|
-
args: [
|
|
25838
|
+
args: [...setArgs, existing.id]
|
|
25291
25839
|
});
|
|
25292
25840
|
if (toRowsAffected(result.rowsAffected) === 0) {
|
|
25293
25841
|
return {
|
|
25294
25842
|
action: "execute",
|
|
25295
|
-
id,
|
|
25843
|
+
id: existing.id,
|
|
25296
25844
|
previousImportance: existing.importance,
|
|
25297
25845
|
importance: existing.importance,
|
|
25846
|
+
previousExpiry: existing.expiry,
|
|
25847
|
+
expiry: existing.expiry,
|
|
25298
25848
|
updated: false
|
|
25299
25849
|
};
|
|
25300
25850
|
}
|
|
25301
25851
|
return {
|
|
25302
25852
|
action: "execute",
|
|
25303
|
-
id,
|
|
25853
|
+
id: existing.id,
|
|
25304
25854
|
previousImportance: existing.importance,
|
|
25305
|
-
importance,
|
|
25855
|
+
importance: nextImportance,
|
|
25856
|
+
previousExpiry: existing.expiry,
|
|
25857
|
+
expiry: nextExpiry,
|
|
25306
25858
|
updated: true
|
|
25307
25859
|
};
|
|
25308
25860
|
}
|
|
@@ -25314,6 +25866,8 @@ async function executeUpdate(request, deps) {
|
|
|
25314
25866
|
id: result.id,
|
|
25315
25867
|
previousImportance: result.previousImportance,
|
|
25316
25868
|
importance: result.importance,
|
|
25869
|
+
previousExpiry: result.previousExpiry,
|
|
25870
|
+
expiry: result.expiry,
|
|
25317
25871
|
updated: result.updated
|
|
25318
25872
|
};
|
|
25319
25873
|
}
|
|
@@ -25325,8 +25879,8 @@ init_client();
|
|
|
25325
25879
|
// src/db/provenance.ts
|
|
25326
25880
|
init_entry_utils();
|
|
25327
25881
|
function mapProvenanceEntry(row, tags) {
|
|
25328
|
-
const importance =
|
|
25329
|
-
const retired =
|
|
25882
|
+
const importance = toNumber2(row.importance);
|
|
25883
|
+
const retired = toNumber2(row.retired);
|
|
25330
25884
|
return {
|
|
25331
25885
|
id: toStringValue(row.id),
|
|
25332
25886
|
subject: toStringValue(row.subject),
|
|
@@ -25349,7 +25903,7 @@ function mapProvenanceRelated(row, tags) {
|
|
|
25349
25903
|
};
|
|
25350
25904
|
}
|
|
25351
25905
|
function mapProvenanceSupport(row) {
|
|
25352
|
-
const claimConfidence =
|
|
25906
|
+
const claimConfidence = toNumber2(row.claim_confidence);
|
|
25353
25907
|
const sourceFile = toStringValue(row.source_file).trim();
|
|
25354
25908
|
const sourceContext = toStringValue(row.source_context).trim();
|
|
25355
25909
|
const sourceCreatedAt = toStringValue(row.source_created_at).trim();
|
|
@@ -26643,6 +27197,7 @@ function resolveOpenClawBridgeStoreProjectAttribution(params) {
|
|
|
26643
27197
|
|
|
26644
27198
|
// src/openclaw-plugin/tools.ts
|
|
26645
27199
|
init_types();
|
|
27200
|
+
init_project();
|
|
26646
27201
|
var KNOWN_PLATFORMS = /* @__PURE__ */ new Set(["openclaw", "codex", "claude-code", "plaud"]);
|
|
26647
27202
|
var log7 = createLogger("tools");
|
|
26648
27203
|
var SUCCESSFUL_STORE_ACTIONS = /* @__PURE__ */ new Set([
|
|
@@ -26657,10 +27212,31 @@ function asString2(value) {
|
|
|
26657
27212
|
const trimmed = value.trim();
|
|
26658
27213
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
26659
27214
|
}
|
|
27215
|
+
function validateExclusiveSelector(params) {
|
|
27216
|
+
const entryId = asString2(params.entry_id);
|
|
27217
|
+
const subject = asString2(params.subject);
|
|
27218
|
+
if (entryId && subject || !entryId && !subject) {
|
|
27219
|
+
throw new Error("exactly one of entry_id or subject is required");
|
|
27220
|
+
}
|
|
27221
|
+
return { entryId, subject };
|
|
27222
|
+
}
|
|
27223
|
+
function formatQuotedSubject(subject) {
|
|
27224
|
+
return JSON.stringify(subject);
|
|
27225
|
+
}
|
|
27226
|
+
function formatEntryLabel(id, subject) {
|
|
27227
|
+
return subject ? `${id} (${formatQuotedSubject(subject)})` : id;
|
|
27228
|
+
}
|
|
27229
|
+
function formatMissingEntryError(selector) {
|
|
27230
|
+
if (selector.subject) {
|
|
27231
|
+
return `No active entry found matching subject: ${formatQuotedSubject(selector.subject)}`;
|
|
27232
|
+
}
|
|
27233
|
+
return `No active entry found with id: ${selector.entryId}`;
|
|
27234
|
+
}
|
|
26660
27235
|
function resolveStoreCandidateProject(explicitProject, sessionProject, defaultProject) {
|
|
26661
27236
|
return asString2(explicitProject) ?? asString2(sessionProject) ?? asString2(defaultProject);
|
|
26662
27237
|
}
|
|
26663
27238
|
function createAgentToolRecallScopeDiagnostic(scope, defaultProjectPresent) {
|
|
27239
|
+
const diagnosticProjects = scope.projects.length > 0 ? scope.projects : scope.projectHints ?? [];
|
|
26664
27240
|
return createProjectScopeResolutionDiagnostic({
|
|
26665
27241
|
surface: "agent-tool-recall",
|
|
26666
27242
|
inputs: {
|
|
@@ -26674,8 +27250,8 @@ function createAgentToolRecallScopeDiagnostic(scope, defaultProjectPresent) {
|
|
|
26674
27250
|
outcome: {
|
|
26675
27251
|
projectSource: scope.projectSource,
|
|
26676
27252
|
reason: scope.reason,
|
|
26677
|
-
projects:
|
|
26678
|
-
primaryProject:
|
|
27253
|
+
projects: diagnosticProjects,
|
|
27254
|
+
primaryProject: diagnosticProjects[0],
|
|
26679
27255
|
recallProjectArg: scope.recallProjectArg,
|
|
26680
27256
|
strictScope: scope.projectStrict,
|
|
26681
27257
|
dependencyExpansionApplied: false,
|
|
@@ -26685,7 +27261,9 @@ function createAgentToolRecallScopeDiagnostic(scope, defaultProjectPresent) {
|
|
|
26685
27261
|
}
|
|
26686
27262
|
function resolveAgentToolRecallScope(explicitProject, defaultProject) {
|
|
26687
27263
|
const normalizedExplicitProject = explicitProject?.trim();
|
|
26688
|
-
const
|
|
27264
|
+
const normalizedDefaultProjects = parseProjectList(defaultProject).filter((project) => project !== "*");
|
|
27265
|
+
const normalizedDefaultProject = normalizedDefaultProjects[0];
|
|
27266
|
+
const defaultProjectPresent = normalizedDefaultProjects.length > 0;
|
|
26689
27267
|
if (normalizedExplicitProject === "*") {
|
|
26690
27268
|
const scope2 = {
|
|
26691
27269
|
surface: "agent-tool-recall",
|
|
@@ -26693,8 +27271,8 @@ function resolveAgentToolRecallScope(explicitProject, defaultProject) {
|
|
|
26693
27271
|
projectSource: "unscoped",
|
|
26694
27272
|
projectArgumentState: "wildcard",
|
|
26695
27273
|
reason: "explicit-tool-project-bypass",
|
|
26696
|
-
projects: [],
|
|
26697
|
-
recallProjectArg:
|
|
27274
|
+
projects: ["*"],
|
|
27275
|
+
recallProjectArg: "*",
|
|
26698
27276
|
projectStrict: false
|
|
26699
27277
|
};
|
|
26700
27278
|
return {
|
|
@@ -26706,14 +27284,34 @@ function resolveAgentToolRecallScope(explicitProject, defaultProject) {
|
|
|
26706
27284
|
};
|
|
26707
27285
|
}
|
|
26708
27286
|
if (!normalizedExplicitProject) {
|
|
27287
|
+
if (normalizedDefaultProject) {
|
|
27288
|
+
const scope3 = {
|
|
27289
|
+
surface: "agent-tool-recall",
|
|
27290
|
+
projectResolutionMode: "explicit-tool-project-only",
|
|
27291
|
+
projectSource: "plugin-default-project",
|
|
27292
|
+
projectArgumentState: "omitted",
|
|
27293
|
+
reason: "plugin-default-project",
|
|
27294
|
+
projects: [],
|
|
27295
|
+
projectHints: [normalizedDefaultProject],
|
|
27296
|
+
recallProjectArg: void 0,
|
|
27297
|
+
projectStrict: false
|
|
27298
|
+
};
|
|
27299
|
+
return {
|
|
27300
|
+
...scope3,
|
|
27301
|
+
memoryReliabilityDiagnostic: createAgentToolRecallScopeDiagnostic(
|
|
27302
|
+
scope3,
|
|
27303
|
+
defaultProjectPresent
|
|
27304
|
+
)
|
|
27305
|
+
};
|
|
27306
|
+
}
|
|
26709
27307
|
const scope2 = {
|
|
26710
27308
|
surface: "agent-tool-recall",
|
|
26711
27309
|
projectResolutionMode: "explicit-tool-project-only",
|
|
26712
27310
|
projectSource: "unscoped",
|
|
26713
27311
|
projectArgumentState: "omitted",
|
|
26714
27312
|
reason: "no-project-candidate",
|
|
26715
|
-
projects: [],
|
|
26716
|
-
recallProjectArg:
|
|
27313
|
+
projects: ["*"],
|
|
27314
|
+
recallProjectArg: "*",
|
|
26717
27315
|
projectStrict: false
|
|
26718
27316
|
};
|
|
26719
27317
|
return {
|
|
@@ -26755,6 +27353,36 @@ function asNumber(value) {
|
|
|
26755
27353
|
}
|
|
26756
27354
|
return void 0;
|
|
26757
27355
|
}
|
|
27356
|
+
function normalizeOptionalUpdateExpiry(value) {
|
|
27357
|
+
if (value === void 0) {
|
|
27358
|
+
return void 0;
|
|
27359
|
+
}
|
|
27360
|
+
const expiry = normalizeExpiry(value);
|
|
27361
|
+
if (!expiry) {
|
|
27362
|
+
throw new Error(`expiry must be one of: ${EXPIRY_LEVELS.join(", ")}`);
|
|
27363
|
+
}
|
|
27364
|
+
return expiry;
|
|
27365
|
+
}
|
|
27366
|
+
function buildChangedUpdateParts(request, result) {
|
|
27367
|
+
const parts = [];
|
|
27368
|
+
if (request.importance !== void 0 && result.previousImportance !== result.importance) {
|
|
27369
|
+
parts.push(`importance ${result.previousImportance} \u2192 ${result.importance}`);
|
|
27370
|
+
}
|
|
27371
|
+
if (request.expiry !== void 0 && result.previousExpiry !== result.expiry) {
|
|
27372
|
+
parts.push(`expiry ${result.previousExpiry} \u2192 ${result.expiry}`);
|
|
27373
|
+
}
|
|
27374
|
+
return parts;
|
|
27375
|
+
}
|
|
27376
|
+
function buildRequestedUpdateParts(request, result) {
|
|
27377
|
+
const parts = [];
|
|
27378
|
+
if (request.importance !== void 0) {
|
|
27379
|
+
parts.push(`importance ${result.importance}`);
|
|
27380
|
+
}
|
|
27381
|
+
if (request.expiry !== void 0) {
|
|
27382
|
+
parts.push(`expiry ${result.expiry}`);
|
|
27383
|
+
}
|
|
27384
|
+
return parts;
|
|
27385
|
+
}
|
|
26758
27386
|
function parseOptionalPositiveInt(value, label) {
|
|
26759
27387
|
if (value === void 0) {
|
|
26760
27388
|
return void 0;
|
|
@@ -26879,6 +27507,7 @@ async function runRecallTool(params, defaultProject, dbPath) {
|
|
|
26879
27507
|
platform: normalizeRecallPlatform(asString2(params.platform)),
|
|
26880
27508
|
project: recallScope.projects,
|
|
26881
27509
|
projectStrict: recallScope.projectStrict,
|
|
27510
|
+
projectHints: recallScope.projectHints,
|
|
26882
27511
|
budget: null
|
|
26883
27512
|
},
|
|
26884
27513
|
dbPath,
|
|
@@ -27069,34 +27698,34 @@ async function runExtractTool(params, dbPath) {
|
|
|
27069
27698
|
}
|
|
27070
27699
|
async function runRetireTool(params, dbPath) {
|
|
27071
27700
|
try {
|
|
27072
|
-
const
|
|
27073
|
-
if (!entryId) {
|
|
27074
|
-
return {
|
|
27075
|
-
content: [{ type: "text", text: "agenr_retire failed: entry_id is required" }]
|
|
27076
|
-
};
|
|
27077
|
-
}
|
|
27701
|
+
const selector = validateExclusiveSelector(params);
|
|
27078
27702
|
const lookup = await lookupRetireCandidates({
|
|
27079
|
-
id: entryId,
|
|
27703
|
+
id: selector.entryId,
|
|
27704
|
+
subject: selector.subject,
|
|
27080
27705
|
dbPath
|
|
27081
27706
|
});
|
|
27082
|
-
|
|
27707
|
+
const candidate = lookup.candidates[0];
|
|
27708
|
+
if (!candidate) {
|
|
27083
27709
|
return {
|
|
27084
|
-
content: [{ type: "text", text: `agenr_retire failed:
|
|
27710
|
+
content: [{ type: "text", text: `agenr_retire failed: ${formatMissingEntryError(selector)}` }]
|
|
27085
27711
|
};
|
|
27086
27712
|
}
|
|
27087
27713
|
const retired = await executeRetire({
|
|
27088
|
-
id:
|
|
27714
|
+
id: candidate.id,
|
|
27089
27715
|
reason: asString2(params.reason),
|
|
27090
27716
|
persist: params.persist === true,
|
|
27091
27717
|
dbPath
|
|
27092
27718
|
});
|
|
27093
27719
|
if (retired.retiredCount === 0) {
|
|
27094
27720
|
return {
|
|
27095
|
-
content: [{ type: "text", text: `agenr_retire failed:
|
|
27721
|
+
content: [{ type: "text", text: `agenr_retire failed: ${formatMissingEntryError(selector)}` }]
|
|
27096
27722
|
};
|
|
27097
27723
|
}
|
|
27098
27724
|
return {
|
|
27099
|
-
content: [{
|
|
27725
|
+
content: [{
|
|
27726
|
+
type: "text",
|
|
27727
|
+
text: `Retired entry ${formatEntryLabel(candidate.id, selector.subject ? candidate.subject : void 0)}.`
|
|
27728
|
+
}]
|
|
27100
27729
|
};
|
|
27101
27730
|
} catch (error) {
|
|
27102
27731
|
return {
|
|
@@ -27106,42 +27735,60 @@ async function runRetireTool(params, dbPath) {
|
|
|
27106
27735
|
}
|
|
27107
27736
|
async function runUpdateTool(params, dbPath) {
|
|
27108
27737
|
try {
|
|
27109
|
-
const
|
|
27738
|
+
const selector = validateExclusiveSelector(params);
|
|
27739
|
+
const importanceProvided = Object.prototype.hasOwnProperty.call(params, "importance");
|
|
27110
27740
|
const importance = asNumber(params.importance);
|
|
27111
|
-
if (!
|
|
27741
|
+
if (importanceProvided && (importance === void 0 || !Number.isInteger(importance) || importance < 1 || importance > 10)) {
|
|
27112
27742
|
return {
|
|
27113
|
-
content: [{ type: "text", text: "agenr_update failed:
|
|
27743
|
+
content: [{ type: "text", text: "agenr_update failed: importance must be an integer between 1 and 10" }]
|
|
27114
27744
|
};
|
|
27115
27745
|
}
|
|
27116
|
-
|
|
27746
|
+
const expiry = normalizeOptionalUpdateExpiry(params.expiry);
|
|
27747
|
+
if (importance === void 0 && expiry === void 0) {
|
|
27117
27748
|
return {
|
|
27118
|
-
content: [{ type: "text", text: "agenr_update failed:
|
|
27749
|
+
content: [{ type: "text", text: "agenr_update failed: at least one of importance or expiry is required" }]
|
|
27119
27750
|
};
|
|
27120
27751
|
}
|
|
27121
27752
|
const lookup = await lookupUpdateCandidate({
|
|
27122
|
-
id: entryId,
|
|
27753
|
+
id: selector.entryId,
|
|
27754
|
+
subject: selector.subject,
|
|
27123
27755
|
dbPath
|
|
27124
27756
|
});
|
|
27125
|
-
|
|
27757
|
+
const candidate = lookup.candidate;
|
|
27758
|
+
if (!candidate) {
|
|
27126
27759
|
return {
|
|
27127
|
-
content: [{ type: "text", text: `agenr_update failed:
|
|
27760
|
+
content: [{ type: "text", text: `agenr_update failed: ${formatMissingEntryError(selector)}` }]
|
|
27128
27761
|
};
|
|
27129
27762
|
}
|
|
27130
27763
|
const updated = await executeUpdate({
|
|
27131
|
-
id:
|
|
27132
|
-
importance,
|
|
27764
|
+
id: candidate.id,
|
|
27765
|
+
...importance !== void 0 ? { importance } : {},
|
|
27766
|
+
...expiry !== void 0 ? { expiry } : {},
|
|
27133
27767
|
dbPath
|
|
27134
27768
|
});
|
|
27769
|
+
const entryLabel = formatEntryLabel(candidate.id, selector.subject ? candidate.subject : void 0);
|
|
27135
27770
|
if (!updated.updated) {
|
|
27136
27771
|
return {
|
|
27137
|
-
content: [{ type: "text", text: `Entry ${
|
|
27772
|
+
content: [{ type: "text", text: `Entry ${entryLabel} was not updated because it is no longer active.` }]
|
|
27773
|
+
};
|
|
27774
|
+
}
|
|
27775
|
+
const changedParts = buildChangedUpdateParts({ importance, expiry }, updated);
|
|
27776
|
+
if (changedParts.length > 0) {
|
|
27777
|
+
return {
|
|
27778
|
+
content: [
|
|
27779
|
+
{
|
|
27780
|
+
type: "text",
|
|
27781
|
+
text: `Updated entry ${entryLabel}: ${changedParts.join(", ")}.`
|
|
27782
|
+
}
|
|
27783
|
+
]
|
|
27138
27784
|
};
|
|
27139
27785
|
}
|
|
27786
|
+
const requestedParts = buildRequestedUpdateParts({ importance, expiry }, updated);
|
|
27140
27787
|
return {
|
|
27141
27788
|
content: [
|
|
27142
27789
|
{
|
|
27143
27790
|
type: "text",
|
|
27144
|
-
text:
|
|
27791
|
+
text: requestedParts.length === 1 ? `Entry ${entryLabel} already has ${requestedParts[0]}.` : `Entry ${entryLabel} already has ${requestedParts.join(" and ")}.`
|
|
27145
27792
|
}
|
|
27146
27793
|
]
|
|
27147
27794
|
};
|
|
@@ -32721,11 +33368,7 @@ async function runClearSessionProjectTool(sessionKey, pluginConfig) {
|
|
|
32721
33368
|
}
|
|
32722
33369
|
|
|
32723
33370
|
// src/openclaw-plugin/hooks/register-tools.ts
|
|
32724
|
-
var EXPIRY_SCHEMA = Type6.
|
|
32725
|
-
Type6.Literal("core"),
|
|
32726
|
-
Type6.Literal("permanent"),
|
|
32727
|
-
Type6.Literal("temporary")
|
|
32728
|
-
]);
|
|
33371
|
+
var EXPIRY_SCHEMA = Type6.String({ enum: ["core", "permanent", "temporary"] });
|
|
32729
33372
|
function optionalExpirySchema(description) {
|
|
32730
33373
|
return Type6.Optional({
|
|
32731
33374
|
...EXPIRY_SCHEMA,
|
|
@@ -32771,12 +33414,10 @@ function registerAgenrTools(api, params) {
|
|
|
32771
33414
|
parameters: Type6.Object({
|
|
32772
33415
|
query: Type6.Optional(Type6.String({ description: "What to search for." })),
|
|
32773
33416
|
context: Type6.Optional(
|
|
32774
|
-
Type6.
|
|
32775
|
-
[
|
|
32776
|
-
|
|
32777
|
-
|
|
32778
|
-
}
|
|
32779
|
-
)
|
|
33417
|
+
Type6.String({
|
|
33418
|
+
enum: ["default", "session-start", "browse"],
|
|
33419
|
+
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)."
|
|
33420
|
+
})
|
|
32780
33421
|
),
|
|
32781
33422
|
limit: Type6.Optional(Type6.Number({ description: "Max results (default: 10)." })),
|
|
32782
33423
|
types: Type6.Optional(Type6.String({ description: "Comma-separated entry types to filter." })),
|
|
@@ -32803,7 +33444,8 @@ function registerAgenrTools(api, params) {
|
|
|
32803
33444
|
return makeDisabledToolResult();
|
|
32804
33445
|
}
|
|
32805
33446
|
const dbPath = runtimeConfig?.dbPath;
|
|
32806
|
-
const
|
|
33447
|
+
const defaultProject = runtimeConfig?.project?.trim() || void 0;
|
|
33448
|
+
const result = await runRecallTool(toolParams, defaultProject, dbPath);
|
|
32807
33449
|
const sessionKey = sessionRef.current;
|
|
32808
33450
|
if (sessionKey && result.agentToolRecallSurface) {
|
|
32809
33451
|
const addedCount = createSessionSurfacedMemoryService(sessionKey).recordByIntent(
|
|
@@ -32992,11 +33634,22 @@ function registerAgenrTools(api, params) {
|
|
|
32992
33634
|
name: "agenr_retire",
|
|
32993
33635
|
label: "Agenr Retire",
|
|
32994
33636
|
description: "Mark a memory entry as retired (soft delete). Retired entries are excluded from all recall.",
|
|
32995
|
-
parameters: Type6.Object(
|
|
32996
|
-
|
|
32997
|
-
|
|
32998
|
-
|
|
32999
|
-
|
|
33637
|
+
parameters: Type6.Object(
|
|
33638
|
+
{
|
|
33639
|
+
entry_id: Type6.Optional(Type6.String({ description: "Entry ID to retire." })),
|
|
33640
|
+
subject: Type6.Optional(
|
|
33641
|
+
Type6.String({ description: "Subject string to match. Mutually exclusive with entry_id." })
|
|
33642
|
+
),
|
|
33643
|
+
reason: Type6.Optional(Type6.String({ description: "Retirement reason." })),
|
|
33644
|
+
persist: Type6.Optional(Type6.Boolean({ description: "Persist retirement to ledger." }))
|
|
33645
|
+
},
|
|
33646
|
+
{
|
|
33647
|
+
anyOf: [
|
|
33648
|
+
{ required: ["entry_id"] },
|
|
33649
|
+
{ required: ["subject"] }
|
|
33650
|
+
]
|
|
33651
|
+
}
|
|
33652
|
+
),
|
|
33000
33653
|
async execute(_toolCallId, toolParams) {
|
|
33001
33654
|
const runtimeConfig = api.pluginConfig;
|
|
33002
33655
|
if (runtimeConfig?.enabled === false) {
|
|
@@ -33011,11 +33664,37 @@ function registerAgenrTools(api, params) {
|
|
|
33011
33664
|
{
|
|
33012
33665
|
name: "agenr_update",
|
|
33013
33666
|
label: "Agenr Update",
|
|
33014
|
-
description: "Update an existing memory entry in place. Currently supports importance
|
|
33015
|
-
parameters: Type6.Object(
|
|
33016
|
-
|
|
33017
|
-
|
|
33018
|
-
|
|
33667
|
+
description: "Update an existing memory entry in place. Currently supports importance and expiry.",
|
|
33668
|
+
parameters: Type6.Object(
|
|
33669
|
+
{
|
|
33670
|
+
entry_id: Type6.Optional(Type6.String({ description: "Entry ID to update." })),
|
|
33671
|
+
subject: Type6.Optional(
|
|
33672
|
+
Type6.String({
|
|
33673
|
+
description: "Subject string to match. Mutually exclusive with entry_id."
|
|
33674
|
+
})
|
|
33675
|
+
),
|
|
33676
|
+
importance: Type6.Optional(
|
|
33677
|
+
Type6.Integer({ minimum: 1, maximum: 10, description: "New importance score." })
|
|
33678
|
+
),
|
|
33679
|
+
expiry: optionalExpirySchema("New expiry tier: core, permanent, or temporary.")
|
|
33680
|
+
},
|
|
33681
|
+
{
|
|
33682
|
+
allOf: [
|
|
33683
|
+
{
|
|
33684
|
+
anyOf: [
|
|
33685
|
+
{ required: ["entry_id"] },
|
|
33686
|
+
{ required: ["subject"] }
|
|
33687
|
+
]
|
|
33688
|
+
},
|
|
33689
|
+
{
|
|
33690
|
+
anyOf: [
|
|
33691
|
+
{ required: ["importance"] },
|
|
33692
|
+
{ required: ["expiry"] }
|
|
33693
|
+
]
|
|
33694
|
+
}
|
|
33695
|
+
]
|
|
33696
|
+
}
|
|
33697
|
+
),
|
|
33019
33698
|
async execute(_toolCallId, toolParams) {
|
|
33020
33699
|
const runtimeConfig = api.pluginConfig;
|
|
33021
33700
|
if (runtimeConfig?.enabled === false) {
|