open-agents-ai 0.187.344 → 0.187.345

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 +181 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -259301,6 +259301,7 @@ print(classes[top])
259301
259301
  textParts.push(`Speech: "${episode.audio.transcript}"`);
259302
259302
  episode.text = { content: textParts.join(". ") || "Multi-modal capture", entities: [] };
259303
259303
  this.saveEpisode(episode);
259304
+ this.bridgeToEpisodeStore(episode);
259304
259305
  return {
259305
259306
  success: true,
259306
259307
  output: `Multi-modal episode captured (${episodeId}):
@@ -259379,6 +259380,7 @@ else:
259379
259380
  }
259380
259381
  }
259381
259382
  this.saveEpisode(episode);
259383
+ this.bridgeToEpisodeStore(episode);
259382
259384
  }
259383
259385
  return {
259384
259386
  success: true,
@@ -259550,6 +259552,88 @@ ${lines.join("\n")}`,
259550
259552
  });
259551
259553
  writeFileSync17(MM_INDEX, JSON.stringify(index, null, 2));
259552
259554
  }
259555
+ /**
259556
+ * WO-AM-GAP-02: Bridge multimodal episode to SQLite EpisodeStore + TemporalGraph.
259557
+ * Makes multimodal episodes visible to PPR retrieval, zettelkasten linking,
259558
+ * and the orchestrator's context injection system.
259559
+ */
259560
+ bridgeToEpisodeStore(episode) {
259561
+ try {
259562
+ const { EpisodeStore: EpisodeStore3, TemporalGraph: TemporalGraph3 } = __require("@open-agents/memory");
259563
+ const { existsSync: fsExists } = __require("node:fs");
259564
+ const { join: pathJoin } = __require("node:path");
259565
+ const cwd4 = process.cwd();
259566
+ const oaDirs = [pathJoin(cwd4, ".oa_test"), pathJoin(cwd4, ".oa")];
259567
+ const oaDir = oaDirs.find((d2) => fsExists(d2));
259568
+ if (!oaDir)
259569
+ return;
259570
+ const es = new EpisodeStore3(pathJoin(oaDir, "memory.db"));
259571
+ const tg = new TemporalGraph3(pathJoin(oaDir, "kg.db"));
259572
+ const contentParts = [];
259573
+ if (episode.social?.personName)
259574
+ contentParts.push(`Met ${episode.social.personName}`);
259575
+ if (episode.audio?.transcript)
259576
+ contentParts.push(`Said: "${episode.audio.transcript}"`);
259577
+ if (episode.audio?.soundClass)
259578
+ contentParts.push(`Sound: ${episode.audio.soundClass}`);
259579
+ if (episode.visual?.faceNames?.length)
259580
+ contentParts.push(`Faces: ${episode.visual.faceNames.join(", ")}`);
259581
+ if (episode.visual?.objects?.length)
259582
+ contentParts.push(`Objects: ${episode.visual.objects.join(", ")}`);
259583
+ if (episode.spatial?.locationLabel)
259584
+ contentParts.push(`Location: ${episode.spatial.locationLabel}`);
259585
+ const content = contentParts.join(". ") || episode.text?.content || "Multimodal capture";
259586
+ const modality = episode.social?.personName ? "social" : episode.visual?.imagePath ? "visual" : episode.audio?.recordingPath ? "audio" : "text";
259587
+ const epId = es.insert({
259588
+ sessionId: episode.sessionId,
259589
+ modality,
259590
+ toolName: "multimodal_memory",
259591
+ content,
259592
+ importance: episode.social?.personName ? 9 : 7,
259593
+ decayClass: episode.social?.personName ? "permanent" : "daily",
259594
+ metadata: {
259595
+ multimodal_episode_id: episode.id,
259596
+ has_face: (episode.visual?.faceIds?.length ?? 0) > 0,
259597
+ has_audio: !!episode.audio?.recordingPath,
259598
+ has_gps: !!episode.spatial?.gps
259599
+ }
259600
+ });
259601
+ if (episode.visual?.clipEmbedding) {
259602
+ const emb = new Float32Array(episode.visual.clipEmbedding);
259603
+ es.setEmbedding(epId, emb);
259604
+ }
259605
+ if (episode.social?.personName) {
259606
+ const personId = tg.upsertNode({ text: episode.social.personName, nodeType: "person" });
259607
+ tg.addEdge({
259608
+ srcId: personId,
259609
+ dstId: personId,
259610
+ relation: "discovered_during",
259611
+ fact: `Met ${episode.social.personName} via multimodal capture`,
259612
+ edgeType: "triple",
259613
+ sourceEpisodeId: epId,
259614
+ modality
259615
+ });
259616
+ }
259617
+ if (episode.spatial?.locationLabel) {
259618
+ const locId = tg.upsertNode({ text: episode.spatial.locationLabel, nodeType: "location" });
259619
+ if (episode.social?.personName) {
259620
+ const personNode = tg.findNode(episode.social.personName, "person");
259621
+ if (personNode) {
259622
+ tg.addEdge({
259623
+ srcId: personNode.id,
259624
+ dstId: locId,
259625
+ relation: "appears_in",
259626
+ fact: `${episode.social.personName} seen at ${episode.spatial.locationLabel}`,
259627
+ sourceEpisodeId: epId
259628
+ });
259629
+ }
259630
+ }
259631
+ }
259632
+ es.close();
259633
+ tg.close();
259634
+ } catch {
259635
+ }
259636
+ }
259553
259637
  loadEpisode(id) {
259554
259638
  const file = join52(MM_DIR, id, "episode.json");
259555
259639
  try {
@@ -267715,12 +267799,14 @@ function autoImportance(toolName, modality, content) {
267715
267799
  return 5;
267716
267800
  if (toolName?.startsWith("memory_"))
267717
267801
  return 6;
267718
- if (modality === "visual" || modality === "audio")
267719
- return 7;
267720
267802
  if (modality === "social")
267721
- return 8;
267722
- if (modality === "spatial")
267803
+ return 9;
267804
+ if (modality === "visual")
267805
+ return 7;
267806
+ if (modality === "audio")
267723
267807
  return 6;
267808
+ if (modality === "spatial")
267809
+ return 5;
267724
267810
  if (modality === "reflection")
267725
267811
  return 7;
267726
267812
  if (modality === "gist")
@@ -267738,7 +267824,13 @@ function autoDecayClass(toolName, modality, content) {
267738
267824
  return "daily";
267739
267825
  if (content.toLowerCase().includes("error") || content.toLowerCase().includes("failed"))
267740
267826
  return "procedural";
267741
- if (["visual", "audio", "social", "spatial"].includes(modality))
267827
+ if (modality === "social")
267828
+ return "permanent";
267829
+ if (modality === "visual")
267830
+ return "procedural";
267831
+ if (modality === "spatial")
267832
+ return "procedural";
267833
+ if (modality === "audio")
267742
267834
  return "daily";
267743
267835
  if (modality === "reflection" || modality === "gist")
267744
267836
  return "procedural";
@@ -267793,6 +267885,10 @@ var init_episodeStore = __esm({
267793
267885
  this.db.exec(`CREATE INDEX IF NOT EXISTS idx_ep_tool ON episodes(tool_name)`);
267794
267886
  this.db.exec(`CREATE INDEX IF NOT EXISTS idx_ep_decay ON episodes(decay_class)`);
267795
267887
  this.db.exec(`CREATE INDEX IF NOT EXISTS idx_ep_hash ON episodes(content_hash, session_id)`);
267888
+ try {
267889
+ this.db.exec(`ALTER TABLE episodes ADD COLUMN clip_embedding BLOB`);
267890
+ } catch {
267891
+ }
267796
267892
  this.db.pragma("journal_mode = WAL");
267797
267893
  this.db.pragma("synchronous = NORMAL");
267798
267894
  }
@@ -267853,7 +267949,37 @@ var init_episodeStore = __esm({
267853
267949
  }
267854
267950
  sql += " ORDER BY timestamp DESC LIMIT ?";
267855
267951
  params.push(Math.min(limit * 5, 500));
267856
- const rows = this.db.prepare(sql).all(...params);
267952
+ let rows = this.db.prepare(sql).all(...params);
267953
+ if (query.metadataFilter || query.soundClass || query.rmsRange) {
267954
+ rows = rows.filter((row) => {
267955
+ let meta = null;
267956
+ try {
267957
+ meta = row.metadata ? typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata : null;
267958
+ } catch {
267959
+ return false;
267960
+ }
267961
+ if (!meta)
267962
+ return false;
267963
+ if (query.metadataFilter) {
267964
+ for (const [k, v] of Object.entries(query.metadataFilter)) {
267965
+ if (meta[k] !== v)
267966
+ return false;
267967
+ }
267968
+ }
267969
+ if (query.soundClass && meta.sound_class !== query.soundClass)
267970
+ return false;
267971
+ if (query.rmsRange) {
267972
+ const rms = meta.rms_db ?? meta.rmsDb;
267973
+ if (typeof rms !== "number")
267974
+ return false;
267975
+ if (query.rmsRange.min !== void 0 && rms < query.rmsRange.min)
267976
+ return false;
267977
+ if (query.rmsRange.max !== void 0 && rms > query.rmsRange.max)
267978
+ return false;
267979
+ }
267980
+ return true;
267981
+ });
267982
+ }
267857
267983
  const scored = rows.map((row) => {
267858
267984
  const ep = this.rowToEpisode(row);
267859
267985
  const tau = DECAY_TAU[ep.decayClass] ?? DECAY_TAU.daily;
@@ -267883,7 +268009,8 @@ var init_episodeStore = __esm({
267883
268009
  emb = Math.max(0, Math.min(1, (emb + 1) / 2));
267884
268010
  }
267885
268011
  const relevance = wLex * lex + wEmb * emb;
267886
- const score = recency + importance + relevance;
268012
+ const strengthBonus = Math.min(1, Math.log2(Math.max(1, ep.strength)));
268013
+ const score = recency + importance + relevance + strengthBonus;
267887
268014
  return { episode: ep, score };
267888
268015
  });
267889
268016
  scored.sort((a2, b) => b.score - a2.score);
@@ -267929,6 +268056,11 @@ var init_episodeStore = __esm({
267929
268056
  const buf = Buffer.from(embedding.buffer);
267930
268057
  this.db.prepare("UPDATE episodes SET embedding = ? WHERE id = ?").run(buf, id);
267931
268058
  }
268059
+ /** WO-AM-GAP-03: Set CLIP embedding for cross-modal retrieval (512d). */
268060
+ setClipEmbedding(id, clipEmbedding) {
268061
+ const buf = Buffer.from(clipEmbedding.buffer);
268062
+ this.db.prepare("UPDATE episodes SET clip_embedding = ? WHERE id = ?").run(buf, id);
268063
+ }
267932
268064
  /** Update gist for an episode (from WO-AM-07 gist compression). */
267933
268065
  setGist(id, gist) {
267934
268066
  this.db.prepare("UPDATE episodes SET gist = ? WHERE id = ?").run(gist, id);
@@ -267961,6 +268093,7 @@ var init_episodeStore = __esm({
267961
268093
  decayClass: row.decay_class,
267962
268094
  strength: typeof row.strength === "number" && Number.isFinite(row.strength) ? row.strength : 1,
267963
268095
  lastRetrieved: row.last_retrieved,
268096
+ clipEmbedding: row.clip_embedding ? new Float32Array(new Uint8Array(row.clip_embedding).buffer) : null,
267964
268097
  gist: row.gist,
267965
268098
  sourceEpisodeId: row.source_episode_id
267966
268099
  };
@@ -269706,6 +269839,19 @@ function repairJson(raw) {
269706
269839
  }
269707
269840
  return found ? result : null;
269708
269841
  }
269842
+ function inferEpisodeModality(toolName) {
269843
+ if (VISUAL_TOOLS.has(toolName))
269844
+ return "visual";
269845
+ if (AUDIO_TOOLS.has(toolName))
269846
+ return "audio";
269847
+ if (SOCIAL_TOOLS.has(toolName))
269848
+ return "social";
269849
+ if (SPATIAL_TOOLS.has(toolName))
269850
+ return "spatial";
269851
+ if (CODE_TOOLS.has(toolName))
269852
+ return "code";
269853
+ return "tool_result";
269854
+ }
269709
269855
  function getSystemPromptForTier(tier) {
269710
269856
  switch (tier) {
269711
269857
  case "small":
@@ -269746,7 +269892,7 @@ ${todoItems}
269746
269892
  </system-reminder>`;
269747
269893
  return { shouldInject: true, content, reason: "injected" };
269748
269894
  }
269749
- var SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, AgenticRunner, OllamaAgenticBackend;
269895
+ var SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, VISUAL_TOOLS, AUDIO_TOOLS, SOCIAL_TOOLS, SPATIAL_TOOLS, CODE_TOOLS, AgenticRunner, OllamaAgenticBackend;
269750
269896
  var init_agenticRunner = __esm({
269751
269897
  "packages/orchestrator/dist/agenticRunner.js"() {
269752
269898
  "use strict";
@@ -269764,6 +269910,11 @@ var init_agenticRunner = __esm({
269764
269910
  SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
269765
269911
  SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
269766
269912
  SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
269913
+ VISUAL_TOOLS = /* @__PURE__ */ new Set(["vision", "camera_capture", "image_read", "screenshot", "ocr", "ocr_image_advanced", "visual_memory", "desktop_describe", "ocr_pdf", "generate_image"]);
269914
+ AUDIO_TOOLS = /* @__PURE__ */ new Set(["audio_capture", "audio_analyze", "asr_listen", "transcribe_file", "transcribe_url", "audio_playback", "youtube_download"]);
269915
+ SOCIAL_TOOLS = /* @__PURE__ */ new Set(["multimodal_memory", "send_message", "jibberlink"]);
269916
+ SPATIAL_TOOLS = /* @__PURE__ */ new Set(["gps_location", "bluetooth_scan", "wifi_control", "sdr_scan", "meshtastic"]);
269917
+ CODE_TOOLS = /* @__PURE__ */ new Set(["file_write", "file_edit", "file_patch", "batch_edit", "code_sandbox", "repl_exec", "notebook_edit"]);
269767
269918
  AgenticRunner = class {
269768
269919
  backend;
269769
269920
  tools = /* @__PURE__ */ new Map();
@@ -271582,17 +271733,33 @@ ${cachedEntry2.result.slice(0, 500)}` : `[BLOCKED — the observer confirmed thi
271582
271733
  if (this._episodeStore) {
271583
271734
  try {
271584
271735
  const episodeContent = result.success ? `${tc.name}: ${(result.output ?? "").slice(0, 500)}` : `${tc.name} ERROR: ${(result.error ?? result.output ?? "").slice(0, 500)}`;
271736
+ const episodeModality = inferEpisodeModality(tc.name);
271737
+ let episodeMetadata = {
271738
+ args_fingerprint: argsKey.slice(0, 200),
271739
+ success: result.success,
271740
+ duration_ms: performance.now() - toolStart
271741
+ };
271742
+ if (result.success && ["audio_analyze", "audio_capture"].includes(tc.name)) {
271743
+ try {
271744
+ const parsed = JSON.parse(result.output ?? "{}");
271745
+ if (parsed.rms_db !== void 0)
271746
+ episodeMetadata.rms_db = parsed.rms_db;
271747
+ if (parsed.classifications)
271748
+ episodeMetadata.sound_class = parsed.classifications[0]?.class;
271749
+ if (parsed.peak_frequencies)
271750
+ episodeMetadata.peak_frequencies = parsed.peak_frequencies.slice(0, 3);
271751
+ if (parsed.band_energy_db)
271752
+ episodeMetadata.band_energy = parsed.band_energy_db;
271753
+ } catch {
271754
+ }
271755
+ }
271585
271756
  const episodeId = this._episodeStore.insert({
271586
271757
  sessionId: this._sessionId,
271587
271758
  turnNumber: turn,
271588
- modality: "tool_result",
271759
+ modality: episodeModality,
271589
271760
  toolName: tc.name,
271590
271761
  content: episodeContent,
271591
- metadata: {
271592
- args_fingerprint: argsKey.slice(0, 200),
271593
- success: result.success,
271594
- duration_ms: performance.now() - toolStart
271595
- }
271762
+ metadata: episodeMetadata
271596
271763
  });
271597
271764
  if (this._embeddingAvailable && episodeContent.length > 20) {
271598
271765
  this._pendingEmbeddings.push({ id: episodeId, content: episodeContent.slice(0, 500) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.344",
3
+ "version": "0.187.345",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) \u2014 interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",