@kal-elsam/kairo-runtime 0.10.0 → 0.12.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/global-template/components/agent-skills/LICENSE +21 -0
- package/global-template/components/agent-skills/PROVENANCE.md +26 -0
- package/global-template/components/agent-skills/skills/context-engineering/SKILL.md +289 -0
- package/global-template/components/agent-skills/skills/frontend-ui-engineering/SKILL.md +328 -0
- package/global-template/components/agent-skills/skills/observability-and-instrumentation/SKILL.md +203 -0
- package/global-template/components/agent-skills/skills/performance-optimization/SKILL.md +396 -0
- package/global-template/components/agent-skills/skills/source-driven-development/SKILL.md +194 -0
- package/global-template/components/catalog.json +29 -0
- package/package.json +5 -2
- package/scripts/cockpit-smoke.mjs +1 -1
- package/src/cli.js +136 -8
- package/src/global/component-builders.js +3 -1
- package/src/global/components/agent-skills.js +27 -0
- package/src/global/ink/brand/wordmark.js +50 -0
- package/src/global/ink/cockpit/primitives.js +45 -35
- package/src/global/ink/cockpit-control-center.js +104 -4
- package/src/global/ink/cockpit-scan.js +20 -2
- package/src/global/ink/cockpit-views.js +2 -1
- package/src/global/ink/ecosystem-updates-display.js +37 -0
- package/src/global/ink/launch-input.js +32 -1
- package/src/global/ink/orchestrator-app.js +14 -5
- package/src/global/ink/orchestrator-state.js +17 -2
- package/src/global/ink/system-resources-display.js +109 -0
- package/src/global/ink/theme.js +13 -8
- package/src/global/ink/use-orchestrator-data.js +40 -4
- package/src/global/ink/ux/live-activity.js +4 -7
- package/src/global/ink/ux/live-alerts.js +2 -5
- package/src/global/ink/ux/live-governance.js +2 -6
- package/src/global/ink/ux/live-orchestration.js +2 -5
- package/src/global/ink/ux/live-overview.js +88 -28
- package/src/global/ink/ux/live-settings.js +3 -6
- package/src/global/ink/ux/live-usage.js +5 -7
- package/src/global/ink/ux/semantic.js +23 -6
- package/src/global/mcp/kairo-mcp.js +230 -0
- package/src/global/observability/build-companion-snapshot.js +281 -0
- package/src/global/observability/build-observability-snapshot.js +24 -0
- package/src/global/observability/ecosystem-updates.js +224 -0
- package/src/global/observability/gentle-bundle-export.js +71 -0
- package/src/global/observability/gentle-bundle-import.js +122 -0
- package/src/global/observability/gentle-probe.js +155 -0
- package/src/global/observability/graphify-ops.js +133 -0
- package/src/global/observability/graphify-parse-cache.js +90 -0
- package/src/global/observability/graphify-probe.js +185 -0
- package/src/global/observability/hermes-activity.js +163 -0
- package/src/global/observability/hermes-probe.js +171 -0
- package/src/global/observability/index.js +85 -0
- package/src/global/observability/passive-snapshot-flight.js +93 -0
- package/src/global/observability/probe-contract.js +38 -0
- package/src/global/observability/probe-registry.js +30 -0
- package/src/global/observability/resource-advisor.js +71 -0
- package/src/global/observability/system-resources.js +171 -0
- package/src/global/runtime/alerts/alert-cli.js +31 -0
- package/src/global/runtime/alerts/alert-store.js +29 -6
- package/src/global/runtime/alerts/alert-validate.js +25 -1
- package/src/global/runtime/alerts/controlled-alert-actions.js +56 -0
- package/src/global/runtime/execution-adapters/claude.js +2 -1
- package/src/global/runtime/execution-adapters/codex.js +2 -1
- package/src/global/runtime/execution-adapters/create-execution-adapter.js +3 -14
- package/src/global/runtime/execution-adapters/cursor.js +2 -1
- package/src/global/runtime/execution-adapters/opencode.js +2 -1
- package/src/global/runtime/execution-adapters/pi.js +2 -1
- package/src/global/runtime/review/index.js +1 -1
- package/src/global/runtime/review/review-cli.js +113 -3
- package/src/global/runtime/review/review-git.js +142 -11
- package/src/global/runtime/review/review-patch.js +2 -0
- package/src/global/runtime/review/review-receipts.js +12 -7
- package/src/global/runtime/review/review-runner.js +2 -2
- package/src/global/runtime/review/review-types.js +8 -5
- package/src/global/runtime/review/review-validate.js +5 -1
- package/src/global/runtime/run-cli.js +2 -0
- package/src/global/runtime/run-manager.js +39 -18
- package/src/global/runtime/run-permissions.js +231 -0
- package/src/global/runtime/run-profile.js +2 -0
- package/src/global/runtime/run-supervisor.js +77 -37
- package/src/global/runtime/run-types.js +2 -0
- package/src/global/updates-cli.js +41 -0
package/src/global/ink/theme.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Kairo Cockpit theme — amber brand, ice interactive, semantic status.
|
|
3
|
+
* Status always has a text label — never color alone.
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
export const COCKPIT_COLORS = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
success: "
|
|
9
|
-
warning: "
|
|
10
|
-
danger: "
|
|
7
|
+
brand: "#E8A017",
|
|
8
|
+
interactive: "#7EC8E8",
|
|
9
|
+
success: "#3DDC97",
|
|
10
|
+
warning: "#F0C674",
|
|
11
|
+
danger: "#FF6B6B",
|
|
11
12
|
muted: "gray",
|
|
12
|
-
|
|
13
|
+
/** @deprecated alias — prefer interactive */
|
|
14
|
+
primary: "#7EC8E8",
|
|
15
|
+
/** @deprecated alias — prefer brand */
|
|
16
|
+
secondary: "#E8A017",
|
|
17
|
+
border: "#7EC8E8"
|
|
13
18
|
};
|
|
14
19
|
|
|
15
20
|
export const STATUS_LABELS = {
|
|
@@ -69,7 +74,7 @@ export function statusColor(kind, { colorEnabled = true } = {}) {
|
|
|
69
74
|
case "muted":
|
|
70
75
|
return COCKPIT_COLORS.muted;
|
|
71
76
|
default:
|
|
72
|
-
return COCKPIT_COLORS.
|
|
77
|
+
return COCKPIT_COLORS.interactive;
|
|
73
78
|
}
|
|
74
79
|
}
|
|
75
80
|
|
|
@@ -40,7 +40,14 @@ import {
|
|
|
40
40
|
} from "./cockpit-settings.js";
|
|
41
41
|
import { listReviewReceipts } from "../runtime/review/review-receipts.js";
|
|
42
42
|
import { assertReceiptSecretFree } from "../runtime/review/review-validate.js";
|
|
43
|
-
import { listAlerts
|
|
43
|
+
import { listAlerts } from "../runtime/alerts/alert-store.js";
|
|
44
|
+
import {
|
|
45
|
+
controlledDismissAlert, controlledResolveAlert
|
|
46
|
+
} from "../runtime/alerts/controlled-alert-actions.js";
|
|
47
|
+
import { buildCompanionSnapshot } from "../observability/build-companion-snapshot.js";
|
|
48
|
+
import { resolveGitHeadSha } from "../observability/graphify-probe.js";
|
|
49
|
+
import { runPassiveObservabilitySnapshot } from "../observability/passive-snapshot-flight.js";
|
|
50
|
+
import { inspectEngramIntegration } from "../integrations/engram-evidence.js";
|
|
44
51
|
|
|
45
52
|
export function useOrchestratorData({
|
|
46
53
|
homeDir,
|
|
@@ -56,6 +63,7 @@ export function useOrchestratorData({
|
|
|
56
63
|
const [dashboard, setDashboard] = useState(null);
|
|
57
64
|
const [diagnostics, setDiagnostics] = useState(null);
|
|
58
65
|
const [snapshot, setSnapshot] = useState(null);
|
|
66
|
+
const [companion, setCompanion] = useState(null);
|
|
59
67
|
const [selectedRun, setSelectedRun] = useState(null);
|
|
60
68
|
const [selectedEvents, setSelectedEvents] = useState([]);
|
|
61
69
|
const [reviews, setReviews] = useState([]);
|
|
@@ -78,7 +86,24 @@ export function useOrchestratorData({
|
|
|
78
86
|
cliVersion,
|
|
79
87
|
buildDashboard: buildRuntimeDashboardData,
|
|
80
88
|
buildDiagnostics: buildReadOnlyDiagnostics,
|
|
81
|
-
buildSnapshot: buildControlPlaneSnapshot
|
|
89
|
+
buildSnapshot: buildControlPlaneSnapshot,
|
|
90
|
+
buildCompanion: async ({ dashboard, snapshot: snap }) => buildCompanionSnapshot({
|
|
91
|
+
controlPlaneHealth: snap?.health ?? null,
|
|
92
|
+
runs: dashboard?.recentRuns ?? [],
|
|
93
|
+
inspectEngram: (ctx) => inspectEngramIntegration({
|
|
94
|
+
env: ctx?.env ?? process.env,
|
|
95
|
+
homeDir: ctx?.homeDir ?? homeDir
|
|
96
|
+
}),
|
|
97
|
+
buildObservability: (ctx) => runPassiveObservabilitySnapshot(ctx, {
|
|
98
|
+
force: Boolean(ctx?.force)
|
|
99
|
+
}),
|
|
100
|
+
observabilityContext: {
|
|
101
|
+
cwd: workspaceRoot, workspaceRoot, env: process.env,
|
|
102
|
+
headSha: resolveGitHeadSha(workspaceRoot)
|
|
103
|
+
},
|
|
104
|
+
loadReviews: async () => listReviewReceipts({ homeDir, limit: 20 }),
|
|
105
|
+
loadAlerts: async () => listAlerts({ homeDir, limit: 50 })
|
|
106
|
+
})
|
|
82
107
|
})), [homeDir, workspaceRoot, packageName, packageRoot, cliVersion]);
|
|
83
108
|
|
|
84
109
|
const reload = async ({ showLoading = false, asRetry = false } = {}) => {
|
|
@@ -98,6 +123,7 @@ export function useOrchestratorData({
|
|
|
98
123
|
setDashboard(outcome.result.dashboard);
|
|
99
124
|
setDiagnostics(outcome.result.diagnostics);
|
|
100
125
|
setSnapshot(outcome.result.snapshot);
|
|
126
|
+
setCompanion(outcome.result.companion ?? null);
|
|
101
127
|
try {
|
|
102
128
|
setAlerts(await listAlerts({ homeDir, limit: 50 }));
|
|
103
129
|
} catch {
|
|
@@ -166,8 +192,14 @@ export function useOrchestratorData({
|
|
|
166
192
|
if (!alert) return;
|
|
167
193
|
setBusy(true);
|
|
168
194
|
try {
|
|
169
|
-
|
|
170
|
-
|
|
195
|
+
const result = action === "dismiss"
|
|
196
|
+
? await controlledDismissAlert({
|
|
197
|
+
alertId: alert.alertId, confirmed: true, source: "cockpit", homeDir
|
|
198
|
+
})
|
|
199
|
+
: await controlledResolveAlert({
|
|
200
|
+
alertId: alert.alertId, confirmed: true, source: "cockpit", homeDir
|
|
201
|
+
});
|
|
202
|
+
if (!result.ok) throw new Error(result.message ?? result.code);
|
|
171
203
|
setAlerts(await listAlerts({ homeDir, limit: 50 }));
|
|
172
204
|
setStatusMessage(action === "dismiss" ? "Alert dismissed" : "Alert resolved");
|
|
173
205
|
} catch (error) {
|
|
@@ -197,6 +229,9 @@ export function useOrchestratorData({
|
|
|
197
229
|
cwd: workspaceRoot,
|
|
198
230
|
model: draft.model.trim() || null,
|
|
199
231
|
permissions,
|
|
232
|
+
allowUnsafePermissions: Boolean(draft.allowUnsafePermissions),
|
|
233
|
+
permissionSource: draft.permissionSource ?? "cockpit",
|
|
234
|
+
permissionConsentType: draft.allowUnsafePermissions ? "cockpit-unsafe-confirm" : null,
|
|
200
235
|
cliVersion,
|
|
201
236
|
profile: profile ?? null,
|
|
202
237
|
follow: false,
|
|
@@ -424,6 +459,7 @@ export function useOrchestratorData({
|
|
|
424
459
|
dashboard,
|
|
425
460
|
diagnostics,
|
|
426
461
|
snapshot,
|
|
462
|
+
companion,
|
|
427
463
|
selectedRun,
|
|
428
464
|
setSelectedRun,
|
|
429
465
|
selectedEvents,
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/** Live semantic Activity/Recovery. Callout=status · Confirm=action · footer=keys · snapshots=focus. */
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
|
-
import { COCKPIT_COLORS } from "../theme.js";
|
|
5
4
|
import { formatConfirmPath } from "../cockpit-path-label.js";
|
|
6
5
|
import {
|
|
7
6
|
RECOVERY_PHASE, listRecoverySnapshots, formatWhen, formatResult, shortName
|
|
8
7
|
} from "../cockpit-recovery.js";
|
|
9
8
|
import { LAYOUT_MODES } from "../layout.js";
|
|
10
|
-
import { ActionList, Callout, Confirm, Details } from "./semantic.js";
|
|
9
|
+
import { ActionList, Callout, Confirm, Details, SectionLabel, ViewTitle } from "./semantic.js";
|
|
11
10
|
import { detailsPathLimit } from "./live-governance.js";
|
|
12
11
|
|
|
13
12
|
export function activityContentLimits(layoutMode = LAYOUT_MODES.COMPACT) {
|
|
@@ -157,9 +156,7 @@ export function SemanticActivityPanel({
|
|
|
157
156
|
snapshot, recoveryAction, dashboard, listIndex, homeDir, detailsOpen, layoutMode
|
|
158
157
|
});
|
|
159
158
|
return React.createElement(Box, { flexDirection: "column" },
|
|
160
|
-
React.createElement(
|
|
161
|
-
bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
|
|
162
|
-
}, view.title),
|
|
159
|
+
React.createElement(ViewTitle, { colorEnabled }, view.title),
|
|
163
160
|
React.createElement(Callout, {
|
|
164
161
|
tone: view.callout.tone, title: view.callout.title,
|
|
165
162
|
body: view.callout.body || undefined, colorEnabled, compact: true
|
|
@@ -174,11 +171,11 @@ export function SemanticActivityPanel({
|
|
|
174
171
|
: null,
|
|
175
172
|
view.primary?.detail && !view.confirm
|
|
176
173
|
? React.createElement(Text, null, view.primary.detail) : null,
|
|
177
|
-
React.createElement(
|
|
174
|
+
React.createElement(SectionLabel, { colorEnabled }, "Recent"),
|
|
178
175
|
React.createElement(ActionList, {
|
|
179
176
|
items: view.recent, selectedIndex: -1, focused: false, colorEnabled, unicode
|
|
180
177
|
}),
|
|
181
|
-
React.createElement(
|
|
178
|
+
React.createElement(SectionLabel, { colorEnabled }, "Snapshots"),
|
|
182
179
|
React.createElement(ActionList, {
|
|
183
180
|
items: view.snapshots, selectedIndex: view.selectedIndex,
|
|
184
181
|
focused: contentFocused, colorEnabled, unicode
|
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { Box, Text } from "ink";
|
|
8
|
-
import { COCKPIT_COLORS } from "../theme.js";
|
|
9
8
|
import { LAYOUT_MODES } from "../layout.js";
|
|
10
9
|
import { ALERT_STATES } from "../../runtime/alerts/alert-types.js";
|
|
11
10
|
import { formatAlertsHeadline, selectAlertFromList } from "../cockpit-alerts.js";
|
|
12
|
-
import { ActionList, Callout } from "./semantic.js";
|
|
11
|
+
import { ActionList, Callout, ViewTitle } from "./semantic.js";
|
|
13
12
|
import { windowSlice } from "./live-activity.js";
|
|
14
13
|
|
|
15
14
|
export function alertsListLimit(layoutMode = LAYOUT_MODES.COMPACT) {
|
|
@@ -138,9 +137,7 @@ export function SemanticAlertsPanel({
|
|
|
138
137
|
const model = adaptAlertsModel({ alerts, listIndex, layoutMode });
|
|
139
138
|
const listFocused = contentFocused && !model.isEmpty && !model.isUnavailable;
|
|
140
139
|
return React.createElement(Box, { flexDirection: "column" },
|
|
141
|
-
React.createElement(
|
|
142
|
-
bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
|
|
143
|
-
}, model.title),
|
|
140
|
+
React.createElement(ViewTitle, { colorEnabled }, model.title),
|
|
144
141
|
React.createElement(Callout, {
|
|
145
142
|
tone: model.callout.tone,
|
|
146
143
|
title: model.callout.title,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/** Live semantic Governance. Ownership: Callout=status · Confirm/primary=action · footer=keys. */
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
|
-
import { COCKPIT_COLORS } from "../theme.js";
|
|
5
4
|
import { formatConfirmPath } from "../cockpit-path-label.js";
|
|
6
5
|
import { CHANGES_PHASE } from "../cockpit-changes.js";
|
|
7
6
|
import { LAYOUT_MODES } from "../layout.js";
|
|
8
|
-
import { ActionList, Callout, Confirm, Details } from "./semantic.js";
|
|
7
|
+
import { ActionList, Callout, Confirm, Details, ViewTitle } from "./semantic.js";
|
|
9
8
|
import { mapHealthTone } from "./live-overview.js";
|
|
10
9
|
|
|
11
10
|
function healthLabel(kind) {
|
|
@@ -151,10 +150,7 @@ export function SemanticGovernancePanel({
|
|
|
151
150
|
snapshot, changesAction, homeDir, detailsOpen, layoutMode
|
|
152
151
|
});
|
|
153
152
|
return React.createElement(Box, { flexDirection: "column" },
|
|
154
|
-
React.createElement(
|
|
155
|
-
bold: true,
|
|
156
|
-
color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
|
|
157
|
-
}, view.title),
|
|
153
|
+
React.createElement(ViewTitle, { colorEnabled }, view.title),
|
|
158
154
|
React.createElement(Callout, {
|
|
159
155
|
tone: view.callout.tone,
|
|
160
156
|
title: view.callout.title,
|
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { Box, Text } from "ink";
|
|
8
|
-
import { COCKPIT_COLORS } from "../theme.js";
|
|
9
8
|
import { LAYOUT_MODES } from "../layout.js";
|
|
10
9
|
import { ORCHESTRATOR_VIEWS, formatRunLines } from "../orchestrator-state.js";
|
|
11
10
|
import {
|
|
12
11
|
RUNS_HUB_ITEMS, formatOrchestrationStatus, formatRunsHubLines
|
|
13
12
|
} from "../cockpit-runs.js";
|
|
14
13
|
import { formatReviewListLines } from "../cockpit-reviews.js";
|
|
15
|
-
import { ActionList, Callout } from "./semantic.js";
|
|
14
|
+
import { ActionList, Callout, ViewTitle } from "./semantic.js";
|
|
16
15
|
import { windowSlice } from "./live-activity.js";
|
|
17
16
|
|
|
18
17
|
export function orchestrationListLimit(layoutMode = LAYOUT_MODES.COMPACT) {
|
|
@@ -167,9 +166,7 @@ export function SemanticOrchestrationPanel({
|
|
|
167
166
|
});
|
|
168
167
|
const listFocused = contentFocused && !model.isEmpty;
|
|
169
168
|
return React.createElement(Box, { flexDirection: "column" },
|
|
170
|
-
React.createElement(
|
|
171
|
-
bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
|
|
172
|
-
}, model.title),
|
|
169
|
+
React.createElement(ViewTitle, { colorEnabled }, model.title),
|
|
173
170
|
React.createElement(Callout, {
|
|
174
171
|
tone: model.callout.tone,
|
|
175
172
|
title: model.callout.title,
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Live semantic Overview for Cockpit HOME.
|
|
2
|
+
* Live semantic Overview for Cockpit HOME — product cover.
|
|
3
3
|
* Nav owns the sole focus mark — this panel never renders `>`.
|
|
4
|
+
* ASCII wordmark only here (wide/compact); minimal is textual.
|
|
4
5
|
*/
|
|
5
6
|
import React from "react";
|
|
6
7
|
import { Box, Text } from "ink";
|
|
7
8
|
import { CONTROL_PLANE_HEALTH } from "../../control-plane-snapshot.js";
|
|
9
|
+
import { LAYOUT_MODES } from "../layout.js";
|
|
8
10
|
import { COCKPIT_COLORS } from "../theme.js";
|
|
11
|
+
import {
|
|
12
|
+
overviewBrandTitle,
|
|
13
|
+
shouldShowWordmark,
|
|
14
|
+
wordmarkLines
|
|
15
|
+
} from "../brand/wordmark.js";
|
|
9
16
|
import { ActionList, Callout, Details } from "./semantic.js";
|
|
10
17
|
|
|
11
18
|
const DESTINATION_LABELS = {
|
|
@@ -48,6 +55,10 @@ export function buildOverviewDetails(model = {}) {
|
|
|
48
55
|
if (typeof model.alerts?.count === "number") {
|
|
49
56
|
lines.push(`Open alerts · ${model.alerts.count}`);
|
|
50
57
|
}
|
|
58
|
+
const secondary = model.companionNextAction;
|
|
59
|
+
if (secondary?.title && secondary.kind !== "idle") {
|
|
60
|
+
lines.push(`Companion · ${secondary.title}`);
|
|
61
|
+
}
|
|
51
62
|
if (lines.length === 0) return ["No extra evidence beyond the metrics above."];
|
|
52
63
|
return lines;
|
|
53
64
|
}
|
|
@@ -55,10 +66,15 @@ export function buildOverviewDetails(model = {}) {
|
|
|
55
66
|
/**
|
|
56
67
|
* Pure adapter: buildControlCenterModel → semantic overview props.
|
|
57
68
|
* Callout / CTA / metrics never include paths or IDs.
|
|
69
|
+
* Primary action is always governance CTA — companion is secondary metrics/details only.
|
|
58
70
|
*/
|
|
59
71
|
export function adaptControlCenterToOverview(model = {}) {
|
|
60
72
|
const status = model.status ?? model.health ?? {};
|
|
61
73
|
const next = model.nextAction ?? model.cta ?? {};
|
|
74
|
+
const companionMetrics = (model.companion?.lines ?? []).map((label, i) => ({
|
|
75
|
+
id: `companion-${i}`,
|
|
76
|
+
label
|
|
77
|
+
}));
|
|
62
78
|
return {
|
|
63
79
|
title: model.title ?? "Overview",
|
|
64
80
|
callout: {
|
|
@@ -74,45 +90,89 @@ export function adaptControlCenterToOverview(model = {}) {
|
|
|
74
90
|
metrics: [
|
|
75
91
|
{ id: "activity", label: `Activity · ${model.activity?.headline ?? "Idle"}` },
|
|
76
92
|
{ id: "alerts", label: `Alerts · ${model.alerts?.headline ?? "Alert data unavailable"}` },
|
|
77
|
-
{ id: "tokens", label: `Tokens · ${model.tokens?.headline ?? "Data unavailable"}` }
|
|
93
|
+
{ id: "tokens", label: `Tokens · ${model.tokens?.headline ?? "Data unavailable"}` },
|
|
94
|
+
...companionMetrics
|
|
78
95
|
],
|
|
79
96
|
details: buildOverviewDetails(model)
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
99
|
|
|
100
|
+
function renderWordmark({ layoutMode, colorEnabled = true, unicode = true }) {
|
|
101
|
+
const lines = wordmarkLines(layoutMode, { unicode });
|
|
102
|
+
if (lines.length === 0) return null;
|
|
103
|
+
return React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
104
|
+
...lines.map((line, i) => React.createElement(Text, {
|
|
105
|
+
key: `wm-${i}`,
|
|
106
|
+
bold: i === 0,
|
|
107
|
+
color: colorEnabled ? COCKPIT_COLORS.brand : undefined
|
|
108
|
+
}, line))
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function renderCallout(view, colorEnabled) {
|
|
113
|
+
return React.createElement(Callout, {
|
|
114
|
+
tone: view.callout.tone,
|
|
115
|
+
title: view.callout.title,
|
|
116
|
+
body: view.callout.body,
|
|
117
|
+
colorEnabled,
|
|
118
|
+
compact: true
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
83
122
|
export function SemanticOverviewPanel({
|
|
84
123
|
model,
|
|
85
124
|
detailsOpen = false,
|
|
86
125
|
colorEnabled = true,
|
|
87
|
-
unicode = true
|
|
126
|
+
unicode = true,
|
|
127
|
+
layoutMode = LAYOUT_MODES.COMPACT
|
|
88
128
|
}) {
|
|
89
129
|
const view = adaptControlCenterToOverview(model);
|
|
130
|
+
const showArt = shouldShowWordmark(layoutMode);
|
|
131
|
+
const brandTitle = overviewBrandTitle(layoutMode);
|
|
132
|
+
const isWide = layoutMode === LAYOUT_MODES.WIDE;
|
|
133
|
+
const mark = renderWordmark({ layoutMode, colorEnabled, unicode });
|
|
134
|
+
const status = renderCallout(view, colorEnabled);
|
|
135
|
+
|
|
136
|
+
const hero = showArt
|
|
137
|
+
? (isWide
|
|
138
|
+
? React.createElement(Box, { flexDirection: "row", marginBottom: 1 },
|
|
139
|
+
React.createElement(Box, { marginRight: 2 }, mark),
|
|
140
|
+
React.createElement(Box, { flexDirection: "column", flexGrow: 1 }, status)
|
|
141
|
+
)
|
|
142
|
+
: React.createElement(Box, { flexDirection: "column" }, mark, status))
|
|
143
|
+
: React.createElement(Box, { flexDirection: "column" },
|
|
144
|
+
React.createElement(Text, {
|
|
145
|
+
bold: true,
|
|
146
|
+
color: colorEnabled ? COCKPIT_COLORS.brand : undefined
|
|
147
|
+
}, brandTitle),
|
|
148
|
+
status
|
|
149
|
+
);
|
|
150
|
+
|
|
90
151
|
return React.createElement(Box, { flexDirection: "column" },
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}),
|
|
152
|
+
hero,
|
|
153
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
154
|
+
React.createElement(Text, {
|
|
155
|
+
bold: true,
|
|
156
|
+
color: colorEnabled ? COCKPIT_COLORS.interactive : undefined
|
|
157
|
+
}, view.primary.label),
|
|
158
|
+
view.primary.detail
|
|
159
|
+
? React.createElement(Text, null, view.primary.detail)
|
|
160
|
+
: null,
|
|
161
|
+
view.primary.hint
|
|
162
|
+
? React.createElement(Text, {
|
|
163
|
+
color: colorEnabled ? COCKPIT_COLORS.muted : undefined
|
|
164
|
+
}, view.primary.hint)
|
|
165
|
+
: null
|
|
166
|
+
),
|
|
167
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
168
|
+
React.createElement(ActionList, {
|
|
169
|
+
items: view.metrics,
|
|
170
|
+
selectedIndex: -1,
|
|
171
|
+
focused: false,
|
|
172
|
+
colorEnabled,
|
|
173
|
+
unicode
|
|
174
|
+
})
|
|
175
|
+
),
|
|
116
176
|
React.createElement(Details, {
|
|
117
177
|
open: detailsOpen,
|
|
118
178
|
summary: "Details",
|
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { Box, Text } from "ink";
|
|
7
|
-
import { COCKPIT_COLORS } from "../theme.js";
|
|
8
7
|
import { LAYOUT_MODES } from "../layout.js";
|
|
9
8
|
import {
|
|
10
9
|
SETTINGS_PHASE, getCuratedIntegration, listCuratedIntegrations
|
|
11
10
|
} from "../cockpit-settings.js";
|
|
12
|
-
import { ActionList, Callout, Confirm, Details, Receipt } from "./semantic.js";
|
|
11
|
+
import { ActionList, Callout, Confirm, Details, Receipt, SectionLabel, ViewTitle } from "./semantic.js";
|
|
13
12
|
import { windowSlice } from "./live-activity.js";
|
|
14
13
|
|
|
15
14
|
export function settingsListLimit(layoutMode = LAYOUT_MODES.COMPACT) {
|
|
@@ -160,9 +159,7 @@ export function SemanticSettingsPanel({
|
|
|
160
159
|
model.receipt && React.createElement(Receipt, {
|
|
161
160
|
title: model.receipt.title, lines: model.receipt.lines, colorEnabled
|
|
162
161
|
}),
|
|
163
|
-
React.createElement(
|
|
164
|
-
bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
|
|
165
|
-
}, model.title),
|
|
162
|
+
React.createElement(ViewTitle, { colorEnabled }, model.title),
|
|
166
163
|
React.createElement(Callout, {
|
|
167
164
|
tone: model.callout.tone, title: model.callout.title,
|
|
168
165
|
body: model.callout.body || undefined, colorEnabled, compact: true
|
|
@@ -176,7 +173,7 @@ export function SemanticSettingsPanel({
|
|
|
176
173
|
focused: listFocused, colorEnabled, unicode
|
|
177
174
|
}),
|
|
178
175
|
model.profilePolicy.length > 0 && React.createElement(Box, { flexDirection: "column" },
|
|
179
|
-
React.createElement(
|
|
176
|
+
React.createElement(SectionLabel, { colorEnabled }, "Profile & Policy"),
|
|
180
177
|
React.createElement(ActionList, {
|
|
181
178
|
items: model.profilePolicy, selectedIndex: -1, focused: false, colorEnabled, unicode
|
|
182
179
|
})
|
|
@@ -7,7 +7,7 @@ import { Box, Text } from "ink";
|
|
|
7
7
|
import { COCKPIT_COLORS } from "../theme.js";
|
|
8
8
|
import { LAYOUT_MODES } from "../layout.js";
|
|
9
9
|
import { adaptUsageModel } from "../cockpit-usage.js";
|
|
10
|
-
import { ActionList, Callout } from "./semantic.js";
|
|
10
|
+
import { ActionList, Callout, SectionLabel, ViewTitle } from "./semantic.js";
|
|
11
11
|
|
|
12
12
|
export function SemanticUsagePanel({
|
|
13
13
|
snapshot = null,
|
|
@@ -19,9 +19,7 @@ export function SemanticUsagePanel({
|
|
|
19
19
|
const model = adaptUsageModel({ snapshot, dashboard, layoutMode });
|
|
20
20
|
const muted = colorEnabled ? COCKPIT_COLORS.muted : undefined;
|
|
21
21
|
return React.createElement(Box, { flexDirection: "column" },
|
|
22
|
-
React.createElement(
|
|
23
|
-
bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
|
|
24
|
-
}, model.title),
|
|
22
|
+
React.createElement(ViewTitle, { colorEnabled }, model.title),
|
|
25
23
|
React.createElement(Callout, {
|
|
26
24
|
tone: model.callout.tone,
|
|
27
25
|
title: model.callout.title,
|
|
@@ -29,11 +27,11 @@ export function SemanticUsagePanel({
|
|
|
29
27
|
colorEnabled,
|
|
30
28
|
compact: true
|
|
31
29
|
}),
|
|
32
|
-
React.createElement(
|
|
30
|
+
React.createElement(SectionLabel, { colorEnabled }, "Measured"),
|
|
33
31
|
React.createElement(Text, null, ` ${model.measured}`),
|
|
34
|
-
React.createElement(
|
|
32
|
+
React.createElement(SectionLabel, { colorEnabled }, "Configured limits"),
|
|
35
33
|
React.createElement(Text, null, ` ${model.configured}`),
|
|
36
|
-
React.createElement(
|
|
34
|
+
React.createElement(SectionLabel, { colorEnabled }, "Run usage"),
|
|
37
35
|
model.runs.length === 0
|
|
38
36
|
? React.createElement(Text, null, " No auditable run tokenUsage yet.")
|
|
39
37
|
: React.createElement(ActionList, {
|
|
@@ -4,6 +4,15 @@ import { Box, Text } from "ink";
|
|
|
4
4
|
import { COCKPIT_COLORS, statusColor, resolveGlyphs } from "../theme.js";
|
|
5
5
|
|
|
6
6
|
const mute = (on) => (on ? COCKPIT_COLORS.muted : undefined);
|
|
7
|
+
const ice = (on) => (on ? COCKPIT_COLORS.interactive : undefined);
|
|
8
|
+
|
|
9
|
+
/** Short typographic view title — brand amber, no border. */
|
|
10
|
+
export function ViewTitle({ children, colorEnabled = true }) {
|
|
11
|
+
return React.createElement(Text, {
|
|
12
|
+
bold: true,
|
|
13
|
+
color: colorEnabled ? COCKPIT_COLORS.brand : undefined
|
|
14
|
+
}, children);
|
|
15
|
+
}
|
|
7
16
|
|
|
8
17
|
export function ActionList({ items = [], selectedIndex = 0, focused = true, colorEnabled = true, unicode = true }) {
|
|
9
18
|
const g = resolveGlyphs(unicode);
|
|
@@ -13,7 +22,7 @@ export function ActionList({ items = [], selectedIndex = 0, focused = true, colo
|
|
|
13
22
|
return React.createElement(Text, {
|
|
14
23
|
key: item.id ?? String(i),
|
|
15
24
|
bold: sel,
|
|
16
|
-
color: sel && focused && colorEnabled ? COCKPIT_COLORS.
|
|
25
|
+
color: sel && focused && colorEnabled ? COCKPIT_COLORS.interactive : undefined
|
|
17
26
|
}, `${sel && focused ? g.focus : " "} ${item.label}${item.hint ? ` ${item.hint}` : ""}`);
|
|
18
27
|
})
|
|
19
28
|
);
|
|
@@ -30,7 +39,7 @@ export function Stepper({ steps = [], currentIndex = 0, colorEnabled = true, uni
|
|
|
30
39
|
const cur = i === currentIndex;
|
|
31
40
|
const color = isDone
|
|
32
41
|
? (colorEnabled ? COCKPIT_COLORS.success : undefined)
|
|
33
|
-
: cur ? (colorEnabled
|
|
42
|
+
: cur ? ice(colorEnabled) : mute(colorEnabled);
|
|
34
43
|
return React.createElement(Text, {
|
|
35
44
|
key: step.id ?? String(i), bold: cur, color
|
|
36
45
|
}, `${isDone ? done : cur ? current : idle} ${i + 1}. ${step.label}`);
|
|
@@ -50,24 +59,24 @@ export function Callout({ tone = "info", title, body, colorEnabled = true, compa
|
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
export function Confirm({ summary, primaryLabel = "Confirm", focused = true, colorEnabled = true, mark = " " }) {
|
|
53
|
-
return React.createElement(Box, { flexDirection: "column" },
|
|
62
|
+
return React.createElement(Box, { flexDirection: "column", marginY: 1 },
|
|
54
63
|
summary ? React.createElement(Text, null, summary) : null,
|
|
55
64
|
React.createElement(Text, {
|
|
56
65
|
bold: focused,
|
|
57
|
-
color: focused && colorEnabled ? COCKPIT_COLORS.
|
|
66
|
+
color: focused && colorEnabled ? COCKPIT_COLORS.interactive : undefined
|
|
58
67
|
}, `${mark} ${primaryLabel}`)
|
|
59
68
|
);
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
export function Receipt({ title = "Receipt", lines = [], colorEnabled = true }) {
|
|
63
|
-
return React.createElement(Box, { flexDirection: "column" },
|
|
72
|
+
return React.createElement(Box, { flexDirection: "column", marginY: 1 },
|
|
64
73
|
React.createElement(Text, { bold: true, color: colorEnabled ? COCKPIT_COLORS.success : undefined }, title),
|
|
65
74
|
...lines.map((line, i) => React.createElement(Text, { key: `r${i}`, color: mute(colorEnabled) }, line))
|
|
66
75
|
);
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
export function Details({ open = false, summary = "Details", lines = [], colorEnabled = true, focused = false, mark = " " }) {
|
|
70
|
-
const color = focused && colorEnabled ? COCKPIT_COLORS.
|
|
79
|
+
const color = focused && colorEnabled ? COCKPIT_COLORS.interactive : mute(colorEnabled);
|
|
71
80
|
if (!open) return React.createElement(Text, { bold: focused, color }, `${mark} ${summary} · Space`);
|
|
72
81
|
return React.createElement(Box, { flexDirection: "column" },
|
|
73
82
|
React.createElement(Text, { bold: true, color }, `${mark} ${summary}`),
|
|
@@ -82,3 +91,11 @@ export function KeyBar({ hints = [], colorEnabled = true, columns = 80 }) {
|
|
|
82
91
|
hints.map((h) => `${h.keys} ${h.label}`).join(" · "))
|
|
83
92
|
);
|
|
84
93
|
}
|
|
94
|
+
|
|
95
|
+
/** Section label inside a panel — muted brand hierarchy under ViewTitle. */
|
|
96
|
+
export function SectionLabel({ children, colorEnabled = true }) {
|
|
97
|
+
return React.createElement(Text, {
|
|
98
|
+
bold: true,
|
|
99
|
+
color: colorEnabled ? COCKPIT_COLORS.muted : undefined
|
|
100
|
+
}, children);
|
|
101
|
+
}
|