@ouro.bot/cli 0.1.0-alpha.119 → 0.1.0-alpha.120

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/changelog.json CHANGED
@@ -1,6 +1,13 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.120",
6
+ "changes": [
7
+ "Daemon startup now kills ALL orphaned ouro processes (daemons AND agents) from previous instances \u2014 fixes stale-version processes handling requests after every update.",
8
+ "Failover error messages no longer contain raw JSON API response bodies. Error messages are sanitized at the source and the failover summary uses clean classification labels only."
9
+ ]
10
+ },
4
11
  {
5
12
  "version": "0.1.0-alpha.119",
6
13
  "changes": [
@@ -34,7 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.OuroDaemon = void 0;
37
- exports.killOrphanAgentProcesses = killOrphanAgentProcesses;
37
+ exports.killOrphanProcesses = killOrphanProcesses;
38
38
  const fs = __importStar(require("fs"));
39
39
  const net = __importStar(require("net"));
40
40
  const path = __importStar(require("path"));
@@ -52,18 +52,21 @@ const pending_1 = require("../../mind/pending");
52
52
  const channel_1 = require("../../mind/friends/channel");
53
53
  const mcp_manager_1 = require("../../repertoire/mcp-manager");
54
54
  /**
55
- * Kill orphaned agent-entry.js processes from previous daemon instances.
56
- * The process manager only tracks agents it spawns in-memory agents from
57
- * a previous daemon are invisible and keep handling requests on old code.
55
+ * Kill ALL orphaned ouro processes from previous daemon instances.
56
+ * On each `ouro up`, old daemon AND agent processes persist because:
57
+ * - Daemons are spawned detached and never killed on restart
58
+ * - Each old daemon keeps respawning agents from its own (stale) code
59
+ * This scans for both daemon-entry.js and agent-entry.js processes
60
+ * and kills everything except the current process.
58
61
  */
59
- /* v8 ignore start -- orphan cleanup: uses ps/kill which can't be unit-tested @preserve */
60
- function killOrphanAgentProcesses() {
62
+ /* v8 ignore start -- orphan cleanup: uses ps/kill, tested via deployment @preserve */
63
+ function killOrphanProcesses() {
61
64
  try {
62
65
  const myPid = process.pid;
63
66
  const result = (0, child_process_1.execSync)("ps -eo pid,command", { encoding: "utf-8", timeout: 5000 });
64
67
  const pidsToKill = [];
65
68
  for (const line of result.split("\n")) {
66
- if (!line.includes("agent-entry.js"))
69
+ if (!line.includes("agent-entry.js") && !line.includes("daemon-entry.js"))
67
70
  continue;
68
71
  const trimmed = line.trim();
69
72
  const pid = parseInt(trimmed, 10);
@@ -81,7 +84,7 @@ function killOrphanAgentProcesses() {
81
84
  (0, runtime_1.emitNervesEvent)({
82
85
  component: "daemon",
83
86
  event: "daemon.orphan_cleanup",
84
- message: `killed ${pidsToKill.length} orphaned agent processes`,
87
+ message: `killed ${pidsToKill.length} orphaned ouro processes`,
85
88
  meta: { pids: pidsToKill },
86
89
  });
87
90
  }
@@ -91,7 +94,7 @@ function killOrphanAgentProcesses() {
91
94
  level: "warn",
92
95
  component: "daemon",
93
96
  event: "daemon.orphan_cleanup_error",
94
- message: "failed to clean up orphaned agent processes",
97
+ message: "failed to clean up orphaned ouro processes",
95
98
  meta: { error: error instanceof Error ? error.message : String(error) },
96
99
  });
97
100
  }
@@ -204,7 +207,7 @@ class OuroDaemon {
204
207
  // Pre-initialize MCP connections so they're ready for the first command (non-blocking)
205
208
  /* v8 ignore next -- catch callback: getSharedMcpManager logs errors internally @preserve */
206
209
  (0, mcp_manager_1.getSharedMcpManager)().catch(() => { });
207
- killOrphanAgentProcesses();
210
+ killOrphanProcesses();
208
211
  await this.processManager.startAutoStartAgents();
209
212
  await this.senseManager?.startAutoStartSenses();
210
213
  this.scheduler.start?.();
@@ -19,12 +19,10 @@ const CLASSIFICATION_LABELS = {
19
19
  "network-error": "is unreachable (network error)",
20
20
  "unknown": "encountered an error",
21
21
  };
22
- function buildFailoverContext(errorMessage, classification, currentProvider, currentModel, agentName, inventory, providerModels) {
22
+ function buildFailoverContext(_errorMessage, classification, currentProvider, currentModel, agentName, inventory, providerModels) {
23
23
  const label = CLASSIFICATION_LABELS[classification];
24
24
  const providerWithModel = currentModel ? `${currentProvider} (${currentModel})` : currentProvider;
25
- const errorSummary = errorMessage
26
- ? `${providerWithModel} ${label} (${errorMessage})`
27
- : `${providerWithModel} ${label}`;
25
+ const errorSummary = `${providerWithModel} ${label}`;
28
26
  const workingProviders = [];
29
27
  const unconfiguredProviders = [];
30
28
  const failingProviders = [];
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitizeErrorMessage = sanitizeErrorMessage;
3
4
  exports.pingProvider = pingProvider;
4
5
  exports.runHealthInventory = runHealthInventory;
5
6
  const anthropic_1 = require("./providers/anthropic");
@@ -10,6 +11,28 @@ const github_copilot_1 = require("./providers/github-copilot");
10
11
  const auth_flow_1 = require("./daemon/auth-flow");
11
12
  const runtime_1 = require("../nerves/runtime");
12
13
  const PING_TIMEOUT_MS = 10_000;
14
+ /**
15
+ * Strip raw JSON API response bodies from error messages.
16
+ * SDK errors often include the full response body: "400 {"type":"error","error":...}".
17
+ * Extract just the HTTP status prefix or a short summary.
18
+ */
19
+ function sanitizeErrorMessage(message) {
20
+ // Match "NNN {json...}" pattern — keep the status code, drop the JSON
21
+ const match = message.match(/^(\d{3})\s*\{/);
22
+ if (match) {
23
+ // Try to extract the inner message from the JSON
24
+ try {
25
+ const json = JSON.parse(message.slice(match[1].length).trim());
26
+ const inner = json?.error?.message;
27
+ if (typeof inner === "string" && inner && inner !== "Error") {
28
+ return `${match[1]} ${inner}`;
29
+ }
30
+ }
31
+ catch { /* not valid JSON, fall through */ }
32
+ return `HTTP ${match[1]}`;
33
+ }
34
+ return message;
35
+ }
13
36
  function hasEmptyCredentials(provider, config) {
14
37
  switch (provider) {
15
38
  case "anthropic":
@@ -106,7 +129,7 @@ async function pingProvider(provider, config) {
106
129
  message: `provider ping failed: ${provider}`,
107
130
  meta: { provider, classification, error: err.message },
108
131
  });
109
- return { ok: false, classification, message: err.message };
132
+ return { ok: false, classification, message: sanitizeErrorMessage(err.message) };
110
133
  }
111
134
  }
112
135
  const PINGABLE_PROVIDERS = ["anthropic", "openai-codex", "azure", "minimax", "github-copilot"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.119",
3
+ "version": "0.1.0-alpha.120",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",