@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.
- package/README.md +11 -7
- package/package.json +1 -1
- package/scripts/check-published-release.mjs +4 -1
- package/scripts/cockpit-smoke-test.sh +3 -1
- package/scripts/cockpit-smoke.mjs +85 -7
- package/src/cli.js +2 -1
- package/src/global/dashboard-guidance.js +146 -17
- package/src/global/ink/cockpit/primitives.js +16 -9
- package/src/global/ink/cockpit-controller.js +84 -44
- package/src/global/ink/cockpit-focus.js +92 -0
- package/src/global/ink/cockpit-home.js +115 -0
- package/src/global/ink/cockpit-models.js +162 -60
- package/src/global/ink/cockpit-views.js +92 -40
- package/src/global/ink/launch-input.js +13 -3
- package/src/global/ink/orchestrator-app.js +132 -50
- package/src/global/ink/orchestrator-state.js +71 -14
- package/src/global/ink/theme.js +7 -1
- package/src/global/ink/use-orchestrator-data.js +6 -2
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { COCKPIT_NAV, COCKPIT_REGIONS, regionsForLayout } from "./cockpit-models.js";
|
|
2
|
+
import { ORCHESTRATOR_VIEWS } from "./orchestrator-state.js";
|
|
3
|
+
import { LAYOUT_MODES } from "./layout.js";
|
|
4
|
+
|
|
5
|
+
const NAV_FOCUSED_VIEWS = new Set([
|
|
6
|
+
ORCHESTRATOR_VIEWS.HOME,
|
|
7
|
+
ORCHESTRATOR_VIEWS.PROVIDERS,
|
|
8
|
+
ORCHESTRATOR_VIEWS.DIAGNOSTICS,
|
|
9
|
+
ORCHESTRATOR_VIEWS.HELP
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
const CONTENT_INTERACTIVE_VIEWS = new Set([
|
|
13
|
+
ORCHESTRATOR_VIEWS.ACTIVE_RUNS,
|
|
14
|
+
ORCHESTRATOR_VIEWS.RECENT_RUNS,
|
|
15
|
+
ORCHESTRATOR_VIEWS.RUN_DETAIL,
|
|
16
|
+
ORCHESTRATOR_VIEWS.LAUNCH
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export function isNavFocusedView(view) {
|
|
20
|
+
return NAV_FOCUSED_VIEWS.has(view);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isContentInteractiveView(view) {
|
|
24
|
+
return CONTENT_INTERACTIVE_VIEWS.has(view);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function defaultRegionForView(view, layoutMode = LAYOUT_MODES.COMPACT) {
|
|
28
|
+
const regions = regionsForLayout(layoutMode);
|
|
29
|
+
if (isContentInteractiveView(view) && regions.includes(COCKPIT_REGIONS.CONTENT)) {
|
|
30
|
+
return COCKPIT_REGIONS.CONTENT;
|
|
31
|
+
}
|
|
32
|
+
if (regions.includes(COCKPIT_REGIONS.NAV)) return COCKPIT_REGIONS.NAV;
|
|
33
|
+
return regions[0] ?? COCKPIT_REGIONS.CONTENT;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function interactiveRegionsFor(state) {
|
|
37
|
+
const regions = regionsForLayout(state.layoutMode);
|
|
38
|
+
if (!isContentInteractiveView(state.view) || state.view === ORCHESTRATOR_VIEWS.RUN_DETAIL) {
|
|
39
|
+
return regions.filter((region) => region === COCKPIT_REGIONS.NAV);
|
|
40
|
+
}
|
|
41
|
+
return regions.filter(
|
|
42
|
+
(region) => region === COCKPIT_REGIONS.NAV || region === COCKPIT_REGIONS.CONTENT
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function canTabBetweenRegions(state) {
|
|
47
|
+
if (!isContentInteractiveView(state.view)) return false;
|
|
48
|
+
if (state.view === ORCHESTRATOR_VIEWS.RUN_DETAIL) return false;
|
|
49
|
+
return interactiveRegionsFor(state).length >= 2;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Map raw key intent to a reducer action (or null when inactive / view-owned).
|
|
54
|
+
*/
|
|
55
|
+
export function routeCockpitKey(state, keyAction) {
|
|
56
|
+
switch (keyAction.type) {
|
|
57
|
+
case "escape":
|
|
58
|
+
return { type: "escape" };
|
|
59
|
+
case "tab":
|
|
60
|
+
return canTabBetweenRegions(state) ? { type: "tab" } : null;
|
|
61
|
+
case "arrow": {
|
|
62
|
+
if (state.region === COCKPIT_REGIONS.SYSTEM) return null;
|
|
63
|
+
if (state.region === COCKPIT_REGIONS.NAV || isNavFocusedView(state.view)) {
|
|
64
|
+
return { type: "arrow", direction: keyAction.direction };
|
|
65
|
+
}
|
|
66
|
+
if (state.region === COCKPIT_REGIONS.CONTENT && isContentInteractiveView(state.view)) {
|
|
67
|
+
if (state.view === ORCHESTRATOR_VIEWS.RUN_DETAIL || state.view === ORCHESTRATOR_VIEWS.LAUNCH) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
type: "arrow",
|
|
72
|
+
direction: keyAction.direction,
|
|
73
|
+
listLength: keyAction.listLength
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
case "enter":
|
|
79
|
+
if (state.region === COCKPIT_REGIONS.NAV || isNavFocusedView(state.view)) {
|
|
80
|
+
return { type: "enter-nav" };
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
default:
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function clamp(value, min, max) {
|
|
89
|
+
return Math.min(max, Math.max(min, value));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { COCKPIT_NAV, COCKPIT_REGIONS, LAYOUT_MODES, ORCHESTRATOR_VIEWS, regionsForLayout };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { ORCHESTRATOR_VIEWS } from "./orchestrator-state.js";
|
|
2
|
+
import {
|
|
3
|
+
DASHBOARD_PURPOSE,
|
|
4
|
+
resolveDashboardRecommendation,
|
|
5
|
+
resolveProjectReadiness
|
|
6
|
+
} from "../dashboard-guidance.js";
|
|
7
|
+
import { LAYOUT_MODES } from "./layout.js";
|
|
8
|
+
|
|
9
|
+
export function formatHomeRecentRun(run) {
|
|
10
|
+
if (!run) return null;
|
|
11
|
+
const agent = humanizeId(run.agentId);
|
|
12
|
+
const result = humanizeRunState(run.state);
|
|
13
|
+
return {
|
|
14
|
+
headline: `Last run · ${agent} · ${result}`,
|
|
15
|
+
hint: "Open History to inspect the result."
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function buildHomeMissionModel({
|
|
20
|
+
projectName = "project",
|
|
21
|
+
hasGlobalState = false,
|
|
22
|
+
diagnostics = null,
|
|
23
|
+
dashboard = null,
|
|
24
|
+
layoutMode = LAYOUT_MODES.COMPACT,
|
|
25
|
+
recentRuns = null
|
|
26
|
+
} = {}) {
|
|
27
|
+
const readiness = resolveProjectReadiness({ hasGlobalState, diagnostics, dashboard });
|
|
28
|
+
const recommendation = resolveDashboardRecommendation({
|
|
29
|
+
hasGlobalState,
|
|
30
|
+
diagnostics,
|
|
31
|
+
dashboard
|
|
32
|
+
});
|
|
33
|
+
const runs = recentRuns ?? dashboard?.recentRuns ?? [];
|
|
34
|
+
const lastRun = formatHomeRecentRun(runs[0] ?? null);
|
|
35
|
+
const includeEmbeddedStatus = layoutMode !== LAYOUT_MODES.WIDE;
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
title: `HOME — ${projectName}`,
|
|
39
|
+
purpose: DASHBOARD_PURPOSE,
|
|
40
|
+
readiness,
|
|
41
|
+
includeEmbeddedStatus,
|
|
42
|
+
next: {
|
|
43
|
+
title: "NEXT",
|
|
44
|
+
actionTitle: recommendation.title,
|
|
45
|
+
actionDetail: recommendation.detail ?? recommendation.message,
|
|
46
|
+
enterHint: "Enter →",
|
|
47
|
+
kind: recommendation.kind,
|
|
48
|
+
targetView: recommendation.targetView,
|
|
49
|
+
targetAction: recommendation.targetAction,
|
|
50
|
+
message: recommendation.message
|
|
51
|
+
},
|
|
52
|
+
recent: lastRun
|
|
53
|
+
? {
|
|
54
|
+
title: "RECENT",
|
|
55
|
+
headline: lastRun.headline,
|
|
56
|
+
hint: lastRun.hint,
|
|
57
|
+
emptyHint: null
|
|
58
|
+
}
|
|
59
|
+
: {
|
|
60
|
+
title: "RECENT",
|
|
61
|
+
headline: null,
|
|
62
|
+
hint: null,
|
|
63
|
+
emptyHint: "No runs yet. Create a new run when an agent is ready."
|
|
64
|
+
},
|
|
65
|
+
explore: {
|
|
66
|
+
title: "EXPLORE",
|
|
67
|
+
lines: [
|
|
68
|
+
"Agents — See which installed tools Kairo can launch and audit.",
|
|
69
|
+
"System health — Inspect intelligence, authentication, and configuration."
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
recommendedTitle: recommendation.title,
|
|
73
|
+
recommendedAction: recommendation.message,
|
|
74
|
+
recommendedKind: recommendation.kind,
|
|
75
|
+
recommendedTargetView: recommendation.targetView,
|
|
76
|
+
recommendedTargetAction: recommendation.targetAction,
|
|
77
|
+
emptyHint: lastRun ? null : "No runs yet. Create a new run when an agent is ready."
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function openRecommendedDestination(recommendation, { navItems } = {}) {
|
|
82
|
+
if (!recommendation?.targetView) return null;
|
|
83
|
+
const index = (navItems ?? []).findIndex((item) => item.view === recommendation.targetView
|
|
84
|
+
|| (recommendation.targetAction && item.action === recommendation.targetAction));
|
|
85
|
+
return {
|
|
86
|
+
view: recommendation.targetView,
|
|
87
|
+
action: recommendation.targetAction ?? null,
|
|
88
|
+
navIndex: index >= 0 ? index : null
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function humanizeId(value) {
|
|
93
|
+
const raw = String(value ?? "agent");
|
|
94
|
+
return raw.charAt(0).toUpperCase() + raw.slice(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function humanizeRunState(state) {
|
|
98
|
+
switch (state) {
|
|
99
|
+
case "succeeded":
|
|
100
|
+
case "completed":
|
|
101
|
+
return "Succeeded";
|
|
102
|
+
case "failed":
|
|
103
|
+
return "Failed";
|
|
104
|
+
case "cancelled":
|
|
105
|
+
case "canceled":
|
|
106
|
+
return "Cancelled";
|
|
107
|
+
case "running":
|
|
108
|
+
case "starting":
|
|
109
|
+
return "Running";
|
|
110
|
+
default:
|
|
111
|
+
return humanizeId(state);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export { ORCHESTRATOR_VIEWS };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { LAYOUT_MODES } from "./layout.js";
|
|
1
|
+
import { LAYOUT_MODES, resolveListLimit } from "./layout.js";
|
|
2
2
|
import { ORCHESTRATOR_VIEWS } from "./orchestrator-state.js";
|
|
3
|
-
import {
|
|
3
|
+
import { resolveProjectReadiness } from "../dashboard-guidance.js";
|
|
4
4
|
import { STATUS_LABELS, resolveGlyphs } from "./theme.js";
|
|
5
5
|
import { windowList } from "./list-window.js";
|
|
6
|
-
import {
|
|
6
|
+
import { buildHomeMissionModel, formatHomeRecentRun } from "./cockpit-home.js";
|
|
7
7
|
|
|
8
8
|
export const COCKPIT_REGIONS = {
|
|
9
9
|
NAV: "nav",
|
|
@@ -12,12 +12,43 @@ export const COCKPIT_REGIONS = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const COCKPIT_NAV = [
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
{
|
|
16
|
+
id: "overview",
|
|
17
|
+
label: "Home",
|
|
18
|
+
view: ORCHESTRATOR_VIEWS.HOME,
|
|
19
|
+
description: "What Kairo does here, readiness, and the next useful action."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "active",
|
|
23
|
+
label: "Running now",
|
|
24
|
+
view: ORCHESTRATOR_VIEWS.ACTIVE_RUNS,
|
|
25
|
+
description: "Supervised runs executing right now."
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "recent",
|
|
29
|
+
label: "History",
|
|
30
|
+
view: ORCHESTRATOR_VIEWS.RECENT_RUNS,
|
|
31
|
+
description: "Past runs with agent, state, and readable result."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "providers",
|
|
35
|
+
label: "Agents",
|
|
36
|
+
view: ORCHESTRATOR_VIEWS.PROVIDERS,
|
|
37
|
+
description: "Installed tools Kairo can launch and audit."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "launch",
|
|
41
|
+
label: "New run",
|
|
42
|
+
view: ORCHESTRATOR_VIEWS.LAUNCH,
|
|
43
|
+
action: "launch",
|
|
44
|
+
description: "Delegate a task to an executable agent."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "diagnostics",
|
|
48
|
+
label: "System health",
|
|
49
|
+
view: ORCHESTRATOR_VIEWS.DIAGNOSTICS,
|
|
50
|
+
description: "Agents, intelligence, authentication, and configuration."
|
|
51
|
+
}
|
|
21
52
|
];
|
|
22
53
|
|
|
23
54
|
export function regionsForLayout(layoutMode) {
|
|
@@ -30,6 +61,11 @@ export function regionsForLayout(layoutMode) {
|
|
|
30
61
|
return [COCKPIT_REGIONS.CONTENT];
|
|
31
62
|
}
|
|
32
63
|
|
|
64
|
+
export function navIndexForView(view, items = COCKPIT_NAV) {
|
|
65
|
+
const index = items.findIndex((item) => item.view === view);
|
|
66
|
+
return index >= 0 ? index : 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
33
69
|
export function buildTopBarModel({
|
|
34
70
|
projectName = "project",
|
|
35
71
|
systemOnline = true,
|
|
@@ -46,28 +82,73 @@ export function buildTopBarModel({
|
|
|
46
82
|
};
|
|
47
83
|
}
|
|
48
84
|
|
|
85
|
+
export function resolveNavStatusSummary(item, { dashboard = null, diagnostics = null } = {}) {
|
|
86
|
+
const active = dashboard?.activeRuns?.length ?? 0;
|
|
87
|
+
const recent = dashboard?.recentRuns?.length ?? 0;
|
|
88
|
+
const providers = dashboard?.providers ?? [];
|
|
89
|
+
const launchable = providers.filter((entry) => entry.launchable).length;
|
|
90
|
+
const detected = diagnostics?.diagnostics?.detected ?? providers.filter((p) => p.available).length;
|
|
91
|
+
const errors = diagnostics?.diagnostics?.errors ?? 0;
|
|
92
|
+
|
|
93
|
+
switch (item.id) {
|
|
94
|
+
case "overview":
|
|
95
|
+
return resolveProjectReadiness({
|
|
96
|
+
hasGlobalState: true,
|
|
97
|
+
diagnostics,
|
|
98
|
+
dashboard
|
|
99
|
+
}).label;
|
|
100
|
+
case "active":
|
|
101
|
+
return active === 0 ? "Idle" : `${active} active`;
|
|
102
|
+
case "recent":
|
|
103
|
+
return recent === 0 ? "No history" : `${recent} recent`;
|
|
104
|
+
case "providers":
|
|
105
|
+
return `${launchable}/${providers.length || detected} ready`;
|
|
106
|
+
case "launch":
|
|
107
|
+
return launchable > 0 ? "Ready" : "Unavailable";
|
|
108
|
+
case "diagnostics":
|
|
109
|
+
return errors > 0 ? `${errors} issues` : "Checked";
|
|
110
|
+
default:
|
|
111
|
+
return "";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
49
115
|
export function buildNavModel({
|
|
50
116
|
navIndex = 0,
|
|
117
|
+
currentView = ORCHESTRATOR_VIEWS.HOME,
|
|
51
118
|
focused = false,
|
|
52
119
|
unicode = true,
|
|
53
|
-
items = COCKPIT_NAV
|
|
120
|
+
items = COCKPIT_NAV,
|
|
121
|
+
dashboard = null,
|
|
122
|
+
diagnostics = null
|
|
54
123
|
} = {}) {
|
|
55
124
|
const glyphs = resolveGlyphs(unicode);
|
|
125
|
+
const selected = items[navIndex] ?? items[0];
|
|
126
|
+
const mapped = items.map((item, index) => {
|
|
127
|
+
const isSelected = index === navIndex;
|
|
128
|
+
const isCurrent = item.view === currentView;
|
|
129
|
+
return {
|
|
130
|
+
...item,
|
|
131
|
+
marker: isSelected ? glyphs.focus : (isCurrent ? glyphs.bullet : " "),
|
|
132
|
+
selected: isSelected,
|
|
133
|
+
current: isCurrent,
|
|
134
|
+
focused: focused && isSelected,
|
|
135
|
+
statusSummary: resolveNavStatusSummary(item, { dashboard, diagnostics })
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
|
|
56
139
|
return {
|
|
57
140
|
title: "NAVIGATION",
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
focused: focused && index === navIndex
|
|
63
|
-
}))
|
|
141
|
+
explanation: selected
|
|
142
|
+
? `${selected.description} (${resolveNavStatusSummary(selected, { dashboard, diagnostics })})`
|
|
143
|
+
: "",
|
|
144
|
+
items: mapped
|
|
64
145
|
};
|
|
65
146
|
}
|
|
66
147
|
|
|
67
148
|
export function buildSystemStripModel({
|
|
68
149
|
dashboard = null,
|
|
69
150
|
diagnostics = null,
|
|
70
|
-
|
|
151
|
+
readiness = null
|
|
71
152
|
} = {}) {
|
|
72
153
|
const agentsDetected = diagnostics?.diagnostics?.detected
|
|
73
154
|
?? (dashboard?.providers ?? []).filter((p) => p.available).length;
|
|
@@ -81,6 +162,11 @@ export function buildSystemStripModel({
|
|
|
81
162
|
: intelligence?.cloudAuthenticated
|
|
82
163
|
? "Cloud"
|
|
83
164
|
: "None";
|
|
165
|
+
const resolved = readiness ?? resolveProjectReadiness({
|
|
166
|
+
hasGlobalState: agentsDetected > 0,
|
|
167
|
+
diagnostics,
|
|
168
|
+
dashboard
|
|
169
|
+
});
|
|
84
170
|
|
|
85
171
|
return {
|
|
86
172
|
title: "SYSTEM",
|
|
@@ -88,62 +174,76 @@ export function buildSystemStripModel({
|
|
|
88
174
|
{ key: "Agents", value: `${agentsDetected}/${agentsTotal}`, kind: agentsDetected > 0 ? "ready" : "warn" },
|
|
89
175
|
{ key: "Runs", value: String(activeRuns), kind: activeRuns > 0 ? "ready" : "muted" },
|
|
90
176
|
{ key: "Intel", value: intelLabel, kind: intelLabel === "None" ? "warn" : "ready" },
|
|
91
|
-
{
|
|
177
|
+
{
|
|
178
|
+
key: "Health",
|
|
179
|
+
value: STATUS_LABELS[resolved.kind] ?? resolved.label ?? resolved.kind,
|
|
180
|
+
kind: resolved.healthKind ?? "warn"
|
|
181
|
+
}
|
|
92
182
|
]
|
|
93
183
|
};
|
|
94
184
|
}
|
|
95
185
|
|
|
96
|
-
export function buildHomeMissionModel({
|
|
97
|
-
hasGlobalState = false,
|
|
98
|
-
diagnostics = null,
|
|
99
|
-
dashboard = null,
|
|
100
|
-
layoutMode = LAYOUT_MODES.COMPACT,
|
|
101
|
-
activityLines = []
|
|
102
|
-
} = {}) {
|
|
103
|
-
const recommendation = resolveDashboardRecommendation({
|
|
104
|
-
hasGlobalState,
|
|
105
|
-
diagnostics,
|
|
106
|
-
dashboard
|
|
107
|
-
});
|
|
108
|
-
const limit = resolveListLimit(layoutMode, { contentRows: 10 });
|
|
109
|
-
const windowed = windowList(activityLines, limit);
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
title: "MISSION CONTROL",
|
|
113
|
-
recommendedTitle: "Recommended action",
|
|
114
|
-
recommendedAction: recommendation.message,
|
|
115
|
-
recommendedKind: recommendation.kind,
|
|
116
|
-
activityTitle: activityLines.length ? "Activity" : "Activity / empty state",
|
|
117
|
-
activityLines: windowed.items,
|
|
118
|
-
moreLine: windowed.moreLine,
|
|
119
|
-
emptyHint: activityLines.length === 0
|
|
120
|
-
? "No recent activity. Launch a run when agents are ready."
|
|
121
|
-
: null
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
186
|
export function buildFooterModel({
|
|
126
187
|
view = ORCHESTRATOR_VIEWS.HOME,
|
|
127
188
|
region = COCKPIT_REGIONS.NAV,
|
|
128
189
|
helpOpen = false,
|
|
129
190
|
canCancel = false,
|
|
130
|
-
unicode = true
|
|
191
|
+
unicode = true,
|
|
192
|
+
hasError = false
|
|
131
193
|
} = {}) {
|
|
132
194
|
const glyphs = resolveGlyphs(unicode);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
195
|
+
const parts = [];
|
|
196
|
+
|
|
197
|
+
if (hasError) {
|
|
198
|
+
parts.push("R Retry");
|
|
199
|
+
parts.push("Esc Exit");
|
|
200
|
+
return { text: parts.join(` ${glyphs.bullet} `) };
|
|
137
201
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
202
|
+
|
|
203
|
+
if (helpOpen || view === ORCHESTRATOR_VIEWS.HELP) {
|
|
204
|
+
parts.push("Esc close help");
|
|
205
|
+
parts.push("? Help");
|
|
206
|
+
return { text: parts.join(` ${glyphs.bullet} `) };
|
|
142
207
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
208
|
+
|
|
209
|
+
if (view === ORCHESTRATOR_VIEWS.RUN_DETAIL) {
|
|
210
|
+
parts.push("R refresh");
|
|
211
|
+
if (canCancel) parts.push("C cancel");
|
|
212
|
+
parts.push("Esc Back");
|
|
213
|
+
return { text: parts.join(` ${glyphs.bullet} `) };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
parts.push("↑↓ Navigate");
|
|
217
|
+
|
|
218
|
+
const showTab = view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS
|
|
219
|
+
|| view === ORCHESTRATOR_VIEWS.RECENT_RUNS
|
|
220
|
+
|| view === ORCHESTRATOR_VIEWS.LAUNCH;
|
|
221
|
+
if (showTab) {
|
|
222
|
+
parts.push("Tab Region");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (view === ORCHESTRATOR_VIEWS.HOME
|
|
226
|
+
|| view === ORCHESTRATOR_VIEWS.PROVIDERS
|
|
227
|
+
|| view === ORCHESTRATOR_VIEWS.DIAGNOSTICS
|
|
228
|
+
|| region === COCKPIT_REGIONS.NAV
|
|
229
|
+
|| view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS
|
|
230
|
+
|| view === ORCHESTRATOR_VIEWS.RECENT_RUNS) {
|
|
231
|
+
parts.push("Enter Open");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (view !== ORCHESTRATOR_VIEWS.LAUNCH) {
|
|
235
|
+
parts.push("R refresh");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
parts.push("? Help");
|
|
239
|
+
parts.push(view === ORCHESTRATOR_VIEWS.HOME ? "Esc Exit" : "Esc Back");
|
|
240
|
+
|
|
241
|
+
return { text: parts.join(` ${glyphs.bullet} `) };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function windowLinesForLayout(lines = [], layoutMode = LAYOUT_MODES.COMPACT, contentRows = 12) {
|
|
245
|
+
const limit = resolveListLimit(layoutMode, { contentRows });
|
|
246
|
+
return windowList(lines, limit);
|
|
147
247
|
}
|
|
148
248
|
|
|
149
249
|
export function resolveProjectName(workspaceRoot = "") {
|
|
@@ -151,3 +251,5 @@ export function resolveProjectName(workspaceRoot = "") {
|
|
|
151
251
|
const parts = String(workspaceRoot).split(/[/\\]/).filter(Boolean);
|
|
152
252
|
return parts[parts.length - 1] || "project";
|
|
153
253
|
}
|
|
254
|
+
|
|
255
|
+
export { buildHomeMissionModel, formatHomeRecentRun };
|