open-agents-ai 0.187.161 → 0.187.162

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.
Files changed (2) hide show
  1. package/dist/index.js +221 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -265041,9 +265041,200 @@ var init_temporalGraph = __esm({
265041
265041
  }
265042
265042
  });
265043
265043
 
265044
+ // packages/memory/dist/zettelkasten.js
265045
+ function cosineSimilarity2(a2, b) {
265046
+ if (a2.length !== b.length || a2.length === 0)
265047
+ return 0;
265048
+ let dot = 0, normA = 0, normB = 0;
265049
+ for (let i2 = 0; i2 < a2.length; i2++) {
265050
+ dot += a2[i2] * b[i2];
265051
+ normA += a2[i2] * a2[i2];
265052
+ normB += b[i2] * b[i2];
265053
+ }
265054
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
265055
+ return denom > 0 ? dot / denom : 0;
265056
+ }
265057
+ function findNeighbors(episode, candidates, topK, minSimilarity) {
265058
+ if (!episode.embedding)
265059
+ return [];
265060
+ const scored = [];
265061
+ for (const candidate of candidates) {
265062
+ if (candidate.id === episode.id)
265063
+ continue;
265064
+ if (!candidate.embedding)
265065
+ continue;
265066
+ const sim = cosineSimilarity2(episode.embedding, candidate.embedding);
265067
+ if (sim >= minSimilarity) {
265068
+ scored.push({ episode: candidate, similarity: sim });
265069
+ }
265070
+ }
265071
+ scored.sort((a2, b) => b.similarity - a2.similarity);
265072
+ return scored.slice(0, topK);
265073
+ }
265074
+ function linkEpisode(episode, episodeStore, graph, config) {
265075
+ const cfg = { ...DEFAULT_CONFIG4, ...config };
265076
+ const result = { episodeId: episode.id, linkedTo: [], linksCreated: 0 };
265077
+ if (!episode.embedding)
265078
+ return result;
265079
+ const candidates = episodeStore.recent(500).filter((e2) => e2.embedding != null);
265080
+ const neighbors2 = findNeighbors(episode, candidates, cfg.topK, cfg.minSimilarity);
265081
+ for (const { episode: neighbor, similarity } of neighbors2) {
265082
+ if (result.linksCreated >= cfg.maxLinksPerEpisode)
265083
+ break;
265084
+ const srcNodeId = graph.upsertNode({
265085
+ text: episode.content.slice(0, 100),
265086
+ nodeType: "event"
265087
+ });
265088
+ const dstNodeId = graph.upsertNode({
265089
+ text: neighbor.content.slice(0, 100),
265090
+ nodeType: "event"
265091
+ });
265092
+ graph.addEdge({
265093
+ srcId: srcNodeId,
265094
+ dstId: dstNodeId,
265095
+ relation: "related_to",
265096
+ fact: `Associated: ${episode.content.slice(0, 50)} \u2194 ${neighbor.content.slice(0, 50)}`,
265097
+ edgeType: "synonym",
265098
+ confidence: similarity,
265099
+ sourceEpisodeId: episode.id
265100
+ });
265101
+ result.linkedTo.push({ neighborId: neighbor.id, similarity, linked: true });
265102
+ result.linksCreated++;
265103
+ if (similarity >= cfg.evolutionThreshold && neighbor.gist !== episode.content.slice(0, 200)) {
265104
+ const evolvedGist = neighbor.gist ? `${neighbor.gist} | Also related: ${episode.content.slice(0, 100)}` : `Related context: ${episode.content.slice(0, 150)}`;
265105
+ episodeStore.setGist(neighbor.id, evolvedGist.slice(0, 500));
265106
+ }
265107
+ }
265108
+ return result;
265109
+ }
265110
+ function batchLink(episodeStore, graph, config) {
265111
+ const episodes = episodeStore.recent(200).filter((e2) => e2.embedding != null);
265112
+ let totalLinks = 0;
265113
+ let processed = 0;
265114
+ for (const ep of episodes) {
265115
+ const result = linkEpisode(ep, episodeStore, graph, config);
265116
+ totalLinks += result.linksCreated;
265117
+ if (result.linksCreated > 0)
265118
+ processed++;
265119
+ }
265120
+ return { processed, linksCreated: totalLinks };
265121
+ }
265122
+ var DEFAULT_CONFIG4;
265123
+ var init_zettelkasten = __esm({
265124
+ "packages/memory/dist/zettelkasten.js"() {
265125
+ "use strict";
265126
+ DEFAULT_CONFIG4 = {
265127
+ topK: 3,
265128
+ minSimilarity: 0.3,
265129
+ evolutionThreshold: 0.6,
265130
+ maxLinksPerEpisode: 10
265131
+ };
265132
+ }
265133
+ });
265134
+
265135
+ // packages/memory/dist/gistCompressor.js
265136
+ function compressToGist(episodes, taskDescription) {
265137
+ if (episodes.length === 0) {
265138
+ return {
265139
+ gist: "Empty task \u2014 no actions taken.",
265140
+ sourceEpisodeIds: [],
265141
+ episodeType: "mixed",
265142
+ turnCount: 0,
265143
+ toolsUsed: [],
265144
+ filesModified: [],
265145
+ errorsEncountered: [],
265146
+ timestamp: Date.now()
265147
+ };
265148
+ }
265149
+ const toolsUsed = [...new Set(episodes.map((e2) => e2.toolName).filter(Boolean))];
265150
+ const filesModified = extractFilePaths(episodes, ["file_write", "file_edit", "file_patch", "batch_edit"]);
265151
+ const filesRead = extractFilePaths(episodes, ["file_read"]);
265152
+ 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);
265153
+ const episodeType = classifyTrajectory(episodes, errorsEncountered);
265154
+ const parts = [];
265155
+ const taskSnippet = taskDescription.slice(0, 100).replace(/\n/g, " ");
265156
+ parts.push(`Task: "${taskSnippet}"`);
265157
+ if (filesModified.length > 0) {
265158
+ parts.push(`Modified ${filesModified.length} file(s): ${filesModified.slice(0, 3).join(", ")}`);
265159
+ }
265160
+ if (errorsEncountered.length > 0 && episodeType === "error_recovery") {
265161
+ parts.push(`Encountered ${errorsEncountered.length} error(s), recovered successfully`);
265162
+ } else if (errorsEncountered.length > 0) {
265163
+ parts.push(`${errorsEncountered.length} error(s) encountered`);
265164
+ }
265165
+ parts.push(`Used ${toolsUsed.length} tools across ${episodes.length} steps`);
265166
+ const lastEp = episodes[episodes.length - 1];
265167
+ if (lastEp.toolName === "task_complete") {
265168
+ parts.push("Completed successfully");
265169
+ } else if (lastEp.content.toLowerCase().includes("error")) {
265170
+ parts.push("Ended with errors");
265171
+ }
265172
+ const gist = parts.join(". ") + ".";
265173
+ return {
265174
+ gist,
265175
+ sourceEpisodeIds: episodes.map((e2) => e2.id),
265176
+ episodeType,
265177
+ turnCount: Math.max(...episodes.map((e2) => e2.turnNumber ?? 0)),
265178
+ toolsUsed,
265179
+ filesModified,
265180
+ errorsEncountered,
265181
+ timestamp: episodes[episodes.length - 1]?.timestamp ?? Date.now()
265182
+ };
265183
+ }
265184
+ function compressAndStore(episodeStore, sessionId, taskDescription, minTurns = 10) {
265185
+ const episodes = episodeStore.recent(500, sessionId);
265186
+ const maxTurn = Math.max(0, ...episodes.map((e2) => e2.turnNumber ?? 0));
265187
+ if (maxTurn < minTurns)
265188
+ return null;
265189
+ const gistRecord = compressToGist(episodes.reverse(), taskDescription);
265190
+ episodeStore.insert({
265191
+ sessionId,
265192
+ modality: "gist",
265193
+ content: gistRecord.gist,
265194
+ importance: 8,
265195
+ decayClass: "procedural",
265196
+ sourceEpisodeId: gistRecord.sourceEpisodeIds[0]
265197
+ });
265198
+ return gistRecord;
265199
+ }
265200
+ function extractFilePaths(episodes, toolNames) {
265201
+ const paths = [];
265202
+ for (const ep of episodes) {
265203
+ if (!ep.toolName || !toolNames.includes(ep.toolName))
265204
+ continue;
265205
+ if (ep.metadata) {
265206
+ const fp = ep.metadata.args_fingerprint;
265207
+ if (fp) {
265208
+ const pathMatch = fp.match(/path=([^,]+)/);
265209
+ if (pathMatch)
265210
+ paths.push(pathMatch[1]);
265211
+ }
265212
+ }
265213
+ }
265214
+ return [...new Set(paths)];
265215
+ }
265216
+ function classifyTrajectory(episodes, errors) {
265217
+ const hasErrors = errors.length > 0;
265218
+ const lastSuccess = episodes.some((e2) => e2.toolName === "task_complete");
265219
+ const hasFileEdits = episodes.some((e2) => ["file_write", "file_edit"].includes(e2.toolName ?? ""));
265220
+ const hasSearch = episodes.some((e2) => ["grep_search", "find_files", "web_search"].includes(e2.toolName ?? ""));
265221
+ if (hasErrors && lastSuccess)
265222
+ return "error_recovery";
265223
+ if (hasSearch && !hasFileEdits)
265224
+ return "discovery";
265225
+ if (!hasErrors && hasFileEdits)
265226
+ return "tool_sequence";
265227
+ return "mixed";
265228
+ }
265229
+ var init_gistCompressor = __esm({
265230
+ "packages/memory/dist/gistCompressor.js"() {
265231
+ "use strict";
265232
+ }
265233
+ });
265234
+
265044
265235
  // packages/memory/dist/embeddings.js
265045
265236
  async function generateEmbedding(text, config) {
265046
- const cfg = { ...DEFAULT_CONFIG4, ...config };
265237
+ const cfg = { ...DEFAULT_CONFIG5, ...config };
265047
265238
  try {
265048
265239
  const url = `${cfg.baseUrl}/api/embed`;
265049
265240
  const resp = await fetch(url, {
@@ -265078,7 +265269,7 @@ async function generateEmbedding(text, config) {
265078
265269
  }
265079
265270
  }
265080
265271
  async function checkEmbeddingAvailable(config) {
265081
- const cfg = { ...DEFAULT_CONFIG4, ...config };
265272
+ const cfg = { ...DEFAULT_CONFIG5, ...config };
265082
265273
  try {
265083
265274
  const resp = await fetch(`${cfg.baseUrl}/api/tags`, {
265084
265275
  signal: AbortSignal.timeout(5e3)
@@ -265105,11 +265296,11 @@ async function pullEmbeddingModel(baseUrl, model, timeoutMs) {
265105
265296
  return false;
265106
265297
  }
265107
265298
  }
265108
- var DEFAULT_CONFIG4;
265299
+ var DEFAULT_CONFIG5;
265109
265300
  var init_embeddings = __esm({
265110
265301
  "packages/memory/dist/embeddings.js"() {
265111
265302
  "use strict";
265112
- DEFAULT_CONFIG4 = {
265303
+ DEFAULT_CONFIG5 = {
265113
265304
  baseUrl: "http://localhost:11434",
265114
265305
  model: "nomic-embed-text",
265115
265306
  timeoutMs: 3e4
@@ -265139,6 +265330,8 @@ var init_dist7 = __esm({
265139
265330
  init_toolPatternStore();
265140
265331
  init_episodeStore();
265141
265332
  init_temporalGraph();
265333
+ init_zettelkasten();
265334
+ init_gistCompressor();
265142
265335
  init_embeddings();
265143
265336
  init_proceduralMemoryStore();
265144
265337
  }
@@ -265898,6 +266091,15 @@ var init_agenticRunner = __esm({
265898
266091
  const embResult = await generateEmbedding(content, { baseUrl });
265899
266092
  if (embResult?.vector) {
265900
266093
  this._episodeStore.setEmbedding(id, embResult.vector);
266094
+ if (this._temporalGraph) {
266095
+ const episode = this._episodeStore.get(id);
266096
+ if (episode?.embedding) {
266097
+ try {
266098
+ linkEpisode(episode, this._episodeStore, this._temporalGraph);
266099
+ } catch {
266100
+ }
266101
+ }
266102
+ }
265901
266103
  }
265902
266104
  } catch {
265903
266105
  }
@@ -268138,6 +268340,19 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
268138
268340
  await this.processPendingEmbeddings();
268139
268341
  }
268140
268342
  this.stopEmbeddingPipeline();
268343
+ const gist = compressAndStore(this._episodeStore, this._sessionId, task, 10);
268344
+ if (gist) {
268345
+ this.emit({ type: "status", content: `Gist compressed: "${gist.gist.slice(0, 100)}..."`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
268346
+ }
268347
+ if (this._temporalGraph) {
268348
+ try {
268349
+ const linkResult = batchLink(this._episodeStore, this._temporalGraph);
268350
+ if (linkResult.linksCreated > 0) {
268351
+ this.emit({ type: "status", content: `Zettelkasten: ${linkResult.linksCreated} associative links created`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
268352
+ }
268353
+ } catch {
268354
+ }
268355
+ }
268141
268356
  if (this._temporalGraph) {
268142
268357
  const nodes = this._temporalGraph.nodeCount();
268143
268358
  const edges = this._temporalGraph.activeEdgeCount();
@@ -303382,7 +303597,7 @@ function createEditHistoryLogger(repoRoot, sessionId) {
303382
303597
  const entry = {
303383
303598
  ts: (/* @__PURE__ */ new Date()).toISOString(),
303384
303599
  tool: toolName,
303385
- files: extractFilePaths(toolName, toolArgs),
303600
+ files: extractFilePaths2(toolName, toolArgs),
303386
303601
  summary: buildSummary(toolName, toolArgs),
303387
303602
  success,
303388
303603
  session: sessionId,
@@ -303395,7 +303610,7 @@ function createEditHistoryLogger(repoRoot, sessionId) {
303395
303610
  }
303396
303611
  return { logToolCall, logPath: logPath2 };
303397
303612
  }
303398
- function extractFilePaths(tool, args) {
303613
+ function extractFilePaths2(tool, args) {
303399
303614
  if (tool === "batch_edit") {
303400
303615
  const edits = args["edits"];
303401
303616
  if (Array.isArray(edits)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.161",
3
+ "version": "0.187.162",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",