agenr 0.9.21 → 0.9.23
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 +20 -0
- package/dist/chunk-56GW7EIS.js +2821 -0
- package/dist/chunk-DVNOWSKK.js +2820 -0
- package/dist/chunk-RM5SLLEM.js +241 -0
- package/dist/cli-main.js +52 -4
- package/dist/co-recall-2UNFBE7S.js +16 -0
- package/dist/openclaw-plugin/index.js +42 -359
- package/package.json +1 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// src/utils/entry-utils.ts
|
|
2
|
+
var MILLISECONDS_PER_DAY = 1e3 * 60 * 60 * 24;
|
|
3
|
+
function toNumber(value) {
|
|
4
|
+
if (typeof value === "number") {
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
if (typeof value === "bigint") {
|
|
8
|
+
return Number(value);
|
|
9
|
+
}
|
|
10
|
+
if (typeof value === "string" && value.trim()) {
|
|
11
|
+
return Number(value);
|
|
12
|
+
}
|
|
13
|
+
return Number.NaN;
|
|
14
|
+
}
|
|
15
|
+
function toStringValue(value) {
|
|
16
|
+
if (typeof value === "string") {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
20
|
+
return String(value);
|
|
21
|
+
}
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
function toRowsAffected(value) {
|
|
25
|
+
if (typeof value === "number") {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === "bigint") {
|
|
29
|
+
return Number(value);
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
32
|
+
return Number(value);
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
function parseDaysBetween(now, pastIso) {
|
|
37
|
+
if (!pastIso) {
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
const parsed = new Date(pastIso);
|
|
41
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
const delta = (now.getTime() - parsed.getTime()) / MILLISECONDS_PER_DAY;
|
|
45
|
+
if (!Number.isFinite(delta)) {
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
return Math.max(delta, 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/db/co-recall.ts
|
|
52
|
+
var DEFAULT_EDGE_INCREMENT = 0.1;
|
|
53
|
+
var MAX_USED_ENTRIES = 20;
|
|
54
|
+
var MIN_EDGE_WEIGHT = 0.05;
|
|
55
|
+
var CO_RECALL_EDGE_TYPE = "co_recalled";
|
|
56
|
+
function normalizePair(a, b) {
|
|
57
|
+
return a < b ? [a, b] : [b, a];
|
|
58
|
+
}
|
|
59
|
+
async function strengthenCoRecallEdges(db, usedEntryIds, timestamp) {
|
|
60
|
+
const uniqueIds = Array.from(
|
|
61
|
+
new Set(
|
|
62
|
+
usedEntryIds.map((id) => id.trim()).filter((id) => id.length > 0)
|
|
63
|
+
)
|
|
64
|
+
).slice(0, MAX_USED_ENTRIES);
|
|
65
|
+
if (uniqueIds.length < 2) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const now = timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
69
|
+
const pairs = [];
|
|
70
|
+
for (let i = 0; i < uniqueIds.length; i += 1) {
|
|
71
|
+
const a = uniqueIds[i];
|
|
72
|
+
if (!a) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
for (let j = i + 1; j < uniqueIds.length; j += 1) {
|
|
76
|
+
const b = uniqueIds[j];
|
|
77
|
+
if (!b || a === b) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
pairs.push(normalizePair(a, b));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (pairs.length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await db.execute("BEGIN");
|
|
87
|
+
try {
|
|
88
|
+
for (const [entryA, entryB] of pairs) {
|
|
89
|
+
await db.execute({
|
|
90
|
+
sql: `
|
|
91
|
+
INSERT INTO co_recall_edges (
|
|
92
|
+
entry_a, entry_b, edge_type, weight, session_count, last_co_recalled, created_at
|
|
93
|
+
)
|
|
94
|
+
VALUES (?, ?, ?, ?, 1, ?, ?)
|
|
95
|
+
ON CONFLICT
|
|
96
|
+
DO UPDATE SET
|
|
97
|
+
weight = MIN(co_recall_edges.weight + excluded.weight, 1.0),
|
|
98
|
+
session_count = co_recall_edges.session_count + 1,
|
|
99
|
+
last_co_recalled = excluded.last_co_recalled
|
|
100
|
+
`,
|
|
101
|
+
args: [
|
|
102
|
+
entryA,
|
|
103
|
+
entryB,
|
|
104
|
+
CO_RECALL_EDGE_TYPE,
|
|
105
|
+
DEFAULT_EDGE_INCREMENT,
|
|
106
|
+
now,
|
|
107
|
+
now
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
await db.execute("COMMIT");
|
|
112
|
+
} catch (error) {
|
|
113
|
+
try {
|
|
114
|
+
await db.execute("ROLLBACK");
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function decayCoRecallEdges(db, decayFactor = 0.95) {
|
|
121
|
+
if (!Number.isFinite(decayFactor) || decayFactor < 0) {
|
|
122
|
+
throw new Error("decayFactor must be a finite number >= 0");
|
|
123
|
+
}
|
|
124
|
+
await db.execute("BEGIN");
|
|
125
|
+
try {
|
|
126
|
+
await db.execute({
|
|
127
|
+
sql: `
|
|
128
|
+
UPDATE co_recall_edges
|
|
129
|
+
SET weight = weight * ?
|
|
130
|
+
WHERE edge_type = ?
|
|
131
|
+
`,
|
|
132
|
+
args: [decayFactor, CO_RECALL_EDGE_TYPE]
|
|
133
|
+
});
|
|
134
|
+
const pruned = await db.execute({
|
|
135
|
+
sql: `
|
|
136
|
+
DELETE FROM co_recall_edges
|
|
137
|
+
WHERE edge_type = ?
|
|
138
|
+
AND weight < ?
|
|
139
|
+
`,
|
|
140
|
+
args: [CO_RECALL_EDGE_TYPE, MIN_EDGE_WEIGHT]
|
|
141
|
+
});
|
|
142
|
+
await db.execute("COMMIT");
|
|
143
|
+
return toRowsAffected(pruned.rowsAffected);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
try {
|
|
146
|
+
await db.execute("ROLLBACK");
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function getCoRecallNeighbors(db, entryId, minWeight = 0.1, limit = 10) {
|
|
153
|
+
const normalizedId = entryId.trim();
|
|
154
|
+
if (!normalizedId) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 10;
|
|
158
|
+
const safeMinWeight = Number.isFinite(minWeight) ? Math.max(minWeight, 0) : 0.1;
|
|
159
|
+
const result = await db.execute({
|
|
160
|
+
sql: `
|
|
161
|
+
SELECT
|
|
162
|
+
CASE WHEN entry_a = ? THEN entry_b ELSE entry_a END AS neighbor_id,
|
|
163
|
+
weight,
|
|
164
|
+
session_count,
|
|
165
|
+
last_co_recalled
|
|
166
|
+
FROM co_recall_edges
|
|
167
|
+
WHERE edge_type = ?
|
|
168
|
+
AND (entry_a = ? OR entry_b = ?)
|
|
169
|
+
AND weight >= ?
|
|
170
|
+
ORDER BY weight DESC, session_count DESC, last_co_recalled DESC
|
|
171
|
+
LIMIT ?
|
|
172
|
+
`,
|
|
173
|
+
args: [normalizedId, CO_RECALL_EDGE_TYPE, normalizedId, normalizedId, safeMinWeight, safeLimit]
|
|
174
|
+
});
|
|
175
|
+
return result.rows.map((row) => ({
|
|
176
|
+
entryId: toStringValue(row.neighbor_id),
|
|
177
|
+
weight: toNumber(row.weight),
|
|
178
|
+
sessionCount: toNumber(row.session_count),
|
|
179
|
+
lastCoRecalled: toStringValue(row.last_co_recalled)
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
async function getCoRecallEdgeCounts(db) {
|
|
183
|
+
const result = await db.execute({
|
|
184
|
+
sql: `
|
|
185
|
+
SELECT entry_id, COUNT(*) AS edge_count
|
|
186
|
+
FROM (
|
|
187
|
+
SELECT entry_a AS entry_id
|
|
188
|
+
FROM co_recall_edges
|
|
189
|
+
WHERE edge_type = ?
|
|
190
|
+
UNION ALL
|
|
191
|
+
SELECT entry_b AS entry_id
|
|
192
|
+
FROM co_recall_edges
|
|
193
|
+
WHERE edge_type = ?
|
|
194
|
+
)
|
|
195
|
+
GROUP BY entry_id
|
|
196
|
+
`,
|
|
197
|
+
args: [CO_RECALL_EDGE_TYPE, CO_RECALL_EDGE_TYPE]
|
|
198
|
+
});
|
|
199
|
+
const counts = /* @__PURE__ */ new Map();
|
|
200
|
+
for (const row of result.rows) {
|
|
201
|
+
const entryId = toStringValue(row.entry_id).trim();
|
|
202
|
+
if (!entryId) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
counts.set(entryId, Math.max(0, toNumber(row.edge_count)));
|
|
206
|
+
}
|
|
207
|
+
return counts;
|
|
208
|
+
}
|
|
209
|
+
async function getTopCoRecallEdges(db, limit = 20) {
|
|
210
|
+
const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 20;
|
|
211
|
+
const result = await db.execute({
|
|
212
|
+
sql: `
|
|
213
|
+
SELECT entry_a, entry_b, weight, session_count, last_co_recalled
|
|
214
|
+
FROM co_recall_edges
|
|
215
|
+
WHERE edge_type = ?
|
|
216
|
+
ORDER BY weight DESC, session_count DESC, last_co_recalled DESC
|
|
217
|
+
LIMIT ?
|
|
218
|
+
`,
|
|
219
|
+
args: [CO_RECALL_EDGE_TYPE, safeLimit]
|
|
220
|
+
});
|
|
221
|
+
return result.rows.map((row) => ({
|
|
222
|
+
entryA: toStringValue(row.entry_a),
|
|
223
|
+
entryB: toStringValue(row.entry_b),
|
|
224
|
+
weight: toNumber(row.weight),
|
|
225
|
+
sessionCount: toNumber(row.session_count),
|
|
226
|
+
lastCoRecalled: toStringValue(row.last_co_recalled)
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export {
|
|
231
|
+
toNumber,
|
|
232
|
+
toStringValue,
|
|
233
|
+
toRowsAffected,
|
|
234
|
+
parseDaysBetween,
|
|
235
|
+
MAX_USED_ENTRIES,
|
|
236
|
+
strengthenCoRecallEdges,
|
|
237
|
+
decayCoRecallEdges,
|
|
238
|
+
getCoRecallNeighbors,
|
|
239
|
+
getCoRecallEdgeCounts,
|
|
240
|
+
getTopCoRecallEdges
|
|
241
|
+
};
|
package/dist/cli-main.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
describeAuth,
|
|
19
19
|
dropFtsTriggersAndIndex,
|
|
20
20
|
embed,
|
|
21
|
+
evolveQualityScores,
|
|
21
22
|
getAuthMethodDefinition,
|
|
22
23
|
getDb,
|
|
23
24
|
getOldestPendingReviewCreatedAt,
|
|
@@ -49,14 +50,14 @@ import {
|
|
|
49
50
|
setStoredCredential,
|
|
50
51
|
walCheckpoint,
|
|
51
52
|
writeConfig
|
|
52
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-56GW7EIS.js";
|
|
53
54
|
import {
|
|
54
55
|
getCoRecallNeighbors,
|
|
55
56
|
getTopCoRecallEdges,
|
|
56
57
|
parseDaysBetween,
|
|
57
58
|
toNumber,
|
|
58
59
|
toStringValue
|
|
59
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-RM5SLLEM.js";
|
|
60
61
|
|
|
61
62
|
// src/cli-main.ts
|
|
62
63
|
import fs37 from "fs/promises";
|
|
@@ -1527,6 +1528,49 @@ async function runDbCheckCommand(options, deps) {
|
|
|
1527
1528
|
resolvedDeps.closeDbFn(db);
|
|
1528
1529
|
}
|
|
1529
1530
|
}
|
|
1531
|
+
async function runDbEvolveQualityCommand(options, deps) {
|
|
1532
|
+
const resolvedDeps = {
|
|
1533
|
+
readConfigFn: deps?.readConfigFn ?? readConfig,
|
|
1534
|
+
getDbFn: deps?.getDbFn ?? getDb,
|
|
1535
|
+
initDbFn: deps?.initDbFn ?? initDb,
|
|
1536
|
+
initSchemaFn: deps?.initSchemaFn ?? initSchema,
|
|
1537
|
+
closeDbFn: deps?.closeDbFn ?? closeDb,
|
|
1538
|
+
backupDbFn: deps?.backupDbFn ?? backupDb,
|
|
1539
|
+
resetDbFn: deps?.resetDbFn ?? resetDb
|
|
1540
|
+
};
|
|
1541
|
+
const dryRun = options.dryRun === true;
|
|
1542
|
+
const config = resolvedDeps.readConfigFn(process.env);
|
|
1543
|
+
const configured = resolveDbPathFromOptions(options.db, config?.db?.path);
|
|
1544
|
+
const db = resolvedDeps.getDbFn(configured);
|
|
1545
|
+
try {
|
|
1546
|
+
await resolvedDeps.initDbFn(db);
|
|
1547
|
+
const evolved = await evolveQualityScores(db, { dryRun });
|
|
1548
|
+
const summary = {
|
|
1549
|
+
updated: evolved.updated,
|
|
1550
|
+
dryRun,
|
|
1551
|
+
stats: evolved.stats
|
|
1552
|
+
};
|
|
1553
|
+
if (options.json) {
|
|
1554
|
+
process.stdout.write(`${JSON.stringify(summary, null, 2)}
|
|
1555
|
+
`);
|
|
1556
|
+
} else {
|
|
1557
|
+
process.stdout.write(
|
|
1558
|
+
`Updated ${summary.updated} entries. Avg quality: ${summary.stats.avgBefore.toFixed(2)} -> ${summary.stats.avgAfter.toFixed(2)}. High: ${summary.stats.high}, Medium: ${summary.stats.medium}, Low: ${summary.stats.low}
|
|
1559
|
+
`
|
|
1560
|
+
);
|
|
1561
|
+
if (dryRun) {
|
|
1562
|
+
process.stdout.write("Dry-run mode enabled - no changes were written.\n");
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
return summary;
|
|
1566
|
+
} catch (error) {
|
|
1567
|
+
throw new Error(
|
|
1568
|
+
`Failed to evolve quality scores: ${error instanceof Error ? error.message : String(error)}`
|
|
1569
|
+
);
|
|
1570
|
+
} finally {
|
|
1571
|
+
resolvedDeps.closeDbFn(db);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1530
1574
|
|
|
1531
1575
|
// src/commands/watcher.ts
|
|
1532
1576
|
import { execFile, spawn } from "child_process";
|
|
@@ -19188,7 +19232,7 @@ async function runIngestCommand(inputPaths, options, deps) {
|
|
|
19188
19232
|
try {
|
|
19189
19233
|
const existingIds = await queue.runExclusive(() => getSourceEntryIds(db, target.file));
|
|
19190
19234
|
if (existingIds.size >= 2) {
|
|
19191
|
-
const { strengthenCoRecallEdges, MAX_USED_ENTRIES } = await import("./co-recall-
|
|
19235
|
+
const { strengthenCoRecallEdges, MAX_USED_ENTRIES } = await import("./co-recall-2UNFBE7S.js");
|
|
19192
19236
|
const idArr = [...existingIds].slice(0, MAX_USED_ENTRIES);
|
|
19193
19237
|
const expectedEdges = idArr.length * (idArr.length - 1) / 2;
|
|
19194
19238
|
const edgeCount = await queue.runExclusive(async () => {
|
|
@@ -19366,7 +19410,7 @@ async function runIngestCommand(inputPaths, options, deps) {
|
|
|
19366
19410
|
try {
|
|
19367
19411
|
const fileEntryIds = await queue.runExclusive(() => getSourceEntryIds(db, target.file));
|
|
19368
19412
|
if (fileEntryIds.size >= 2) {
|
|
19369
|
-
const { strengthenCoRecallEdges } = await import("./co-recall-
|
|
19413
|
+
const { strengthenCoRecallEdges } = await import("./co-recall-2UNFBE7S.js");
|
|
19370
19414
|
const edgeTimestamp = resolvedDeps.nowFn().toISOString();
|
|
19371
19415
|
await queue.runExclusive(() => strengthenCoRecallEdges(db, [...fileEntryIds], edgeTimestamp));
|
|
19372
19416
|
}
|
|
@@ -26238,6 +26282,10 @@ function createProgram() {
|
|
|
26238
26282
|
const result = await runDbRebuildIndexCommand({ db: opts.db });
|
|
26239
26283
|
process.exitCode = result.exitCode;
|
|
26240
26284
|
});
|
|
26285
|
+
dbCommand.command("evolve-quality").description("Recompute quality scores from recall activity and co-recall graph signals").option("--db <path>", "Database path override").option("--dry-run", "Compute and print score changes without writing", false).option("--json", "Print machine-readable output", false).action(async (opts) => {
|
|
26286
|
+
await runDbEvolveQualityCommand({ db: opts.db, dryRun: opts.dryRun, json: opts.json });
|
|
26287
|
+
process.exitCode = 0;
|
|
26288
|
+
});
|
|
26241
26289
|
program.command("setup").description("Interactive setup for provider/auth/task-model defaults").action(async () => {
|
|
26242
26290
|
await runSetup(process.env);
|
|
26243
26291
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_USED_ENTRIES,
|
|
3
|
+
decayCoRecallEdges,
|
|
4
|
+
getCoRecallEdgeCounts,
|
|
5
|
+
getCoRecallNeighbors,
|
|
6
|
+
getTopCoRecallEdges,
|
|
7
|
+
strengthenCoRecallEdges
|
|
8
|
+
} from "./chunk-RM5SLLEM.js";
|
|
9
|
+
export {
|
|
10
|
+
MAX_USED_ENTRIES,
|
|
11
|
+
decayCoRecallEdges,
|
|
12
|
+
getCoRecallEdgeCounts,
|
|
13
|
+
getCoRecallNeighbors,
|
|
14
|
+
getTopCoRecallEdges,
|
|
15
|
+
strengthenCoRecallEdges
|
|
16
|
+
};
|