@ouro.bot/cli 0.1.0-alpha.410 → 0.1.0-alpha.411

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.411",
6
+ "changes": [
7
+ "`ouro up` interactive repair now re-evaluates each agent after a successful vault-unlock or provider-auth, so users see immediate confirmation or an updated next step instead of stale context.",
8
+ "Repair prompts now include agent names (`Unlock slugger's vault now?`) instead of generic phrasing.",
9
+ "Terminal `Repair flow complete.` message printed when at least one repair was attempted, giving clear closure to the interactive flow.",
10
+ "Redundant repair queue summary suppressed in the post-daemon-start path where the status block already listed degraded agents."
11
+ ]
12
+ },
4
13
  {
5
14
  "version": "0.1.0-alpha.410",
6
15
  "changes": [
@@ -51,6 +51,7 @@ function makeInteractiveRepairDeps(deps) {
51
51
  /* v8 ignore next -- fallback no-op: tests always inject runAuthFlow; default is for production @preserve */
52
52
  runAuthFlow: deps.runAuthFlow ?? (async () => undefined),
53
53
  runVaultUnlock: deps.runVaultUnlock,
54
+ skipQueueSummary: deps.skipQueueSummary,
54
55
  };
55
56
  }
56
57
  async function runDeterministicRepair(degraded, deps) {
@@ -2677,6 +2677,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
2677
2677
  runVaultUnlock: async (agent) => {
2678
2678
  await executeVaultUnlock({ kind: "vault.unlock", agent }, deps);
2679
2679
  },
2680
+ skipQueueSummary: true,
2680
2681
  });
2681
2682
  if (repairResult.repairsAttempted) {
2682
2683
  const repairedAgents = daemonResult.stability.degraded
@@ -182,6 +182,97 @@ function writeRepairQueueSummary(degraded, deps) {
182
182
  if (lines.length > 0)
183
183
  deps.writeStdout(lines.join("\n"));
184
184
  }
185
+ async function attemptVaultUnlock(entry, action, deps) {
186
+ deps.writeStdout(renderActionPromptLines(entry.agent, action).join("\n"));
187
+ const answer = await deps.promptInput(`Unlock ${entry.agent}'s vault now? [y/N] `);
188
+ if (!isAffirmativeAnswer(answer)) {
189
+ writeDeclinedRepair(entry, action.command, deps);
190
+ return { succeeded: false, attempted: false };
191
+ }
192
+ try {
193
+ if (!deps.runVaultUnlock) {
194
+ deps.writeStdout(renderManualRepairHint(entry.agent, entry.fixHint));
195
+ return { succeeded: false, attempted: false };
196
+ }
197
+ await deps.runVaultUnlock(entry.agent);
198
+ return { succeeded: true, attempted: true };
199
+ }
200
+ catch (error) {
201
+ const msg = error instanceof Error ? error.message : String(error);
202
+ deps.writeStdout(`Vault unlock did not finish for ${entry.agent}.\n ${msg}`);
203
+ (0, runtime_1.emitNervesEvent)({
204
+ level: "error",
205
+ component: "daemon",
206
+ event: "daemon.interactive_repair_vault_unlock_error",
207
+ message: `vault unlock failed for ${entry.agent}`,
208
+ meta: { agent: entry.agent, error: msg },
209
+ });
210
+ return { succeeded: false, attempted: true };
211
+ }
212
+ }
213
+ async function attemptProviderAuth(entry, action, deps) {
214
+ deps.writeStdout(renderActionPromptLines(entry.agent, action).join("\n"));
215
+ const answer = await deps.promptInput(`Open the auth flow for ${entry.agent} now? [y/N] `);
216
+ if (!isAffirmativeAnswer(answer)) {
217
+ writeDeclinedRepair(entry, action.command, deps);
218
+ return { succeeded: false, attempted: false };
219
+ }
220
+ try {
221
+ if (action.provider) {
222
+ await deps.runAuthFlow(entry.agent, action.provider);
223
+ }
224
+ else {
225
+ await deps.runAuthFlow(entry.agent);
226
+ }
227
+ return { succeeded: true, attempted: true };
228
+ }
229
+ catch (error) {
230
+ const msg = error instanceof Error ? error.message : String(error);
231
+ deps.writeStdout(`Auth did not finish for ${entry.agent}.\n ${msg}`);
232
+ (0, runtime_1.emitNervesEvent)({
233
+ level: "error",
234
+ component: "daemon",
235
+ event: "daemon.interactive_repair_auth_error",
236
+ message: `auth flow failed for ${entry.agent}`,
237
+ meta: { agent: entry.agent, error: msg },
238
+ });
239
+ return { succeeded: false, attempted: true };
240
+ }
241
+ }
242
+ async function processEntry(entry, deps) {
243
+ let current = entry;
244
+ while (current) {
245
+ const action = runnableRepairActionFor(current);
246
+ let outcome;
247
+ if (action?.kind === "vault-unlock") {
248
+ outcome = await attemptVaultUnlock(current, action, deps);
249
+ }
250
+ else if (action?.kind === "provider-auth") {
251
+ outcome = await attemptProviderAuth(current, action, deps);
252
+ }
253
+ else if (isConfigError(current)) {
254
+ deps.writeStdout(renderManualRepairHint(current.agent, current.fixHint));
255
+ return { attempted: false };
256
+ }
257
+ else {
258
+ deps.writeStdout(renderUnknownRepair(current.agent, current.errorReason));
259
+ return { attempted: false };
260
+ }
261
+ if (!outcome.succeeded || !deps.recheckAgent) {
262
+ return { attempted: outcome.attempted };
263
+ }
264
+ // Re-evaluate the agent after successful repair
265
+ const recheckResult = await deps.recheckAgent(current.agent);
266
+ if (recheckResult === null) {
267
+ deps.writeStdout(`${current.agent} recovered.`);
268
+ return { attempted: true };
269
+ }
270
+ // Agent still degraded with a new error -- loop to present the new action
271
+ current = recheckResult;
272
+ }
273
+ /* v8 ignore next -- unreachable: loop always returns from within @preserve */
274
+ return { attempted: false };
275
+ }
185
276
  async function runInteractiveRepair(degraded, deps) {
186
277
  (0, runtime_1.emitNervesEvent)({
187
278
  level: "info",
@@ -194,76 +285,16 @@ async function runInteractiveRepair(degraded, deps) {
194
285
  return { repairsAttempted: false };
195
286
  }
196
287
  let repairsAttempted = false;
197
- writeRepairQueueSummary(degraded, deps);
288
+ if (!deps.skipQueueSummary) {
289
+ writeRepairQueueSummary(degraded, deps);
290
+ }
198
291
  for (const entry of degraded) {
199
- const action = runnableRepairActionFor(entry);
200
- if (action?.kind === "vault-unlock") {
201
- deps.writeStdout(renderActionPromptLines(entry.agent, action).join("\n"));
202
- const answer = await deps.promptInput("Unlock it now? [y/N] ");
203
- if (isAffirmativeAnswer(answer)) {
204
- try {
205
- if (!deps.runVaultUnlock) {
206
- deps.writeStdout(renderManualRepairHint(entry.agent, entry.fixHint));
207
- }
208
- else {
209
- await deps.runVaultUnlock(entry.agent);
210
- repairsAttempted = true;
211
- }
212
- }
213
- catch (error) {
214
- const msg = error instanceof Error ? error.message : String(error);
215
- deps.writeStdout(`Vault unlock did not finish for ${entry.agent}.\n ${msg}`);
216
- repairsAttempted = true;
217
- (0, runtime_1.emitNervesEvent)({
218
- level: "error",
219
- component: "daemon",
220
- event: "daemon.interactive_repair_vault_unlock_error",
221
- message: `vault unlock failed for ${entry.agent}`,
222
- meta: { agent: entry.agent, error: msg },
223
- });
224
- }
225
- }
226
- else {
227
- writeDeclinedRepair(entry, action.command, deps);
228
- }
229
- }
230
- else if (action?.kind === "provider-auth") {
231
- deps.writeStdout(renderActionPromptLines(entry.agent, action).join("\n"));
232
- const answer = await deps.promptInput("Open the auth flow now? [y/N] ");
233
- if (isAffirmativeAnswer(answer)) {
234
- try {
235
- if (action.provider) {
236
- await deps.runAuthFlow(entry.agent, action.provider);
237
- }
238
- else {
239
- await deps.runAuthFlow(entry.agent);
240
- }
241
- repairsAttempted = true;
242
- }
243
- catch (error) {
244
- const msg = error instanceof Error ? error.message : String(error);
245
- deps.writeStdout(`Auth did not finish for ${entry.agent}.\n ${msg}`);
246
- repairsAttempted = true;
247
- (0, runtime_1.emitNervesEvent)({
248
- level: "error",
249
- component: "daemon",
250
- event: "daemon.interactive_repair_auth_error",
251
- message: `auth flow failed for ${entry.agent}`,
252
- meta: { agent: entry.agent, error: msg },
253
- });
254
- }
255
- }
256
- else {
257
- writeDeclinedRepair(entry, action.command, deps);
258
- }
259
- }
260
- else if (isConfigError(entry)) {
261
- deps.writeStdout(renderManualRepairHint(entry.agent, entry.fixHint));
262
- }
263
- else {
264
- // Unknown error with no actionable fix hint
265
- deps.writeStdout(renderUnknownRepair(entry.agent, entry.errorReason));
266
- }
292
+ const result = await processEntry(entry, deps);
293
+ if (result.attempted)
294
+ repairsAttempted = true;
295
+ }
296
+ if (repairsAttempted) {
297
+ deps.writeStdout("Repair flow complete.");
267
298
  }
268
299
  (0, runtime_1.emitNervesEvent)({
269
300
  level: "info",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.410",
3
+ "version": "0.1.0-alpha.411",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",