@ouro.bot/cli 0.1.0-alpha.528 → 0.1.0-alpha.529
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,14 @@
|
|
|
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.529",
|
|
6
|
+
"changes": [
|
|
7
|
+
"MCP agent status now asks the daemon for proof-bearing runtime health, including per-agent worker rows and enabled sense rows with proof method, proof age, failure layer, and recovery counters.",
|
|
8
|
+
"MCP status reports daemon/socket unreachability as an explicit status line instead of hiding it behind otherwise successful diary/session facts.",
|
|
9
|
+
"MCP status now includes its own package version and flags MCP-vs-daemon version mismatches so stale long-lived MCP servers are visible during reliability checks."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"version": "0.1.0-alpha.528",
|
|
6
14
|
"changes": [
|
|
@@ -58,6 +58,7 @@ const path = __importStar(require("path"));
|
|
|
58
58
|
const identity_1 = require("../identity");
|
|
59
59
|
const diary_1 = require("../../mind/diary");
|
|
60
60
|
const runtime_1 = require("../../nerves/runtime");
|
|
61
|
+
const socket_client_1 = require("./socket-client");
|
|
61
62
|
/** Format diary hits the same way the search_notes tool does. */
|
|
62
63
|
function formatDiaryHits(hits) {
|
|
63
64
|
return hits.map((f) => `[diary] ${f.text} (source=${f.source}, createdAt=${f.createdAt})`);
|
|
@@ -149,6 +150,152 @@ function listTaskFiles(agent) {
|
|
|
149
150
|
function emit(event, message, meta) {
|
|
150
151
|
(0, runtime_1.emitNervesEvent)({ component: "daemon", event, message, meta });
|
|
151
152
|
}
|
|
153
|
+
function objectRecord(value) {
|
|
154
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
155
|
+
? value
|
|
156
|
+
: null;
|
|
157
|
+
}
|
|
158
|
+
function stringValue(value) {
|
|
159
|
+
return typeof value === "string" ? value : null;
|
|
160
|
+
}
|
|
161
|
+
function booleanValue(value) {
|
|
162
|
+
return typeof value === "boolean" ? value : null;
|
|
163
|
+
}
|
|
164
|
+
function numberValue(value) {
|
|
165
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
166
|
+
}
|
|
167
|
+
function readMcpRuntimeVersion() {
|
|
168
|
+
const packagePath = path.resolve(__dirname, "..", "..", "..", "package.json");
|
|
169
|
+
try {
|
|
170
|
+
const parsed = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
|
|
171
|
+
return stringValue(parsed.version);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function summarizeRuntimeStatus(data, agent) {
|
|
178
|
+
const payload = objectRecord(data);
|
|
179
|
+
if (!payload)
|
|
180
|
+
return null;
|
|
181
|
+
const overview = objectRecord(payload.overview);
|
|
182
|
+
const workers = Array.isArray(payload.workers) ? payload.workers : [];
|
|
183
|
+
const senses = Array.isArray(payload.senses) ? payload.senses : [];
|
|
184
|
+
return {
|
|
185
|
+
daemonReachable: true,
|
|
186
|
+
overview: overview
|
|
187
|
+
? {
|
|
188
|
+
daemon: stringValue(overview.daemon) ?? "unknown",
|
|
189
|
+
health: stringValue(overview.health) ?? "unknown",
|
|
190
|
+
version: stringValue(overview.version),
|
|
191
|
+
mode: stringValue(overview.mode),
|
|
192
|
+
}
|
|
193
|
+
: undefined,
|
|
194
|
+
workers: workers.flatMap((row) => {
|
|
195
|
+
const record = objectRecord(row);
|
|
196
|
+
if (!record || stringValue(record.agent) !== agent)
|
|
197
|
+
return [];
|
|
198
|
+
const worker = stringValue(record.worker);
|
|
199
|
+
const status = stringValue(record.status);
|
|
200
|
+
return worker && status ? [{ worker, status }] : [];
|
|
201
|
+
}),
|
|
202
|
+
senses: senses.flatMap((row) => {
|
|
203
|
+
const record = objectRecord(row);
|
|
204
|
+
if (!record || stringValue(record.agent) !== agent)
|
|
205
|
+
return [];
|
|
206
|
+
const sense = stringValue(record.sense);
|
|
207
|
+
const status = stringValue(record.status);
|
|
208
|
+
const enabled = booleanValue(record.enabled);
|
|
209
|
+
if (!sense || !status || enabled === null)
|
|
210
|
+
return [];
|
|
211
|
+
return [{
|
|
212
|
+
sense,
|
|
213
|
+
status,
|
|
214
|
+
enabled,
|
|
215
|
+
detail: stringValue(record.detail),
|
|
216
|
+
proofMethod: stringValue(record.proofMethod),
|
|
217
|
+
lastProofAt: stringValue(record.lastProofAt),
|
|
218
|
+
proofAgeMs: numberValue(record.proofAgeMs),
|
|
219
|
+
pendingRecoveryCount: numberValue(record.pendingRecoveryCount),
|
|
220
|
+
failedRecoveryCount: numberValue(record.failedRecoveryCount),
|
|
221
|
+
failureLayer: stringValue(record.failureLayer),
|
|
222
|
+
lastFailure: stringValue(record.lastFailure),
|
|
223
|
+
recoveryAction: stringValue(record.recoveryAction),
|
|
224
|
+
}];
|
|
225
|
+
}),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
async function readRuntimeStatus(socketPath, agent) {
|
|
229
|
+
if (!socketPath)
|
|
230
|
+
return null;
|
|
231
|
+
try {
|
|
232
|
+
const response = await (0, socket_client_1.sendDaemonCommand)(socketPath, { kind: "daemon.status" });
|
|
233
|
+
if (!response.ok) {
|
|
234
|
+
return {
|
|
235
|
+
daemonReachable: false,
|
|
236
|
+
workers: [],
|
|
237
|
+
senses: [],
|
|
238
|
+
error: response.error ?? response.message ?? "daemon status did not answer cleanly",
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return summarizeRuntimeStatus(response.data, agent);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
return {
|
|
245
|
+
daemonReachable: false,
|
|
246
|
+
workers: [],
|
|
247
|
+
senses: [],
|
|
248
|
+
error: error instanceof Error ? error.message : String(error),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function formatRuntimeStatusLines(runtime, mcpVersion) {
|
|
253
|
+
if (!runtime)
|
|
254
|
+
return mcpVersion ? [`mcpVersion=${mcpVersion}`] : [];
|
|
255
|
+
if (!runtime.daemonReachable) {
|
|
256
|
+
return [
|
|
257
|
+
`daemon=unreachable${runtime.error ? `\terror=${runtime.error}` : ""}`,
|
|
258
|
+
...(mcpVersion ? [`mcpVersion=${mcpVersion}`] : []),
|
|
259
|
+
];
|
|
260
|
+
}
|
|
261
|
+
const lines = [];
|
|
262
|
+
if (runtime.overview) {
|
|
263
|
+
const versionPart = runtime.overview.version ? `\tdaemonVersion=${runtime.overview.version}` : "";
|
|
264
|
+
const modePart = runtime.overview.mode ? `\tmode=${runtime.overview.mode}` : "";
|
|
265
|
+
const mcpVersionPart = mcpVersion ? `\tmcpVersion=${mcpVersion}` : "";
|
|
266
|
+
const mismatchPart = mcpVersion && runtime.overview.version && mcpVersion !== runtime.overview.version
|
|
267
|
+
? `\tversionMismatch=mcp:${mcpVersion},daemon:${runtime.overview.version}`
|
|
268
|
+
: "";
|
|
269
|
+
lines.push(`daemon=${runtime.overview.daemon}\thealth=${runtime.overview.health}${versionPart}${modePart}${mcpVersionPart}${mismatchPart}`);
|
|
270
|
+
}
|
|
271
|
+
for (const worker of runtime.workers) {
|
|
272
|
+
lines.push(`worker=${worker.worker}:${worker.status}`);
|
|
273
|
+
}
|
|
274
|
+
for (const sense of runtime.senses) {
|
|
275
|
+
const detailPart = sense.detail ? `\tdetail=${sense.detail}` : "";
|
|
276
|
+
const proofPart = sense.proofMethod ? `\tproof=${sense.proofMethod}` : "";
|
|
277
|
+
const lastProofPart = sense.lastProofAt ? `\tlastProofAt=${sense.lastProofAt}` : "";
|
|
278
|
+
const proofAgePart = sense.proofAgeMs !== null ? `\tproofAgeMs=${sense.proofAgeMs}` : "";
|
|
279
|
+
const pendingPart = sense.pendingRecoveryCount !== null ? `\tpendingRecovery=${sense.pendingRecoveryCount}` : "";
|
|
280
|
+
const failedPart = sense.failedRecoveryCount !== null ? `\tfailedRecovery=${sense.failedRecoveryCount}` : "";
|
|
281
|
+
const failureLayerPart = sense.failureLayer ? `\tfailureLayer=${sense.failureLayer}` : "";
|
|
282
|
+
const failurePart = sense.lastFailure ? `\tlastFailure=${sense.lastFailure}` : "";
|
|
283
|
+
const recoveryPart = sense.recoveryAction ? `\trecovery=${sense.recoveryAction}` : "";
|
|
284
|
+
lines.push(`sense=${sense.sense}:${sense.enabled ? sense.status : "disabled"}`
|
|
285
|
+
+ detailPart
|
|
286
|
+
+ proofPart
|
|
287
|
+
+ lastProofPart
|
|
288
|
+
+ proofAgePart
|
|
289
|
+
+ pendingPart
|
|
290
|
+
+ failedPart
|
|
291
|
+
+ failureLayerPart
|
|
292
|
+
+ failurePart
|
|
293
|
+
+ recoveryPart);
|
|
294
|
+
}
|
|
295
|
+
if (lines.length === 0 && mcpVersion)
|
|
296
|
+
lines.push(`mcpVersion=${mcpVersion}`);
|
|
297
|
+
return lines;
|
|
298
|
+
}
|
|
152
299
|
// ─── Handlers ────────────────────────────────────────────────────────────────
|
|
153
300
|
async function handleAgentStatus(params) {
|
|
154
301
|
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.agent_service_start", message: "handling agent.status", meta: { agent: params.agent } });
|
|
@@ -156,16 +303,20 @@ async function handleAgentStatus(params) {
|
|
|
156
303
|
const facts = (0, diary_1.readDiaryEntries)(diaryRoot);
|
|
157
304
|
const innerStatus = readInnerDialogStatus(params.agent);
|
|
158
305
|
const sessions = enumerateSessions(params.agent);
|
|
306
|
+
const mcpVersion = readMcpRuntimeVersion();
|
|
307
|
+
const runtime = await readRuntimeStatus(params.socketPath ?? socket_client_1.DEFAULT_DAEMON_SOCKET_PATH, params.agent);
|
|
159
308
|
emit("daemon.agent_service_end", "completed agent.status", { agent: params.agent });
|
|
160
309
|
const innerStatusValue = innerStatus?.status ?? "unknown";
|
|
161
310
|
const lastThoughtAt = innerStatus?.lastCompletedAt ?? null;
|
|
162
|
-
const
|
|
311
|
+
const agentLine = [
|
|
163
312
|
`agent=${params.agent}`,
|
|
164
313
|
`innerStatus=${innerStatusValue}`,
|
|
165
314
|
`lastThoughtAt=${lastThoughtAt ?? "never"}`,
|
|
166
315
|
`sessionCount=${sessions.length}`,
|
|
167
316
|
`diaryEntries=${facts.length}`,
|
|
168
317
|
].join("\t");
|
|
318
|
+
const runtimeLines = formatRuntimeStatusLines(runtime, mcpVersion);
|
|
319
|
+
const message = [agentLine, ...runtimeLines].join("\n");
|
|
169
320
|
return {
|
|
170
321
|
ok: true,
|
|
171
322
|
message,
|
|
@@ -176,6 +327,8 @@ async function handleAgentStatus(params) {
|
|
|
176
327
|
sessionCount: sessions.length,
|
|
177
328
|
hasDiaryEntries: facts.length > 0,
|
|
178
329
|
factCount: facts.length,
|
|
330
|
+
runtime,
|
|
331
|
+
mcpVersion,
|
|
179
332
|
},
|
|
180
333
|
};
|
|
181
334
|
}
|
|
@@ -425,7 +425,7 @@ function createMcpServer(options) {
|
|
|
425
425
|
if (serviceHandler && typeof agentService[serviceHandler] === "function") {
|
|
426
426
|
const handlerFn = agentService[serviceHandler];
|
|
427
427
|
try {
|
|
428
|
-
response = await handlerFn({ agent, friendId, ...toolArgs });
|
|
428
|
+
response = await handlerFn({ agent, friendId, socketPath, ...toolArgs });
|
|
429
429
|
}
|
|
430
430
|
catch (error) {
|
|
431
431
|
const errorMessage = error instanceof Error ? error.message : String(error);
|