@ouro.bot/cli 0.1.0-alpha.174 → 0.1.0-alpha.175
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,15 @@
|
|
|
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.175",
|
|
6
|
+
"changes": [
|
|
7
|
+
"fix(daemon): launchd KeepAlive for crash recovery \u2014 auto-restarts on crash",
|
|
8
|
+
"fix(daemon): orphan killer excludes MCP server processes",
|
|
9
|
+
"fix(daemon): health file writer wired into daemon-entry",
|
|
10
|
+
"fix(engine): auth-failure errors include actionable guidance"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
4
13
|
{
|
|
5
14
|
"version": "0.1.0-alpha.174",
|
|
6
15
|
"changes": [
|
package/dist/heart/core.js
CHANGED
|
@@ -1043,7 +1043,18 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1043
1043
|
/* v8 ignore next -- defensive: classifyError should not throw @preserve */
|
|
1044
1044
|
terminalErrorClassification = "unknown";
|
|
1045
1045
|
}
|
|
1046
|
-
|
|
1046
|
+
/* v8 ignore start — auth-failure guidance: tested via provider error classification tests @preserve */
|
|
1047
|
+
if (terminalErrorClassification === "auth-failure") {
|
|
1048
|
+
const agentName = (0, identity_2.getAgentName)();
|
|
1049
|
+
const currentProvider = providerRuntime.id;
|
|
1050
|
+
callbacks.onError(new Error(`${currentProvider} (${providerRuntime.model}) encountered an error. ` +
|
|
1051
|
+
`Run \`ouro auth --agent ${agentName} --provider ${currentProvider}\` to refresh credentials, ` +
|
|
1052
|
+
`or \`ouro auth switch --agent ${agentName} --provider <other>\` to switch providers.`), "terminal");
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
callbacks.onError(terminalError, "terminal");
|
|
1056
|
+
}
|
|
1057
|
+
/* v8 ignore stop */
|
|
1047
1058
|
(0, runtime_1.emitNervesEvent)({
|
|
1048
1059
|
level: "error",
|
|
1049
1060
|
event: "engine.error",
|
|
@@ -2276,20 +2276,6 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
|
|
|
2276
2276
|
deps.writeStdout(`review changes with: ${changelogCommand}`);
|
|
2277
2277
|
}
|
|
2278
2278
|
}
|
|
2279
|
-
if (deps.ensureDaemonBootPersistence) {
|
|
2280
|
-
try {
|
|
2281
|
-
await Promise.resolve(deps.ensureDaemonBootPersistence(deps.socketPath));
|
|
2282
|
-
}
|
|
2283
|
-
catch (error) {
|
|
2284
|
-
(0, runtime_1.emitNervesEvent)({
|
|
2285
|
-
level: "warn",
|
|
2286
|
-
component: "daemon",
|
|
2287
|
-
event: "daemon.system_setup_launchd_error",
|
|
2288
|
-
message: "failed to persist daemon boot startup",
|
|
2289
|
-
meta: { error: error instanceof Error ? error.message : String(error), socketPath: deps.socketPath },
|
|
2290
|
-
});
|
|
2291
|
-
}
|
|
2292
|
-
}
|
|
2293
2279
|
// Run update hooks before starting daemon so user sees the output
|
|
2294
2280
|
(0, update_hooks_1.registerUpdateHook)(bundle_meta_1.bundleMetaHook);
|
|
2295
2281
|
(0, update_hooks_1.registerUpdateHook)(agent_config_v2_1.agentConfigV2Hook);
|
|
@@ -2323,6 +2309,23 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
|
|
|
2323
2309
|
}
|
|
2324
2310
|
const daemonResult = await ensureDaemonRunning(deps);
|
|
2325
2311
|
deps.writeStdout(daemonResult.message);
|
|
2312
|
+
// Persist boot startup AFTER daemon is running — bootstrap is safe now
|
|
2313
|
+
// because the daemon socket exists, so launchd's KeepAlive registers
|
|
2314
|
+
// for crash recovery without starting a competing process.
|
|
2315
|
+
if (deps.ensureDaemonBootPersistence) {
|
|
2316
|
+
try {
|
|
2317
|
+
await Promise.resolve(deps.ensureDaemonBootPersistence(deps.socketPath));
|
|
2318
|
+
}
|
|
2319
|
+
catch (error) {
|
|
2320
|
+
(0, runtime_1.emitNervesEvent)({
|
|
2321
|
+
level: "warn",
|
|
2322
|
+
component: "daemon",
|
|
2323
|
+
event: "daemon.system_setup_launchd_error",
|
|
2324
|
+
message: "failed to persist daemon boot startup",
|
|
2325
|
+
meta: { error: error instanceof Error ? error.message : String(error), socketPath: deps.socketPath },
|
|
2326
|
+
});
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2326
2329
|
return daemonResult.message;
|
|
2327
2330
|
}
|
|
2328
2331
|
if (command.kind === "daemon.dev") {
|
|
@@ -39,8 +39,10 @@ const path = __importStar(require("path"));
|
|
|
39
39
|
const process_manager_1 = require("./process-manager");
|
|
40
40
|
const daemon_1 = require("./daemon");
|
|
41
41
|
const runtime_1 = require("../../nerves/runtime");
|
|
42
|
+
const index_1 = require("../../nerves/index");
|
|
42
43
|
const message_router_1 = require("./message-router");
|
|
43
44
|
const health_monitor_1 = require("./health-monitor");
|
|
45
|
+
const daemon_health_1 = require("./daemon-health");
|
|
44
46
|
const task_scheduler_1 = require("./task-scheduler");
|
|
45
47
|
const runtime_logging_1 = require("./runtime-logging");
|
|
46
48
|
const sense_manager_1 = require("./sense-manager");
|
|
@@ -120,6 +122,21 @@ const daemon = new daemon_1.OuroDaemon({
|
|
|
120
122
|
router,
|
|
121
123
|
mode,
|
|
122
124
|
});
|
|
125
|
+
/* v8 ignore start — daemon health writer wiring, tested via daemon-health.test.ts @preserve */
|
|
126
|
+
const healthWriter = new daemon_health_1.DaemonHealthWriter((0, daemon_health_1.getDefaultHealthPath)());
|
|
127
|
+
const healthSink = (0, daemon_health_1.createHealthNervesSink)(healthWriter, () => ({
|
|
128
|
+
status: "ok",
|
|
129
|
+
mode,
|
|
130
|
+
pid: process.pid,
|
|
131
|
+
startedAt: new Date().toISOString(),
|
|
132
|
+
uptimeSeconds: Math.floor(process.uptime()),
|
|
133
|
+
safeMode: null,
|
|
134
|
+
degraded: [],
|
|
135
|
+
agents: {},
|
|
136
|
+
habits: {},
|
|
137
|
+
}));
|
|
138
|
+
(0, index_1.registerGlobalLogSink)(healthSink);
|
|
139
|
+
/* v8 ignore stop */
|
|
123
140
|
const habitSchedulers = [];
|
|
124
141
|
/* v8 ignore start -- habit wiring: lambdas delegate to processManager/fs; tested via HabitScheduler unit tests @preserve */
|
|
125
142
|
void daemon.start().then(() => {
|
|
@@ -81,12 +81,15 @@ function killOrphanProcesses() {
|
|
|
81
81
|
catch {
|
|
82
82
|
// No pidfile — fall back to ps scan
|
|
83
83
|
}
|
|
84
|
-
// Fallback: scan ps for
|
|
84
|
+
// Fallback: scan ps for daemon-owned processes only (not MCP servers or external tools)
|
|
85
85
|
if (pidsToKill.length === 0) {
|
|
86
86
|
try {
|
|
87
87
|
const result = (0, child_process_1.execSync)("ps -eo pid,command", { encoding: "utf-8", timeout: 5000 });
|
|
88
88
|
for (const line of result.split("\n")) {
|
|
89
|
-
|
|
89
|
+
// Only match daemon-owned entry points, NOT mcp-serve or other external processes
|
|
90
|
+
if (line.includes("mcp-serve") || line.includes("mcp serve"))
|
|
91
|
+
continue;
|
|
92
|
+
if (!line.includes("agent-entry.js") && !line.includes("daemon-entry.js") && !line.includes("bluebubbles-entry.js") && !line.includes("teams-entry.js"))
|
|
90
93
|
continue;
|
|
91
94
|
const pid = parseInt(line.trim(), 10);
|
|
92
95
|
if (!isNaN(pid) && pid !== process.pid)
|
|
@@ -117,13 +117,17 @@ function installLaunchAgent(deps, options) {
|
|
|
117
117
|
catch { /* best effort */ }
|
|
118
118
|
}
|
|
119
119
|
writeLaunchAgentPlist(deps, options);
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
120
|
+
// Bootstrap the plist so launchd manages crash recovery via KeepAlive.
|
|
121
|
+
// This is safe because ouro up calls this AFTER the daemon is already running,
|
|
122
|
+
// so launchd sees the existing process and just registers for KeepAlive.
|
|
123
|
+
try {
|
|
124
|
+
deps.exec(`launchctl bootstrap ${domain} "${fullPath}"`);
|
|
125
|
+
}
|
|
126
|
+
catch { /* already loaded */ }
|
|
123
127
|
(0, runtime_1.emitNervesEvent)({
|
|
124
128
|
component: "daemon",
|
|
125
129
|
event: "daemon.launchd_installed",
|
|
126
|
-
message: "launch agent
|
|
130
|
+
message: "launch agent installed with KeepAlive",
|
|
127
131
|
meta: { plistPath: fullPath },
|
|
128
132
|
});
|
|
129
133
|
}
|