@ouro.bot/cli 0.1.0-alpha.444 → 0.1.0-alpha.446
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 +1 -1
- package/changelog.json +16 -0
- package/dist/heart/daemon/agentic-repair.js +2 -0
- package/dist/heart/daemon/cli-exec.js +3 -11
- package/dist/heart/daemon/connect-bay.js +69 -245
- package/dist/heart/daemon/human-command-screens.js +112 -114
- package/dist/heart/daemon/interactive-repair.js +96 -9
- package/dist/heart/daemon/startup-tui.js +2 -10
- package/dist/heart/daemon/terminal-ui.js +311 -27
- package/dist/heart/daemon/up-progress.js +37 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ Task docs do not live in this repo anymore. Planning and doing docs live in the
|
|
|
99
99
|
- Vault unlock material is local machine state. Prefer macOS Keychain, Windows DPAPI, or Linux Secret Service; plaintext fallback is allowed only by explicit human choice.
|
|
100
100
|
- New vault unlock secrets are confirmed before use and rejected if they do not meet the minimum strength requirements.
|
|
101
101
|
- Provider and runtime credentials are loaded into process memory at startup/auth/unlock/refresh and reused. The remote vault is not queried for every model or sense request.
|
|
102
|
-
- Human TTY commands share one CLI surface family: bare `ouro` opens the home deck, `ouro up
|
|
102
|
+
- Human TTY commands share one CLI surface family: bare `ouro` opens the home deck, `ouro up` uses the boot checklist, `ouro connect`/`ouro auth verify`/`ouro repair` reuse the same readiness truth, and `ouro help`/`ouro whoami`/`ouro versions`/`ouro hatch` render through the same Ouro-branded wizard/guide language instead of raw transcript walls.
|
|
103
103
|
- Human-facing CLI commands that can wait on browser auth, vault IO, daemon startup, daemon restart, provider checks, or connector setup use a shared progress checklist. If a cursor may blink for more than a few seconds, the command should print or animate the current step instead of going quiet.
|
|
104
104
|
- CLI commands that mutate bundle config, such as vault setup or `ouro connect bluebubbles`, run bundle sync after the change when `sync.enabled` is true and report a compact `bundle sync:` line.
|
|
105
105
|
- The daemon discovers bundles dynamically from `~/AgentBundles`.
|
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.446",
|
|
6
|
+
"changes": [
|
|
7
|
+
"`ouro connect`, the home deck, readiness repair prompts, and the interactive repair queue now render through one shared wizard language instead of a mix of framed panels and transcript walls. Humans can choose by number or name, see one recommended next step, and keep the same visual footing across setup and repair.",
|
|
8
|
+
"Connector, auth, vault, hatch, and other info-heavy command flows now use a matching guide surface with the same Ouro masthead, ruled sections, and `Next moves` treatment, so the CLI stops jumping between unrelated visual grammars as soon as a command leaves the root menu.",
|
|
9
|
+
"The new surfaces stay truthful to the underlying work: connect still runs the shared live provider verification path before rendering, repair prompts surface the real next command without dead air, and new renderer plus command-layer coverage lock the wizard/guide family into the shipped CLI."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.1.0-alpha.445",
|
|
14
|
+
"changes": [
|
|
15
|
+
"`ouro up` no longer smears old lines across the screen when the live frame shrinks. The boot checklist and daemon-start polling now share one overwrite primitive, so long waits keep breathing without duplicating the masthead or leaving stale rows behind.",
|
|
16
|
+
"`ouro status` is back to being a compact runtime cockpit instead of a generic wizard board. The TTY command now routes through the dense status deck again, so operators get the fast, scannable view they actually need.",
|
|
17
|
+
"The boot surface itself is lighter and truer: the masthead only uses the wide wordmark when it really fits, the checklist stays in plan order while a middle step is active, and the current-work panel now reads like a real boot sequencer instead of a stack of `Overview` cards."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
4
20
|
{
|
|
5
21
|
"version": "0.1.0-alpha.444",
|
|
6
22
|
"changes": [
|
|
@@ -52,6 +52,8 @@ function makeInteractiveRepairDeps(deps) {
|
|
|
52
52
|
runAuthFlow: deps.runAuthFlow ?? (async () => undefined),
|
|
53
53
|
runVaultUnlock: deps.runVaultUnlock,
|
|
54
54
|
skipQueueSummary: deps.skipQueueSummary,
|
|
55
|
+
isTTY: deps.isTTY,
|
|
56
|
+
stdoutColumns: deps.stdoutColumns,
|
|
55
57
|
};
|
|
56
58
|
}
|
|
57
59
|
async function runDeterministicRepair(degraded, deps) {
|
|
@@ -4316,6 +4316,8 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
4316
4316
|
await executeVaultUnlock({ kind: "vault.unlock", agent }, deps);
|
|
4317
4317
|
},
|
|
4318
4318
|
skipQueueSummary: true,
|
|
4319
|
+
isTTY: deps.isTTY ?? process.stdout.isTTY === true,
|
|
4320
|
+
stdoutColumns: deps.stdoutColumns ?? process.stdout.columns,
|
|
4319
4321
|
});
|
|
4320
4322
|
if (repairResult.repairsAttempted) {
|
|
4321
4323
|
repairsAttempted = true;
|
|
@@ -5756,17 +5758,7 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
5756
5758
|
}
|
|
5757
5759
|
const fallbackMessage = response.summary ?? response.message ?? (response.ok ? "ok" : `error: ${response.error ?? "unknown error"}`);
|
|
5758
5760
|
const message = command.kind === "daemon.status"
|
|
5759
|
-
? (()
|
|
5760
|
-
const payload = (0, cli_render_1.parseStatusPayload)(response.data);
|
|
5761
|
-
if (payload && ttyBoardEnabled(deps)) {
|
|
5762
|
-
return (0, human_command_screens_1.renderHouseStatusScreen)({
|
|
5763
|
-
payload,
|
|
5764
|
-
isTTY: true,
|
|
5765
|
-
columns: deps.stdoutColumns ?? process.stdout.columns,
|
|
5766
|
-
}).trimEnd();
|
|
5767
|
-
}
|
|
5768
|
-
return (0, cli_render_1.formatDaemonStatusOutput)(response, fallbackMessage);
|
|
5769
|
-
})()
|
|
5761
|
+
? (0, cli_render_1.formatDaemonStatusOutput)(response, fallbackMessage)
|
|
5770
5762
|
: fallbackMessage;
|
|
5771
5763
|
deps.writeStdout(message);
|
|
5772
5764
|
return message;
|
|
@@ -17,52 +17,6 @@ const CONNECT_STATUS_PRIORITY = {
|
|
|
17
17
|
ready: 6,
|
|
18
18
|
attached: 6,
|
|
19
19
|
};
|
|
20
|
-
const RESET = "\x1b[0m";
|
|
21
|
-
const BOLD = "\x1b[1m";
|
|
22
|
-
const TEAL = "\x1b[38;2;78;201;176m";
|
|
23
|
-
const GREEN = "\x1b[38;2;46;204;64m";
|
|
24
|
-
const GOLD = "\x1b[38;2;230;190;50m";
|
|
25
|
-
const BONE = "\x1b[38;2;238;242;234m";
|
|
26
|
-
const MIST = "\x1b[38;2;165;184;168m";
|
|
27
|
-
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
28
|
-
function stripAnsi(text) {
|
|
29
|
-
return text.replace(ANSI_RE, "");
|
|
30
|
-
}
|
|
31
|
-
function visibleLength(text) {
|
|
32
|
-
return stripAnsi(text).length;
|
|
33
|
-
}
|
|
34
|
-
function padAnsi(text, width) {
|
|
35
|
-
const missing = Math.max(0, width - visibleLength(text));
|
|
36
|
-
return `${text}${" ".repeat(missing)}`;
|
|
37
|
-
}
|
|
38
|
-
function wrapPlain(text, width) {
|
|
39
|
-
const normalized = text.trim();
|
|
40
|
-
if (!normalized)
|
|
41
|
-
return [""];
|
|
42
|
-
const words = normalized.split(/\s+/);
|
|
43
|
-
const lines = [];
|
|
44
|
-
let current = "";
|
|
45
|
-
for (const word of words) {
|
|
46
|
-
if (!current) {
|
|
47
|
-
current = word;
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const candidate = `${current} ${word}`;
|
|
51
|
-
if (candidate.length <= width) {
|
|
52
|
-
current = candidate;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
lines.push(current);
|
|
56
|
-
current = word;
|
|
57
|
-
}
|
|
58
|
-
lines.push(current);
|
|
59
|
-
return lines;
|
|
60
|
-
}
|
|
61
|
-
function tty(text, color, bold = false) {
|
|
62
|
-
if (bold)
|
|
63
|
-
return `${color}${BOLD}${text}${RESET}`;
|
|
64
|
-
return `${color}${text}${RESET}`;
|
|
65
|
-
}
|
|
66
20
|
function escapeRegExp(value) {
|
|
67
21
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
68
22
|
}
|
|
@@ -133,213 +87,65 @@ function resolveProviderHealthCommand(providerHealth, status) {
|
|
|
133
87
|
function isProblemStatus(status) {
|
|
134
88
|
return status !== "ready" && status !== "attached";
|
|
135
89
|
}
|
|
136
|
-
function
|
|
137
|
-
|
|
138
|
-
? "●"
|
|
139
|
-
: status === "not attached"
|
|
140
|
-
? "◌"
|
|
141
|
-
: "◆";
|
|
142
|
-
const label = `${symbol} ${status}`;
|
|
143
|
-
if (status === "ready" || status === "attached")
|
|
144
|
-
return tty(label, GREEN, true);
|
|
145
|
-
if (status === "not attached")
|
|
146
|
-
return tty(label, MIST);
|
|
147
|
-
return tty(label, GOLD, true);
|
|
148
|
-
}
|
|
149
|
-
function sectionTitle(title, width) {
|
|
150
|
-
const plain = `╭─ ${title} `;
|
|
151
|
-
const rule = "─".repeat(Math.max(0, width - plain.length - 1));
|
|
152
|
-
return `${tty("╭─ ", TEAL)}${tty(title, BONE, true)}${tty(` ${rule}╮`, TEAL)}`;
|
|
153
|
-
}
|
|
154
|
-
function bottomRule(width) {
|
|
155
|
-
const line = `╰${"─".repeat(Math.max(0, width - 2))}╯`;
|
|
156
|
-
return tty(line, TEAL);
|
|
157
|
-
}
|
|
158
|
-
function bodyLine(text, width) {
|
|
159
|
-
const padded = padAnsi(text, Math.max(0, width - 4));
|
|
160
|
-
return `${tty("│ ", TEAL)}${padded}${tty(" │", TEAL)}`;
|
|
161
|
-
}
|
|
162
|
-
function panel(title, body, width) {
|
|
163
|
-
const lines = [sectionTitle(title, width)];
|
|
164
|
-
for (const line of body) {
|
|
165
|
-
lines.push(bodyLine(line, width));
|
|
166
|
-
}
|
|
167
|
-
lines.push(bottomRule(width));
|
|
168
|
-
return lines;
|
|
169
|
-
}
|
|
170
|
-
function renderHeader(agent, width) {
|
|
171
|
-
return panel(`${agent} connections`, [
|
|
172
|
-
tty("Set up or review one capability at a time.", BONE, true),
|
|
173
|
-
tty("Everything on this screen was checked live just now.", MIST),
|
|
174
|
-
], width);
|
|
90
|
+
function providerEntrySummary(entry) {
|
|
91
|
+
return entry.description ?? "Selected provider lanes for this machine.";
|
|
175
92
|
}
|
|
176
|
-
function
|
|
177
|
-
if (!entry) {
|
|
178
|
-
return [
|
|
179
|
-
tty("Everything here is ready.", BONE, true),
|
|
180
|
-
tty("Pick what you want to review or refresh.", MIST),
|
|
181
|
-
];
|
|
182
|
-
}
|
|
183
|
-
const lines = [
|
|
184
|
-
`${entry.name} ${statusChip(entry.status)}`,
|
|
185
|
-
];
|
|
186
|
-
if (entry.nextNote)
|
|
187
|
-
lines.push(entry.nextNote);
|
|
188
|
-
if (entry.nextAction)
|
|
189
|
-
lines.push(tty(entry.nextAction, MIST));
|
|
190
|
-
return lines;
|
|
191
|
-
}
|
|
192
|
-
function renderProviderBody(entry, width) {
|
|
193
|
-
const lines = [
|
|
194
|
-
`${entry.option} ${entry.name} ${statusChip(entry.status)}`,
|
|
195
|
-
];
|
|
196
|
-
const lanes = entry.laneSummaries ?? [];
|
|
197
|
-
for (const [index, lane] of lanes.entries()) {
|
|
198
|
-
if (index > 0)
|
|
199
|
-
lines.push("");
|
|
200
|
-
const laneLabel = lane.lane === "outward" ? "Outward lane" : "Inner lane";
|
|
201
|
-
lines.push(tty(laneLabel, BONE, true));
|
|
202
|
-
lines.push(lane.title);
|
|
203
|
-
lines.push(isProblemStatus(lane.status) ? lane.detail : tty(lane.detail, MIST));
|
|
204
|
-
}
|
|
205
|
-
if (lanes.length === 0) {
|
|
206
|
-
for (const detail of entry.detailLines ?? [])
|
|
207
|
-
lines.push(detail);
|
|
208
|
-
}
|
|
209
|
-
return normalizeWrappedBody(lines, width);
|
|
210
|
-
}
|
|
211
|
-
function renderCapabilityBody(entries, width) {
|
|
93
|
+
function providerEntryDetailLines(entry) {
|
|
212
94
|
const lines = [];
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
lines.push("");
|
|
216
|
-
lines.push(`${entry.option} ${entry.name} ${statusChip(entry.status)}`);
|
|
217
|
-
if (entry.description) {
|
|
218
|
-
lines.push(isProblemStatus(entry.status) ? entry.description : tty(entry.description, MIST));
|
|
219
|
-
}
|
|
220
|
-
for (const detail of entry.detailLines ?? []) {
|
|
221
|
-
lines.push(detail);
|
|
222
|
-
}
|
|
95
|
+
if (entry.nextNote && !/^(Outward|Inner) lane: /.test(entry.nextNote)) {
|
|
96
|
+
lines.push(entry.nextNote);
|
|
223
97
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
for (const line of lines) {
|
|
229
|
-
if (!line) {
|
|
230
|
-
wrapped.push("");
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
const plain = stripAnsi(line);
|
|
234
|
-
if (plain.length <= width - 4) {
|
|
235
|
-
wrapped.push(line);
|
|
236
|
-
continue;
|
|
98
|
+
if (entry.laneSummaries && entry.laneSummaries.length > 0) {
|
|
99
|
+
for (const lane of entry.laneSummaries) {
|
|
100
|
+
const laneLabel = lane.lane === "outward" ? "Outward lane" : "Inner lane";
|
|
101
|
+
lines.push(`${laneLabel}: ${lane.title} — ${lane.detail}`);
|
|
237
102
|
}
|
|
238
|
-
|
|
239
|
-
wrapped.push(...segments);
|
|
103
|
+
return lines;
|
|
240
104
|
}
|
|
241
|
-
return
|
|
105
|
+
return [...lines, ...(entry.detailLines ?? [])];
|
|
242
106
|
}
|
|
243
|
-
function
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
lines.push("");
|
|
248
|
-
lines.push(...panelLines);
|
|
249
|
-
}
|
|
250
|
-
return lines;
|
|
251
|
-
}
|
|
252
|
-
function combineColumns(left, right, leftWidth, rightWidth, gap = 2) {
|
|
253
|
-
const total = Math.max(left.length, right.length);
|
|
254
|
-
const lines = [];
|
|
255
|
-
for (let index = 0; index < total; index += 1) {
|
|
256
|
-
const leftLine = left[index] ?? " ".repeat(leftWidth);
|
|
257
|
-
const rightLine = right[index] ?? " ".repeat(rightWidth);
|
|
258
|
-
lines.push(`${padAnsi(leftLine, leftWidth)}${" ".repeat(gap)}${padAnsi(rightLine, rightWidth)}`);
|
|
259
|
-
}
|
|
260
|
-
return lines;
|
|
261
|
-
}
|
|
262
|
-
function renderTtyBay(entries, options) {
|
|
263
|
-
const columns = Math.max(options.columns ?? 108, 72);
|
|
264
|
-
const fullWidth = Math.max(56, columns - 2);
|
|
265
|
-
const masthead = (0, terminal_ui_1.renderOuroMasthead)({
|
|
266
|
-
isTTY: true,
|
|
267
|
-
columns,
|
|
268
|
-
subtitle: "Set up connections one step at a time.",
|
|
269
|
-
}).trimEnd();
|
|
270
|
-
const header = renderHeader(options.agent, fullWidth);
|
|
271
|
-
const nextEntry = entries.find((entry) => isProblemStatus(entry.status));
|
|
272
|
-
const providerEntry = entries.find((entry) => entry.section === "Providers");
|
|
273
|
-
const portableEntries = entries.filter((entry) => entry.section === "Portable");
|
|
274
|
-
const machineEntries = entries.filter((entry) => entry.section === "This machine");
|
|
275
|
-
const wide = columns >= 118;
|
|
276
|
-
const footer = [
|
|
277
|
-
tty("Choose a number, or type the capability name.", MIST),
|
|
278
|
-
options.prompt,
|
|
107
|
+
function capabilityEntryDetailLines(entry) {
|
|
108
|
+
return [
|
|
109
|
+
...(entry.detailLines ?? []),
|
|
110
|
+
...(entry.nextNote ? [entry.nextNote] : []),
|
|
279
111
|
];
|
|
280
|
-
if (!wide) {
|
|
281
|
-
const panels = [
|
|
282
|
-
header,
|
|
283
|
-
panel("Recommended next step", nextMoveBody(nextEntry), fullWidth),
|
|
284
|
-
panel("Providers", renderProviderBody(providerEntry, fullWidth), fullWidth),
|
|
285
|
-
panel("Portable", renderCapabilityBody(portableEntries, fullWidth), fullWidth),
|
|
286
|
-
panel("This machine", renderCapabilityBody(machineEntries, fullWidth), fullWidth),
|
|
287
|
-
];
|
|
288
|
-
return [masthead, "", ...stackPanels(panels), "", ...footer].join("\n");
|
|
289
|
-
}
|
|
290
|
-
const gap = 2;
|
|
291
|
-
const leftWidth = Math.max(52, Math.floor((fullWidth - gap) / 2));
|
|
292
|
-
const rightWidth = Math.max(40, fullWidth - gap - leftWidth);
|
|
293
|
-
const topRow = combineColumns(panel("Recommended next step", nextMoveBody(nextEntry), leftWidth), panel("This machine", renderCapabilityBody(machineEntries, rightWidth), rightWidth), leftWidth, rightWidth, gap);
|
|
294
|
-
const bottomRow = combineColumns(panel("Providers", renderProviderBody(providerEntry, leftWidth), leftWidth), panel("Portable", renderCapabilityBody(portableEntries, rightWidth), rightWidth), leftWidth, rightWidth, gap);
|
|
295
|
-
return [masthead, "", ...header, "", ...topRow, "", ...bottomRow, "", ...footer].join("\n");
|
|
296
112
|
}
|
|
297
|
-
function
|
|
113
|
+
function entryToWizardItem(entry) {
|
|
114
|
+
return {
|
|
115
|
+
key: entry.option,
|
|
116
|
+
label: entry.name,
|
|
117
|
+
status: entry.status,
|
|
118
|
+
...(entry.section === "Providers"
|
|
119
|
+
? { summary: providerEntrySummary(entry) }
|
|
120
|
+
: entry.description
|
|
121
|
+
? { summary: entry.description }
|
|
122
|
+
: {}),
|
|
123
|
+
detailLines: entry.section === "Providers"
|
|
124
|
+
? providerEntryDetailLines(entry)
|
|
125
|
+
: capabilityEntryDetailLines(entry),
|
|
126
|
+
...(entry.nextAction ? { command: entry.nextAction } : {}),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function nextStepFor(entries) {
|
|
298
130
|
const nextEntry = entries.find((entry) => isProblemStatus(entry.status));
|
|
299
|
-
const lines = [
|
|
300
|
-
`${options.agent} connections`,
|
|
301
|
-
"Set up or review one capability at a time. Provider status was checked live just now.",
|
|
302
|
-
"",
|
|
303
|
-
"Recommended next step",
|
|
304
|
-
"---------------------",
|
|
305
|
-
];
|
|
306
131
|
if (!nextEntry) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (nextEntry.nextNote)
|
|
312
|
-
lines.push(nextEntry.nextNote);
|
|
313
|
-
if (nextEntry.nextAction)
|
|
314
|
-
lines.push(`run: ${nextEntry.nextAction}`);
|
|
315
|
-
}
|
|
316
|
-
lines.push("");
|
|
317
|
-
for (const section of ["Providers", "Portable", "This machine"]) {
|
|
318
|
-
lines.push(section);
|
|
319
|
-
lines.push("-".repeat(Math.max(6, section.length + 4)));
|
|
320
|
-
for (const entry of entries.filter((candidate) => candidate.section === section)) {
|
|
321
|
-
lines.push(`${entry.option}. ${entry.name} [${entry.status}]`);
|
|
322
|
-
if (entry.laneSummaries && entry.laneSummaries.length > 0) {
|
|
323
|
-
for (const lane of entry.laneSummaries) {
|
|
324
|
-
const laneLabel = lane.lane === "outward" ? "Outward lane" : "Inner lane";
|
|
325
|
-
lines.push(` ${laneLabel}: ${lane.title}`);
|
|
326
|
-
lines.push(` ${lane.detail}`);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
for (const detail of entry.detailLines ?? [])
|
|
331
|
-
lines.push(` ${detail}`);
|
|
332
|
-
}
|
|
333
|
-
if (entry.description)
|
|
334
|
-
lines.push(` ${entry.description}`);
|
|
335
|
-
lines.push("");
|
|
336
|
-
}
|
|
132
|
+
return {
|
|
133
|
+
label: "Everything here is already connected.",
|
|
134
|
+
detail: "Pick any capability if you want to review it, refresh it, or change its setup.",
|
|
135
|
+
};
|
|
337
136
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
137
|
+
return {
|
|
138
|
+
label: `Start with ${nextEntry.name}.`,
|
|
139
|
+
detail: nextEntry.nextNote ?? nextEntry.description ?? `Status: ${nextEntry.status}.`,
|
|
140
|
+
command: nextEntry.nextAction,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function sectionToWizard(entries, section, summary) {
|
|
144
|
+
return {
|
|
145
|
+
title: section,
|
|
146
|
+
summary,
|
|
147
|
+
items: entries.filter((entry) => entry.section === section).map((entry) => entryToWizardItem(entry)),
|
|
148
|
+
};
|
|
343
149
|
}
|
|
344
150
|
function summarizeProviderLane(agent, lane, providerHealth) {
|
|
345
151
|
const providerHealthStatus = resolveProviderHealthStatus(providerHealth);
|
|
@@ -450,7 +256,25 @@ function renderConnectBay(entries, options) {
|
|
|
450
256
|
columns: options.columns ?? null,
|
|
451
257
|
},
|
|
452
258
|
});
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
259
|
+
return (0, terminal_ui_1.renderTerminalWizard)({
|
|
260
|
+
isTTY: options.isTTY,
|
|
261
|
+
columns: options.columns,
|
|
262
|
+
masthead: {
|
|
263
|
+
subtitle: "Set up connections one step at a time.",
|
|
264
|
+
},
|
|
265
|
+
title: `Connect ${options.agent}`,
|
|
266
|
+
summary: "Choose one capability to bring online. Each row tells you whether Ouro checked it live just now or is showing saved setup on this machine.",
|
|
267
|
+
nextStep: nextStepFor(entries),
|
|
268
|
+
sections: [
|
|
269
|
+
sectionToWizard(entries, "Providers", "Selected outward and inner lanes for this machine."),
|
|
270
|
+
sectionToWizard(entries, "Portable", "These travel with the agent bundle when their secrets are portable."),
|
|
271
|
+
sectionToWizard(entries, "This machine", "These depend on local attachments or machine-specific setup."),
|
|
272
|
+
],
|
|
273
|
+
footerLines: [
|
|
274
|
+
"6. Not now",
|
|
275
|
+
"Choose a number, or type the capability name.",
|
|
276
|
+
],
|
|
277
|
+
prompt: options.prompt,
|
|
278
|
+
suppressEvent: true,
|
|
279
|
+
});
|
|
456
280
|
}
|