open-agents-ai 0.187.161 → 0.187.163
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +528 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3680,7 +3680,7 @@ var init_memory_search = __esm({
|
|
|
3680
3680
|
"use strict";
|
|
3681
3681
|
MemorySearchTool = class {
|
|
3682
3682
|
name = "memory_search";
|
|
3683
|
-
description = "Search across all memory entries by relevance. Unlike memory_read (exact topic+key), this finds relevant memories using text matching. Use when you don't know the exact topic or key, or want to find all memories related to a concept.";
|
|
3683
|
+
description = "Search across all memory entries by relevance. Unlike memory_read (exact topic+key), this finds relevant memories using text matching or associative graph traversal. Use when you don't know the exact topic or key, or want to find all memories related to a concept. Mode 'graph' uses knowledge graph traversal for multi-hop associative queries (e.g. 'what caused the auth error?').";
|
|
3684
3684
|
parameters = {
|
|
3685
3685
|
type: "object",
|
|
3686
3686
|
properties: {
|
|
@@ -3691,6 +3691,11 @@ var init_memory_search = __esm({
|
|
|
3691
3691
|
max_results: {
|
|
3692
3692
|
type: "number",
|
|
3693
3693
|
description: "Maximum number of results to return (default: 10)"
|
|
3694
|
+
},
|
|
3695
|
+
mode: {
|
|
3696
|
+
type: "string",
|
|
3697
|
+
enum: ["text", "graph", "episodes"],
|
|
3698
|
+
description: "Search mode: 'text' (default \u2014 TF-IDF), 'graph' (PPR traversal), 'episodes' (recent episodes). Default: text."
|
|
3694
3699
|
}
|
|
3695
3700
|
},
|
|
3696
3701
|
required: ["query"]
|
|
@@ -3702,7 +3707,87 @@ var init_memory_search = __esm({
|
|
|
3702
3707
|
async execute(args) {
|
|
3703
3708
|
const query = args["query"];
|
|
3704
3709
|
const maxResults = args["max_results"] ?? 10;
|
|
3710
|
+
const mode = args["mode"] ?? "text";
|
|
3705
3711
|
const start2 = performance.now();
|
|
3712
|
+
if (mode === "graph" || mode === "episodes") {
|
|
3713
|
+
try {
|
|
3714
|
+
const { join: pathJoin } = await import("node:path");
|
|
3715
|
+
const { existsSync: pathExists } = await import("node:fs");
|
|
3716
|
+
const { createRequire: createRequire7 } = await import("node:module");
|
|
3717
|
+
const oaDir = pathJoin(this.workingDir, ".oa");
|
|
3718
|
+
const epDbPath = pathJoin(oaDir, "episodes.db");
|
|
3719
|
+
const kgDbPath = pathJoin(oaDir, "knowledge.db");
|
|
3720
|
+
if (!pathExists(epDbPath)) {
|
|
3721
|
+
return { success: true, output: `No episode store found. Run tasks to build the knowledge graph.`, durationMs: performance.now() - start2 };
|
|
3722
|
+
}
|
|
3723
|
+
const req2 = createRequire7(import.meta.url);
|
|
3724
|
+
const Database2 = req2("better-sqlite3");
|
|
3725
|
+
if (mode === "episodes") {
|
|
3726
|
+
const db = new Database2(epDbPath, { readonly: true });
|
|
3727
|
+
const queryLower = query.toLowerCase();
|
|
3728
|
+
const rows = db.prepare(`
|
|
3729
|
+
SELECT * FROM episodes
|
|
3730
|
+
WHERE content LIKE ? OR tool_name LIKE ?
|
|
3731
|
+
ORDER BY importance DESC, timestamp DESC
|
|
3732
|
+
LIMIT ?
|
|
3733
|
+
`).all(`%${queryLower}%`, `%${queryLower}%`, maxResults);
|
|
3734
|
+
db.close();
|
|
3735
|
+
if (rows.length === 0) {
|
|
3736
|
+
return { success: true, output: `No episodes found for "${query}".`, durationMs: performance.now() - start2 };
|
|
3737
|
+
}
|
|
3738
|
+
const lines = rows.map((r2) => `[${r2.tool_name ?? r2.modality}] (importance: ${r2.importance}, decay: ${r2.decay_class})
|
|
3739
|
+
${r2.content.slice(0, 200)}`);
|
|
3740
|
+
return {
|
|
3741
|
+
success: true,
|
|
3742
|
+
output: `Episode search for "${query}" (${rows.length} results):
|
|
3743
|
+
|
|
3744
|
+
${lines.join("\n\n")}`,
|
|
3745
|
+
durationMs: performance.now() - start2
|
|
3746
|
+
};
|
|
3747
|
+
}
|
|
3748
|
+
if (mode === "graph" && pathExists(kgDbPath)) {
|
|
3749
|
+
const db = new Database2(kgDbPath, { readonly: true });
|
|
3750
|
+
const queryLower = query.toLowerCase();
|
|
3751
|
+
const nodes = db.prepare(`
|
|
3752
|
+
SELECT * FROM kg_nodes WHERE text LIKE ? ORDER BY mention_count DESC LIMIT 20
|
|
3753
|
+
`).all(`%${queryLower}%`);
|
|
3754
|
+
const episodeIds = /* @__PURE__ */ new Set();
|
|
3755
|
+
const nodeInfo = [];
|
|
3756
|
+
for (const node of nodes.slice(0, 5)) {
|
|
3757
|
+
const edges = db.prepare(`
|
|
3758
|
+
SELECT * FROM kg_edges WHERE (src_id = ? OR dst_id = ?) AND valid_until IS NULL
|
|
3759
|
+
`).all(node.id, node.id);
|
|
3760
|
+
nodeInfo.push(`${node.text} (${node.node_type}, ${node.mention_count} mentions, ${edges.length} edges)`);
|
|
3761
|
+
for (const edge of edges) {
|
|
3762
|
+
if (edge.source_episode_id)
|
|
3763
|
+
episodeIds.add(edge.source_episode_id);
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
db.close();
|
|
3767
|
+
const epLines = [];
|
|
3768
|
+
if (episodeIds.size > 0 && pathExists(epDbPath)) {
|
|
3769
|
+
const epDb = new Database2(epDbPath, { readonly: true });
|
|
3770
|
+
for (const epId of [...episodeIds].slice(0, maxResults)) {
|
|
3771
|
+
const ep = epDb.prepare("SELECT * FROM episodes WHERE id = ?").get(epId);
|
|
3772
|
+
if (ep)
|
|
3773
|
+
epLines.push(`[${ep.tool_name ?? ep.modality}] ${ep.content.slice(0, 150)}`);
|
|
3774
|
+
}
|
|
3775
|
+
epDb.close();
|
|
3776
|
+
}
|
|
3777
|
+
const output = [
|
|
3778
|
+
`Knowledge graph search for "${query}":`,
|
|
3779
|
+
`
|
|
3780
|
+
Nodes found: ${nodes.length}`,
|
|
3781
|
+
nodeInfo.length > 0 ? nodeInfo.map((n2) => ` - ${n2}`).join("\n") : " (no matching nodes)",
|
|
3782
|
+
epLines.length > 0 ? `
|
|
3783
|
+
Linked episodes (${epLines.length}):
|
|
3784
|
+
${epLines.map((l2) => ` ${l2}`).join("\n")}` : ""
|
|
3785
|
+
].filter(Boolean).join("\n");
|
|
3786
|
+
return { success: true, output, durationMs: performance.now() - start2 };
|
|
3787
|
+
}
|
|
3788
|
+
} catch {
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3706
3791
|
try {
|
|
3707
3792
|
const allEntries = await this.loadAllMemories();
|
|
3708
3793
|
if (allEntries.length === 0) {
|
|
@@ -265041,9 +265126,405 @@ var init_temporalGraph = __esm({
|
|
|
265041
265126
|
}
|
|
265042
265127
|
});
|
|
265043
265128
|
|
|
265129
|
+
// packages/memory/dist/zettelkasten.js
|
|
265130
|
+
function cosineSimilarity2(a2, b) {
|
|
265131
|
+
if (a2.length !== b.length || a2.length === 0)
|
|
265132
|
+
return 0;
|
|
265133
|
+
let dot = 0, normA = 0, normB = 0;
|
|
265134
|
+
for (let i2 = 0; i2 < a2.length; i2++) {
|
|
265135
|
+
dot += a2[i2] * b[i2];
|
|
265136
|
+
normA += a2[i2] * a2[i2];
|
|
265137
|
+
normB += b[i2] * b[i2];
|
|
265138
|
+
}
|
|
265139
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
265140
|
+
return denom > 0 ? dot / denom : 0;
|
|
265141
|
+
}
|
|
265142
|
+
function findNeighbors(episode, candidates, topK, minSimilarity) {
|
|
265143
|
+
if (!episode.embedding)
|
|
265144
|
+
return [];
|
|
265145
|
+
const scored = [];
|
|
265146
|
+
for (const candidate of candidates) {
|
|
265147
|
+
if (candidate.id === episode.id)
|
|
265148
|
+
continue;
|
|
265149
|
+
if (!candidate.embedding)
|
|
265150
|
+
continue;
|
|
265151
|
+
const sim = cosineSimilarity2(episode.embedding, candidate.embedding);
|
|
265152
|
+
if (sim >= minSimilarity) {
|
|
265153
|
+
scored.push({ episode: candidate, similarity: sim });
|
|
265154
|
+
}
|
|
265155
|
+
}
|
|
265156
|
+
scored.sort((a2, b) => b.similarity - a2.similarity);
|
|
265157
|
+
return scored.slice(0, topK);
|
|
265158
|
+
}
|
|
265159
|
+
function linkEpisode(episode, episodeStore, graph, config) {
|
|
265160
|
+
const cfg = { ...DEFAULT_CONFIG4, ...config };
|
|
265161
|
+
const result = { episodeId: episode.id, linkedTo: [], linksCreated: 0 };
|
|
265162
|
+
if (!episode.embedding)
|
|
265163
|
+
return result;
|
|
265164
|
+
const candidates = episodeStore.recent(500).filter((e2) => e2.embedding != null);
|
|
265165
|
+
const neighbors2 = findNeighbors(episode, candidates, cfg.topK, cfg.minSimilarity);
|
|
265166
|
+
for (const { episode: neighbor, similarity } of neighbors2) {
|
|
265167
|
+
if (result.linksCreated >= cfg.maxLinksPerEpisode)
|
|
265168
|
+
break;
|
|
265169
|
+
const srcNodeId = graph.upsertNode({
|
|
265170
|
+
text: episode.content.slice(0, 100),
|
|
265171
|
+
nodeType: "event"
|
|
265172
|
+
});
|
|
265173
|
+
const dstNodeId = graph.upsertNode({
|
|
265174
|
+
text: neighbor.content.slice(0, 100),
|
|
265175
|
+
nodeType: "event"
|
|
265176
|
+
});
|
|
265177
|
+
graph.addEdge({
|
|
265178
|
+
srcId: srcNodeId,
|
|
265179
|
+
dstId: dstNodeId,
|
|
265180
|
+
relation: "related_to",
|
|
265181
|
+
fact: `Associated: ${episode.content.slice(0, 50)} \u2194 ${neighbor.content.slice(0, 50)}`,
|
|
265182
|
+
edgeType: "synonym",
|
|
265183
|
+
confidence: similarity,
|
|
265184
|
+
sourceEpisodeId: episode.id
|
|
265185
|
+
});
|
|
265186
|
+
result.linkedTo.push({ neighborId: neighbor.id, similarity, linked: true });
|
|
265187
|
+
result.linksCreated++;
|
|
265188
|
+
if (similarity >= cfg.evolutionThreshold && neighbor.gist !== episode.content.slice(0, 200)) {
|
|
265189
|
+
const evolvedGist = neighbor.gist ? `${neighbor.gist} | Also related: ${episode.content.slice(0, 100)}` : `Related context: ${episode.content.slice(0, 150)}`;
|
|
265190
|
+
episodeStore.setGist(neighbor.id, evolvedGist.slice(0, 500));
|
|
265191
|
+
}
|
|
265192
|
+
}
|
|
265193
|
+
return result;
|
|
265194
|
+
}
|
|
265195
|
+
function batchLink(episodeStore, graph, config) {
|
|
265196
|
+
const episodes = episodeStore.recent(200).filter((e2) => e2.embedding != null);
|
|
265197
|
+
let totalLinks = 0;
|
|
265198
|
+
let processed = 0;
|
|
265199
|
+
for (const ep of episodes) {
|
|
265200
|
+
const result = linkEpisode(ep, episodeStore, graph, config);
|
|
265201
|
+
totalLinks += result.linksCreated;
|
|
265202
|
+
if (result.linksCreated > 0)
|
|
265203
|
+
processed++;
|
|
265204
|
+
}
|
|
265205
|
+
return { processed, linksCreated: totalLinks };
|
|
265206
|
+
}
|
|
265207
|
+
var DEFAULT_CONFIG4;
|
|
265208
|
+
var init_zettelkasten = __esm({
|
|
265209
|
+
"packages/memory/dist/zettelkasten.js"() {
|
|
265210
|
+
"use strict";
|
|
265211
|
+
DEFAULT_CONFIG4 = {
|
|
265212
|
+
topK: 3,
|
|
265213
|
+
minSimilarity: 0.3,
|
|
265214
|
+
evolutionThreshold: 0.6,
|
|
265215
|
+
maxLinksPerEpisode: 10
|
|
265216
|
+
};
|
|
265217
|
+
}
|
|
265218
|
+
});
|
|
265219
|
+
|
|
265220
|
+
// packages/memory/dist/gistCompressor.js
|
|
265221
|
+
function compressToGist(episodes, taskDescription) {
|
|
265222
|
+
if (episodes.length === 0) {
|
|
265223
|
+
return {
|
|
265224
|
+
gist: "Empty task \u2014 no actions taken.",
|
|
265225
|
+
sourceEpisodeIds: [],
|
|
265226
|
+
episodeType: "mixed",
|
|
265227
|
+
turnCount: 0,
|
|
265228
|
+
toolsUsed: [],
|
|
265229
|
+
filesModified: [],
|
|
265230
|
+
errorsEncountered: [],
|
|
265231
|
+
timestamp: Date.now()
|
|
265232
|
+
};
|
|
265233
|
+
}
|
|
265234
|
+
const toolsUsed = [...new Set(episodes.map((e2) => e2.toolName).filter(Boolean))];
|
|
265235
|
+
const filesModified = extractFilePaths(episodes, ["file_write", "file_edit", "file_patch", "batch_edit"]);
|
|
265236
|
+
const filesRead = extractFilePaths(episodes, ["file_read"]);
|
|
265237
|
+
const errorsEncountered = episodes.filter((e2) => e2.content.toLowerCase().includes("error") || e2.content.toLowerCase().includes("failed")).map((e2) => e2.content.slice(0, 80)).slice(0, 3);
|
|
265238
|
+
const episodeType = classifyTrajectory(episodes, errorsEncountered);
|
|
265239
|
+
const parts = [];
|
|
265240
|
+
const taskSnippet = taskDescription.slice(0, 100).replace(/\n/g, " ");
|
|
265241
|
+
parts.push(`Task: "${taskSnippet}"`);
|
|
265242
|
+
if (filesModified.length > 0) {
|
|
265243
|
+
parts.push(`Modified ${filesModified.length} file(s): ${filesModified.slice(0, 3).join(", ")}`);
|
|
265244
|
+
}
|
|
265245
|
+
if (errorsEncountered.length > 0 && episodeType === "error_recovery") {
|
|
265246
|
+
parts.push(`Encountered ${errorsEncountered.length} error(s), recovered successfully`);
|
|
265247
|
+
} else if (errorsEncountered.length > 0) {
|
|
265248
|
+
parts.push(`${errorsEncountered.length} error(s) encountered`);
|
|
265249
|
+
}
|
|
265250
|
+
parts.push(`Used ${toolsUsed.length} tools across ${episodes.length} steps`);
|
|
265251
|
+
const lastEp = episodes[episodes.length - 1];
|
|
265252
|
+
if (lastEp.toolName === "task_complete") {
|
|
265253
|
+
parts.push("Completed successfully");
|
|
265254
|
+
} else if (lastEp.content.toLowerCase().includes("error")) {
|
|
265255
|
+
parts.push("Ended with errors");
|
|
265256
|
+
}
|
|
265257
|
+
const gist = parts.join(". ") + ".";
|
|
265258
|
+
return {
|
|
265259
|
+
gist,
|
|
265260
|
+
sourceEpisodeIds: episodes.map((e2) => e2.id),
|
|
265261
|
+
episodeType,
|
|
265262
|
+
turnCount: Math.max(...episodes.map((e2) => e2.turnNumber ?? 0)),
|
|
265263
|
+
toolsUsed,
|
|
265264
|
+
filesModified,
|
|
265265
|
+
errorsEncountered,
|
|
265266
|
+
timestamp: episodes[episodes.length - 1]?.timestamp ?? Date.now()
|
|
265267
|
+
};
|
|
265268
|
+
}
|
|
265269
|
+
function compressAndStore(episodeStore, sessionId, taskDescription, minTurns = 10) {
|
|
265270
|
+
const episodes = episodeStore.recent(500, sessionId);
|
|
265271
|
+
const maxTurn = Math.max(0, ...episodes.map((e2) => e2.turnNumber ?? 0));
|
|
265272
|
+
if (maxTurn < minTurns)
|
|
265273
|
+
return null;
|
|
265274
|
+
const gistRecord = compressToGist(episodes.reverse(), taskDescription);
|
|
265275
|
+
episodeStore.insert({
|
|
265276
|
+
sessionId,
|
|
265277
|
+
modality: "gist",
|
|
265278
|
+
content: gistRecord.gist,
|
|
265279
|
+
importance: 8,
|
|
265280
|
+
decayClass: "procedural",
|
|
265281
|
+
sourceEpisodeId: gistRecord.sourceEpisodeIds[0]
|
|
265282
|
+
});
|
|
265283
|
+
return gistRecord;
|
|
265284
|
+
}
|
|
265285
|
+
function extractFilePaths(episodes, toolNames) {
|
|
265286
|
+
const paths = [];
|
|
265287
|
+
for (const ep of episodes) {
|
|
265288
|
+
if (!ep.toolName || !toolNames.includes(ep.toolName))
|
|
265289
|
+
continue;
|
|
265290
|
+
if (ep.metadata) {
|
|
265291
|
+
const fp = ep.metadata.args_fingerprint;
|
|
265292
|
+
if (fp) {
|
|
265293
|
+
const pathMatch = fp.match(/path=([^,]+)/);
|
|
265294
|
+
if (pathMatch)
|
|
265295
|
+
paths.push(pathMatch[1]);
|
|
265296
|
+
}
|
|
265297
|
+
}
|
|
265298
|
+
}
|
|
265299
|
+
return [...new Set(paths)];
|
|
265300
|
+
}
|
|
265301
|
+
function classifyTrajectory(episodes, errors) {
|
|
265302
|
+
const hasErrors = errors.length > 0;
|
|
265303
|
+
const lastSuccess = episodes.some((e2) => e2.toolName === "task_complete");
|
|
265304
|
+
const hasFileEdits = episodes.some((e2) => ["file_write", "file_edit"].includes(e2.toolName ?? ""));
|
|
265305
|
+
const hasSearch = episodes.some((e2) => ["grep_search", "find_files", "web_search"].includes(e2.toolName ?? ""));
|
|
265306
|
+
if (hasErrors && lastSuccess)
|
|
265307
|
+
return "error_recovery";
|
|
265308
|
+
if (hasSearch && !hasFileEdits)
|
|
265309
|
+
return "discovery";
|
|
265310
|
+
if (!hasErrors && hasFileEdits)
|
|
265311
|
+
return "tool_sequence";
|
|
265312
|
+
return "mixed";
|
|
265313
|
+
}
|
|
265314
|
+
var init_gistCompressor = __esm({
|
|
265315
|
+
"packages/memory/dist/gistCompressor.js"() {
|
|
265316
|
+
"use strict";
|
|
265317
|
+
}
|
|
265318
|
+
});
|
|
265319
|
+
|
|
265320
|
+
// packages/memory/dist/pprRetrieval.js
|
|
265321
|
+
function extractQueryEntities(query) {
|
|
265322
|
+
const entities = [];
|
|
265323
|
+
const seen = /* @__PURE__ */ new Set();
|
|
265324
|
+
const add2 = (text) => {
|
|
265325
|
+
const normalized = text.trim().toLowerCase();
|
|
265326
|
+
if (normalized.length < 2 || seen.has(normalized))
|
|
265327
|
+
return;
|
|
265328
|
+
seen.add(normalized);
|
|
265329
|
+
entities.push(text.trim());
|
|
265330
|
+
};
|
|
265331
|
+
const filePattern = /(?:[\w./-]+\/[\w./-]+|[\w-]+\.\w{1,5})\b/g;
|
|
265332
|
+
for (const match of query.matchAll(filePattern)) {
|
|
265333
|
+
if (match[0].includes(".") || match[0].includes("/"))
|
|
265334
|
+
add2(match[0]);
|
|
265335
|
+
}
|
|
265336
|
+
const errorPattern = /\b[A-Z][a-z]+(?:[A-Z][a-z]+)+\b|\b\w+(?:Error|Exception|Failed|Failure)\b/g;
|
|
265337
|
+
for (const match of query.matchAll(errorPattern))
|
|
265338
|
+
add2(match[0]);
|
|
265339
|
+
const toolPattern = /\b(?:file_read|file_write|file_edit|shell|grep_search|find_files|memory_\w+|web_\w+|camera_\w+|audio_\w+|wifi_\w+|bluetooth_\w+|sdr_\w+|flipper_\w+|meshtastic|gps_\w+|visual_\w+)\b/g;
|
|
265340
|
+
for (const match of query.matchAll(toolPattern))
|
|
265341
|
+
add2(match[0]);
|
|
265342
|
+
const quotedPattern = /["']([^"']{2,50})["']/g;
|
|
265343
|
+
for (const match of query.matchAll(quotedPattern))
|
|
265344
|
+
add2(match[1]);
|
|
265345
|
+
const STOP_WORDS2 = /* @__PURE__ */ new Set([
|
|
265346
|
+
"the",
|
|
265347
|
+
"and",
|
|
265348
|
+
"for",
|
|
265349
|
+
"was",
|
|
265350
|
+
"are",
|
|
265351
|
+
"not",
|
|
265352
|
+
"but",
|
|
265353
|
+
"had",
|
|
265354
|
+
"has",
|
|
265355
|
+
"have",
|
|
265356
|
+
"this",
|
|
265357
|
+
"that",
|
|
265358
|
+
"with",
|
|
265359
|
+
"from",
|
|
265360
|
+
"what",
|
|
265361
|
+
"when",
|
|
265362
|
+
"where",
|
|
265363
|
+
"how",
|
|
265364
|
+
"why",
|
|
265365
|
+
"which",
|
|
265366
|
+
"who",
|
|
265367
|
+
"did",
|
|
265368
|
+
"does",
|
|
265369
|
+
"can",
|
|
265370
|
+
"could",
|
|
265371
|
+
"would",
|
|
265372
|
+
"should",
|
|
265373
|
+
"will",
|
|
265374
|
+
"been",
|
|
265375
|
+
"being",
|
|
265376
|
+
"were",
|
|
265377
|
+
"about",
|
|
265378
|
+
"than",
|
|
265379
|
+
"then",
|
|
265380
|
+
"also",
|
|
265381
|
+
"just",
|
|
265382
|
+
"more",
|
|
265383
|
+
"some",
|
|
265384
|
+
"only",
|
|
265385
|
+
"into",
|
|
265386
|
+
"over"
|
|
265387
|
+
]);
|
|
265388
|
+
const words = query.split(/\s+/).filter((w) => w.length >= 4 && !STOP_WORDS2.has(w.toLowerCase()));
|
|
265389
|
+
for (const word2 of words) {
|
|
265390
|
+
if (/^[A-Z]/.test(word2) || /[._-]/.test(word2) || /\d/.test(word2)) {
|
|
265391
|
+
add2(word2.replace(/[.,;:!?]+$/, ""));
|
|
265392
|
+
}
|
|
265393
|
+
}
|
|
265394
|
+
return entities;
|
|
265395
|
+
}
|
|
265396
|
+
function personalizedPageRank(graph, seedNodeIds, config) {
|
|
265397
|
+
const cfg = { ...DEFAULT_CONFIG5, ...config };
|
|
265398
|
+
const scores = /* @__PURE__ */ new Map();
|
|
265399
|
+
if (seedNodeIds.length === 0)
|
|
265400
|
+
return scores;
|
|
265401
|
+
const nodeCount = graph.nodeCount();
|
|
265402
|
+
if (nodeCount === 0)
|
|
265403
|
+
return scores;
|
|
265404
|
+
const teleportProb = 1 / seedNodeIds.length;
|
|
265405
|
+
const seedSet = new Set(seedNodeIds);
|
|
265406
|
+
const allNodes = /* @__PURE__ */ new Set();
|
|
265407
|
+
for (const seedId of seedNodeIds) {
|
|
265408
|
+
allNodes.add(seedId);
|
|
265409
|
+
const neighbors2 = graph.neighbors(seedId);
|
|
265410
|
+
for (const { node } of neighbors2) {
|
|
265411
|
+
allNodes.add(node.id);
|
|
265412
|
+
const hop2 = graph.neighbors(node.id);
|
|
265413
|
+
for (const { node: n2 } of hop2)
|
|
265414
|
+
allNodes.add(n2.id);
|
|
265415
|
+
}
|
|
265416
|
+
}
|
|
265417
|
+
for (const nodeId of allNodes) {
|
|
265418
|
+
scores.set(nodeId, seedSet.has(nodeId) ? teleportProb : 0);
|
|
265419
|
+
}
|
|
265420
|
+
for (let iter = 0; iter < cfg.maxIterations; iter++) {
|
|
265421
|
+
const newScores = /* @__PURE__ */ new Map();
|
|
265422
|
+
let maxDelta = 0;
|
|
265423
|
+
for (const nodeId of allNodes) {
|
|
265424
|
+
const teleport = seedSet.has(nodeId) ? (1 - cfg.damping) * teleportProb : 0;
|
|
265425
|
+
let walkSum = 0;
|
|
265426
|
+
const inEdges = graph.currentEdges(nodeId);
|
|
265427
|
+
for (const edge of inEdges) {
|
|
265428
|
+
const neighborId = edge.srcId === nodeId ? edge.dstId : edge.srcId;
|
|
265429
|
+
const neighborScore = scores.get(neighborId) ?? 0;
|
|
265430
|
+
const neighborOutDegree = graph.currentEdges(neighborId).length || 1;
|
|
265431
|
+
walkSum += neighborScore / neighborOutDegree;
|
|
265432
|
+
}
|
|
265433
|
+
const newScore = teleport + cfg.damping * walkSum;
|
|
265434
|
+
newScores.set(nodeId, newScore);
|
|
265435
|
+
const delta = Math.abs(newScore - (scores.get(nodeId) ?? 0));
|
|
265436
|
+
if (delta > maxDelta)
|
|
265437
|
+
maxDelta = delta;
|
|
265438
|
+
}
|
|
265439
|
+
for (const [id, score] of newScores)
|
|
265440
|
+
scores.set(id, score);
|
|
265441
|
+
if (maxDelta < cfg.convergenceThreshold) {
|
|
265442
|
+
return scores;
|
|
265443
|
+
}
|
|
265444
|
+
}
|
|
265445
|
+
return scores;
|
|
265446
|
+
}
|
|
265447
|
+
function retrieveByPPR(query, graph, episodeStore, config) {
|
|
265448
|
+
const cfg = { ...DEFAULT_CONFIG5, ...config };
|
|
265449
|
+
const queryEntities = extractQueryEntities(query);
|
|
265450
|
+
if (queryEntities.length === 0) {
|
|
265451
|
+
return { episodes: [], queryEntities: [], seedNodes: [], iterations: 0 };
|
|
265452
|
+
}
|
|
265453
|
+
const seedNodes = [];
|
|
265454
|
+
for (const entity of queryEntities) {
|
|
265455
|
+
const node = graph.findNode(entity);
|
|
265456
|
+
if (node) {
|
|
265457
|
+
seedNodes.push(node.id);
|
|
265458
|
+
continue;
|
|
265459
|
+
}
|
|
265460
|
+
for (const nodeType of ["file", "error", "tool", "entity", "event", "concept", "person"]) {
|
|
265461
|
+
const candidates = graph.nodesByType(nodeType, 50);
|
|
265462
|
+
for (const candidate of candidates) {
|
|
265463
|
+
if (candidate.text.toLowerCase().includes(entity.toLowerCase()) || entity.toLowerCase().includes(candidate.text.toLowerCase())) {
|
|
265464
|
+
seedNodes.push(candidate.id);
|
|
265465
|
+
break;
|
|
265466
|
+
}
|
|
265467
|
+
}
|
|
265468
|
+
if (seedNodes.length > queryEntities.indexOf(entity))
|
|
265469
|
+
break;
|
|
265470
|
+
}
|
|
265471
|
+
}
|
|
265472
|
+
if (seedNodes.length === 0) {
|
|
265473
|
+
return { episodes: [], queryEntities, seedNodes: [], iterations: 0 };
|
|
265474
|
+
}
|
|
265475
|
+
const pprScores = personalizedPageRank(graph, seedNodes, cfg);
|
|
265476
|
+
const episodeScores = /* @__PURE__ */ new Map();
|
|
265477
|
+
for (const [nodeId, score] of pprScores) {
|
|
265478
|
+
if (score < 1e-3)
|
|
265479
|
+
continue;
|
|
265480
|
+
const node = graph.getNode(nodeId);
|
|
265481
|
+
if (!node)
|
|
265482
|
+
continue;
|
|
265483
|
+
const edges = graph.currentEdges(nodeId);
|
|
265484
|
+
for (const edge of edges) {
|
|
265485
|
+
if (edge.sourceEpisodeId) {
|
|
265486
|
+
const existing = episodeScores.get(edge.sourceEpisodeId);
|
|
265487
|
+
if (existing) {
|
|
265488
|
+
existing.score += score;
|
|
265489
|
+
existing.matchedNodes.push(node.text);
|
|
265490
|
+
} else {
|
|
265491
|
+
episodeScores.set(edge.sourceEpisodeId, { score, matchedNodes: [node.text] });
|
|
265492
|
+
}
|
|
265493
|
+
}
|
|
265494
|
+
}
|
|
265495
|
+
}
|
|
265496
|
+
const ranked = [...episodeScores.entries()].sort((a2, b) => b[1].score - a2[1].score).slice(0, cfg.topK);
|
|
265497
|
+
const episodes = [];
|
|
265498
|
+
for (const [epId, { score, matchedNodes }] of ranked) {
|
|
265499
|
+
const episode = episodeStore.get(epId);
|
|
265500
|
+
if (episode) {
|
|
265501
|
+
episodes.push({ episode, pprScore: score, matchedNodes: [...new Set(matchedNodes)] });
|
|
265502
|
+
}
|
|
265503
|
+
}
|
|
265504
|
+
return {
|
|
265505
|
+
episodes,
|
|
265506
|
+
queryEntities,
|
|
265507
|
+
seedNodes,
|
|
265508
|
+
iterations: cfg.maxIterations
|
|
265509
|
+
};
|
|
265510
|
+
}
|
|
265511
|
+
var DEFAULT_CONFIG5;
|
|
265512
|
+
var init_pprRetrieval = __esm({
|
|
265513
|
+
"packages/memory/dist/pprRetrieval.js"() {
|
|
265514
|
+
"use strict";
|
|
265515
|
+
init_zettelkasten();
|
|
265516
|
+
DEFAULT_CONFIG5 = {
|
|
265517
|
+
damping: 0.5,
|
|
265518
|
+
maxIterations: 50,
|
|
265519
|
+
convergenceThreshold: 1e-6,
|
|
265520
|
+
topK: 10
|
|
265521
|
+
};
|
|
265522
|
+
}
|
|
265523
|
+
});
|
|
265524
|
+
|
|
265044
265525
|
// packages/memory/dist/embeddings.js
|
|
265045
265526
|
async function generateEmbedding(text, config) {
|
|
265046
|
-
const cfg = { ...
|
|
265527
|
+
const cfg = { ...DEFAULT_CONFIG6, ...config };
|
|
265047
265528
|
try {
|
|
265048
265529
|
const url = `${cfg.baseUrl}/api/embed`;
|
|
265049
265530
|
const resp = await fetch(url, {
|
|
@@ -265078,7 +265559,7 @@ async function generateEmbedding(text, config) {
|
|
|
265078
265559
|
}
|
|
265079
265560
|
}
|
|
265080
265561
|
async function checkEmbeddingAvailable(config) {
|
|
265081
|
-
const cfg = { ...
|
|
265562
|
+
const cfg = { ...DEFAULT_CONFIG6, ...config };
|
|
265082
265563
|
try {
|
|
265083
265564
|
const resp = await fetch(`${cfg.baseUrl}/api/tags`, {
|
|
265084
265565
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -265105,11 +265586,11 @@ async function pullEmbeddingModel(baseUrl, model, timeoutMs) {
|
|
|
265105
265586
|
return false;
|
|
265106
265587
|
}
|
|
265107
265588
|
}
|
|
265108
|
-
var
|
|
265589
|
+
var DEFAULT_CONFIG6;
|
|
265109
265590
|
var init_embeddings = __esm({
|
|
265110
265591
|
"packages/memory/dist/embeddings.js"() {
|
|
265111
265592
|
"use strict";
|
|
265112
|
-
|
|
265593
|
+
DEFAULT_CONFIG6 = {
|
|
265113
265594
|
baseUrl: "http://localhost:11434",
|
|
265114
265595
|
model: "nomic-embed-text",
|
|
265115
265596
|
timeoutMs: 3e4
|
|
@@ -265139,6 +265620,9 @@ var init_dist7 = __esm({
|
|
|
265139
265620
|
init_toolPatternStore();
|
|
265140
265621
|
init_episodeStore();
|
|
265141
265622
|
init_temporalGraph();
|
|
265623
|
+
init_zettelkasten();
|
|
265624
|
+
init_gistCompressor();
|
|
265625
|
+
init_pprRetrieval();
|
|
265142
265626
|
init_embeddings();
|
|
265143
265627
|
init_proceduralMemoryStore();
|
|
265144
265628
|
}
|
|
@@ -265898,6 +266382,15 @@ var init_agenticRunner = __esm({
|
|
|
265898
266382
|
const embResult = await generateEmbedding(content, { baseUrl });
|
|
265899
266383
|
if (embResult?.vector) {
|
|
265900
266384
|
this._episodeStore.setEmbedding(id, embResult.vector);
|
|
266385
|
+
if (this._temporalGraph) {
|
|
266386
|
+
const episode = this._episodeStore.get(id);
|
|
266387
|
+
if (episode?.embedding) {
|
|
266388
|
+
try {
|
|
266389
|
+
linkEpisode(episode, this._episodeStore, this._temporalGraph);
|
|
266390
|
+
} catch {
|
|
266391
|
+
}
|
|
266392
|
+
}
|
|
266393
|
+
}
|
|
265901
266394
|
}
|
|
265902
266395
|
} catch {
|
|
265903
266396
|
}
|
|
@@ -266798,6 +267291,21 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
266798
267291
|
if (compacted.length < prevLen)
|
|
266799
267292
|
recentToolResults.clear();
|
|
266800
267293
|
}
|
|
267294
|
+
if (turn > 0 && turn % 3 === 0 && this._temporalGraph && this._episodeStore) {
|
|
267295
|
+
try {
|
|
267296
|
+
const taskGoal = this._taskState.goal || task.slice(0, 200);
|
|
267297
|
+
const pprResult = retrieveByPPR(taskGoal, this._temporalGraph, this._episodeStore, { topK: 3 });
|
|
267298
|
+
if (pprResult.episodes.length > 0) {
|
|
267299
|
+
const memoryLines = pprResult.episodes.map(({ episode, pprScore, matchedNodes }) => `- [${episode.toolName ?? episode.modality}] ${episode.content.slice(0, 120)} (via: ${matchedNodes.slice(0, 2).join(", ")})`);
|
|
267300
|
+
compacted.push({
|
|
267301
|
+
role: "system",
|
|
267302
|
+
content: `[Associative Memory \u2014 related prior experience]
|
|
267303
|
+
${memoryLines.join("\n")}`
|
|
267304
|
+
});
|
|
267305
|
+
}
|
|
267306
|
+
} catch {
|
|
267307
|
+
}
|
|
267308
|
+
}
|
|
266801
267309
|
if (this.options.environmentProvider) {
|
|
266802
267310
|
try {
|
|
266803
267311
|
const envStr = this.options.environmentProvider();
|
|
@@ -268138,6 +268646,19 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
268138
268646
|
await this.processPendingEmbeddings();
|
|
268139
268647
|
}
|
|
268140
268648
|
this.stopEmbeddingPipeline();
|
|
268649
|
+
const gist = compressAndStore(this._episodeStore, this._sessionId, task, 10);
|
|
268650
|
+
if (gist) {
|
|
268651
|
+
this.emit({ type: "status", content: `Gist compressed: "${gist.gist.slice(0, 100)}..."`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
268652
|
+
}
|
|
268653
|
+
if (this._temporalGraph) {
|
|
268654
|
+
try {
|
|
268655
|
+
const linkResult = batchLink(this._episodeStore, this._temporalGraph);
|
|
268656
|
+
if (linkResult.linksCreated > 0) {
|
|
268657
|
+
this.emit({ type: "status", content: `Zettelkasten: ${linkResult.linksCreated} associative links created`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
268658
|
+
}
|
|
268659
|
+
} catch {
|
|
268660
|
+
}
|
|
268661
|
+
}
|
|
268141
268662
|
if (this._temporalGraph) {
|
|
268142
268663
|
const nodes = this._temporalGraph.nodeCount();
|
|
268143
268664
|
const edges = this._temporalGraph.activeEdgeCount();
|
|
@@ -303382,7 +303903,7 @@ function createEditHistoryLogger(repoRoot, sessionId) {
|
|
|
303382
303903
|
const entry = {
|
|
303383
303904
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
303384
303905
|
tool: toolName,
|
|
303385
|
-
files:
|
|
303906
|
+
files: extractFilePaths2(toolName, toolArgs),
|
|
303386
303907
|
summary: buildSummary(toolName, toolArgs),
|
|
303387
303908
|
success,
|
|
303388
303909
|
session: sessionId,
|
|
@@ -303395,7 +303916,7 @@ function createEditHistoryLogger(repoRoot, sessionId) {
|
|
|
303395
303916
|
}
|
|
303396
303917
|
return { logToolCall, logPath: logPath2 };
|
|
303397
303918
|
}
|
|
303398
|
-
function
|
|
303919
|
+
function extractFilePaths2(tool, args) {
|
|
303399
303920
|
if (tool === "batch_edit") {
|
|
303400
303921
|
const edits = args["edits"];
|
|
303401
303922
|
if (Array.isArray(edits)) {
|
package/package.json
CHANGED