@kal-elsam/kairo-runtime 0.3.0 → 0.4.0

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.
@@ -3,38 +3,60 @@ import { Box, Text } from "ink";
3
3
  import { COCKPIT_COLORS } from "./theme.js";
4
4
  import { CockpitEmptyState } from "./cockpit/primitives.js";
5
5
  import {
6
- formatDiagnosticsLines,
7
- formatLaunchWizardLines,
8
6
  formatProviderLines,
9
7
  formatRunDetailLines,
10
8
  formatRunLines,
9
+ formatSystemHealthLines,
10
+ formatLaunchWizardLines,
11
11
  ORCHESTRATOR_VIEWS,
12
12
  LAUNCH_WIZARD_STEPS
13
13
  } from "./orchestrator-state.js";
14
+ import { windowLinesForLayout } from "./cockpit-models.js";
15
+ import { LAYOUT_MODES } from "./layout.js";
14
16
 
15
17
  export function HomeMissionPanel({ model, colorEnabled = true }) {
18
+ const readiness = model.readiness;
16
19
  return React.createElement(Box, { flexDirection: "column" },
17
20
  React.createElement(Text, {
18
21
  bold: true,
19
22
  color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
20
23
  }, model.title),
21
- React.createElement(Text, { bold: true }, model.recommendedTitle),
24
+ React.createElement(Text, null, model.purpose),
25
+ React.createElement(Text, null, ""),
26
+ React.createElement(Box, { flexDirection: "column" },
27
+ React.createElement(Text, {
28
+ bold: true,
29
+ color: colorEnabled ? COCKPIT_COLORS.primary : undefined
30
+ }, readiness.headline),
31
+ React.createElement(Text, null, readiness.summaryLine),
32
+ ...(readiness.capabilityLines ?? []).map((line) =>
33
+ React.createElement(Text, { key: line, color: COCKPIT_COLORS.muted }, line)
34
+ ),
35
+ React.createElement(Text, null, "")
36
+ ),
37
+ React.createElement(Text, { bold: true }, model.next.title),
22
38
  React.createElement(Text, {
39
+ bold: true,
23
40
  color: colorEnabled ? COCKPIT_COLORS.primary : undefined
24
- }, model.recommendedAction),
41
+ }, model.next.actionTitle),
42
+ React.createElement(Text, null, model.next.actionDetail),
43
+ React.createElement(Text, { color: COCKPIT_COLORS.muted }, model.next.enterHint),
25
44
  React.createElement(Text, null, ""),
26
- React.createElement(Text, { bold: true }, model.activityTitle),
27
- model.emptyHint
45
+ React.createElement(Text, { bold: true }, model.recent.title),
46
+ model.recent.emptyHint
28
47
  ? React.createElement(CockpitEmptyState, {
29
- message: model.emptyHint,
30
- hint: "Enter on Launch run when ready."
48
+ message: model.recent.emptyHint,
49
+ hint: "Enter opens the recommended next step."
31
50
  })
32
- : model.activityLines.map((line) =>
33
- React.createElement(Text, { key: line }, line)
51
+ : React.createElement(Box, { flexDirection: "column" },
52
+ React.createElement(Text, null, model.recent.headline),
53
+ React.createElement(Text, { color: COCKPIT_COLORS.muted }, model.recent.hint)
34
54
  ),
35
- model.moreLine && React.createElement(Text, {
36
- color: COCKPIT_COLORS.muted
37
- }, model.moreLine)
55
+ React.createElement(Text, null, ""),
56
+ React.createElement(Text, { bold: true }, model.explore.title),
57
+ model.explore.lines.map((line) =>
58
+ React.createElement(Text, { key: line, color: COCKPIT_COLORS.muted }, line)
59
+ )
38
60
  );
39
61
  }
40
62
 
@@ -51,6 +73,7 @@ export function renderCockpitView({
51
73
  selectedRun,
52
74
  selectedEvents,
53
75
  homeMission,
76
+ layoutMode = LAYOUT_MODES.COMPACT,
54
77
  colorEnabled = true
55
78
  }) {
56
79
  switch (view) {
@@ -58,34 +81,52 @@ export function renderCockpitView({
58
81
  return React.createElement(HomeMissionPanel, { model: homeMission, colorEnabled });
59
82
  case ORCHESTRATOR_VIEWS.ACTIVE_RUNS:
60
83
  return listBlock(
61
- "Active runs",
62
- formatRunLines(dashboard?.activeRuns ?? [], { emptyMessage: "No active runs." }),
84
+ "Running now",
85
+ formatRunLines(dashboard?.activeRuns ?? [], {
86
+ emptyMessage: "No runs are executing. Open New run to start one.",
87
+ readable: true
88
+ }),
63
89
  listIndex,
64
- colorEnabled
90
+ colorEnabled,
91
+ "Nothing is running yet — that means Kairo is idle, not broken."
65
92
  );
66
93
  case ORCHESTRATOR_VIEWS.RECENT_RUNS:
67
94
  return listBlock(
68
- "Recent runs",
69
- formatRunLines(dashboard?.recentRuns ?? [], { emptyMessage: "No completed runs yet." }),
95
+ "History",
96
+ formatRunLines(dashboard?.recentRuns ?? [], {
97
+ emptyMessage: "No completed runs yet. Create a new run to build history.",
98
+ readable: true
99
+ }),
70
100
  listIndex,
71
- colorEnabled
101
+ colorEnabled,
102
+ "History fills after supervised runs finish."
72
103
  );
73
- case ORCHESTRATOR_VIEWS.PROVIDERS:
104
+ case ORCHESTRATOR_VIEWS.PROVIDERS: {
105
+ const lines = formatProviderLines(dashboard?.providers ?? []);
106
+ const windowed = windowLinesForLayout(lines, layoutMode);
74
107
  return React.createElement(Box, { flexDirection: "column" },
75
- React.createElement(Text, { bold: true }, "Providers"),
76
- formatProviderLines(dashboard?.providers ?? [])
77
- .map((line) => React.createElement(Text, { key: line }, line))
108
+ React.createElement(Text, { bold: true }, "Agents"),
109
+ lines.length === 0
110
+ ? React.createElement(CockpitEmptyState, {
111
+ message: "No agents detected yet.",
112
+ hint: "Open System health or finish setup, then return here."
113
+ })
114
+ : windowed.items.map((line) => React.createElement(Text, { key: line }, line)),
115
+ windowed.moreLine && React.createElement(Text, {
116
+ color: COCKPIT_COLORS.muted
117
+ }, windowed.moreLine)
78
118
  );
119
+ }
79
120
  case ORCHESTRATOR_VIEWS.LAUNCH:
80
121
  if (launchableAgents.length === 0) {
81
122
  return React.createElement(CockpitEmptyState, {
82
- title: "Launch run",
83
- message: "No launchable agents detected.",
84
- hint: "Esc to return · check Diagnostics"
123
+ title: "New run",
124
+ message: "No executable agents are ready. Kairo cannot start a run yet.",
125
+ hint: "Esc to return · open System health or Agents"
85
126
  });
86
127
  }
87
128
  return React.createElement(Box, { flexDirection: "column" },
88
- React.createElement(Text, { bold: true }, "Launch run"),
129
+ React.createElement(Text, { bold: true }, "New run"),
89
130
  formatLaunchWizardLines({
90
131
  step: launchStep,
91
132
  draft: launchDraft,
@@ -105,18 +146,23 @@ export function renderCockpitView({
105
146
  formatRunDetailLines(selectedRun, selectedEvents)
106
147
  .map((line) => React.createElement(Text, { key: line }, line))
107
148
  );
108
- case ORCHESTRATOR_VIEWS.DIAGNOSTICS:
149
+ case ORCHESTRATOR_VIEWS.DIAGNOSTICS: {
150
+ const lines = formatSystemHealthLines(diagnostics);
151
+ const windowed = windowLinesForLayout(lines, layoutMode);
109
152
  return React.createElement(Box, { flexDirection: "column" },
110
- React.createElement(Text, { bold: true }, "Diagnostics"),
111
- formatDiagnosticsLines(diagnostics)
112
- .map((line) => React.createElement(Text, { key: line }, line))
153
+ React.createElement(Text, { bold: true }, "System health"),
154
+ windowed.items.map((line) => React.createElement(Text, { key: line }, line)),
155
+ windowed.moreLine && React.createElement(Text, {
156
+ color: COCKPIT_COLORS.muted
157
+ }, windowed.moreLine)
113
158
  );
159
+ }
114
160
  case ORCHESTRATOR_VIEWS.HELP:
115
161
  return React.createElement(Box, { flexDirection: "column" },
116
162
  React.createElement(Text, { bold: true }, "Help"),
117
- React.createElement(Text, null, "Kairo runtime launches and audits agent CLIs you manage."),
118
- React.createElement(Text, null, "↑↓ navigate · Tab region · Enter open · Esc back/exit"),
119
- React.createElement(Text, null, "R refresh · C cancel active run · ? toggle help"),
163
+ React.createElement(Text, null, "Kairo coordinates installed AI agents with controlled, auditable runs."),
164
+ React.createElement(Text, null, "↑↓ navigate · Enter open recommended or selected section · Esc back/exit"),
165
+ React.createElement(Text, null, "Tab region (lists / New run) · R refresh/retry · C cancel · ? help"),
120
166
  React.createElement(Text, null, "CLI: kairo run --agent <id> --task \"...\""),
121
167
  React.createElement(Text, null, "Audit trail: ~/.harness/runs/<runId>/")
122
168
  );
@@ -127,14 +173,20 @@ export function renderCockpitView({
127
173
  }
128
174
  }
129
175
 
130
- function listBlock(title, lines, listIndex, colorEnabled) {
176
+ function listBlock(title, lines, listIndex, colorEnabled, emptyHint) {
177
+ const isEmpty = lines.length === 1 && /no |nothing |empty/i.test(lines[0]);
131
178
  return React.createElement(Box, { flexDirection: "column" },
132
179
  React.createElement(Text, { bold: true }, title),
133
- lines.map((line, index) => React.createElement(Text, {
134
- key: `${index}-${line}`,
135
- bold: index === listIndex,
136
- color: index === listIndex && colorEnabled ? COCKPIT_COLORS.primary : undefined
137
- }, `${index === listIndex ? "› " : " "}${line}`))
180
+ isEmpty
181
+ ? React.createElement(CockpitEmptyState, {
182
+ message: lines[0],
183
+ hint: emptyHint
184
+ })
185
+ : lines.map((line, index) => React.createElement(Text, {
186
+ key: `${index}-${line}`,
187
+ bold: index === listIndex,
188
+ color: index === listIndex && colorEnabled ? COCKPIT_COLORS.primary : undefined
189
+ }, `${index === listIndex ? "› " : " "}${line}`))
138
190
  );
139
191
  }
140
192
 
@@ -5,7 +5,8 @@ import {
5
5
  } from "./orchestrator-state.js";
6
6
 
7
7
  /**
8
- * Launch-wizard key handler. Returns true when the key was consumed.
8
+ * Launch-wizard key handler.
9
+ * Returns true when consumed, "retreated" when Esc stepped back, false otherwise.
9
10
  */
10
11
  export function handleLaunchInput(ctx) {
11
12
  const {
@@ -22,9 +23,18 @@ export function handleLaunchInput(ctx) {
22
23
  setLaunchPermissionIndex,
23
24
  setError,
24
25
  handleLaunch,
25
- reload
26
+ reload,
27
+ allowEscapeRetreat = false
26
28
  } = ctx;
27
29
 
30
+ if (allowEscapeRetreat && key.escape) {
31
+ if (launchStep === LAUNCH_WIZARD_STEPS.AGENT) {
32
+ return false;
33
+ }
34
+ setLaunchStep(retreatLaunchWizardStep(launchStep));
35
+ return "retreated";
36
+ }
37
+
28
38
  if (launchStep === LAUNCH_WIZARD_STEPS.AGENT) {
29
39
  if (key.upArrow) {
30
40
  setLaunchAgentIndex((index) => Math.max(0, index - 1));
@@ -87,7 +97,7 @@ export function handleLaunchInput(ctx) {
87
97
  }
88
98
  if (key.escape) {
89
99
  setLaunchStep(retreatLaunchWizardStep(launchStep));
90
- return true;
100
+ return allowEscapeRetreat ? "retreated" : true;
91
101
  }
92
102
  }
93
103
 
@@ -8,9 +8,12 @@ import {
8
8
  import {
9
9
  createCockpitUiState,
10
10
  reduceCockpitUi,
11
- resolveNavAction
11
+ resolveNavAction,
12
+ routeCockpitKey,
13
+ isContentInteractiveView
12
14
  } from "./cockpit-controller.js";
13
15
  import {
16
+ COCKPIT_NAV,
14
17
  COCKPIT_REGIONS,
15
18
  buildFooterModel,
16
19
  buildHomeMissionModel,
@@ -19,6 +22,8 @@ import {
19
22
  buildTopBarModel,
20
23
  resolveProjectName
21
24
  } from "./cockpit-models.js";
25
+ import { openRecommendedDestination } from "./cockpit-home.js";
26
+ import { resolveProjectReadiness } from "../dashboard-guidance.js";
22
27
  import { CockpitShell } from "./cockpit/primitives.js";
23
28
  import { renderCockpitView } from "./cockpit-views.js";
24
29
  import { handleLaunchInput } from "./launch-input.js";
@@ -64,8 +69,61 @@ export function OrchestratorApp({
64
69
  exit();
65
70
  };
66
71
 
72
+ const openDestination = (recommendation) => {
73
+ const destination = openRecommendedDestination(recommendation, { navItems: COCKPIT_NAV });
74
+ if (!destination) return false;
75
+ if (destination.action === "launch") {
76
+ data.resetLaunchWizard();
77
+ }
78
+ dispatch({
79
+ type: "set-view",
80
+ view: destination.view,
81
+ navIndex: destination.navIndex ?? undefined
82
+ });
83
+ return true;
84
+ };
85
+
67
86
  useInput((inputKey, key) => {
87
+ if (data.loading) return;
88
+
89
+ if (data.error) {
90
+ if (key.escape) {
91
+ finish({ cancelled: true });
92
+ return;
93
+ }
94
+ if (inputKey.toLowerCase() === "r") {
95
+ data.setError(null);
96
+ data.reload().catch((reloadError) => {
97
+ data.setError(reloadError instanceof Error ? reloadError.message : String(reloadError));
98
+ });
99
+ }
100
+ return;
101
+ }
102
+
103
+ if (data.busy) return;
104
+
68
105
  if (key.escape) {
106
+ if (ui.view === ORCHESTRATOR_VIEWS.LAUNCH && data.launchableAgents.length > 0) {
107
+ const retreated = handleLaunchInput({
108
+ key,
109
+ inputKey,
110
+ launchStep: data.launchStep,
111
+ launchDraft: data.launchDraft,
112
+ launchableAgents: data.launchableAgents,
113
+ launchAgentIndex: data.launchAgentIndex,
114
+ launchPermissionIndex: data.launchPermissionIndex,
115
+ setLaunchAgentIndex: data.setLaunchAgentIndex,
116
+ setLaunchDraft: data.setLaunchDraft,
117
+ setLaunchStep: data.setLaunchStep,
118
+ setLaunchPermissionIndex: data.setLaunchPermissionIndex,
119
+ setError: data.setError,
120
+ handleLaunch: (draft) => data.handleLaunch(draft, data.dashboard?.profile, dispatch),
121
+ reload: data.reload,
122
+ allowEscapeRetreat: true
123
+ });
124
+ if (retreated === "retreated") return;
125
+ }
126
+
69
127
  const next = reduceCockpitUi(ui, { type: "escape" });
70
128
  if (next.shouldExit) {
71
129
  finish({ cancelled: true });
@@ -77,14 +135,54 @@ export function OrchestratorApp({
77
135
  return;
78
136
  }
79
137
 
80
- if (data.loading || data.error || data.busy) return;
81
-
82
138
  if (inputKey === "?") {
83
139
  dispatch({ type: "toggle-help" });
84
140
  return;
85
141
  }
142
+
143
+ const listLength = ui.view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS
144
+ ? (data.dashboard?.activeRuns ?? []).length
145
+ : ui.view === ORCHESTRATOR_VIEWS.RECENT_RUNS
146
+ ? (data.dashboard?.recentRuns ?? []).length
147
+ : 0;
148
+
149
+ let routed = null;
86
150
  if (key.tab) {
87
- dispatch({ type: "tab" });
151
+ routed = routeCockpitKey(ui, { type: "tab" });
152
+ } else if (key.upArrow || key.downArrow) {
153
+ routed = routeCockpitKey(ui, {
154
+ type: "arrow",
155
+ direction: key.upArrow ? "up" : "down",
156
+ listLength
157
+ });
158
+ } else if (key.return) {
159
+ routed = routeCockpitKey(ui, { type: "enter" });
160
+ }
161
+
162
+ if (routed) {
163
+ if (routed.type === "enter-nav") {
164
+ const item = resolveNavAction(ui.navIndex);
165
+ if (item?.id === "overview" || item?.view === ORCHESTRATOR_VIEWS.HOME) {
166
+ const mission = buildHomeMissionModel({
167
+ projectName: resolveProjectName(workspaceRoot),
168
+ hasGlobalState,
169
+ diagnostics: data.diagnostics,
170
+ dashboard: data.dashboard,
171
+ layoutMode: ui.layoutMode ?? LAYOUT_MODES.COMPACT
172
+ });
173
+ if (openDestination(mission.next)) return;
174
+ }
175
+ if (item?.action === "launch") {
176
+ data.resetLaunchWizard();
177
+ dispatch({
178
+ type: "set-view",
179
+ view: ORCHESTRATOR_VIEWS.LAUNCH,
180
+ navIndex: ui.navIndex
181
+ });
182
+ return;
183
+ }
184
+ }
185
+ dispatch(routed);
88
186
  return;
89
187
  }
90
188
 
@@ -109,22 +207,14 @@ export function OrchestratorApp({
109
207
  }
110
208
  }
111
209
 
112
- if (ui.view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS || ui.view === ORCHESTRATOR_VIEWS.RECENT_RUNS) {
210
+ if (ui.region === COCKPIT_REGIONS.CONTENT
211
+ && (ui.view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS || ui.view === ORCHESTRATOR_VIEWS.RECENT_RUNS)
212
+ && key.return) {
113
213
  const runs = ui.view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS
114
214
  ? data.dashboard?.activeRuns ?? []
115
215
  : data.dashboard?.recentRuns ?? [];
116
- if (key.upArrow || key.downArrow) {
117
- dispatch({
118
- type: "arrow",
119
- direction: key.upArrow ? "up" : "down",
120
- listLength: runs.length
121
- });
122
- return;
123
- }
124
- if (key.return) {
125
- data.openRunDetail(selectRunFromList(runs, ui.listIndex), dispatch);
126
- return;
127
- }
216
+ data.openRunDetail(selectRunFromList(runs, ui.listIndex), dispatch, ui.view);
217
+ return;
128
218
  }
129
219
 
130
220
  if (ui.view === ORCHESTRATOR_VIEWS.RUN_DETAIL) {
@@ -133,7 +223,7 @@ export function OrchestratorApp({
133
223
  return;
134
224
  }
135
225
  if (inputKey.toLowerCase() === "r") {
136
- data.openRunDetail(data.selectedRun, dispatch);
226
+ data.openRunDetail(data.selectedRun, dispatch, ui.returnView);
137
227
  return;
138
228
  }
139
229
  }
@@ -142,23 +232,6 @@ export function OrchestratorApp({
142
232
  data.reload().catch((reloadError) => {
143
233
  data.setError(reloadError instanceof Error ? reloadError.message : String(reloadError));
144
234
  });
145
- return;
146
- }
147
-
148
- if (ui.view === ORCHESTRATOR_VIEWS.HOME || ui.region === COCKPIT_REGIONS.NAV) {
149
- if (key.upArrow || key.downArrow) {
150
- dispatch({ type: "arrow", direction: key.upArrow ? "up" : "down" });
151
- return;
152
- }
153
- if (key.return) {
154
- const item = resolveNavAction(ui.navIndex);
155
- if (item?.action === "launch") {
156
- data.resetLaunchWizard();
157
- dispatch({ type: "set-view", view: ORCHESTRATOR_VIEWS.LAUNCH });
158
- return;
159
- }
160
- dispatch({ type: "enter-nav" });
161
- }
162
235
  }
163
236
  });
164
237
 
@@ -173,13 +246,26 @@ export function OrchestratorApp({
173
246
  return React.createElement(Box, { flexDirection: "column" },
174
247
  React.createElement(Text, { bold: true, color: COCKPIT_COLORS.danger }, "Runtime error"),
175
248
  React.createElement(Text, null, data.error),
176
- React.createElement(Text, { dimColor: true }, "Esc to exit")
249
+ React.createElement(Text, { dimColor: true }, "R Retry · Esc to exit")
177
250
  );
178
251
  }
179
252
 
180
253
  const mode = ui.layoutMode ?? LAYOUT_MODES.COMPACT;
181
254
  const colorEnabled = caps.color;
182
255
  const unicode = caps.unicode;
256
+ const projectName = resolveProjectName(workspaceRoot);
257
+ const readiness = resolveProjectReadiness({
258
+ hasGlobalState,
259
+ diagnostics: data.diagnostics,
260
+ dashboard: data.dashboard
261
+ });
262
+ const homeMission = buildHomeMissionModel({
263
+ projectName,
264
+ hasGlobalState,
265
+ diagnostics: data.diagnostics,
266
+ dashboard: data.dashboard,
267
+ layoutMode: mode
268
+ });
183
269
 
184
270
  return React.createElement(Box, { flexDirection: "column" },
185
271
  data.statusMessage && React.createElement(Text, {
@@ -187,8 +273,8 @@ export function OrchestratorApp({
187
273
  }, data.statusMessage),
188
274
  React.createElement(CockpitShell, {
189
275
  topBar: buildTopBarModel({
190
- projectName: resolveProjectName(workspaceRoot),
191
- systemOnline: true,
276
+ projectName,
277
+ systemOnline: readiness.kind !== "needs_setup",
192
278
  unicode
193
279
  }),
194
280
  footer: buildFooterModel({
@@ -201,13 +287,16 @@ export function OrchestratorApp({
201
287
  layoutMode: mode,
202
288
  nav: buildNavModel({
203
289
  navIndex: ui.navIndex,
204
- focused: ui.region === COCKPIT_REGIONS.NAV,
205
- unicode
290
+ currentView: ui.view,
291
+ focused: ui.region === COCKPIT_REGIONS.NAV || !isContentInteractiveView(ui.view),
292
+ unicode,
293
+ dashboard: data.dashboard,
294
+ diagnostics: data.diagnostics
206
295
  }),
207
296
  system: buildSystemStripModel({
208
297
  dashboard: data.dashboard,
209
298
  diagnostics: data.diagnostics,
210
- healthKind: "ready"
299
+ readiness
211
300
  }),
212
301
  navFocused: ui.region === COCKPIT_REGIONS.NAV,
213
302
  contentFocused: ui.region === COCKPIT_REGIONS.CONTENT,
@@ -226,15 +315,8 @@ export function OrchestratorApp({
226
315
  launchableAgents: data.launchableAgents,
227
316
  selectedRun: data.selectedRun,
228
317
  selectedEvents: data.selectedEvents,
229
- homeMission: buildHomeMissionModel({
230
- hasGlobalState,
231
- diagnostics: data.diagnostics,
232
- dashboard: data.dashboard,
233
- layoutMode: mode,
234
- activityLines: (data.dashboard?.recentRuns ?? []).map((run) =>
235
- `${run.runId} ${run.state} ${run.agentId}`
236
- )
237
- }),
318
+ homeMission,
319
+ layoutMode: mode,
238
320
  colorEnabled
239
321
  })
240
322
  )
@@ -23,11 +23,11 @@ export const ORCHESTRATOR_VIEWS = {
23
23
  };
24
24
 
25
25
  export const ORCHESTRATOR_MENU = [
26
- { id: "active", label: "Active runs", view: ORCHESTRATOR_VIEWS.ACTIVE_RUNS },
27
- { id: "recent", label: "Recent runs", view: ORCHESTRATOR_VIEWS.RECENT_RUNS },
28
- { id: "providers", label: "Providers", view: ORCHESTRATOR_VIEWS.PROVIDERS },
29
- { id: "launch", label: "Launch run", view: ORCHESTRATOR_VIEWS.LAUNCH, action: "launch" },
30
- { id: "diagnostics", label: "Diagnostics", view: ORCHESTRATOR_VIEWS.DIAGNOSTICS },
26
+ { id: "active", label: "Running now", view: ORCHESTRATOR_VIEWS.ACTIVE_RUNS },
27
+ { id: "recent", label: "History", view: ORCHESTRATOR_VIEWS.RECENT_RUNS },
28
+ { id: "providers", label: "Agents", view: ORCHESTRATOR_VIEWS.PROVIDERS },
29
+ { id: "launch", label: "New run", view: ORCHESTRATOR_VIEWS.LAUNCH, action: "launch" },
30
+ { id: "diagnostics", label: "System health", view: ORCHESTRATOR_VIEWS.DIAGNOSTICS },
31
31
  { id: "help", label: "Help", view: ORCHESTRATOR_VIEWS.HELP }
32
32
  ];
33
33
 
@@ -157,13 +157,22 @@ export function shiftMenuIndex(currentIndex, direction, menuLength = ORCHESTRATO
157
157
  return Math.min(menuLength - 1, Math.max(0, currentIndex + delta));
158
158
  }
159
159
 
160
- export function formatRunLines(runs, { emptyMessage = "No runs." } = {}) {
160
+ export function formatRunLines(runs, {
161
+ emptyMessage = "No runs.",
162
+ readable = false
163
+ } = {}) {
161
164
  if (!runs || runs.length === 0) return [emptyMessage];
162
165
 
163
166
  return runs.map((run) => {
164
- const state = run.state.padEnd(12);
165
- const agent = run.agentId.padEnd(10);
166
- return `${run.runId} ${state} ${agent} ${formatTaskLabel(run)}`;
167
+ const agent = humanizeToken(run.agentId);
168
+ const state = humanizeRunState(run.state);
169
+ const task = formatTaskLabel(run);
170
+ if (readable) {
171
+ return `${agent} · ${state} · ${task}`;
172
+ }
173
+ const statePad = run.state.padEnd(12);
174
+ const agentPad = run.agentId.padEnd(10);
175
+ return `${run.runId} ${statePad} ${agentPad} ${task}`;
167
176
  });
168
177
  }
169
178
 
@@ -181,17 +190,42 @@ export function formatProviderLines(providers) {
181
190
  }
182
191
 
183
192
  export function formatDiagnosticsLines(diagnostics) {
193
+ return formatSystemHealthLines(diagnostics);
194
+ }
195
+
196
+ export function formatSystemHealthLines(diagnostics) {
184
197
  const summary = diagnostics?.diagnostics;
198
+ const intelligence = diagnostics?.intelligence?.summary;
199
+ const profile = diagnostics?.profile;
200
+ const capabilities = diagnostics?.capabilities ?? [];
201
+ const authKnown = capabilities.filter((entry) => entry.authenticated != null);
202
+ const authReady = authKnown.filter((entry) => entry.authenticated).length;
203
+
185
204
  const lines = [
186
- "Summary",
187
- `CLI version: ${diagnostics?.cliVersion ?? "unknown"}`,
188
- `Agents detected: ${summary?.detected ?? 0}/${diagnostics?.capabilities?.length ?? 0}`,
205
+ "Agents",
206
+ `Detected: ${summary?.detected ?? 0}/${capabilities.length}`,
189
207
  `Available: ${summary?.available ?? 0}`,
190
208
  `Unknown: ${summary?.unknown ?? 0}`,
191
209
  `Errors: ${summary?.errors ?? 0}`,
210
+ ...formatAgentStatusLines(capabilities),
211
+ "",
212
+ "Intelligence",
213
+ intelligence?.localAvailable
214
+ ? "Local backend available"
215
+ : "Local backend unavailable",
216
+ intelligence?.cloudAuthenticated
217
+ ? "Cloud backend authenticated"
218
+ : "Cloud backend not configured",
219
+ `Routing: ${diagnostics?.intelligence?.routingPreview?.reason ?? "n/a"}`,
220
+ "",
221
+ "Authentication",
222
+ authKnown.length === 0
223
+ ? "No agent authentication signals yet"
224
+ : `${authReady}/${authKnown.length} agents report ready auth`,
192
225
  "",
193
- "Agent capabilities",
194
- ...formatAgentStatusLines(diagnostics?.capabilities ?? [])
226
+ "Configuration",
227
+ `CLI version: ${diagnostics?.cliVersion ?? "unknown"}`,
228
+ `Profile sources: ${(profile?.sources ?? []).join(", ") || "none"}`
195
229
  ];
196
230
 
197
231
  const recommendations = diagnostics?.recommendations ?? [];
@@ -265,6 +299,29 @@ export function isRunCancellable(run) {
265
299
  return run && isActiveRunState(run.state);
266
300
  }
267
301
 
302
+ function humanizeToken(value) {
303
+ const raw = String(value ?? "agent");
304
+ return raw.charAt(0).toUpperCase() + raw.slice(1);
305
+ }
306
+
307
+ function humanizeRunState(state) {
308
+ switch (state) {
309
+ case "succeeded":
310
+ case "completed":
311
+ return "Succeeded";
312
+ case "failed":
313
+ return "Failed";
314
+ case "cancelled":
315
+ case "canceled":
316
+ return "Cancelled";
317
+ case "running":
318
+ case "starting":
319
+ return "Running";
320
+ default:
321
+ return humanizeToken(state);
322
+ }
323
+ }
324
+
268
325
  function summarizeEvent(event) {
269
326
  if (event.type === "agent.tool_call") {
270
327
  return event.data?.tool_name ?? event.data?.name ?? "tool";
@@ -19,7 +19,10 @@ export const STATUS_LABELS = {
19
19
  offline: "Offline",
20
20
  local: "Local",
21
21
  online: "ONLINE",
22
- loading: "Loading"
22
+ loading: "Loading",
23
+ needs_setup: "Needs setup",
24
+ needs_attention: "Needs attention",
25
+ limited: "Limited"
23
26
  };
24
27
 
25
28
  export const COCKPIT_GLYPHS = {
@@ -55,9 +58,12 @@ export function statusColor(kind, { colorEnabled = true } = {}) {
55
58
  return COCKPIT_COLORS.success;
56
59
  case "warn":
57
60
  case "warning":
61
+ case "needs_setup":
62
+ case "limited":
58
63
  return COCKPIT_COLORS.warning;
59
64
  case "error":
60
65
  case "danger":
66
+ case "needs_attention":
61
67
  return COCKPIT_COLORS.danger;
62
68
  case "offline":
63
69
  case "muted":