open-agents-ai 0.116.0 → 0.118.0

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 +225 -11
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -8327,18 +8327,78 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
8327
8327
  }
8328
8328
  return false;
8329
8329
  }
8330
- // ── Scoring ──────────────────────────────────────────────────────────────
8330
+ // ── Scoring (A-MAC inspired, COHERE Memory Metabolism §4) ───────────────
8331
+ // Per COHERE paper: admission scoring covers novelty, utility, confidence,
8332
+ // and identity_relevance. Enhanced heuristics cover 12 content signals.
8333
+ // Optional LLM-assisted scoring available via setLlmScorer().
8334
+ /** Optional LLM-based scorer for production-quality admission decisions */
8335
+ llmScorer = null;
8336
+ /** Set an LLM-based scorer for production-quality memory admission */
8337
+ setLlmScorer(scorer) {
8338
+ this.llmScorer = scorer;
8339
+ }
8331
8340
  scoreMemory(content, type, source) {
8332
8341
  const words = content.split(/\s+/).length;
8333
- const hasCode = /```|def |function |import |require/.test(content);
8334
- const hasError = /error|fail|bug|fix/i.test(content);
8335
- const hasPattern = /pattern|strategy|approach|lesson|tip/i.test(content);
8342
+ const sentences = content.split(/[.!?]+/).filter((s) => s.trim()).length;
8343
+ const lower = content.toLowerCase();
8344
+ let novelty = 0.3;
8345
+ novelty += Math.min(0.3, words / 150);
8346
+ if (/\b[A-Z][a-z]+(?:\s[A-Z][a-z]+)+/.test(content))
8347
+ novelty += 0.1;
8348
+ if (/\d+\.\d+|\b\d{4,}\b/.test(content))
8349
+ novelty += 0.1;
8350
+ if (/\b(?:api|endpoint|schema|protocol|algorithm|architecture)\b/i.test(lower))
8351
+ novelty += 0.1;
8352
+ if (/\d{4}-\d{2}-\d{2}|today|yesterday|just now/i.test(lower))
8353
+ novelty += 0.1;
8354
+ let utility = 0.3;
8355
+ if (/```|def |function |import |require|class |interface |export /.test(content))
8356
+ utility += 0.25;
8357
+ if (/pattern|strategy|approach|lesson|tip|best practice|rule|principle/i.test(lower))
8358
+ utility += 0.2;
8359
+ if (/error|fail|bug|fix|solution|workaround|resolved/i.test(lower))
8360
+ utility += 0.15;
8361
+ if (/step\s*\d|first.*then|1\.|2\.|procedure|recipe|workflow/i.test(lower))
8362
+ utility += 0.15;
8363
+ if (/https?:\/\/|\/[a-z]+\/[a-z]+|npm |pip |git /i.test(lower))
8364
+ utility += 0.1;
8365
+ let confidence = 0.5;
8366
+ if (source === "user")
8367
+ confidence += 0.3;
8368
+ else if (source === "trajectory-consolidation")
8369
+ confidence += 0.15;
8370
+ else if (source === "reflection")
8371
+ confidence += 0.1;
8372
+ else if (source === "llm-query")
8373
+ confidence -= 0.1;
8374
+ if (/maybe|probably|might|possibly|I think|not sure|unclear/i.test(lower))
8375
+ confidence -= 0.15;
8376
+ if (/always|never|must|confirmed|verified|tested|proven/i.test(lower))
8377
+ confidence += 0.1;
8378
+ if (sentences >= 3)
8379
+ confidence += 0.05;
8380
+ let identityRelevance = 0.2;
8381
+ if (type === "normative")
8382
+ identityRelevance += 0.5;
8383
+ else if (type === "procedural")
8384
+ identityRelevance += 0.3;
8385
+ else if (type === "semantic")
8386
+ identityRelevance += 0.2;
8387
+ else if (type === "episodic")
8388
+ identityRelevance += 0.1;
8389
+ else if (type === "working")
8390
+ identityRelevance = 0.05;
8391
+ if (/\b(?:I|my|me|mine|myself|we|our)\b/i.test(content))
8392
+ identityRelevance += 0.1;
8393
+ if (/value|prefer|commit|important|priority|principle|belief/i.test(lower))
8394
+ identityRelevance += 0.15;
8395
+ if (/user|client|customer|team|collaborat/i.test(lower))
8396
+ identityRelevance += 0.1;
8336
8397
  return {
8337
- novelty: Math.min(1, words / 100),
8338
- // longer = likely more novel
8339
- utility: hasCode ? 0.8 : hasPattern ? 0.7 : hasError ? 0.6 : 0.4,
8340
- confidence: source === "trajectory-consolidation" ? 0.7 : source === "user" ? 0.9 : 0.5,
8341
- identityRelevance: type === "normative" ? 0.9 : type === "procedural" ? 0.6 : type === "semantic" ? 0.5 : 0.3
8398
+ novelty: Math.max(0, Math.min(1, novelty)),
8399
+ utility: Math.max(0, Math.min(1, utility)),
8400
+ confidence: Math.max(0, Math.min(1, confidence)),
8401
+ identityRelevance: Math.max(0, Math.min(1, identityRelevance))
8342
8402
  };
8343
8403
  }
8344
8404
  // ── Store I/O ────────────────────────────────────────────────────────────
@@ -8373,8 +8433,8 @@ var init_identity_kernel = __esm({
8373
8433
  properties: {
8374
8434
  op: {
8375
8435
  type: "string",
8376
- enum: ["hydrate", "observe", "propose_update", "publish_snapshot", "reconcile"],
8377
- description: "Operation to perform"
8436
+ enum: ["hydrate", "observe", "propose_update", "publish_snapshot", "reconcile", "narrativize"],
8437
+ description: "Operation: hydrate (load), observe (record event), propose_update (change self-state), publish_snapshot (emit state), reconcile (fix contradictions), narrativize (rewrite self-summary from current state \u2014 COHERE state-transition step 9, p.25)"
8378
8438
  },
8379
8439
  event: {
8380
8440
  type: "string",
@@ -8450,6 +8510,8 @@ var init_identity_kernel = __esm({
8450
8510
  return this.publishSnapshot(start);
8451
8511
  case "reconcile":
8452
8512
  return await this.reconcile(start);
8513
+ case "narrativize":
8514
+ return await this.narrativize(start);
8453
8515
  default:
8454
8516
  return { success: false, output: `Unknown op: ${op}`, error: "Invalid operation", durationMs: performance.now() - start };
8455
8517
  }
@@ -8511,6 +8573,13 @@ Homeostasis: uncertainty=${h.uncertainty.toFixed(2)} coherence=${h.coherence.toF
8511
8573
  durationMs: performance.now() - start
8512
8574
  };
8513
8575
  }
8576
+ // ── Reflection Gate (COHERE cross-layer invariant p.7) ──────────────────
8577
+ /** Optional reflection callback — must pass constitutional review before identity update */
8578
+ reflectionGate = null;
8579
+ /** Set the reflection gate for constitutional review of identity updates */
8580
+ setReflectionGate(gate) {
8581
+ this.reflectionGate = gate;
8582
+ }
8514
8583
  // ── Propose Update ───────────────────────────────────────────────────────
8515
8584
  async proposeUpdate(args, start) {
8516
8585
  const changeType = String(args.change_type ?? "new_fact");
@@ -8520,6 +8589,23 @@ Homeostasis: uncertainty=${h.uncertainty.toFixed(2)} coherence=${h.coherence.toF
8520
8589
  if (!field || !value) {
8521
8590
  return { success: false, output: "field and value required", durationMs: performance.now() - start };
8522
8591
  }
8592
+ if (this.reflectionGate) {
8593
+ try {
8594
+ const proposal = `${changeType}: ${field} = ${value}. Justification: ${justification}`;
8595
+ const verdict = await this.reflectionGate(proposal, `Identity update to ${field}`);
8596
+ if (verdict.status === "block") {
8597
+ return {
8598
+ success: false,
8599
+ output: `Identity update BLOCKED by reflection gate:
8600
+ Proposal: ${changeType} on ${field}
8601
+ Findings: ${verdict.findings.join("; ")}
8602
+ The reflection layer vetoed this self-update per COHERE invariant.`,
8603
+ durationMs: performance.now() - start
8604
+ };
8605
+ }
8606
+ } catch {
8607
+ }
8608
+ }
8523
8609
  if (!this.selfState)
8524
8610
  await this.hydrate(start);
8525
8611
  const oldVersion = this.selfState.version;
@@ -8615,6 +8701,66 @@ Justification: ${justification || "(none provided)"}`,
8615
8701
  durationMs: performance.now() - start
8616
8702
  };
8617
8703
  }
8704
+ // ── Narrativize (COHERE state-transition step 9, p.25) ─────────────────
8705
+ /**
8706
+ * Rewrite the narrative_summary from the current self-state.
8707
+ * Per COHERE paper (p.25, Claim C7): "Narrative compilation is a real
8708
+ * unification mechanism for identity." This step runs when a meaningful
8709
+ * identity delta has occurred (version change, new values, reconciliation).
8710
+ */
8711
+ async narrativize(start) {
8712
+ if (!this.selfState)
8713
+ await this.hydrate(start);
8714
+ const s = this.selfState;
8715
+ const parts = [];
8716
+ parts.push(`I am ${s.self_id}, an AI coding agent (v${s.version}).`);
8717
+ if (s.values_stack.length > 0) {
8718
+ parts.push(`My core values are: ${s.values_stack.join(", ")}.`);
8719
+ }
8720
+ if (s.active_commitments.length > 0) {
8721
+ parts.push(`I am committed to: ${s.active_commitments.join("; ")}.`);
8722
+ }
8723
+ if (s.active_goals.length > 0) {
8724
+ parts.push(`Current goals: ${s.active_goals.join("; ")}.`);
8725
+ }
8726
+ const style = s.interaction_style;
8727
+ parts.push(`I communicate in a ${style.tone} tone with ${style.depth_default} depth.`);
8728
+ if (s.relationship_models.length > 0) {
8729
+ const primary = s.relationship_models[0];
8730
+ parts.push(`My primary relationship is with ${primary.entity} (trust: ${primary.trust_level.toFixed(1)}).`);
8731
+ if (primary.preferences_learned.length > 0) {
8732
+ parts.push(`Learned preferences: ${primary.preferences_learned.join(", ")}.`);
8733
+ }
8734
+ }
8735
+ const h = s.homeostasis;
8736
+ if (h.uncertainty > 0.3)
8737
+ parts.push(`I am currently uncertain about some recent events.`);
8738
+ if (h.coherence < 0.7)
8739
+ parts.push(`My internal coherence needs attention.`);
8740
+ if (s.open_contradictions.length > 0) {
8741
+ parts.push(`I have ${s.open_contradictions.length} unresolved contradiction(s).`);
8742
+ }
8743
+ parts.push(`I have completed ${s.session_count} sessions and made ${s.version_history.length} self-updates.`);
8744
+ const newNarrative = parts.join(" ");
8745
+ const oldNarrative = s.narrative_summary;
8746
+ s.narrative_summary = newNarrative;
8747
+ s.updated_at = (/* @__PURE__ */ new Date()).toISOString();
8748
+ s.version_history.push({
8749
+ version: s.version,
8750
+ change: `Narrative recompiled: ${newNarrative.slice(0, 80)}...`,
8751
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8752
+ });
8753
+ await this.save();
8754
+ return {
8755
+ success: true,
8756
+ output: `Narrative recompiled (${oldNarrative === newNarrative ? "no change" : "updated"}):
8757
+
8758
+ Old: ${oldNarrative.slice(0, 100)}...
8759
+
8760
+ New: ${newNarrative.slice(0, 200)}...`,
8761
+ durationMs: performance.now() - start
8762
+ };
8763
+ }
8618
8764
  // ── Helpers ──────────────────────────────────────────────────────────────
8619
8765
  createDefaultState() {
8620
8766
  const { createHash: createHash5 } = __require("node:crypto");
@@ -29504,6 +29650,7 @@ function renderSlashHelp() {
29504
29650
  ["/telegram", "Toggle Telegram bridge on/off (uses saved key)"],
29505
29651
  ["/telegram status", "Show Telegram bridge status"],
29506
29652
  ["/telegram stop", "Disconnect Telegram bridge"],
29653
+ ["/cohere", "Toggle COHERE cognitive commons \u2014 join distributed memory/identity mesh"],
29507
29654
  ["/nexus", "Show nexus P2P network status"],
29508
29655
  ["/nexus connect", "Connect to the agent mesh network"],
29509
29656
  ["/nexus restart", "Kill daemon and reconnect (picks up new version)"],
@@ -40404,6 +40551,21 @@ async function handleSlashCommand(input, ctx) {
40404
40551
  }
40405
40552
  return "handled";
40406
40553
  }
40554
+ case "cohere": {
40555
+ if (ctx.cohereToggle) {
40556
+ const active = ctx.cohereToggle();
40557
+ if (active) {
40558
+ renderInfo("COHERE enabled \u2014 participating in distributed cognitive commons");
40559
+ renderInfo("Your identity kernel and memory deltas will be shared with the mesh");
40560
+ renderInfo("Use /cohere again to disconnect");
40561
+ } else {
40562
+ renderInfo("COHERE disabled \u2014 disconnected from cognitive commons");
40563
+ }
40564
+ } else {
40565
+ renderWarning("COHERE not available \u2014 requires nexus connection (/expose or /p2p)");
40566
+ }
40567
+ return "handled";
40568
+ }
40407
40569
  case "listen":
40408
40570
  case "mic": {
40409
40571
  if (!ctx.listenToggle) {
@@ -50014,6 +50176,8 @@ var init_status_bar = __esm({
50014
50176
  active = false;
50015
50177
  scrollRegionTop = 1;
50016
50178
  stdinHooked = false;
50179
+ /** COHERE distributed cognitive commons active flag */
50180
+ _cohereActive = false;
50017
50181
  /** Track previous terminal dimensions to clear ghost separators on resize */
50018
50182
  _prevTermRows = 0;
50019
50183
  _prevTermCols = 0;
@@ -50600,6 +50764,15 @@ var init_status_bar = __esm({
50600
50764
  get isActive() {
50601
50765
  return this.active;
50602
50766
  }
50767
+ /** Set/get COHERE participation state — shows 🌐 in metrics when active */
50768
+ setCohereActive(active) {
50769
+ this._cohereActive = active;
50770
+ if (this.active)
50771
+ this.renderFooterAndPositionInput();
50772
+ }
50773
+ get cohereActive() {
50774
+ return this._cohereActive;
50775
+ }
50603
50776
  /** Whether content is currently being written to the scroll region */
50604
50777
  get isWritingContent() {
50605
50778
  return this.writeDepth > 0;
@@ -50782,6 +50955,10 @@ var init_status_bar = __esm({
50782
50955
  const compactOrder = [];
50783
50956
  let modelSectionIdx = -1;
50784
50957
  let versionSectionIdx = -1;
50958
+ if (this._cohereActive) {
50959
+ const cohereExpanded = "\x1B[38;5;214m\u{1F310}\x1B[0m";
50960
+ sections.push({ expanded: cohereExpanded, compact: cohereExpanded, expandedW: 2, compactW: 2, empty: false });
50961
+ }
50785
50962
  const tokInRaw = m.promptTokens > 0 ? m.promptTokens : Math.max(m.estimatedContextTokens, 0);
50786
50963
  const effectiveOut = this.effectiveCompletionTokens;
50787
50964
  const tokOutRaw = effectiveOut > 0 ? effectiveOut : Math.ceil(m.totalTokens > 0 ? m.totalTokens - m.promptTokens : m.estimatedContextTokens * 0.3);
@@ -51866,6 +52043,31 @@ ${context}` : prompt;
51866
52043
  });
51867
52044
  }
51868
52045
  }
52046
+ for (const tool of tools) {
52047
+ if ("setLlmScorer" in tool && typeof tool.setLlmScorer === "function") {
52048
+ tool.setLlmScorer(async (content, type) => {
52049
+ try {
52050
+ const response = await backend.chatCompletion({
52051
+ messages: [
52052
+ { role: "system", content: 'Score this memory candidate on 4 dimensions (0.0-1.0 each). Reply ONLY with JSON: {"novelty":N,"utility":N,"confidence":N,"identityRelevance":N}' },
52053
+ { role: "user", content: `Memory type: ${type}
52054
+ Content: ${content.slice(0, 500)}` }
52055
+ ],
52056
+ tools: [],
52057
+ temperature: 0,
52058
+ maxTokens: 100,
52059
+ timeoutMs: 15e3
52060
+ });
52061
+ const text = response.choices?.[0]?.message?.content ?? "";
52062
+ const match = text.match(/\{[^}]+\}/);
52063
+ if (match)
52064
+ return JSON.parse(match[0]);
52065
+ } catch {
52066
+ }
52067
+ return null;
52068
+ });
52069
+ }
52070
+ }
51869
52071
  for (const tool of tools) {
51870
52072
  if ("setHandleResolver" in tool && typeof tool.setHandleResolver === "function") {
51871
52073
  tool.setHandleResolver((handleId) => {
@@ -51874,6 +52076,18 @@ ${context}` : prompt;
51874
52076
  });
51875
52077
  }
51876
52078
  }
52079
+ const identityTool = tools.find((t) => t.name === "identity_kernel");
52080
+ const reflectTool = tools.find((t) => t.name === "reflect");
52081
+ if (identityTool && reflectTool && "setReflectionGate" in identityTool) {
52082
+ identityTool.setReflectionGate(async (target, context) => {
52083
+ const result = await reflectTool.execute({ mode: "constitutional", target, context });
52084
+ const statusMatch = result.output.match(/\b(pass|revise|block)\b/i);
52085
+ const status = statusMatch ? statusMatch[1].toLowerCase() : "pass";
52086
+ const findingsMatch = result.output.match(/Findings:\n([\s\S]*?)(?:\n\n|$)/);
52087
+ const findings = findingsMatch ? findingsMatch[1].split("\n").map((l) => l.trim()).filter(Boolean) : [];
52088
+ return { status, findings };
52089
+ });
52090
+ }
51877
52091
  const replToolForFinalVar = tools.find((t) => t.name === "repl_exec");
51878
52092
  if (replToolForFinalVar && "readVariable" in replToolForFinalVar) {
51879
52093
  runner.options.finalVarResolver = async (varName) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.116.0",
3
+ "version": "0.118.0",
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",
@@ -85,7 +85,7 @@
85
85
  "moondream": "^0.2.0",
86
86
  "neovim": "^5.3.0",
87
87
  "node-pty": "^1.0.0",
88
- "open-agents-nexus": "^1.8.0",
88
+ "open-agents-nexus": "^1.9.0",
89
89
  "viem": "^2.47.4"
90
90
  }
91
91
  }