@ouro.bot/cli 0.1.0-alpha.422 → 0.1.0-alpha.425
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/README.md +3 -0
- package/changelog.json +31 -0
- package/dist/heart/daemon/cli-defaults.js +1 -2
- package/dist/heart/daemon/cli-exec.js +510 -88
- package/dist/heart/daemon/cli-help.js +56 -41
- package/dist/heart/daemon/cli-parse.js +82 -77
- package/dist/heart/daemon/up-progress.js +43 -2
- package/dist/mind/prompt.js +2 -2
- package/dist/repertoire/tasks/index.js +12 -4
- package/package.json +1 -1
|
@@ -71,6 +71,7 @@ const auth_flow_1 = require("../auth/auth-flow");
|
|
|
71
71
|
const provider_credentials_1 = require("../provider-credentials");
|
|
72
72
|
const runtime_credentials_1 = require("../runtime-credentials");
|
|
73
73
|
const provider_binding_resolver_1 = require("../provider-binding-resolver");
|
|
74
|
+
const provider_visibility_1 = require("../provider-visibility");
|
|
74
75
|
const provider_state_1 = require("../provider-state");
|
|
75
76
|
const machine_identity_1 = require("../machine-identity");
|
|
76
77
|
const provider_models_1 = require("../provider-models");
|
|
@@ -157,6 +158,132 @@ async function listCliAgents(deps) {
|
|
|
157
158
|
}
|
|
158
159
|
return [];
|
|
159
160
|
}
|
|
161
|
+
function runtimeContextAgentName(deps) {
|
|
162
|
+
try {
|
|
163
|
+
return deps.whoamiInfo?.().agentName.trim() || undefined;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function normalizeCliAgentNames(agentNames) {
|
|
170
|
+
return [...new Set(agentNames.map((agent) => agent.trim()).filter((agent) => agent.length > 0))];
|
|
171
|
+
}
|
|
172
|
+
function resolveSelectedCliAgent(answer, agentNames) {
|
|
173
|
+
const trimmed = answer.trim();
|
|
174
|
+
if (!trimmed)
|
|
175
|
+
return undefined;
|
|
176
|
+
const byName = agentNames.find((agent) => agent.toLowerCase() === trimmed.toLowerCase());
|
|
177
|
+
if (byName)
|
|
178
|
+
return byName;
|
|
179
|
+
const parsedIndex = Number.parseInt(trimmed, 10);
|
|
180
|
+
if (Number.isNaN(parsedIndex))
|
|
181
|
+
return undefined;
|
|
182
|
+
return agentNames[parsedIndex - 1];
|
|
183
|
+
}
|
|
184
|
+
function noAgentsFoundMessage() {
|
|
185
|
+
return "no agents found. Run `ouro` to hatch one or `ouro clone <remote>` to add an existing agent.";
|
|
186
|
+
}
|
|
187
|
+
function multipleAgentsFoundMessage(agentNames) {
|
|
188
|
+
return [
|
|
189
|
+
`multiple agents found: ${agentNames.join(", ")}`,
|
|
190
|
+
"Re-run with --agent <name>.",
|
|
191
|
+
].join("\n");
|
|
192
|
+
}
|
|
193
|
+
function invalidAgentSelectionMessage(agentNames) {
|
|
194
|
+
return [
|
|
195
|
+
`invalid agent selection. Available agents: ${agentNames.join(", ")}`,
|
|
196
|
+
"Re-run with --agent <name>.",
|
|
197
|
+
].join("\n");
|
|
198
|
+
}
|
|
199
|
+
function agentResolutionFailureMode(command) {
|
|
200
|
+
switch (command.kind) {
|
|
201
|
+
case "task.board":
|
|
202
|
+
case "task.create":
|
|
203
|
+
case "task.update":
|
|
204
|
+
case "task.show":
|
|
205
|
+
case "task.actionable":
|
|
206
|
+
case "task.deps":
|
|
207
|
+
case "task.sessions":
|
|
208
|
+
case "task.fix":
|
|
209
|
+
case "reminder.create":
|
|
210
|
+
case "friend.list":
|
|
211
|
+
case "friend.show":
|
|
212
|
+
case "friend.create":
|
|
213
|
+
case "friend.update":
|
|
214
|
+
case "habit.list":
|
|
215
|
+
case "habit.create":
|
|
216
|
+
case "thoughts":
|
|
217
|
+
case "attention.list":
|
|
218
|
+
case "attention.show":
|
|
219
|
+
case "attention.history":
|
|
220
|
+
case "inner.status":
|
|
221
|
+
case "session.list":
|
|
222
|
+
return "return-message";
|
|
223
|
+
case "provider.use":
|
|
224
|
+
case "provider.check":
|
|
225
|
+
case "provider.status":
|
|
226
|
+
case "provider.refresh":
|
|
227
|
+
case "vault.create":
|
|
228
|
+
case "vault.replace":
|
|
229
|
+
case "vault.recover":
|
|
230
|
+
case "vault.unlock":
|
|
231
|
+
case "vault.status":
|
|
232
|
+
case "vault.config.set":
|
|
233
|
+
case "vault.config.status":
|
|
234
|
+
case "connect":
|
|
235
|
+
case "auth.run":
|
|
236
|
+
case "auth.verify":
|
|
237
|
+
case "auth.switch":
|
|
238
|
+
case "config.model":
|
|
239
|
+
case "config.models":
|
|
240
|
+
case "setup":
|
|
241
|
+
case "bluebubbles.replay":
|
|
242
|
+
return "throw";
|
|
243
|
+
default:
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async function resolveMissingAgentName(deps, failureMode) {
|
|
248
|
+
const runtimeAgent = runtimeContextAgentName(deps);
|
|
249
|
+
if (runtimeAgent) {
|
|
250
|
+
return { ok: true, agent: runtimeAgent };
|
|
251
|
+
}
|
|
252
|
+
const discoveredAgents = normalizeCliAgentNames(await listCliAgents(deps));
|
|
253
|
+
if (discoveredAgents.length === 0) {
|
|
254
|
+
return { ok: false, message: noAgentsFoundMessage(), failureMode };
|
|
255
|
+
}
|
|
256
|
+
if (discoveredAgents.length === 1) {
|
|
257
|
+
return { ok: true, agent: discoveredAgents[0] };
|
|
258
|
+
}
|
|
259
|
+
if (!deps.promptInput) {
|
|
260
|
+
return { ok: false, message: multipleAgentsFoundMessage(discoveredAgents), failureMode };
|
|
261
|
+
}
|
|
262
|
+
const answer = await deps.promptInput([
|
|
263
|
+
"Which agent should this use?",
|
|
264
|
+
...discoveredAgents.map((agent, index) => `${index + 1}. ${agent}`),
|
|
265
|
+
`Choose [1-${discoveredAgents.length}] or type a name: `,
|
|
266
|
+
].join("\n"));
|
|
267
|
+
const selectedAgent = resolveSelectedCliAgent(answer, discoveredAgents);
|
|
268
|
+
if (!selectedAgent) {
|
|
269
|
+
return { ok: false, message: invalidAgentSelectionMessage(discoveredAgents), failureMode };
|
|
270
|
+
}
|
|
271
|
+
return { ok: true, agent: selectedAgent };
|
|
272
|
+
}
|
|
273
|
+
async function resolveCommandAgent(command, deps) {
|
|
274
|
+
const failureMode = agentResolutionFailureMode(command);
|
|
275
|
+
if (!failureMode) {
|
|
276
|
+
return { ok: true, command: command };
|
|
277
|
+
}
|
|
278
|
+
const explicitAgent = "agent" in command && typeof command.agent === "string" ? command.agent.trim() : "";
|
|
279
|
+
if (explicitAgent) {
|
|
280
|
+
return { ok: true, command: { ...command, agent: explicitAgent } };
|
|
281
|
+
}
|
|
282
|
+
const resolvedAgent = await resolveMissingAgentName(deps, failureMode);
|
|
283
|
+
if (!resolvedAgent.ok)
|
|
284
|
+
return resolvedAgent;
|
|
285
|
+
return { ok: true, command: { ...command, agent: resolvedAgent.agent } };
|
|
286
|
+
}
|
|
160
287
|
function managedAgentsSignature(agentNames) {
|
|
161
288
|
const unique = [...new Set(agentNames.map((agent) => agent.trim()).filter((agent) => agent.length > 0))].sort();
|
|
162
289
|
return unique.length > 0 ? unique.join(",") : "(none)";
|
|
@@ -197,7 +324,7 @@ async function runCommandProgressPhase(progress, label, run, detail) {
|
|
|
197
324
|
return result;
|
|
198
325
|
}
|
|
199
326
|
catch (error) {
|
|
200
|
-
progress.
|
|
327
|
+
progress.failPhase(label, "failed");
|
|
201
328
|
throw error;
|
|
202
329
|
}
|
|
203
330
|
}
|
|
@@ -1227,6 +1354,50 @@ function currentMachineId(deps) {
|
|
|
1227
1354
|
now: () => providerCliNow(deps),
|
|
1228
1355
|
}).machineId;
|
|
1229
1356
|
}
|
|
1357
|
+
const DEFAULT_RUNTIME_APPLY_TIMEOUT_MS = 15_000;
|
|
1358
|
+
const DEFAULT_RUNTIME_APPLY_POLL_INTERVAL_MS = 500;
|
|
1359
|
+
const DEFAULT_DAEMON_STATUS_TIMEOUT_MS = 4_000;
|
|
1360
|
+
const DEFAULT_AGENT_RESTART_TIMEOUT_MS = 8_000;
|
|
1361
|
+
const CONNECT_PROVIDER_CHOICES = ["openai-codex", "anthropic", "minimax", "azure", "github-copilot"];
|
|
1362
|
+
function hasRuntimeConfigValue(config, key) {
|
|
1363
|
+
const segments = key.split(".");
|
|
1364
|
+
let cursor = config;
|
|
1365
|
+
for (const segment of segments) {
|
|
1366
|
+
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor))
|
|
1367
|
+
return false;
|
|
1368
|
+
cursor = cursor[segment];
|
|
1369
|
+
}
|
|
1370
|
+
return typeof cursor === "string" && cursor.trim().length > 0;
|
|
1371
|
+
}
|
|
1372
|
+
function runtimeConfigReadStatus(runtime) {
|
|
1373
|
+
if (runtime.reason === "missing")
|
|
1374
|
+
return "missing";
|
|
1375
|
+
if (/locked/i.test(runtime.error))
|
|
1376
|
+
return "locked";
|
|
1377
|
+
return "needs attention";
|
|
1378
|
+
}
|
|
1379
|
+
function cliNowMs(deps) {
|
|
1380
|
+
return (deps.now ?? Date.now)();
|
|
1381
|
+
}
|
|
1382
|
+
function cliSleep(deps, ms) {
|
|
1383
|
+
if (deps.sleep)
|
|
1384
|
+
return deps.sleep(ms);
|
|
1385
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1386
|
+
}
|
|
1387
|
+
async function withCliTimeout(timeoutMs, label, run) {
|
|
1388
|
+
let timer;
|
|
1389
|
+
try {
|
|
1390
|
+
return await Promise.race([
|
|
1391
|
+
run(),
|
|
1392
|
+
new Promise((_, reject) => {
|
|
1393
|
+
timer = setTimeout(() => reject(new Error(label)), timeoutMs);
|
|
1394
|
+
}),
|
|
1395
|
+
]);
|
|
1396
|
+
}
|
|
1397
|
+
finally {
|
|
1398
|
+
clearTimeout(timer);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1230
1401
|
async function promptRuntimeConfigValue(command, deps) {
|
|
1231
1402
|
if (command.value !== undefined)
|
|
1232
1403
|
return command.value;
|
|
@@ -1242,7 +1413,7 @@ async function promptRuntimeConfigValue(command, deps) {
|
|
|
1242
1413
|
function runtimeScopeLabel(scope) {
|
|
1243
1414
|
return scope === "machine" ? "this machine's vault runtime config item" : "the agent vault runtime/config item";
|
|
1244
1415
|
}
|
|
1245
|
-
async function
|
|
1416
|
+
async function storeRuntimeConfigKeys(input) {
|
|
1246
1417
|
const machineId = input.scope === "machine" ? currentMachineId(input.deps) : undefined;
|
|
1247
1418
|
input.onProgress?.("checking existing runtime config");
|
|
1248
1419
|
const current = input.scope === "machine"
|
|
@@ -1251,23 +1422,77 @@ async function storeRuntimeConfigKey(input) {
|
|
|
1251
1422
|
if (!current.ok && current.reason !== "missing") {
|
|
1252
1423
|
throw new Error(`cannot read existing runtime credentials from ${current.itemPath}: ${current.error}`);
|
|
1253
1424
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1425
|
+
let nextConfig = current.ok ? current.config : {};
|
|
1426
|
+
for (const entry of input.entries) {
|
|
1427
|
+
input.onProgress?.(`storing ${entry.key} in ${current.itemPath}`);
|
|
1428
|
+
nextConfig = setRuntimeConfigValue(nextConfig, entry.key, entry.value);
|
|
1429
|
+
}
|
|
1256
1430
|
const stored = input.scope === "machine"
|
|
1257
1431
|
? await (0, runtime_credentials_1.upsertMachineRuntimeCredentialConfig)(input.agent, machineId, nextConfig, providerCliNow(input.deps))
|
|
1258
1432
|
: await (0, runtime_credentials_1.upsertRuntimeCredentialConfig)(input.agent, nextConfig, providerCliNow(input.deps));
|
|
1259
|
-
input.onProgress?.(`stored ${input.key}; credential
|
|
1433
|
+
input.onProgress?.(`stored ${input.entries.map((entry) => entry.key).join(", ")}; credential values were not printed`);
|
|
1260
1434
|
return { revision: stored.revision, itemPath: stored.itemPath, ...(machineId ? { machineId } : {}) };
|
|
1261
1435
|
}
|
|
1262
|
-
async function
|
|
1436
|
+
async function storeRuntimeConfigKey(input) {
|
|
1437
|
+
return storeRuntimeConfigKeys({
|
|
1438
|
+
agent: input.agent,
|
|
1439
|
+
entries: [{ key: input.key, value: input.value }],
|
|
1440
|
+
scope: input.scope,
|
|
1441
|
+
deps: input.deps,
|
|
1442
|
+
onProgress: input.onProgress,
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
function readRuntimeApplyWorker(payload, agent) {
|
|
1446
|
+
return payload.workers.find((worker) => worker.agent === agent) ?? null;
|
|
1447
|
+
}
|
|
1448
|
+
async function applyRuntimeChangeToRunningAgent(agent, deps, onProgress) {
|
|
1263
1449
|
try {
|
|
1450
|
+
onProgress?.("checking daemon socket");
|
|
1264
1451
|
const alive = await deps.checkSocketAlive(deps.socketPath);
|
|
1265
1452
|
if (!alive)
|
|
1266
|
-
return "daemon is not running; next `ouro up` will load
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1453
|
+
return "daemon is not running; next `ouro up` will load the change";
|
|
1454
|
+
onProgress?.("requesting restart from daemon");
|
|
1455
|
+
const response = await withCliTimeout(DEFAULT_AGENT_RESTART_TIMEOUT_MS, "daemon restart request timed out", () => deps.sendCommand(deps.socketPath, { kind: "agent.restart", agent }));
|
|
1456
|
+
if (!response.ok)
|
|
1457
|
+
return `daemon restart skipped: ${response.error ?? response.message ?? "unknown daemon error"}`;
|
|
1458
|
+
const deadline = cliNowMs(deps) + DEFAULT_RUNTIME_APPLY_TIMEOUT_MS;
|
|
1459
|
+
onProgress?.(`waiting for ${agent} to report running state`);
|
|
1460
|
+
while (cliNowMs(deps) < deadline) {
|
|
1461
|
+
try {
|
|
1462
|
+
const statusResponse = await withCliTimeout(DEFAULT_DAEMON_STATUS_TIMEOUT_MS, "daemon status timed out", () => deps.sendCommand(deps.socketPath, { kind: "daemon.status" }));
|
|
1463
|
+
if (statusResponse.ok) {
|
|
1464
|
+
const payload = (0, cli_render_1.parseStatusPayload)(statusResponse.data);
|
|
1465
|
+
if (!payload) {
|
|
1466
|
+
onProgress?.("daemon status did not include structured worker state");
|
|
1467
|
+
return "restart requested; daemon status is unavailable, so verify with `ouro status` if needed";
|
|
1468
|
+
}
|
|
1469
|
+
const worker = readRuntimeApplyWorker(payload, agent);
|
|
1470
|
+
if (!worker) {
|
|
1471
|
+
onProgress?.(`still waiting: ${agent} is not listed by daemon`);
|
|
1472
|
+
}
|
|
1473
|
+
else if (worker.status === "running") {
|
|
1474
|
+
onProgress?.(`daemon reports ${agent}/${worker.worker} running`);
|
|
1475
|
+
return `restarted ${agent} and the daemon reports it running`;
|
|
1476
|
+
}
|
|
1477
|
+
else if (worker.status === "crashed") {
|
|
1478
|
+
return `restart requested, but ${agent}/${worker.worker} crashed before reporting running${worker.errorReason ? `: ${worker.errorReason}` : worker.fixHint ? `: ${worker.fixHint}` : ""}`;
|
|
1479
|
+
}
|
|
1480
|
+
else {
|
|
1481
|
+
onProgress?.(`still waiting: ${agent}/${worker.worker} is ${worker.status}`);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
else {
|
|
1485
|
+
onProgress?.(`still waiting: daemon status returned ${statusResponse.error ?? statusResponse.message ?? "unknown error"}`);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
catch (error) {
|
|
1489
|
+
onProgress?.(`still waiting: ${error instanceof Error ? error.message : String(error)}`);
|
|
1490
|
+
}
|
|
1491
|
+
if (cliNowMs(deps) >= deadline - DEFAULT_RUNTIME_APPLY_POLL_INTERVAL_MS)
|
|
1492
|
+
break;
|
|
1493
|
+
await cliSleep(deps, DEFAULT_RUNTIME_APPLY_POLL_INTERVAL_MS);
|
|
1494
|
+
}
|
|
1495
|
+
return `restart requested, but ${agent} did not report running before timeout. The change is stored; run \`ouro status\` or \`ouro up\` if it still looks stale.`;
|
|
1271
1496
|
}
|
|
1272
1497
|
catch (error) {
|
|
1273
1498
|
return `daemon restart skipped: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -1401,23 +1626,70 @@ function enableAgentSense(agent, sense, deps) {
|
|
|
1401
1626
|
};
|
|
1402
1627
|
fs.writeFileSync(configPath, `${JSON.stringify(raw, null, 2)}\n`, "utf-8");
|
|
1403
1628
|
}
|
|
1404
|
-
function
|
|
1629
|
+
async function buildConnectMenu(agent, deps) {
|
|
1630
|
+
const providerVisibility = (0, provider_visibility_1.buildAgentProviderVisibility)({
|
|
1631
|
+
agentName: agent,
|
|
1632
|
+
agentRoot: providerCliAgentRoot({ agent }, deps),
|
|
1633
|
+
homeDir: providerCliHomeDir(deps),
|
|
1634
|
+
});
|
|
1635
|
+
const providerStatus = providerVisibility.lanes.some((lane) => lane.status === "unconfigured")
|
|
1636
|
+
? "needs setup"
|
|
1637
|
+
: providerVisibility.lanes.some((lane) => lane.status === "configured" && lane.credential.status !== "present")
|
|
1638
|
+
? "needs auth"
|
|
1639
|
+
: providerVisibility.lanes.some((lane) => lane.status === "configured" && (lane.readiness.status === "failed" || lane.readiness.status === "stale"))
|
|
1640
|
+
? "needs attention"
|
|
1641
|
+
: "ready";
|
|
1642
|
+
const providerDetail = providerVisibility.lanes.map((lane) => lane.status === "configured"
|
|
1643
|
+
? `${lane.lane}: ${lane.provider} / ${lane.model}`
|
|
1644
|
+
: `${lane.lane}: choose provider/model`).join(" | ");
|
|
1645
|
+
const runtimeConfig = await (0, runtime_credentials_1.refreshRuntimeCredentialConfig)(agent, { preserveCachedOnFailure: true });
|
|
1646
|
+
const machineRuntime = await (0, runtime_credentials_1.refreshMachineRuntimeCredentialConfig)(agent, currentMachineId(deps), { preserveCachedOnFailure: true });
|
|
1647
|
+
const agentConfig = (0, auth_flow_1.readAgentConfigForAgent)(agent, deps.bundlesRoot).config;
|
|
1648
|
+
const teamsEnabled = agentConfig.senses?.teams?.enabled === true;
|
|
1649
|
+
const blueBubblesEnabled = agentConfig.senses?.bluebubbles?.enabled === true;
|
|
1650
|
+
const perplexityStatus = runtimeConfig.ok
|
|
1651
|
+
? hasRuntimeConfigValue(runtimeConfig.config, "integrations.perplexityApiKey") ? "ready" : "missing"
|
|
1652
|
+
: runtimeConfigReadStatus(runtimeConfig);
|
|
1653
|
+
const embeddingsStatus = runtimeConfig.ok
|
|
1654
|
+
? hasRuntimeConfigValue(runtimeConfig.config, "integrations.openaiEmbeddingsApiKey") ? "ready" : "missing"
|
|
1655
|
+
: runtimeConfigReadStatus(runtimeConfig);
|
|
1656
|
+
const teamsStatus = runtimeConfig.ok
|
|
1657
|
+
? hasRuntimeConfigValue(runtimeConfig.config, "teams.clientId")
|
|
1658
|
+
&& hasRuntimeConfigValue(runtimeConfig.config, "teams.clientSecret")
|
|
1659
|
+
&& hasRuntimeConfigValue(runtimeConfig.config, "teams.tenantId")
|
|
1660
|
+
&& teamsEnabled
|
|
1661
|
+
? "ready"
|
|
1662
|
+
: "missing"
|
|
1663
|
+
: runtimeConfigReadStatus(runtimeConfig);
|
|
1664
|
+
const blueBubblesStatus = machineRuntime.ok
|
|
1665
|
+
? hasRuntimeConfigValue(machineRuntime.config, "bluebubbles.serverUrl")
|
|
1666
|
+
&& hasRuntimeConfigValue(machineRuntime.config, "bluebubbles.password")
|
|
1667
|
+
&& blueBubblesEnabled
|
|
1668
|
+
? "attached"
|
|
1669
|
+
: "not attached"
|
|
1670
|
+
: machineRuntimeReadStatus(machineRuntime);
|
|
1405
1671
|
return [
|
|
1406
|
-
|
|
1407
|
-
"
|
|
1672
|
+
`${agent} // connect bay`,
|
|
1673
|
+
"Bring one capability online at a time.",
|
|
1674
|
+
"",
|
|
1675
|
+
` 1. [${providerStatus}] Providers`,
|
|
1676
|
+
` ${providerDetail}`,
|
|
1408
1677
|
"",
|
|
1409
|
-
|
|
1410
|
-
" Portable.
|
|
1678
|
+
` 2. [${perplexityStatus}] Perplexity search`,
|
|
1679
|
+
" Portable. Web search via Perplexity.",
|
|
1411
1680
|
"",
|
|
1412
|
-
|
|
1413
|
-
"
|
|
1681
|
+
` 3. [${embeddingsStatus}] Memory embeddings`,
|
|
1682
|
+
" Portable. Memory retrieval and note search.",
|
|
1414
1683
|
"",
|
|
1415
|
-
|
|
1416
|
-
|
|
1684
|
+
` 4. [${teamsStatus}] Teams`,
|
|
1685
|
+
" Portable. Microsoft Teams sense credentials.",
|
|
1417
1686
|
"",
|
|
1418
|
-
|
|
1687
|
+
` 5. [${blueBubblesStatus}] BlueBubbles iMessage`,
|
|
1688
|
+
" This machine only. Local Mac Messages bridge.",
|
|
1419
1689
|
"",
|
|
1420
|
-
"
|
|
1690
|
+
" 6. Cancel",
|
|
1691
|
+
"",
|
|
1692
|
+
"Choose [1-6] or type a name: ",
|
|
1421
1693
|
].join("\n");
|
|
1422
1694
|
}
|
|
1423
1695
|
async function executeConnectPerplexity(agent, deps) {
|
|
@@ -1437,30 +1709,24 @@ async function executeConnectPerplexity(agent, deps) {
|
|
|
1437
1709
|
let stored;
|
|
1438
1710
|
let reload;
|
|
1439
1711
|
try {
|
|
1440
|
-
progress
|
|
1441
|
-
stored = await storeRuntimeConfigKey({
|
|
1712
|
+
stored = await runCommandProgressPhase(progress, "saving Perplexity search", () => storeRuntimeConfigKey({
|
|
1442
1713
|
agent,
|
|
1443
1714
|
key: "integrations.perplexityApiKey",
|
|
1444
1715
|
value: key,
|
|
1445
1716
|
scope: "agent",
|
|
1446
1717
|
deps,
|
|
1447
1718
|
onProgress: (message) => progress.updateDetail(message),
|
|
1448
|
-
});
|
|
1449
|
-
progress
|
|
1450
|
-
progress.startPhase(`reloading ${agent}`);
|
|
1451
|
-
reload = await reloadRunningAgentAfterCredentialChange(agent, deps);
|
|
1452
|
-
progress.completePhase(`reloading ${agent}`, reload);
|
|
1453
|
-
progress.end();
|
|
1719
|
+
}), () => "secret stored");
|
|
1720
|
+
reload = await runCommandProgressPhase(progress, `applying change to running ${agent}`, () => applyRuntimeChangeToRunningAgent(agent, deps, (message) => progress.updateDetail(message)), (result) => result);
|
|
1454
1721
|
}
|
|
1455
|
-
|
|
1722
|
+
finally {
|
|
1456
1723
|
progress.end();
|
|
1457
|
-
throw error;
|
|
1458
1724
|
}
|
|
1459
1725
|
const message = [
|
|
1460
1726
|
`Perplexity connected for ${agent}`,
|
|
1461
1727
|
"capability: Perplexity search",
|
|
1462
1728
|
`stored: ${stored.itemPath}`,
|
|
1463
|
-
`
|
|
1729
|
+
`running agent: ${reload}`,
|
|
1464
1730
|
"secret was not printed",
|
|
1465
1731
|
"",
|
|
1466
1732
|
"Next: ask the agent to search.",
|
|
@@ -1468,6 +1734,102 @@ async function executeConnectPerplexity(agent, deps) {
|
|
|
1468
1734
|
deps.writeStdout(message);
|
|
1469
1735
|
return message;
|
|
1470
1736
|
}
|
|
1737
|
+
async function executeConnectEmbeddings(agent, deps) {
|
|
1738
|
+
if (agent === "SerpentGuide") {
|
|
1739
|
+
throw new Error("SerpentGuide has no persistent runtime credentials. Connect embeddings on the hatchling agent instead.");
|
|
1740
|
+
}
|
|
1741
|
+
const promptSecret = requirePromptSecret(deps, "OpenAI embeddings API key entry");
|
|
1742
|
+
deps.writeStdout([
|
|
1743
|
+
`Connect embeddings for ${agent}`,
|
|
1744
|
+
"The API key stays hidden while you type.",
|
|
1745
|
+
`Ouro stores it in ${agent}'s vault runtime/config item.`,
|
|
1746
|
+
].join("\n"));
|
|
1747
|
+
const key = (await promptSecret("OpenAI embeddings API key: ")).trim();
|
|
1748
|
+
if (!key)
|
|
1749
|
+
throw new Error("OpenAI embeddings API key cannot be blank");
|
|
1750
|
+
const progress = createHumanCommandProgress(deps, "connect embeddings");
|
|
1751
|
+
let stored;
|
|
1752
|
+
let reload;
|
|
1753
|
+
try {
|
|
1754
|
+
stored = await runCommandProgressPhase(progress, "saving memory embeddings", () => storeRuntimeConfigKey({
|
|
1755
|
+
agent,
|
|
1756
|
+
key: "integrations.openaiEmbeddingsApiKey",
|
|
1757
|
+
value: key,
|
|
1758
|
+
scope: "agent",
|
|
1759
|
+
deps,
|
|
1760
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
1761
|
+
}), () => "secret stored");
|
|
1762
|
+
reload = await runCommandProgressPhase(progress, `applying change to running ${agent}`, () => applyRuntimeChangeToRunningAgent(agent, deps, (message) => progress.updateDetail(message)), (result) => result);
|
|
1763
|
+
}
|
|
1764
|
+
finally {
|
|
1765
|
+
progress.end();
|
|
1766
|
+
}
|
|
1767
|
+
const message = [
|
|
1768
|
+
`Embeddings connected for ${agent}`,
|
|
1769
|
+
"capability: memory embeddings",
|
|
1770
|
+
`stored: ${stored.itemPath}`,
|
|
1771
|
+
`running agent: ${reload}`,
|
|
1772
|
+
"secret was not printed",
|
|
1773
|
+
"",
|
|
1774
|
+
"Next: ask the agent to search notes or memory.",
|
|
1775
|
+
].join("\n");
|
|
1776
|
+
deps.writeStdout(message);
|
|
1777
|
+
return message;
|
|
1778
|
+
}
|
|
1779
|
+
async function executeConnectTeams(agent, deps) {
|
|
1780
|
+
if (agent === "SerpentGuide") {
|
|
1781
|
+
throw new Error("SerpentGuide has no persistent runtime credentials. Connect Teams on the hatchling agent instead.");
|
|
1782
|
+
}
|
|
1783
|
+
const promptInput = requirePromptInput(deps, "Teams setup");
|
|
1784
|
+
const promptSecret = requirePromptSecret(deps, "Teams client secret entry");
|
|
1785
|
+
deps.writeStdout([
|
|
1786
|
+
`Connect Teams for ${agent}`,
|
|
1787
|
+
"This connects the Teams sense.",
|
|
1788
|
+
"The client secret stays hidden while you type.",
|
|
1789
|
+
].join("\n"));
|
|
1790
|
+
const clientId = (await promptInput("Teams client ID: ")).trim();
|
|
1791
|
+
if (!clientId)
|
|
1792
|
+
throw new Error("Teams client ID cannot be blank");
|
|
1793
|
+
const clientSecret = (await promptSecret("Teams client secret: ")).trim();
|
|
1794
|
+
if (!clientSecret)
|
|
1795
|
+
throw new Error("Teams client secret cannot be blank");
|
|
1796
|
+
const tenantId = (await promptInput("Teams tenant ID: ")).trim();
|
|
1797
|
+
if (!tenantId)
|
|
1798
|
+
throw new Error("Teams tenant ID cannot be blank");
|
|
1799
|
+
const managedIdentityClientId = (await promptInput("Teams managed identity client ID [blank to skip]: ")).trim();
|
|
1800
|
+
const progress = createHumanCommandProgress(deps, "connect teams");
|
|
1801
|
+
let stored;
|
|
1802
|
+
try {
|
|
1803
|
+
stored = await runCommandProgressPhase(progress, "saving Teams setup", () => storeRuntimeConfigKeys({
|
|
1804
|
+
agent,
|
|
1805
|
+
entries: [
|
|
1806
|
+
{ key: "teams.clientId", value: clientId },
|
|
1807
|
+
{ key: "teams.clientSecret", value: clientSecret },
|
|
1808
|
+
{ key: "teams.tenantId", value: tenantId },
|
|
1809
|
+
...(managedIdentityClientId ? [{ key: "teams.managedIdentityClientId", value: managedIdentityClientId }] : []),
|
|
1810
|
+
],
|
|
1811
|
+
scope: "agent",
|
|
1812
|
+
deps,
|
|
1813
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
1814
|
+
}), () => "secret stored");
|
|
1815
|
+
progress.updateDetail("enabling Teams in agent.json");
|
|
1816
|
+
enableAgentSense(agent, "teams", deps);
|
|
1817
|
+
}
|
|
1818
|
+
finally {
|
|
1819
|
+
progress.end();
|
|
1820
|
+
}
|
|
1821
|
+
const message = appendBundleSyncSummary([
|
|
1822
|
+
`Teams connected for ${agent}`,
|
|
1823
|
+
"capability: Teams sense",
|
|
1824
|
+
`stored: ${stored.itemPath}`,
|
|
1825
|
+
"agent.json: senses.teams.enabled = true",
|
|
1826
|
+
"secret was not printed",
|
|
1827
|
+
"",
|
|
1828
|
+
"Next: run `ouro up` so the daemon picks up the Teams sense change.",
|
|
1829
|
+
].join("\n"), agent, deps);
|
|
1830
|
+
deps.writeStdout(message);
|
|
1831
|
+
return message;
|
|
1832
|
+
}
|
|
1471
1833
|
async function executeConnectBlueBubbles(agent, deps) {
|
|
1472
1834
|
if (agent === "SerpentGuide") {
|
|
1473
1835
|
throw new Error("SerpentGuide has no persistent runtime credentials. Attach BlueBubbles on the hatchling agent instead.");
|
|
@@ -1535,39 +1897,86 @@ async function executeConnectBlueBubbles(agent, deps) {
|
|
|
1535
1897
|
deps.writeStdout(message);
|
|
1536
1898
|
return message;
|
|
1537
1899
|
}
|
|
1900
|
+
async function executeConnectProviders(agent, deps) {
|
|
1901
|
+
const promptInput = deps.promptInput;
|
|
1902
|
+
if (!promptInput) {
|
|
1903
|
+
const message = [
|
|
1904
|
+
`Provider auth for ${agent}`,
|
|
1905
|
+
"Run one of:",
|
|
1906
|
+
...CONNECT_PROVIDER_CHOICES.map((provider) => ` ouro auth --agent ${agent} --provider ${provider}`),
|
|
1907
|
+
].join("\n");
|
|
1908
|
+
deps.writeStdout(message);
|
|
1909
|
+
return message;
|
|
1910
|
+
}
|
|
1911
|
+
const choice = (await promptInput([
|
|
1912
|
+
`Which provider should ${agent} use credentials for?`,
|
|
1913
|
+
...CONNECT_PROVIDER_CHOICES.map((provider) => ` - ${provider}`),
|
|
1914
|
+
"",
|
|
1915
|
+
"Provider: ",
|
|
1916
|
+
].join("\n"))).trim().toLowerCase();
|
|
1917
|
+
if (!(0, cli_parse_2.isAgentProvider)(choice)) {
|
|
1918
|
+
throw new Error(`Unknown provider '${choice}'. Use ${CONNECT_PROVIDER_CHOICES.join("|")}.`);
|
|
1919
|
+
}
|
|
1920
|
+
return executeAuthRun({ kind: "auth.run", agent, provider: choice }, deps);
|
|
1921
|
+
}
|
|
1922
|
+
function machineRuntimeReadStatus(runtime) {
|
|
1923
|
+
if (runtime.reason === "missing")
|
|
1924
|
+
return "not attached";
|
|
1925
|
+
if (/locked/i.test(runtime.error))
|
|
1926
|
+
return "locked";
|
|
1927
|
+
return "needs attention";
|
|
1928
|
+
}
|
|
1929
|
+
function connectMenuTarget(answer) {
|
|
1930
|
+
const normalized = answer.trim().toLowerCase();
|
|
1931
|
+
if (normalized === "1" || normalized === "providers" || normalized === "provider" || normalized === "auth")
|
|
1932
|
+
return "providers";
|
|
1933
|
+
if (normalized === "2" || normalized === "perplexity" || normalized === "perplexity-search" || normalized === "search")
|
|
1934
|
+
return "perplexity";
|
|
1935
|
+
if (normalized === "3" || normalized === "embeddings" || normalized === "embedding" || normalized === "memory" || normalized === "note-search" || normalized === "notes")
|
|
1936
|
+
return "embeddings";
|
|
1937
|
+
if (normalized === "4" || normalized === "teams" || normalized === "msteams" || normalized === "microsoft-teams")
|
|
1938
|
+
return "teams";
|
|
1939
|
+
if (normalized === "5" || normalized === "bluebubbles" || normalized === "imessage" || normalized === "messages")
|
|
1940
|
+
return "bluebubbles";
|
|
1941
|
+
return "cancel";
|
|
1942
|
+
}
|
|
1538
1943
|
async function executeConnect(command, deps) {
|
|
1944
|
+
if (command.target === "providers")
|
|
1945
|
+
return executeConnectProviders(command.agent, deps);
|
|
1539
1946
|
if (command.target === "perplexity")
|
|
1540
1947
|
return executeConnectPerplexity(command.agent, deps);
|
|
1948
|
+
if (command.target === "embeddings")
|
|
1949
|
+
return executeConnectEmbeddings(command.agent, deps);
|
|
1950
|
+
if (command.target === "teams")
|
|
1951
|
+
return executeConnectTeams(command.agent, deps);
|
|
1541
1952
|
if (command.target === "bluebubbles")
|
|
1542
1953
|
return executeConnectBlueBubbles(command.agent, deps);
|
|
1954
|
+
const menu = await buildConnectMenu(command.agent, deps);
|
|
1543
1955
|
const promptInput = deps.promptInput;
|
|
1544
1956
|
if (!promptInput) {
|
|
1545
1957
|
const message = [
|
|
1546
|
-
|
|
1958
|
+
menu.replace(/\nChoose \[1-6\] or type a name: $/, ""),
|
|
1547
1959
|
"",
|
|
1960
|
+
`Run: ouro connect providers --agent ${command.agent}`,
|
|
1548
1961
|
`Run: ouro connect perplexity --agent ${command.agent}`,
|
|
1549
|
-
`
|
|
1962
|
+
`Run: ouro connect embeddings --agent ${command.agent}`,
|
|
1963
|
+
`Run: ouro connect teams --agent ${command.agent}`,
|
|
1964
|
+
`Run: ouro connect bluebubbles --agent ${command.agent}`,
|
|
1550
1965
|
].join("\n");
|
|
1551
1966
|
deps.writeStdout(message);
|
|
1552
1967
|
return message;
|
|
1553
1968
|
}
|
|
1554
|
-
const answer = (await promptInput(
|
|
1555
|
-
if (answer === "
|
|
1969
|
+
const answer = connectMenuTarget(await promptInput(menu));
|
|
1970
|
+
if (answer === "providers")
|
|
1971
|
+
return executeConnectProviders(command.agent, deps);
|
|
1972
|
+
if (answer === "perplexity")
|
|
1556
1973
|
return executeConnectPerplexity(command.agent, deps);
|
|
1557
|
-
|
|
1558
|
-
|
|
1974
|
+
if (answer === "embeddings")
|
|
1975
|
+
return executeConnectEmbeddings(command.agent, deps);
|
|
1976
|
+
if (answer === "teams")
|
|
1977
|
+
return executeConnectTeams(command.agent, deps);
|
|
1978
|
+
if (answer === "bluebubbles")
|
|
1559
1979
|
return executeConnectBlueBubbles(command.agent, deps);
|
|
1560
|
-
}
|
|
1561
|
-
if (answer === "3" || answer === "provider" || answer === "providers" || answer === "auth") {
|
|
1562
|
-
const message = [
|
|
1563
|
-
"Provider auth is its own flow:",
|
|
1564
|
-
` ouro auth --agent ${command.agent} --provider <provider>`,
|
|
1565
|
-
"",
|
|
1566
|
-
"Use `ouro connect` for integrations and local senses after provider auth is ready.",
|
|
1567
|
-
].join("\n");
|
|
1568
|
-
deps.writeStdout(message);
|
|
1569
|
-
return message;
|
|
1570
|
-
}
|
|
1571
1980
|
const message = "connect cancelled.";
|
|
1572
1981
|
deps.writeStdout(message);
|
|
1573
1982
|
return message;
|
|
@@ -1896,13 +2305,9 @@ async function executeProviderRefresh(command, deps) {
|
|
|
1896
2305
|
deps.writeStdout(message);
|
|
1897
2306
|
return message;
|
|
1898
2307
|
}
|
|
1899
|
-
progress
|
|
1900
|
-
const reload = await reloadRunningAgentAfterCredentialChange(command.agent, deps);
|
|
1901
|
-
progress.completePhase(`reloading ${command.agent}`, reload);
|
|
2308
|
+
const reload = await runCommandProgressPhase(progress, `applying change to running ${command.agent}`, () => applyRuntimeChangeToRunningAgent(command.agent, deps, (message) => progress.updateDetail(message)), (result) => result);
|
|
1902
2309
|
progress.end();
|
|
1903
|
-
lines.push(
|
|
1904
|
-
? "daemon is not running; the next start will load the refreshed snapshot"
|
|
1905
|
-
: reload);
|
|
2310
|
+
lines.push(`running agent: ${reload}`);
|
|
1906
2311
|
const message = lines.join("\n");
|
|
1907
2312
|
deps.writeStdout(message);
|
|
1908
2313
|
return message;
|
|
@@ -2608,9 +3013,9 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
2608
3013
|
deps.writeStdout(text);
|
|
2609
3014
|
return text;
|
|
2610
3015
|
}
|
|
2611
|
-
let
|
|
3016
|
+
let parsedCommand;
|
|
2612
3017
|
try {
|
|
2613
|
-
|
|
3018
|
+
parsedCommand = (0, cli_parse_1.parseOuroCommand)(args);
|
|
2614
3019
|
}
|
|
2615
3020
|
catch (parseError) {
|
|
2616
3021
|
if (deps.startChat && deps.listDiscoveredAgents && args.length === 1) {
|
|
@@ -2623,6 +3028,15 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
2623
3028
|
}
|
|
2624
3029
|
throw parseError;
|
|
2625
3030
|
}
|
|
3031
|
+
const resolvedCommand = await resolveCommandAgent(parsedCommand, deps);
|
|
3032
|
+
if (!resolvedCommand.ok) {
|
|
3033
|
+
if (resolvedCommand.failureMode === "return-message") {
|
|
3034
|
+
deps.writeStdout(resolvedCommand.message);
|
|
3035
|
+
return resolvedCommand.message;
|
|
3036
|
+
}
|
|
3037
|
+
throw new Error(resolvedCommand.message);
|
|
3038
|
+
}
|
|
3039
|
+
let command = resolvedCommand.command;
|
|
2626
3040
|
if (args.length === 0) {
|
|
2627
3041
|
const discovered = await Promise.resolve(deps.listDiscoveredAgents ? deps.listDiscoveredAgents() : (0, cli_defaults_1.defaultListDiscoveredAgents)());
|
|
2628
3042
|
if (discovered.length === 0 && deps.runSerpentGuide) {
|
|
@@ -3502,7 +3916,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3502
3916
|
command.kind === "task.show" || command.kind === "task.actionable" || command.kind === "task.deps" ||
|
|
3503
3917
|
command.kind === "task.sessions" || command.kind === "task.fix") {
|
|
3504
3918
|
/* v8 ignore start -- production default: requires full identity setup @preserve */
|
|
3505
|
-
const taskMod = deps.taskModule ?? (0, tasks_1.
|
|
3919
|
+
const taskMod = deps.taskModule ?? (0, tasks_1.createTaskModule)(path.join(deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(), `${command.agent}.ouro`, "tasks"));
|
|
3506
3920
|
/* v8 ignore stop */
|
|
3507
3921
|
const message = executeTaskCommand(command, taskMod);
|
|
3508
3922
|
deps.writeStdout(message);
|
|
@@ -3511,7 +3925,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3511
3925
|
// ── reminder subcommands (local, no daemon socket needed) ──
|
|
3512
3926
|
if (command.kind === "reminder.create") {
|
|
3513
3927
|
/* v8 ignore start -- production default: requires full identity setup @preserve */
|
|
3514
|
-
const taskMod = deps.taskModule ?? (0, tasks_1.
|
|
3928
|
+
const taskMod = deps.taskModule ?? (0, tasks_1.createTaskModule)(path.join(deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(), `${command.agent}.ouro`, "tasks"));
|
|
3515
3929
|
/* v8 ignore stop */
|
|
3516
3930
|
const message = executeReminderCommand(command, taskMod);
|
|
3517
3931
|
deps.writeStdout(message);
|
|
@@ -3521,8 +3935,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3521
3935
|
if (command.kind === "habit.list" || command.kind === "habit.create") {
|
|
3522
3936
|
const { parseHabitFile, renderHabitFile } = await Promise.resolve().then(() => __importStar(require("../habits/habit-parser")));
|
|
3523
3937
|
/* v8 ignore start -- production default: uses real bundle root @preserve */
|
|
3524
|
-
const
|
|
3525
|
-
const bundleRoot = deps.agentBundleRoot ?? path.join((0, identity_1.getAgentBundlesRoot)(), `${agentName}.ouro`);
|
|
3938
|
+
const bundleRoot = deps.agentBundleRoot ?? path.join(deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(), `${command.agent}.ouro`);
|
|
3526
3939
|
/* v8 ignore stop */
|
|
3527
3940
|
const habitsDir = path.join(bundleRoot, "habits");
|
|
3528
3941
|
if (command.kind === "habit.list") {
|
|
@@ -3581,8 +3994,8 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3581
3994
|
// Derive agent-scoped friends dir from --agent flag or link/unlink's agent field
|
|
3582
3995
|
const agentName = ("agent" in command && command.agent) ? command.agent : undefined;
|
|
3583
3996
|
const friendsDir = agentName
|
|
3584
|
-
? path.join((0, identity_1.getAgentBundlesRoot)(), `${agentName}.ouro`, "friends")
|
|
3585
|
-
: path.join((0, identity_1.getAgentBundlesRoot)(), "friends");
|
|
3997
|
+
? path.join(deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(), `${agentName}.ouro`, "friends")
|
|
3998
|
+
: path.join(deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(), "friends");
|
|
3586
3999
|
store = new store_file_1.FileFriendStore(friendsDir);
|
|
3587
4000
|
}
|
|
3588
4001
|
/* v8 ignore stop */
|
|
@@ -3765,29 +4178,41 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3765
4178
|
deps.writeStdout(message);
|
|
3766
4179
|
return message;
|
|
3767
4180
|
}
|
|
3768
|
-
/* v8 ignore start -- production default: requires full identity setup @preserve */
|
|
3769
4181
|
try {
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
4182
|
+
if (deps.whoamiInfo) {
|
|
4183
|
+
try {
|
|
4184
|
+
const info = deps.whoamiInfo();
|
|
4185
|
+
const message = [
|
|
4186
|
+
`agent: ${info.agentName}`,
|
|
4187
|
+
`home: ${info.homePath}`,
|
|
4188
|
+
`bones: ${info.bonesVersion}`,
|
|
4189
|
+
].join("\n");
|
|
4190
|
+
deps.writeStdout(message);
|
|
4191
|
+
return message;
|
|
4192
|
+
}
|
|
4193
|
+
catch {
|
|
4194
|
+
// Fall through to shared agent selection when no runtime identity is available.
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
const resolvedAgent = await resolveMissingAgentName(deps, "return-message");
|
|
4198
|
+
if (!resolvedAgent.ok) {
|
|
4199
|
+
deps.writeStdout(resolvedAgent.message);
|
|
4200
|
+
return resolvedAgent.message;
|
|
4201
|
+
}
|
|
4202
|
+
const agentRoot = path.join((0, identity_1.getAgentBundlesRoot)(), `${resolvedAgent.agent}.ouro`);
|
|
3777
4203
|
const message = [
|
|
3778
|
-
`agent: ${
|
|
3779
|
-
`home: ${
|
|
3780
|
-
`bones: ${
|
|
4204
|
+
`agent: ${resolvedAgent.agent}`,
|
|
4205
|
+
`home: ${agentRoot}`,
|
|
4206
|
+
`bones: ${(0, runtime_metadata_1.getRuntimeMetadata)().version}`,
|
|
3781
4207
|
].join("\n");
|
|
3782
4208
|
deps.writeStdout(message);
|
|
3783
4209
|
return message;
|
|
3784
4210
|
}
|
|
3785
4211
|
catch {
|
|
3786
|
-
const message =
|
|
4212
|
+
const message = noAgentsFoundMessage();
|
|
3787
4213
|
deps.writeStdout(message);
|
|
3788
4214
|
return message;
|
|
3789
4215
|
}
|
|
3790
|
-
/* v8 ignore stop */
|
|
3791
4216
|
}
|
|
3792
4217
|
// ── changelog (local, no daemon socket needed) ──
|
|
3793
4218
|
if (command.kind === "changelog") {
|
|
@@ -3831,10 +4256,9 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3831
4256
|
// ── thoughts (local, no daemon socket needed) ──
|
|
3832
4257
|
if (command.kind === "thoughts") {
|
|
3833
4258
|
try {
|
|
3834
|
-
const agentName = command.agent ?? (0, identity_1.getAgentName)();
|
|
3835
4259
|
/* v8 ignore next -- production fallback: tests always inject bundlesRoot via createTmpBundle @preserve */
|
|
3836
4260
|
const bundlesRoot = deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
|
|
3837
|
-
const agentRoot = path.join(bundlesRoot, `${
|
|
4261
|
+
const agentRoot = path.join(bundlesRoot, `${command.agent}.ouro`);
|
|
3838
4262
|
const sessionFilePath = (0, thoughts_1.getInnerDialogSessionPath)(agentRoot);
|
|
3839
4263
|
if (command.json) {
|
|
3840
4264
|
try {
|
|
@@ -3877,10 +4301,9 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3877
4301
|
/* v8 ignore start -- CLI attention handler: requires real obligation store on disk @preserve */
|
|
3878
4302
|
if (command.kind === "attention.list" || command.kind === "attention.show" || command.kind === "attention.history") {
|
|
3879
4303
|
try {
|
|
3880
|
-
const agentName = command.agent ?? (0, identity_1.getAgentName)();
|
|
3881
4304
|
const { listActiveReturnObligations, readReturnObligation } = await Promise.resolve().then(() => __importStar(require("../../arc/obligations")));
|
|
3882
4305
|
if (command.kind === "attention.list") {
|
|
3883
|
-
const obligations = listActiveReturnObligations(
|
|
4306
|
+
const obligations = listActiveReturnObligations(command.agent);
|
|
3884
4307
|
if (obligations.length === 0) {
|
|
3885
4308
|
const message = "nothing held — attention queue is empty";
|
|
3886
4309
|
deps.writeStdout(message);
|
|
@@ -3892,7 +4315,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3892
4315
|
return message;
|
|
3893
4316
|
}
|
|
3894
4317
|
if (command.kind === "attention.show") {
|
|
3895
|
-
const obligation = readReturnObligation(
|
|
4318
|
+
const obligation = readReturnObligation(command.agent, command.id);
|
|
3896
4319
|
if (!obligation) {
|
|
3897
4320
|
const message = `no obligation found with id ${command.id}`;
|
|
3898
4321
|
deps.writeStdout(message);
|
|
@@ -3904,7 +4327,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3904
4327
|
}
|
|
3905
4328
|
// attention.history: show returned obligations
|
|
3906
4329
|
const { getReturnObligationsDir } = await Promise.resolve().then(() => __importStar(require("../../arc/obligations")));
|
|
3907
|
-
const obligationsDir = getReturnObligationsDir(
|
|
4330
|
+
const obligationsDir = getReturnObligationsDir(command.agent);
|
|
3908
4331
|
let attEntries = [];
|
|
3909
4332
|
try {
|
|
3910
4333
|
attEntries = fs.readdirSync(obligationsDir);
|
|
@@ -3945,8 +4368,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3945
4368
|
/* v8 ignore start -- inner status handler: requires real agent state on disk @preserve */
|
|
3946
4369
|
if (command.kind === "inner.status") {
|
|
3947
4370
|
try {
|
|
3948
|
-
const
|
|
3949
|
-
const agentRoot = (0, identity_1.getAgentRoot)(agentName);
|
|
4371
|
+
const agentRoot = (0, identity_1.getAgentRoot)(command.agent);
|
|
3950
4372
|
const { buildInnerStatusOutput } = await Promise.resolve().then(() => __importStar(require("./inner-status")));
|
|
3951
4373
|
const { sessionPath: getSessionPath } = await Promise.resolve().then(() => __importStar(require("../config")));
|
|
3952
4374
|
const { parseCadenceToMs: parseCadenceMs, DEFAULT_CADENCE_MS } = await Promise.resolve().then(() => __importStar(require("./cadence")));
|
|
@@ -4004,9 +4426,9 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
4004
4426
|
}
|
|
4005
4427
|
catch { /* no habits — heartbeat unknown */ }
|
|
4006
4428
|
// Attention count
|
|
4007
|
-
const activeObligations = listActiveReturnObligations(
|
|
4429
|
+
const activeObligations = listActiveReturnObligations(command.agent);
|
|
4008
4430
|
const message = buildInnerStatusOutput({
|
|
4009
|
-
agentName,
|
|
4431
|
+
agentName: command.agent,
|
|
4010
4432
|
runtimeState,
|
|
4011
4433
|
journalFiles,
|
|
4012
4434
|
heartbeat,
|
|
@@ -4028,7 +4450,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
4028
4450
|
/* v8 ignore start -- production default: requires full identity setup @preserve */
|
|
4029
4451
|
const scanner = deps.scanSessions ?? (async () => []);
|
|
4030
4452
|
/* v8 ignore stop */
|
|
4031
|
-
const sessions = await scanner();
|
|
4453
|
+
const sessions = await scanner(command.agent);
|
|
4032
4454
|
if (sessions.length === 0) {
|
|
4033
4455
|
const message = "no active sessions";
|
|
4034
4456
|
deps.writeStdout(message);
|