@kal-elsam/kairo-runtime 0.9.0 → 0.11.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.
- package/README.md +14 -8
- package/package.json +1 -1
- package/scripts/cockpit-smoke.mjs +3 -3
- package/scripts/ux-prototype-tty.mjs +9 -0
- package/src/global/control-plane-proposals.js +2 -1
- package/src/global/control-plane-snapshot.js +1 -1
- package/src/global/ink/brand/wordmark.js +50 -0
- package/src/global/ink/cockpit/primitives.js +72 -50
- package/src/global/ink/cockpit-changes.js +2 -2
- package/src/global/ink/cockpit-control-center.js +12 -64
- package/src/global/ink/cockpit-controller.js +41 -5
- package/src/global/ink/cockpit-enter.js +1 -0
- package/src/global/ink/cockpit-models.js +14 -7
- package/src/global/ink/cockpit-palette.js +18 -7
- package/src/global/ink/cockpit-recovery.js +9 -6
- package/src/global/ink/cockpit-usage.js +111 -0
- package/src/global/ink/cockpit-views.js +70 -97
- package/src/global/ink/orchestrator-app.js +44 -4
- package/src/global/ink/setup-app.js +55 -72
- package/src/global/ink/setup-state.js +16 -0
- package/src/global/ink/theme.js +40 -8
- package/src/global/ink/ux/live-activity.js +191 -0
- package/src/global/ink/ux/live-alerts.js +156 -0
- package/src/global/ink/ux/live-governance.js +191 -0
- package/src/global/ink/ux/live-orchestration.js +185 -0
- package/src/global/ink/ux/live-overview.js +175 -0
- package/src/global/ink/ux/live-settings.js +186 -0
- package/src/global/ink/ux/live-setup.js +160 -0
- package/src/global/ink/ux/live-usage.js +49 -0
- package/src/global/ink/ux/semantic.js +101 -0
- package/src/global/ink/ux/task-flow-app.js +85 -0
- package/src/global/ink/ux/task-flow.js +173 -0
- package/src/global/orchestrator.js +37 -20
|
@@ -243,6 +243,7 @@ export function buildFooterModel({
|
|
|
243
243
|
hasError = false,
|
|
244
244
|
changesPhase = null,
|
|
245
245
|
recoveryPhase = null,
|
|
246
|
+
recoveryHasPreview = false,
|
|
246
247
|
settingsPhase = null,
|
|
247
248
|
columns = 80
|
|
248
249
|
} = {}) {
|
|
@@ -290,7 +291,8 @@ export function buildFooterModel({
|
|
|
290
291
|
|
|
291
292
|
if (view === ORCHESTRATOR_VIEWS.ACTIVITY) {
|
|
292
293
|
return {
|
|
293
|
-
text: buildRecoveryFooterParts(recoveryPhase
|
|
294
|
+
text: buildRecoveryFooterParts(recoveryPhase, { hasPreview: recoveryHasPreview })
|
|
295
|
+
.join(` ${glyphs.bullet} `),
|
|
294
296
|
columns: footerColumns
|
|
295
297
|
};
|
|
296
298
|
}
|
|
@@ -315,16 +317,21 @@ export function buildFooterModel({
|
|
|
315
317
|
parts.push("Tab Region");
|
|
316
318
|
}
|
|
317
319
|
|
|
318
|
-
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
// HOME footer must stay on one line at 80 cols (frame already near 24 rows).
|
|
321
|
+
if (view === ORCHESTRATOR_VIEWS.HOME) {
|
|
322
|
+
return {
|
|
323
|
+
text: ["↑↓", "Enter", "Space", "R", "?", "/", "Esc"].join(` ${glyphs.bullet} `),
|
|
324
|
+
columns: footerColumns
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (region === COCKPIT_REGIONS.NAV
|
|
329
|
+
|| view === ORCHESTRATOR_VIEWS.IDES
|
|
322
330
|
|| view === ORCHESTRATOR_VIEWS.MODULES
|
|
323
331
|
|| view === ORCHESTRATOR_VIEWS.PROFILE
|
|
324
332
|
|| view === ORCHESTRATOR_VIEWS.PROVIDERS
|
|
325
333
|
|| view === ORCHESTRATOR_VIEWS.DIAGNOSTICS
|
|
326
334
|
|| view === ORCHESTRATOR_VIEWS.USAGE
|
|
327
|
-
|| region === COCKPIT_REGIONS.NAV
|
|
328
335
|
|| view === ORCHESTRATOR_VIEWS.RUNS
|
|
329
336
|
|| view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS
|
|
330
337
|
|| view === ORCHESTRATOR_VIEWS.RECENT_RUNS
|
|
@@ -337,7 +344,7 @@ export function buildFooterModel({
|
|
|
337
344
|
|
|
338
345
|
parts.push("? Help");
|
|
339
346
|
parts.push("/ Actions");
|
|
340
|
-
parts.push(
|
|
347
|
+
parts.push("Esc Back");
|
|
341
348
|
|
|
342
349
|
return { text: parts.join(` ${glyphs.bullet} `), columns: footerColumns };
|
|
343
350
|
}
|
|
@@ -4,7 +4,8 @@ import { ORCHESTRATOR_VIEWS } from "./orchestrator-state.js";
|
|
|
4
4
|
export const PALETTE_KINDS = Object.freeze({
|
|
5
5
|
NAVIGATE: "navigate",
|
|
6
6
|
REFRESH: "refresh",
|
|
7
|
-
HELP: "help"
|
|
7
|
+
HELP: "help",
|
|
8
|
+
SETUP: "setup"
|
|
8
9
|
});
|
|
9
10
|
|
|
10
11
|
const DESTINATION_VIEWS = Object.freeze({
|
|
@@ -37,15 +38,25 @@ export function buildPaletteActions({
|
|
|
37
38
|
navItems = COCKPIT_NAV
|
|
38
39
|
} = {}) {
|
|
39
40
|
const actions = [];
|
|
40
|
-
|
|
41
|
-
if (recommendedView) {
|
|
41
|
+
if (ctaDestination === "setup") {
|
|
42
42
|
actions.push({
|
|
43
43
|
id: "recommended",
|
|
44
|
-
kind: PALETTE_KINDS.
|
|
45
|
-
label: ctaTitle?.trim() || "
|
|
46
|
-
view:
|
|
47
|
-
description: ctaDetail?.trim() || "
|
|
44
|
+
kind: PALETTE_KINDS.SETUP,
|
|
45
|
+
label: ctaTitle?.trim() || "Finish local setup",
|
|
46
|
+
view: null,
|
|
47
|
+
description: ctaDetail?.trim() || "Open the local setup wizard."
|
|
48
48
|
});
|
|
49
|
+
} else {
|
|
50
|
+
const recommendedView = resolvePaletteDestination(ctaDestination);
|
|
51
|
+
if (recommendedView) {
|
|
52
|
+
actions.push({
|
|
53
|
+
id: "recommended",
|
|
54
|
+
kind: PALETTE_KINDS.NAVIGATE,
|
|
55
|
+
label: ctaTitle?.trim() || "Recommended next action",
|
|
56
|
+
view: recommendedView,
|
|
57
|
+
description: ctaDetail?.trim() || "Overview recommended destination."
|
|
58
|
+
});
|
|
59
|
+
}
|
|
49
60
|
}
|
|
50
61
|
for (const item of navItems) {
|
|
51
62
|
actions.push({
|
|
@@ -75,7 +75,7 @@ export function listRecoverySnapshots(snapshot) {
|
|
|
75
75
|
return snapshot?.backups?.snapshots ?? [];
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
function formatWhen(timestamp) {
|
|
78
|
+
export function formatWhen(timestamp) {
|
|
79
79
|
if (!timestamp) return "unknown time";
|
|
80
80
|
const raw = String(timestamp);
|
|
81
81
|
if (/^\d{4}-\d{2}-\d{2}/.test(raw)) return raw.slice(0, 16).replace("T", " ");
|
|
@@ -84,7 +84,7 @@ function formatWhen(timestamp) {
|
|
|
84
84
|
return date.toISOString().slice(0, 16).replace("T", " ");
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function formatResult(action) {
|
|
87
|
+
export function formatResult(action) {
|
|
88
88
|
const value = String(action ?? "").toLowerCase();
|
|
89
89
|
if (!value) return "done";
|
|
90
90
|
if (value === "applied" || value === "ok" || value === "success") return "ok";
|
|
@@ -93,7 +93,7 @@ function formatResult(action) {
|
|
|
93
93
|
return value;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
function shortName(name) {
|
|
96
|
+
export function shortName(name) {
|
|
97
97
|
const raw = String(name ?? "").trim();
|
|
98
98
|
if (!raw) return "snapshot";
|
|
99
99
|
const parts = raw.split(/[/\\]/).filter(Boolean);
|
|
@@ -176,8 +176,11 @@ export function formatRecoveryLines({
|
|
|
176
176
|
return lines;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
export function buildRecoveryFooterParts(phase) {
|
|
179
|
+
export function buildRecoveryFooterParts(phase, { hasPreview = false } = {}) {
|
|
180
180
|
if (phase === RECOVERY_PHASE.PREVIEWING || phase === RECOVERY_PHASE.APPLYING) return ["Working…", "Esc Back"];
|
|
181
|
-
if (phase === RECOVERY_PHASE.CONFIRMING) return ["Y Restore", "N/Esc Cancel"];
|
|
182
|
-
|
|
181
|
+
if (phase === RECOVERY_PHASE.CONFIRMING) return ["Y Restore", "N/Esc Cancel", "Space"];
|
|
182
|
+
const parts = ["↑↓ Select", "Enter Preview", "R Re-scan"];
|
|
183
|
+
if (hasPreview) parts.push("Space");
|
|
184
|
+
parts.push("Esc Back");
|
|
185
|
+
return parts;
|
|
183
186
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure Usage / Tokens model — no React/Ink.
|
|
3
|
+
* Shared by formatUsageLines and SemanticUsagePanel.
|
|
4
|
+
*/
|
|
5
|
+
import { LAYOUT_MODES } from "./layout.js";
|
|
6
|
+
|
|
7
|
+
export function usageRunLimit(layoutMode = LAYOUT_MODES.COMPACT) {
|
|
8
|
+
return layoutMode === LAYOUT_MODES.WIDE ? 8 : 3;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function formatMeasuredBudgets(budgets) {
|
|
12
|
+
if (!budgets || typeof budgets !== "object") return null;
|
|
13
|
+
const parts = [];
|
|
14
|
+
if (Number.isFinite(budgets.stableUsedTokens) && Number.isFinite(budgets.stableBudgetTokens)) {
|
|
15
|
+
parts.push(`stable ${budgets.stableUsedTokens}/${budgets.stableBudgetTokens}`);
|
|
16
|
+
}
|
|
17
|
+
if (Number.isFinite(budgets.requestUsedTokens) && Number.isFinite(budgets.requestBudgetTokens)) {
|
|
18
|
+
parts.push(`request ${budgets.requestUsedTokens}/${budgets.requestBudgetTokens}`);
|
|
19
|
+
}
|
|
20
|
+
return parts.length > 0 ? parts.join(" · ") : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function resolveConfiguredLimits(dashboard) {
|
|
24
|
+
const resolved = dashboard?.profile?.profile ?? {};
|
|
25
|
+
const configured = [];
|
|
26
|
+
if (Number.isFinite(resolved.tokenBudget)) configured.push(`token ${resolved.tokenBudget}`);
|
|
27
|
+
if (Number.isFinite(resolved.stableContextBudget)) configured.push(`stable ${resolved.stableContextBudget}`);
|
|
28
|
+
if (Number.isFinite(resolved.requestContextBudget)) configured.push(`request ${resolved.requestContextBudget}`);
|
|
29
|
+
return configured;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function hasFiniteUsage(usage) {
|
|
33
|
+
if (!usage || typeof usage !== "object") return false;
|
|
34
|
+
return Number.isFinite(usage.total)
|
|
35
|
+
|| Number.isFinite(usage.input)
|
|
36
|
+
|| Number.isFinite(usage.output);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function formatRunUsageLabel(run) {
|
|
40
|
+
const usage = run?.tokenUsage;
|
|
41
|
+
if (!hasFiniteUsage(usage)) return null;
|
|
42
|
+
const parts = [];
|
|
43
|
+
if (Number.isFinite(usage.input)) parts.push(`in ${usage.input}`);
|
|
44
|
+
if (Number.isFinite(usage.output)) parts.push(`out ${usage.output}`);
|
|
45
|
+
if (Number.isFinite(usage.total)) parts.push(`total ${usage.total}`);
|
|
46
|
+
return `${run.agentId ?? "agent"} · ${parts.join(" · ")}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function collectAuditableRuns(dashboard) {
|
|
50
|
+
return [...(dashboard?.activeRuns ?? []), ...(dashboard?.recentRuns ?? [])]
|
|
51
|
+
.filter((run) => hasFiniteUsage(run?.tokenUsage));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Pure adapter: Callout=status · Measured section owns the value. */
|
|
55
|
+
export function adaptUsageModel({
|
|
56
|
+
snapshot = null,
|
|
57
|
+
dashboard = null,
|
|
58
|
+
layoutMode = LAYOUT_MODES.COMPACT
|
|
59
|
+
} = {}) {
|
|
60
|
+
const measured = formatMeasuredBudgets(snapshot?.budgets);
|
|
61
|
+
const configured = resolveConfiguredLimits(dashboard);
|
|
62
|
+
const allRuns = collectAuditableRuns(dashboard);
|
|
63
|
+
const limit = usageRunLimit(layoutMode);
|
|
64
|
+
const visible = allRuns.slice(0, limit);
|
|
65
|
+
const hidden = Math.max(0, allRuns.length - visible.length);
|
|
66
|
+
const hasEvidence = Boolean(measured) || configured.length > 0 || allRuns.length > 0;
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
title: "Usage",
|
|
70
|
+
callout: hasEvidence
|
|
71
|
+
? {
|
|
72
|
+
tone: "info",
|
|
73
|
+
title: "Usage evidence available",
|
|
74
|
+
body: "Budgets and run tokenUsage only — no invented totals."
|
|
75
|
+
}
|
|
76
|
+
: {
|
|
77
|
+
tone: "info",
|
|
78
|
+
title: "Data unavailable",
|
|
79
|
+
body: "No measured budgets, profile limits, or auditable run tokenUsage."
|
|
80
|
+
},
|
|
81
|
+
measured: measured ?? "Data unavailable",
|
|
82
|
+
configured: configured.length > 0
|
|
83
|
+
? configured.join(" · ")
|
|
84
|
+
: "No profile token budgets configured.",
|
|
85
|
+
runs: visible.map((run, i) => ({
|
|
86
|
+
id: `usage-run-${i}`,
|
|
87
|
+
label: formatRunUsageLabel(run)
|
|
88
|
+
})),
|
|
89
|
+
runTotal: allRuns.length,
|
|
90
|
+
runLimit: limit,
|
|
91
|
+
moreLine: hidden > 0 ? `… ${hidden} more` : null,
|
|
92
|
+
hasEvidence,
|
|
93
|
+
footnote: "Auditable budgets only — no invented token savings."
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function formatUsageLinesFromModel(model) {
|
|
98
|
+
const lines = [
|
|
99
|
+
"MEASURED", model.measured, "",
|
|
100
|
+
"CONFIGURED LIMITS", model.configured, "",
|
|
101
|
+
"RUN USAGE"
|
|
102
|
+
];
|
|
103
|
+
if (model.runs.length === 0) {
|
|
104
|
+
lines.push("No auditable run tokenUsage yet.");
|
|
105
|
+
} else {
|
|
106
|
+
for (const item of model.runs) lines.push(item.label);
|
|
107
|
+
if (model.moreLine) lines.push(model.moreLine);
|
|
108
|
+
}
|
|
109
|
+
lines.push("", model.footnote);
|
|
110
|
+
return lines;
|
|
111
|
+
}
|
|
@@ -5,7 +5,6 @@ import { CockpitEmptyState } from "./cockpit/primitives.js";
|
|
|
5
5
|
import {
|
|
6
6
|
formatProviderLines,
|
|
7
7
|
formatRunDetailLines,
|
|
8
|
-
formatRunLines,
|
|
9
8
|
formatSystemHealthLines,
|
|
10
9
|
formatLaunchWizardLines,
|
|
11
10
|
ORCHESTRATOR_VIEWS,
|
|
@@ -13,14 +12,15 @@ import {
|
|
|
13
12
|
} from "./orchestrator-state.js";
|
|
14
13
|
import { windowLinesForLayout } from "./cockpit-models.js";
|
|
15
14
|
import { LAYOUT_MODES } from "./layout.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
15
|
+
import { SemanticOverviewPanel } from "./ux/live-overview.js";
|
|
16
|
+
import { SemanticGovernancePanel } from "./ux/live-governance.js";
|
|
17
|
+
import { SemanticActivityPanel } from "./ux/live-activity.js";
|
|
18
|
+
import { SemanticOrchestrationPanel } from "./ux/live-orchestration.js";
|
|
19
|
+
import { SemanticAlertsPanel } from "./ux/live-alerts.js";
|
|
20
|
+
import { SemanticSettingsPanel } from "./ux/live-settings.js";
|
|
21
|
+
import { SemanticUsagePanel } from "./ux/live-usage.js";
|
|
22
|
+
import { formatReviewDetailLines } from "./cockpit-reviews.js";
|
|
23
|
+
import { listCuratedIntegrations } from "./cockpit-settings.js";
|
|
24
24
|
|
|
25
25
|
export function PalettePanel({ model, colorEnabled = true }) {
|
|
26
26
|
return React.createElement(Box, { flexDirection: "column" },
|
|
@@ -95,6 +95,11 @@ export function renderCockpitView({
|
|
|
95
95
|
recoveryAction = null,
|
|
96
96
|
settingsAction = null,
|
|
97
97
|
colorEnabled = true,
|
|
98
|
+
unicode = true,
|
|
99
|
+
overviewDetailsOpen = false,
|
|
100
|
+
governanceDetailsOpen = false,
|
|
101
|
+
activityDetailsOpen = false,
|
|
102
|
+
contentFocused = false,
|
|
98
103
|
homeDir = null
|
|
99
104
|
}) {
|
|
100
105
|
if (palette) {
|
|
@@ -102,14 +107,21 @@ export function renderCockpitView({
|
|
|
102
107
|
}
|
|
103
108
|
switch (view) {
|
|
104
109
|
case ORCHESTRATOR_VIEWS.HOME:
|
|
105
|
-
return React.createElement(
|
|
110
|
+
return React.createElement(SemanticOverviewPanel, {
|
|
111
|
+
model: controlCenter,
|
|
112
|
+
detailsOpen: overviewDetailsOpen,
|
|
113
|
+
colorEnabled,
|
|
114
|
+
unicode,
|
|
115
|
+
layoutMode
|
|
116
|
+
});
|
|
106
117
|
case ORCHESTRATOR_VIEWS.USAGE:
|
|
107
|
-
return
|
|
108
|
-
|
|
109
|
-
|
|
118
|
+
return React.createElement(SemanticUsagePanel, {
|
|
119
|
+
snapshot,
|
|
120
|
+
dashboard,
|
|
110
121
|
layoutMode,
|
|
111
|
-
colorEnabled
|
|
112
|
-
|
|
122
|
+
colorEnabled,
|
|
123
|
+
unicode
|
|
124
|
+
});
|
|
113
125
|
case ORCHESTRATOR_VIEWS.IDES:
|
|
114
126
|
case ORCHESTRATOR_VIEWS.PROVIDERS:
|
|
115
127
|
return governanceList("IDEs & models", [
|
|
@@ -120,73 +132,54 @@ export function renderCockpitView({
|
|
|
120
132
|
case ORCHESTRATOR_VIEWS.MODULES:
|
|
121
133
|
return governanceList("Harness modules", formatModuleLines(snapshot), layoutMode, colorEnabled);
|
|
122
134
|
case ORCHESTRATOR_VIEWS.CHANGES:
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
return React.createElement(SemanticGovernancePanel, {
|
|
136
|
+
snapshot,
|
|
137
|
+
changesAction,
|
|
138
|
+
homeDir,
|
|
139
|
+
detailsOpen: governanceDetailsOpen,
|
|
126
140
|
layoutMode,
|
|
127
|
-
colorEnabled
|
|
128
|
-
|
|
141
|
+
colorEnabled,
|
|
142
|
+
unicode
|
|
143
|
+
});
|
|
129
144
|
case ORCHESTRATOR_VIEWS.ACTIVITY:
|
|
130
|
-
return
|
|
131
|
-
|
|
132
|
-
|
|
145
|
+
return React.createElement(SemanticActivityPanel, {
|
|
146
|
+
snapshot,
|
|
147
|
+
recoveryAction,
|
|
148
|
+
dashboard,
|
|
149
|
+
listIndex,
|
|
150
|
+
homeDir,
|
|
151
|
+
detailsOpen: activityDetailsOpen,
|
|
133
152
|
layoutMode,
|
|
134
|
-
|
|
135
|
-
|
|
153
|
+
contentFocused,
|
|
154
|
+
colorEnabled,
|
|
155
|
+
unicode
|
|
156
|
+
});
|
|
136
157
|
case ORCHESTRATOR_VIEWS.PROFILE:
|
|
137
|
-
return
|
|
138
|
-
|
|
139
|
-
formatSettingsLines({
|
|
140
|
-
listIndex,
|
|
141
|
-
settingsAction,
|
|
142
|
-
snapshot,
|
|
143
|
-
diagnostics
|
|
144
|
-
}),
|
|
145
|
-
layoutMode,
|
|
146
|
-
colorEnabled
|
|
147
|
-
);
|
|
148
|
-
case ORCHESTRATOR_VIEWS.RUNS:
|
|
149
|
-
return listBlock(
|
|
150
|
-
`Orchestration · ${formatOrchestrationStatus({
|
|
151
|
-
active: (dashboard?.activeRuns ?? []).length,
|
|
152
|
-
recent: (dashboard?.recentRuns ?? []).length,
|
|
153
|
-
reviews: (reviews ?? []).length
|
|
154
|
-
})}`,
|
|
155
|
-
formatRunsHubLines(RUNS_HUB_ITEMS),
|
|
158
|
+
return React.createElement(SemanticSettingsPanel, {
|
|
159
|
+
integrations: listCuratedIntegrations(),
|
|
156
160
|
listIndex,
|
|
161
|
+
settingsAction,
|
|
162
|
+
snapshot,
|
|
163
|
+
diagnostics,
|
|
164
|
+
layoutMode,
|
|
165
|
+
contentFocused,
|
|
157
166
|
colorEnabled,
|
|
158
|
-
|
|
159
|
-
);
|
|
167
|
+
unicode
|
|
168
|
+
});
|
|
169
|
+
case ORCHESTRATOR_VIEWS.RUNS:
|
|
160
170
|
case ORCHESTRATOR_VIEWS.ACTIVE_RUNS:
|
|
161
|
-
return listBlock(
|
|
162
|
-
"Active runs",
|
|
163
|
-
formatRunLines(dashboard?.activeRuns ?? [], {
|
|
164
|
-
emptyMessage: "No runs executing. Governance first — launch only after setup/repairs.",
|
|
165
|
-
readable: true
|
|
166
|
-
}),
|
|
167
|
-
listIndex,
|
|
168
|
-
colorEnabled,
|
|
169
|
-
"Enter opens detail · Esc back to Orchestration"
|
|
170
|
-
);
|
|
171
171
|
case ORCHESTRATOR_VIEWS.RECENT_RUNS:
|
|
172
|
-
return listBlock(
|
|
173
|
-
"Run history",
|
|
174
|
-
formatRunLines(dashboard?.recentRuns ?? [], {
|
|
175
|
-
emptyMessage: "No completed runs yet.",
|
|
176
|
-
readable: true
|
|
177
|
-
}),
|
|
178
|
-
listIndex,
|
|
179
|
-
colorEnabled,
|
|
180
|
-
"Enter opens detail · Esc back to Orchestration"
|
|
181
|
-
);
|
|
182
172
|
case ORCHESTRATOR_VIEWS.REVIEWS:
|
|
183
|
-
return
|
|
184
|
-
|
|
185
|
-
|
|
173
|
+
return React.createElement(SemanticOrchestrationPanel, {
|
|
174
|
+
view,
|
|
175
|
+
dashboard,
|
|
176
|
+
reviews,
|
|
186
177
|
listIndex,
|
|
178
|
+
layoutMode,
|
|
179
|
+
contentFocused,
|
|
187
180
|
colorEnabled,
|
|
188
|
-
|
|
189
|
-
);
|
|
181
|
+
unicode
|
|
182
|
+
});
|
|
190
183
|
case ORCHESTRATOR_VIEWS.LAUNCH:
|
|
191
184
|
if (launchableAgents.length === 0) {
|
|
192
185
|
return React.createElement(CockpitEmptyState, {
|
|
@@ -223,13 +216,14 @@ export function renderCockpitView({
|
|
|
223
216
|
.map((line) => React.createElement(Text, { key: line }, line))
|
|
224
217
|
);
|
|
225
218
|
case ORCHESTRATOR_VIEWS.ALERTS:
|
|
226
|
-
return
|
|
227
|
-
|
|
228
|
-
formatAlertListLines(alerts),
|
|
219
|
+
return React.createElement(SemanticAlertsPanel, {
|
|
220
|
+
alerts,
|
|
229
221
|
listIndex,
|
|
222
|
+
layoutMode,
|
|
223
|
+
contentFocused,
|
|
230
224
|
colorEnabled,
|
|
231
|
-
|
|
232
|
-
);
|
|
225
|
+
unicode
|
|
226
|
+
});
|
|
233
227
|
case ORCHESTRATOR_VIEWS.DIAGNOSTICS:
|
|
234
228
|
return governanceList(
|
|
235
229
|
"System health",
|
|
@@ -287,25 +281,4 @@ function formatModuleLines(snapshot) {
|
|
|
287
281
|
];
|
|
288
282
|
}
|
|
289
283
|
|
|
290
|
-
function formatChangeLines(snapshot, changesAction, layoutMode = LAYOUT_MODES.COMPACT, homeDir = null) {
|
|
291
|
-
return formatChangesActionLines({ snapshot, changesAction, layoutMode, homeDir });
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function listBlock(title, lines, listIndex, colorEnabled, emptyHint) {
|
|
295
|
-
const isEmpty = lines.length === 1 && /no |nothing |empty/i.test(lines[0]);
|
|
296
|
-
return React.createElement(Box, { flexDirection: "column" },
|
|
297
|
-
React.createElement(Text, { bold: true }, title),
|
|
298
|
-
isEmpty
|
|
299
|
-
? React.createElement(CockpitEmptyState, {
|
|
300
|
-
message: lines[0],
|
|
301
|
-
hint: emptyHint
|
|
302
|
-
})
|
|
303
|
-
: lines.map((line, index) => React.createElement(Text, {
|
|
304
|
-
key: `${index}-${line}`,
|
|
305
|
-
bold: index === listIndex,
|
|
306
|
-
color: index === listIndex && colorEnabled ? COCKPIT_COLORS.primary : undefined
|
|
307
|
-
}, `${index === listIndex ? "› " : " "}${line}`))
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
284
|
export { LAUNCH_WIZARD_STEPS };
|
|
@@ -41,7 +41,7 @@ import { handleLaunchInput } from "./launch-input.js";
|
|
|
41
41
|
import { useTerminalSize } from "./use-terminal-size.js";
|
|
42
42
|
import { useOrchestratorData } from "./use-orchestrator-data.js";
|
|
43
43
|
import { resolveTerminalCapabilities } from "./terminal-capabilities.js";
|
|
44
|
-
import { COCKPIT_COLORS } from "./theme.js";
|
|
44
|
+
import { COCKPIT_COLORS, resolveInkColor } from "./theme.js";
|
|
45
45
|
import { LAYOUT_MODES } from "./layout.js";
|
|
46
46
|
import { CHANGES_PHASE } from "./cockpit-changes.js";
|
|
47
47
|
import { RECOVERY_PHASE, listRecoverySnapshots } from "./cockpit-recovery.js";
|
|
@@ -146,6 +146,10 @@ export function OrchestratorApp({
|
|
|
146
146
|
data.reload().catch(() => {});
|
|
147
147
|
return;
|
|
148
148
|
}
|
|
149
|
+
if (selected.kind === PALETTE_KINDS.SETUP) {
|
|
150
|
+
finish({ cancelled: false, action: "setup" });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
149
153
|
dispatch({
|
|
150
154
|
type: "run-palette",
|
|
151
155
|
kind: selected.kind,
|
|
@@ -161,6 +165,24 @@ export function OrchestratorApp({
|
|
|
161
165
|
return;
|
|
162
166
|
}
|
|
163
167
|
|
|
168
|
+
if (inputKey === " " && ui.view === ORCHESTRATOR_VIEWS.HOME && !ui.paletteOpen) {
|
|
169
|
+
dispatch({ type: "toggle-overview-details" });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (inputKey === " " && ui.view === ORCHESTRATOR_VIEWS.CHANGES && !ui.paletteOpen) {
|
|
174
|
+
dispatch({ type: "toggle-governance-details" });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (inputKey === " "
|
|
179
|
+
&& ui.view === ORCHESTRATOR_VIEWS.ACTIVITY
|
|
180
|
+
&& !ui.paletteOpen
|
|
181
|
+
&& data.recoveryAction?.preview) {
|
|
182
|
+
dispatch({ type: "toggle-activity-details" });
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
164
186
|
if (key.escape) {
|
|
165
187
|
if (ui.view === ORCHESTRATOR_VIEWS.CHANGES
|
|
166
188
|
&& data.changesAction?.phase === CHANGES_PHASE.CONFIRMING) {
|
|
@@ -262,6 +284,10 @@ export function OrchestratorApp({
|
|
|
262
284
|
navItem: item,
|
|
263
285
|
ctaDestination: data.snapshot?.cta?.destination ?? null
|
|
264
286
|
});
|
|
287
|
+
if (intent.kind === "activate-setup") {
|
|
288
|
+
finish({ cancelled: false, action: "setup" });
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
265
291
|
if (intent.kind === "activate-cta") {
|
|
266
292
|
if (openDestination(intent.destination)) return;
|
|
267
293
|
}
|
|
@@ -440,14 +466,22 @@ export function OrchestratorApp({
|
|
|
440
466
|
|
|
441
467
|
if (data.loading) {
|
|
442
468
|
return React.createElement(Box, { flexDirection: "column" },
|
|
443
|
-
React.createElement(Text, {
|
|
444
|
-
|
|
469
|
+
React.createElement(Text, {
|
|
470
|
+
bold: true,
|
|
471
|
+
color: resolveInkColor(caps.color, COCKPIT_COLORS.brand)
|
|
472
|
+
}, "KAIRO"),
|
|
473
|
+
React.createElement(Text, {
|
|
474
|
+
color: resolveInkColor(caps.color, COCKPIT_COLORS.muted)
|
|
475
|
+
}, "Loading cockpit…")
|
|
445
476
|
);
|
|
446
477
|
}
|
|
447
478
|
|
|
448
479
|
if (data.error) {
|
|
449
480
|
return React.createElement(Box, { flexDirection: "column" },
|
|
450
|
-
React.createElement(Text, {
|
|
481
|
+
React.createElement(Text, {
|
|
482
|
+
bold: true,
|
|
483
|
+
color: resolveInkColor(caps.color, COCKPIT_COLORS.danger)
|
|
484
|
+
}, "Runtime error"),
|
|
451
485
|
React.createElement(Text, null, data.error),
|
|
452
486
|
React.createElement(Text, { dimColor: true },
|
|
453
487
|
data.retrying ? "Retrying read-only scan…" : "R Retry · Esc to exit")
|
|
@@ -495,6 +529,7 @@ export function OrchestratorApp({
|
|
|
495
529
|
unicode,
|
|
496
530
|
changesPhase: data.changesAction?.phase ?? null,
|
|
497
531
|
recoveryPhase: data.recoveryAction?.phase ?? null,
|
|
532
|
+
recoveryHasPreview: Boolean(data.recoveryAction?.preview),
|
|
498
533
|
settingsPhase: data.settingsAction?.phase ?? null,
|
|
499
534
|
columns
|
|
500
535
|
}),
|
|
@@ -542,6 +577,11 @@ export function OrchestratorApp({
|
|
|
542
577
|
: null,
|
|
543
578
|
layoutMode: mode,
|
|
544
579
|
colorEnabled,
|
|
580
|
+
unicode,
|
|
581
|
+
overviewDetailsOpen: ui.overviewDetailsOpen,
|
|
582
|
+
governanceDetailsOpen: ui.governanceDetailsOpen,
|
|
583
|
+
activityDetailsOpen: ui.activityDetailsOpen,
|
|
584
|
+
contentFocused: ui.region === COCKPIT_REGIONS.CONTENT,
|
|
545
585
|
homeDir
|
|
546
586
|
})
|
|
547
587
|
)
|