@ouro.bot/cli 0.1.0-alpha.313 → 0.1.0-alpha.314
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 +6 -0
- package/dist/heart/daemon/cli-exec.js +26 -0
- package/dist/heart/daemon/startup-tui.js +19 -13
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
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.314",
|
|
6
|
+
"changes": [
|
|
7
|
+
"fix(daemon): remove 60s startup TUI timeout and show progress while socket is unavailable. `pollDaemonStartup()` now waits indefinitely until all agents are stable or failed, instead of timing out after 60s and falsely reporting degraded status. Added 'waiting for daemon' spinner with elapsed time and latest daemon log event while the socket is not yet available."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "0.1.0-alpha.313",
|
|
6
12
|
"changes": [
|
|
@@ -123,6 +123,32 @@ async function ensureDaemonRunning(deps) {
|
|
|
123
123
|
now: () => Date.now(),
|
|
124
124
|
/* v8 ignore next -- thin wrapper: real setTimeout injected for testability @preserve */
|
|
125
125
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
126
|
+
/* v8 ignore start -- daemon log tail: reads real filesystem, tested via deployment @preserve */
|
|
127
|
+
readLatestDaemonEvent: () => {
|
|
128
|
+
try {
|
|
129
|
+
const agents = fs.readdirSync((0, identity_1.getAgentBundlesRoot)()).filter((d) => d.endsWith(".ouro"));
|
|
130
|
+
for (const agent of agents) {
|
|
131
|
+
const logPath = path.join((0, identity_1.getAgentBundlesRoot)(), agent, "state", "daemon", "logs", "daemon.ndjson");
|
|
132
|
+
if (!fs.existsSync(logPath))
|
|
133
|
+
continue;
|
|
134
|
+
const buf = Buffer.alloc(2048);
|
|
135
|
+
const fd = fs.openSync(logPath, "r");
|
|
136
|
+
const stat = fs.fstatSync(fd);
|
|
137
|
+
const readFrom = Math.max(0, stat.size - 2048);
|
|
138
|
+
fs.readSync(fd, buf, 0, 2048, readFrom);
|
|
139
|
+
fs.closeSync(fd);
|
|
140
|
+
const lines = buf.toString("utf-8").trim().split("\n").filter(Boolean);
|
|
141
|
+
const last = lines[lines.length - 1];
|
|
142
|
+
if (!last)
|
|
143
|
+
continue;
|
|
144
|
+
const parsed = JSON.parse(last);
|
|
145
|
+
return parsed.message ?? null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch { /* best effort */ }
|
|
149
|
+
return null;
|
|
150
|
+
},
|
|
151
|
+
/* v8 ignore stop */
|
|
126
152
|
});
|
|
127
153
|
return {
|
|
128
154
|
alreadyRunning: false,
|
|
@@ -20,7 +20,6 @@ const runtime_1 = require("../../nerves/runtime");
|
|
|
20
20
|
const SPINNER_FRAMES = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏";
|
|
21
21
|
const STABILITY_THRESHOLD_MS = 5_000;
|
|
22
22
|
const POLL_INTERVAL_MS = 500;
|
|
23
|
-
const MAX_POLL_MS = 60_000;
|
|
24
23
|
// ── ANSI helpers ──
|
|
25
24
|
const RESET = "\x1b[0m";
|
|
26
25
|
const BOLD = "\x1b[1m";
|
|
@@ -133,24 +132,31 @@ async function pollDaemonStartup(deps) {
|
|
|
133
132
|
while (true) {
|
|
134
133
|
const now = deps.now();
|
|
135
134
|
const elapsed = now - startTime;
|
|
136
|
-
if (elapsed > MAX_POLL_MS) {
|
|
137
|
-
(0, runtime_1.emitNervesEvent)({
|
|
138
|
-
level: "warn",
|
|
139
|
-
component: "daemon",
|
|
140
|
-
event: "daemon.startup_poll_timeout",
|
|
141
|
-
message: "startup polling timed out",
|
|
142
|
-
meta: { elapsedMs: elapsed },
|
|
143
|
-
});
|
|
144
|
-
// Timeout: treat any unresolved agents as degraded
|
|
145
|
-
return { stable: [], degraded: [] };
|
|
146
|
-
}
|
|
147
135
|
let payload = null;
|
|
148
136
|
try {
|
|
149
137
|
const response = await deps.sendCommand(deps.socketPath, { kind: "daemon.status" });
|
|
150
138
|
payload = (0, cli_render_1.parseStatusPayload)(response.data);
|
|
151
139
|
}
|
|
152
140
|
catch {
|
|
153
|
-
// Socket not yet available —
|
|
141
|
+
// Socket not yet available — show what the daemon is doing from its log
|
|
142
|
+
const elapsedSec = (elapsed / 1000).toFixed(1);
|
|
143
|
+
const frameIndex = Math.floor(elapsed / 100) % SPINNER_FRAMES.length;
|
|
144
|
+
const spinner = SPINNER_FRAMES[frameIndex];
|
|
145
|
+
const latestEvent = deps.readLatestDaemonEvent?.() ?? null;
|
|
146
|
+
const lines = [];
|
|
147
|
+
lines.push(`${spinner} ${BOLD}waiting for daemon${RESET} ${DIM}(${elapsedSec}s)${RESET}`);
|
|
148
|
+
if (latestEvent) {
|
|
149
|
+
lines.push(` ${DIM}${latestEvent}${RESET}`);
|
|
150
|
+
}
|
|
151
|
+
let output = "";
|
|
152
|
+
if (prevLineCount > 0) {
|
|
153
|
+
output += `\x1b[${prevLineCount}A`;
|
|
154
|
+
}
|
|
155
|
+
for (const line of lines) {
|
|
156
|
+
output += `\x1b[2K${line}\n`;
|
|
157
|
+
}
|
|
158
|
+
deps.writeStdout(output);
|
|
159
|
+
prevLineCount = lines.length;
|
|
154
160
|
}
|
|
155
161
|
if (payload) {
|
|
156
162
|
const output = renderStartupProgress(payload, elapsed, prevLineCount);
|