@ouro.bot/cli 0.1.0-alpha.457 → 0.1.0-alpha.459
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,22 @@
|
|
|
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.459",
|
|
6
|
+
"changes": [
|
|
7
|
+
"`ouro connect bluebubbles` now applies a machine-local attachment to a running daemon by recycling Ouro once after the vault and bundle update, so the webhook listener starts immediately instead of requiring a manual `ouro down && ouro up` discovery step.",
|
|
8
|
+
"`ouro status` and daemon health now probe the BlueBubbles listener declared in the agent's machine-local vault config, including non-default webhook ports, instead of reporting stale health against the default port.",
|
|
9
|
+
"BlueBubbles setup docs now state the live-apply behavior directly, and daemon coverage locks the dynamic sense-health probe plus running-daemon connect path."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.1.0-alpha.458",
|
|
14
|
+
"changes": [
|
|
15
|
+
"Agent Mail setup guidance now explicitly forbids telling the human to run setup CLI commands; the agent must run `ouro account ensure`, `ouro connect mail`, `ouro mail import-mbox`, `ouro status`, and `ouro doctor` itself when doing setup.",
|
|
16
|
+
"If the agent's current surface cannot run shell/tools, the setup contract now says to move to a tool-capable Ouro setup session or companion instead of offloading CLI operation to the human.",
|
|
17
|
+
"Prompt and runbook contract tests now cover the live failure mode where the agent says it owns setup but still asks Ari to run `ouro connect mail`."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
4
20
|
{
|
|
5
21
|
"version": "0.1.0-alpha.457",
|
|
6
22
|
"changes": [
|
|
@@ -1911,6 +1911,29 @@ async function applyRuntimeChangeToRunningAgent(agent, deps, onProgress) {
|
|
|
1911
1911
|
return `daemon restart skipped: ${error instanceof Error ? error.message : String(error)}`;
|
|
1912
1912
|
}
|
|
1913
1913
|
}
|
|
1914
|
+
async function applyLocalSenseChangeToRunningDaemon(agent, senseLabel, deps, onProgress) {
|
|
1915
|
+
try {
|
|
1916
|
+
onProgress?.("checking whether Ouro is already running");
|
|
1917
|
+
const alive = await deps.checkSocketAlive(deps.socketPath);
|
|
1918
|
+
if (!alive)
|
|
1919
|
+
return "daemon is not running; next `ouro up` will load the change";
|
|
1920
|
+
onProgress?.(`restarting Ouro so ${senseLabel} is attached in the live sense manager`);
|
|
1921
|
+
const stopped = await withCliTimeout(DEFAULT_AGENT_RESTART_TIMEOUT_MS, "daemon stop request timed out", () => deps.sendCommand(deps.socketPath, { kind: "daemon.stop" }));
|
|
1922
|
+
if (!stopped.ok)
|
|
1923
|
+
return `daemon restart skipped: ${stopped.error ?? stopped.message ?? "unknown daemon error"}`;
|
|
1924
|
+
deps.cleanupStaleSocket(deps.socketPath);
|
|
1925
|
+
const started = await ensureDaemonRunning({
|
|
1926
|
+
...deps,
|
|
1927
|
+
reportDaemonStartupPhase: (message) => onProgress?.(message),
|
|
1928
|
+
}, { initialAlive: false });
|
|
1929
|
+
if (!started.ok)
|
|
1930
|
+
return `daemon restart requested, but startup failed: ${started.message}`;
|
|
1931
|
+
return `restarted Ouro; ${senseLabel} is loaded for ${agent}`;
|
|
1932
|
+
}
|
|
1933
|
+
catch (error) {
|
|
1934
|
+
return `daemon restart skipped: ${error instanceof Error ? error.message : String(error)}`;
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1914
1937
|
async function executeVaultConfigSet(command, deps) {
|
|
1915
1938
|
if (command.agent === "SerpentGuide") {
|
|
1916
1939
|
throw new Error("SerpentGuide does not have persistent runtime credentials. Store credentials in the hatchling agent vault.");
|
|
@@ -2623,6 +2646,7 @@ async function executeConnectBlueBubbles(agent, deps) {
|
|
|
2623
2646
|
const machineId = currentMachineId(deps);
|
|
2624
2647
|
const progress = createHumanCommandProgress(deps, "connect bluebubbles");
|
|
2625
2648
|
let stored;
|
|
2649
|
+
let daemonApply = "not applied";
|
|
2626
2650
|
try {
|
|
2627
2651
|
progress.startPhase("saving BlueBubbles attachment");
|
|
2628
2652
|
progress.updateDetail("checking existing machine runtime config");
|
|
@@ -2649,6 +2673,7 @@ async function executeConnectBlueBubbles(agent, deps) {
|
|
|
2649
2673
|
progress.updateDetail("enabling BlueBubbles in agent.json");
|
|
2650
2674
|
enableAgentSense(agent, "bluebubbles", deps);
|
|
2651
2675
|
progress.completePhase("saving BlueBubbles attachment", "secret stored");
|
|
2676
|
+
daemonApply = await runCommandProgressPhase(progress, "applying BlueBubbles to running Ouro", () => applyLocalSenseChangeToRunningDaemon(agent, "BlueBubbles", deps, (message) => progress.updateDetail(message)), (result) => result);
|
|
2652
2677
|
progress.end();
|
|
2653
2678
|
}
|
|
2654
2679
|
catch (error) {
|
|
@@ -2663,11 +2688,13 @@ async function executeConnectBlueBubbles(agent, deps) {
|
|
|
2663
2688
|
`Machine: ${machineId}`,
|
|
2664
2689
|
`Stored: ${stored.itemPath}`,
|
|
2665
2690
|
"agent.json: senses.bluebubbles.enabled = true",
|
|
2691
|
+
`Runtime: ${daemonApply}`,
|
|
2666
2692
|
"secret was not printed",
|
|
2667
2693
|
...(syncSummary ? [syncSummary] : []),
|
|
2668
2694
|
],
|
|
2669
2695
|
nextMoves: [
|
|
2670
|
-
|
|
2696
|
+
`Point BlueBubbles at this machine's webhook listener on port ${port}${webhookPath}.`,
|
|
2697
|
+
"If BlueBubbles was already pointed there, messages can now reach the agent.",
|
|
2671
2698
|
`Attach other machines separately if ${agent} should use BlueBubbles there too.`,
|
|
2672
2699
|
],
|
|
2673
2700
|
fallbackLines: [
|
|
@@ -2675,9 +2702,10 @@ async function executeConnectBlueBubbles(agent, deps) {
|
|
|
2675
2702
|
`machine: ${machineId}`,
|
|
2676
2703
|
`stored: ${stored.itemPath}`,
|
|
2677
2704
|
"agent.json: senses.bluebubbles.enabled = true",
|
|
2705
|
+
`runtime: ${daemonApply}`,
|
|
2678
2706
|
"secret was not printed",
|
|
2679
2707
|
"",
|
|
2680
|
-
|
|
2708
|
+
`Next: point BlueBubbles at this machine's webhook listener on port ${port}${webhookPath}.`,
|
|
2681
2709
|
...(syncSummary ? [syncSummary] : []),
|
|
2682
2710
|
],
|
|
2683
2711
|
});
|
|
@@ -58,8 +58,6 @@ const agent_config_check_1 = require("./agent-config-check");
|
|
|
58
58
|
const pulse_1 = require("./pulse");
|
|
59
59
|
const socket_client_1 = require("./socket-client");
|
|
60
60
|
const bundle_manifest_1 = require("../../mind/bundle-manifest");
|
|
61
|
-
const http_health_probe_1 = require("./http-health-probe");
|
|
62
|
-
const config_1 = require("../config");
|
|
63
61
|
function parseSocketPath(argv) {
|
|
64
62
|
const socketIndex = argv.indexOf("--socket");
|
|
65
63
|
if (socketIndex >= 0) {
|
|
@@ -128,19 +126,10 @@ const router = new message_router_1.FileMessageRouter();
|
|
|
128
126
|
const senseManager = new sense_manager_1.DaemonSenseManager({
|
|
129
127
|
agents: [...managedAgents],
|
|
130
128
|
});
|
|
131
|
-
/* v8 ignore next 5 -- entry-point wiring: probe factory and HealthMonitor both have full unit tests @preserve */
|
|
132
|
-
let bbPort = 18790;
|
|
133
|
-
try {
|
|
134
|
-
bbPort = (0, config_1.getBlueBubblesChannelConfig)().port;
|
|
135
|
-
}
|
|
136
|
-
catch {
|
|
137
|
-
// Daemon runs without --agent; agent-scoped config may not be available.
|
|
138
|
-
}
|
|
139
|
-
const bbProbe = (0, http_health_probe_1.createHttpHealthProbe)("bluebubbles", bbPort);
|
|
140
129
|
const healthMonitor = new health_monitor_1.HealthMonitor({
|
|
141
130
|
processManager,
|
|
142
131
|
scheduler,
|
|
143
|
-
|
|
132
|
+
senseProbeProvider: () => senseManager.listHealthProbes(),
|
|
144
133
|
alertSink: (message) => {
|
|
145
134
|
(0, runtime_1.emitNervesEvent)({
|
|
146
135
|
level: "error",
|
|
@@ -9,6 +9,7 @@ class HealthMonitor {
|
|
|
9
9
|
diskUsagePercent;
|
|
10
10
|
onCriticalAgent;
|
|
11
11
|
senseProbes;
|
|
12
|
+
senseProbeProvider;
|
|
12
13
|
intervalHandle = null;
|
|
13
14
|
constructor(options) {
|
|
14
15
|
this.processManager = options.processManager;
|
|
@@ -17,6 +18,7 @@ class HealthMonitor {
|
|
|
17
18
|
this.diskUsagePercent = options.diskUsagePercent ?? (() => 0);
|
|
18
19
|
this.onCriticalAgent = options.onCriticalAgent ?? (() => undefined);
|
|
19
20
|
this.senseProbes = options.senseProbes ?? [];
|
|
21
|
+
this.senseProbeProvider = options.senseProbeProvider ?? (() => []);
|
|
20
22
|
}
|
|
21
23
|
startPeriodicChecks(intervalMs) {
|
|
22
24
|
if (this.intervalHandle !== null)
|
|
@@ -113,7 +115,18 @@ class HealthMonitor {
|
|
|
113
115
|
message: `disk usage healthy (${diskPercent}%)`,
|
|
114
116
|
});
|
|
115
117
|
}
|
|
116
|
-
|
|
118
|
+
const senseProbes = [...this.senseProbes];
|
|
119
|
+
try {
|
|
120
|
+
senseProbes.push(...this.senseProbeProvider());
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
results.push({
|
|
124
|
+
name: "sense-probes",
|
|
125
|
+
status: "warn",
|
|
126
|
+
message: `sense probe discovery failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
for (const probe of senseProbes) {
|
|
117
130
|
try {
|
|
118
131
|
const outcome = await probe.check();
|
|
119
132
|
if (outcome.ok) {
|
|
@@ -43,6 +43,7 @@ const runtime_credentials_1 = require("../runtime-credentials");
|
|
|
43
43
|
const sense_truth_1 = require("../sense-truth");
|
|
44
44
|
const machine_identity_1 = require("../machine-identity");
|
|
45
45
|
const process_manager_1 = require("./process-manager");
|
|
46
|
+
const http_health_probe_1 = require("./http-health-probe");
|
|
46
47
|
const DEFAULT_TEAMS_PORT = 3978;
|
|
47
48
|
const DEFAULT_BLUEBUBBLES_PORT = 18790;
|
|
48
49
|
const DEFAULT_BLUEBUBBLES_WEBHOOK_PATH = "/bluebubbles-webhook";
|
|
@@ -352,6 +353,22 @@ class DaemonSenseManager {
|
|
|
352
353
|
.filter((pid) => pid !== null && pid !== undefined);
|
|
353
354
|
}
|
|
354
355
|
/* v8 ignore stop */
|
|
356
|
+
listHealthProbes() {
|
|
357
|
+
const probes = [];
|
|
358
|
+
for (const [agent, context] of this.contexts.entries()) {
|
|
359
|
+
const runtimeConfig = (0, runtime_credentials_1.readRuntimeCredentialConfig)(agent);
|
|
360
|
+
const machineRuntimeConfig = (0, runtime_credentials_1.readMachineRuntimeCredentialConfig)(agent);
|
|
361
|
+
context.facts = senseFactsFromRuntimeConfig(agent, context.senses, runtimeConfig, machineRuntimeConfig);
|
|
362
|
+
if (!context.senses.bluebubbles.enabled || !context.facts.bluebubbles.configured || !machineRuntimeConfig.ok) {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
const machinePayload = machineRuntimeConfig.config;
|
|
366
|
+
const bluebubblesChannel = machinePayload.bluebubblesChannel;
|
|
367
|
+
const port = numberField(bluebubblesChannel, "port", DEFAULT_BLUEBUBBLES_PORT);
|
|
368
|
+
probes.push((0, http_health_probe_1.createHttpHealthProbe)(`bluebubbles:${agent}`, port));
|
|
369
|
+
}
|
|
370
|
+
return probes;
|
|
371
|
+
}
|
|
355
372
|
listSenseRows() {
|
|
356
373
|
const runtime = new Map();
|
|
357
374
|
for (const snapshot of this.processManager.listAgentSnapshots()) {
|
package/dist/mind/prompt.js
CHANGED
|
@@ -465,6 +465,7 @@ function senseRuntimeGuidance(channel, preReadStatusLines) {
|
|
|
465
465
|
lines.push("teams setup truth: run `ouro connect teams --agent <agent>` from the connect bay; it stores Teams runtime/config fields and enables `senses.teams.enabled`.");
|
|
466
466
|
lines.push("bluebubbles setup truth: run `ouro connect bluebubbles --agent <agent>` from the connect bay; it stores this machine's BlueBubbles URL/password/listener config in the agent vault machine runtime item.");
|
|
467
467
|
lines.push("mail setup AX: if a human asks me to set up email, I do not hand them a terminal checklist. I guide the flow end-to-end: name the current phase, run agent-runnable commands myself with shell/tools when available, ask the human only for human-required facts or browser actions, wait for their reply, verify the result, then continue.");
|
|
468
|
+
lines.push("mail setup hard rule: never tell the human to run `ouro account ensure`, `ouro connect mail`, `ouro mail import-mbox`, `ouro status`, or `ouro doctor` for setup. Say what I am about to run, run it myself, and report the result. If my current surface cannot run shell/tools, I ask for a tool-capable Ouro setup session or companion to continue; I do not offload CLI operation to the human.");
|
|
468
469
|
lines.push("mail setup truth: Agent Mail uses Mailroom, not HEY OAuth/IMAP. For the full work substrate account, the agent-runnable command is `ouro account ensure --agent <agent> --owner-email <email> --source hey`; use `ouro connect mail --agent <agent> --owner-email <email> --source hey` for mail-only repair/provisioning, or `--no-delegated-source` for native-only mail. The detailed runbook is `docs/agent-mail-setup.md`.");
|
|
469
470
|
lines.push("mail setup truth: HEY archive bootstrap is human-exported MBOX only. I ask for the browser-downloaded MBOX path, then I run `ouro mail import-mbox --file <path> --owner-email <email> --source hey --agent <agent>` myself and verify the import.");
|
|
470
471
|
lines.push("mail setup truth: verify with `ouro status`, `ouro doctor`, bounded mail tools (`mail_recent`, `mail_search`, `mail_thread`, `mail_access_log`), and the read-only Outlook Mailbox tab. `ouro doctor` is installation-wide; do not invent `ouro doctor --agent <agent>`.");
|