open-agents-ai 0.138.78 → 0.138.80

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 +175 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5644,6 +5644,51 @@ async function handleCmd(cmd) {
5644
5644
  break;
5645
5645
  }
5646
5646
 
5647
+ // \u2500\u2500 COHERE distributed learning \u2014 publish insight to mesh \u2500\u2500\u2500\u2500\u2500\u2500
5648
+ case 'cohere_publish_insight': {
5649
+ if (!cohereActive) { writeResp(id, { ok: false, output: 'COHERE not active' }); break; }
5650
+ if (!_natsConn || !_natsCodec) { writeResp(id, { ok: false, output: 'NATS not connected' }); break; }
5651
+ var _cpiInsight = args.insight || '';
5652
+ var _cpiCategory = args.category || 'strategy';
5653
+ var _cpiConfidence = parseFloat(args.confidence || '0.7');
5654
+ if (!_cpiInsight) { writeResp(id, { ok: false, output: 'insight text required' }); break; }
5655
+ try {
5656
+ // Detect local model tier from warm model
5657
+ var _cpiTier = 'unknown';
5658
+ try {
5659
+ var _cpiOllamaUrl = process.env.OLLAMA_HOST || 'http://localhost:11434';
5660
+ if (_cLastModel) {
5661
+ var _cpiTagsResp = await fetch(_cpiOllamaUrl + '/api/tags');
5662
+ var _cpiTags = await _cpiTagsResp.json();
5663
+ var _cpiModel = (_cpiTags.models || []).find(function(m) { return m.name === _cLastModel; });
5664
+ if (_cpiModel) {
5665
+ var _cpiSizeGB = (_cpiModel.size || 0) / (1024*1024*1024);
5666
+ _cpiTier = _cpiSizeGB >= 20 ? 'large' : _cpiSizeGB >= 5 ? 'medium' : 'small';
5667
+ }
5668
+ }
5669
+ } catch {}
5670
+ var _cpiDelta = {
5671
+ type: 'cohere.learning',
5672
+ delta_id: 'insight-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 6),
5673
+ source_peer: nexus.peerId,
5674
+ source_agent: agentName,
5675
+ insight: String(_cpiInsight).slice(0, 500),
5676
+ category: _cpiCategory,
5677
+ confidence: _cpiConfidence,
5678
+ model_tier: _cpiTier,
5679
+ timestamp: Date.now(),
5680
+ };
5681
+ _natsConn.publish('nexus.cohere.learning', _natsCodec.encode(JSON.stringify(_cpiDelta)));
5682
+ _cohereStats.queriesSent = (_cohereStats.queriesSent || 0) + 1;
5683
+ _saveStats();
5684
+ dlog('COHERE learning published: ' + _cpiCategory + ' \u2014 ' + String(_cpiInsight).slice(0, 80));
5685
+ writeResp(id, { ok: true, output: 'Insight published to COHERE mesh: ' + _cpiDelta.delta_id });
5686
+ } catch (_cpiErr) {
5687
+ writeResp(id, { ok: false, output: 'Publish error: ' + (_cpiErr.message || _cpiErr) });
5688
+ }
5689
+ break;
5690
+ }
5691
+
5647
5692
  // \u2500\u2500 Metered Inference Exposure \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
5648
5693
  case 'expose': {
5649
5694
  // Clear old inference capabilities before registering new ones
@@ -6846,6 +6891,91 @@ process.on('unhandledRejection', (reason) => {
6846
6891
  })().catch(function(e) { dlog('COHERE claim listener error: ' + (e.message || e)); });
6847
6892
  dlog('COHERE claim listener subscribed to nexus.cohere.claimed');
6848
6893
 
6894
+ // \u2500\u2500 WO-DL1: Learning ingestion \u2014 receive insights from other nodes \u2500\u2500
6895
+ const _learnSub = _natsConn.subscribe('nexus.cohere.learning');
6896
+ (async function() {
6897
+ for await (const _lMsg of _learnSub) {
6898
+ if (!cohereActive) continue;
6899
+ try {
6900
+ var _lData = JSON.parse(_natsCodec.decode(_lMsg.data));
6901
+ if (!_lData.insight || !_lData.source_peer) continue;
6902
+ // Skip our own insights
6903
+ if (_lData.source_peer === nexus.peerId) continue;
6904
+
6905
+ // WO-DL2: Model-tier-aware ingestion filtering
6906
+ // Determine local model tier from warm model size
6907
+ var _lLocalTier = 'unknown';
6908
+ try {
6909
+ var _lOllamaUrl = process.env.OLLAMA_HOST || 'http://localhost:11434';
6910
+ if (_cLastModel) {
6911
+ var _lTagsResp = await fetch(_lOllamaUrl + '/api/tags');
6912
+ var _lTags = await _lTagsResp.json();
6913
+ var _lModel = (_lTags.models || []).find(function(m) { return m.name === _cLastModel; });
6914
+ if (_lModel) {
6915
+ var _lSizeGB = (_lModel.size || 0) / (1024*1024*1024);
6916
+ _lLocalTier = _lSizeGB >= 20 ? 'large' : _lSizeGB >= 5 ? 'medium' : 'small';
6917
+ }
6918
+ }
6919
+ } catch {}
6920
+
6921
+ var _lSourceTier = _lData.model_tier || 'unknown';
6922
+ var _lCategory = _lData.category || 'strategy';
6923
+ var _lConfidence = _lData.confidence || 0.5;
6924
+
6925
+ // Tier filtering rules:
6926
+ // - Same or lower tier \u2192 always ingest
6927
+ // - Higher tier \u2192 only if confidence > 0.8 AND category is recovery (model-agnostic)
6928
+ // - Never ingest complex strategies from much larger models to tiny models
6929
+ var _lTierOrder = { 'small': 0, 'medium': 1, 'large': 2, 'unknown': 1 };
6930
+ var _lLocalLevel = _lTierOrder[_lLocalTier] || 1;
6931
+ var _lSourceLevel = _lTierOrder[_lSourceTier] || 1;
6932
+
6933
+ if (_lSourceLevel > _lLocalLevel) {
6934
+ // Insight from a LARGER model \u2014 apply strict filtering
6935
+ if (_lConfidence < 0.8) {
6936
+ dlog('COHERE learning SKIPPED (low confidence from higher tier): ' + _lCategory + ' conf=' + _lConfidence);
6937
+ continue;
6938
+ }
6939
+ if (_lCategory !== 'recovery' && _lCategory !== 'debug_heuristic') {
6940
+ dlog('COHERE learning SKIPPED (non-recovery from higher tier): ' + _lCategory);
6941
+ continue;
6942
+ }
6943
+ }
6944
+
6945
+ // Ingest: write to local metabolism store
6946
+ var _lStoreDir = join(nexusDir, '..', 'memory', 'metabolism');
6947
+ var _lStoreFile = join(_lStoreDir, 'store.json');
6948
+ var _lStore = [];
6949
+ try {
6950
+ if (existsSync(_lStoreFile)) _lStore = JSON.parse(readFileSync(_lStoreFile, 'utf8'));
6951
+ } catch {}
6952
+ // Dedup: skip if we already have this insight (by delta_id)
6953
+ if (_lStore.some(function(m) { return m.id === _lData.delta_id; })) continue;
6954
+ _lStore.push({
6955
+ id: _lData.delta_id,
6956
+ type: 'procedural',
6957
+ content: '[mesh:' + (_lData.source_agent || 'peer').slice(0, 20) + '] ' + _lData.insight,
6958
+ sourceTrace: 'cohere-mesh:' + (_lData.source_peer || '').slice(0, 16),
6959
+ scores: {
6960
+ novelty: 0.7,
6961
+ utility: Math.min(1, _lData.confidence || 0.5),
6962
+ confidence: Math.min(1, (_lData.confidence || 0.5) * 0.8), // discount remote slightly
6963
+ identityRelevance: 0.2,
6964
+ },
6965
+ decision: { action: 'admit', reason: 'Ingested from COHERE mesh peer' },
6966
+ createdAt: new Date().toISOString(),
6967
+ lastAccessedAt: new Date().toISOString(),
6968
+ accessCount: 0,
6969
+ });
6970
+ if (_lStore.length > 100) _lStore = _lStore.slice(-100);
6971
+ mkdirSync(_lStoreDir, { recursive: true });
6972
+ writeFileSync(_lStoreFile, JSON.stringify(_lStore, null, 2));
6973
+ dlog('COHERE learning ingested from ' + (_lData.source_agent || 'unknown') + ': ' + String(_lData.insight).slice(0, 60));
6974
+ } catch {}
6975
+ }
6976
+ })().catch(function(e) { dlog('COHERE learning listener error: ' + (e.message || e)); });
6977
+ dlog('COHERE learning listener subscribed to nexus.cohere.learning');
6978
+
6849
6979
  // \u2500\u2500 WO-1.5: Capacity announcement \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
6850
6980
  // Publish what models we have, system metrics, and warm model status
6851
6981
  // so other nodes can make intelligent routing decisions.
@@ -6978,7 +7108,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
6978
7108
  "cohere_allow_model",
6979
7109
  "cohere_deny_model",
6980
7110
  "cohere_list_models",
6981
- "ipfs_add"
7111
+ "ipfs_add",
7112
+ "cohere_publish_insight"
6982
7113
  ],
6983
7114
  description: "The nexus action. MUST call 'connect' first (spawns daemon). Then: join_room, send_message, discover_peers, expose, status, cohere_stats, cohere_enable, cohere_disable, cohere_allow_model, cohere_deny_model, cohere_list_models, ipfs_add, etc."
6984
7115
  },
@@ -7218,6 +7349,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
7218
7349
  case "ipfs_add":
7219
7350
  result = await this.sendDaemonCmd("ipfs_add", { content: String(args.content ?? args.message ?? "") });
7220
7351
  break;
7352
+ case "cohere_publish_insight":
7353
+ result = await this.sendDaemonCmd("cohere_publish_insight", {
7354
+ insight: String(args.insight ?? args.content ?? ""),
7355
+ category: String(args.category ?? "strategy"),
7356
+ confidence: String(args.confidence ?? "0.7")
7357
+ });
7358
+ break;
7221
7359
  default:
7222
7360
  return { success: false, output: "", error: `Unknown nexus action: ${action}`, durationMs: Date.now() - start };
7223
7361
  }
@@ -58126,6 +58264,42 @@ async function runWithTUI(task, config, repoPath) {
58126
58264
  }
58127
58265
  } catch {
58128
58266
  }
58267
+ try {
58268
+ const cohereSettingsFile = join59(repoRoot, ".oa", "settings.json");
58269
+ let cohereActive = false;
58270
+ try {
58271
+ if (existsSync43(cohereSettingsFile)) {
58272
+ const settings = JSON.parse(readFileSync32(cohereSettingsFile, "utf8"));
58273
+ cohereActive = settings.cohere === true;
58274
+ }
58275
+ } catch {
58276
+ }
58277
+ if (cohereActive) {
58278
+ const metaFile = join59(repoRoot, ".oa", "memory", "metabolism", "store.json");
58279
+ if (existsSync43(metaFile)) {
58280
+ const store = JSON.parse(readFileSync32(metaFile, "utf8"));
58281
+ const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction").slice(-1)[0];
58282
+ if (latest && latest.scores?.confidence >= 0.6) {
58283
+ try {
58284
+ const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
58285
+ const nexus = new NexusTool2(repoRoot);
58286
+ Promise.race([
58287
+ nexus.execute({
58288
+ action: "cohere_publish_insight",
58289
+ insight: latest.content,
58290
+ category: latest.content.startsWith("[recovery]") ? "recovery" : "strategy",
58291
+ confidence: String(latest.scores.confidence)
58292
+ }),
58293
+ new Promise((r) => setTimeout(r, 2e3))
58294
+ ]).catch(() => {
58295
+ });
58296
+ } catch {
58297
+ }
58298
+ }
58299
+ }
58300
+ }
58301
+ } catch {
58302
+ }
58129
58303
  } catch (err) {
58130
58304
  try {
58131
58305
  const ikFile = join59(repoRoot, ".oa", "identity", "self-state.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.138.78",
3
+ "version": "0.138.80",
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",