@kal-elsam/kairo-runtime 0.2.3 → 0.3.1

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.
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { render } from "ink";
3
3
  import { OrchestratorApp } from "./orchestrator-app.js";
4
+ import { createFullscreenSession } from "./fullscreen-session.js";
4
5
 
5
6
  export async function runOrchestratorInk({
6
7
  homeDir,
@@ -9,23 +10,42 @@ export async function runOrchestratorInk({
9
10
  packageName,
10
11
  cliVersion,
11
12
  hasGlobalState = false,
12
- renderImpl = render
13
+ renderImpl = render,
14
+ fullscreenSession = null,
15
+ stdout = process.stdout
13
16
  }) {
14
- return new Promise((resolve) => {
15
- const { waitUntilExit } = renderImpl(
16
- React.createElement(OrchestratorApp, {
17
- homeDir,
18
- workspaceRoot,
19
- packageRoot,
20
- packageName,
21
- cliVersion,
22
- hasGlobalState,
23
- onComplete: resolve
24
- })
25
- );
17
+ const ownsSession = !fullscreenSession;
18
+ const session = fullscreenSession ?? createFullscreenSession({
19
+ stdout,
20
+ enabled: Boolean(stdout?.isTTY)
21
+ });
22
+
23
+ if (ownsSession) {
24
+ session.enter();
25
+ }
26
26
 
27
- waitUntilExit().catch((error) => {
28
- resolve({ cancelled: true, error });
27
+ try {
28
+ return await new Promise((resolve) => {
29
+ const { waitUntilExit } = renderImpl(
30
+ React.createElement(OrchestratorApp, {
31
+ homeDir,
32
+ workspaceRoot,
33
+ packageRoot,
34
+ packageName,
35
+ cliVersion,
36
+ hasGlobalState,
37
+ onComplete: resolve
38
+ }),
39
+ stdout ? { stdout } : undefined
40
+ );
41
+
42
+ waitUntilExit().catch((error) => {
43
+ resolve({ cancelled: true, error });
44
+ });
29
45
  });
30
- });
46
+ } finally {
47
+ if (ownsSession) {
48
+ session.leave();
49
+ }
50
+ }
31
51
  }
@@ -5,6 +5,7 @@ import { loadConsentAudit } from "../policy.js";
5
5
  import { formatResultNote } from "../clack/theme.js";
6
6
  import { SetupWizardCancelledError } from "../clack/setup-wizard-constants.js";
7
7
  import { SetupApp } from "./setup-app.js";
8
+ import { createFullscreenSession } from "./fullscreen-session.js";
8
9
 
9
10
  export { SetupWizardCancelledError };
10
11
 
@@ -23,26 +24,46 @@ export async function runSetupInk({
23
24
  yesExplicit = false,
24
25
  confirmExplicit = false,
25
26
  interactive = true,
26
- renderImpl = render
27
+ renderImpl = render,
28
+ fullscreenSession = null,
29
+ stdout = process.stdout
27
30
  }) {
28
- const outcome = await new Promise((resolve) => {
29
- const { waitUntilExit } = renderImpl(
30
- React.createElement(SetupApp, {
31
- homeDir,
32
- workspaceRoot,
33
- packageRoot,
34
- packageName,
35
- cliVersion,
36
- dryRun,
37
- onboarding,
38
- onComplete: resolve
39
- })
40
- );
31
+ const ownsSession = !fullscreenSession;
32
+ const session = fullscreenSession ?? createFullscreenSession({
33
+ stdout,
34
+ enabled: Boolean(stdout?.isTTY)
35
+ });
36
+
37
+ if (ownsSession) {
38
+ session.enter();
39
+ }
41
40
 
42
- waitUntilExit().catch((error) => {
43
- resolve({ cancelled: true, usedWizard: true, error });
41
+ let outcome;
42
+ try {
43
+ outcome = await new Promise((resolve) => {
44
+ const { waitUntilExit } = renderImpl(
45
+ React.createElement(SetupApp, {
46
+ homeDir,
47
+ workspaceRoot,
48
+ packageRoot,
49
+ packageName,
50
+ cliVersion,
51
+ dryRun,
52
+ onboarding,
53
+ onComplete: resolve
54
+ }),
55
+ stdout ? { stdout } : undefined
56
+ );
57
+
58
+ waitUntilExit().catch((error) => {
59
+ resolve({ cancelled: true, usedWizard: true, error });
60
+ });
44
61
  });
45
- });
62
+ } finally {
63
+ if (ownsSession) {
64
+ session.leave();
65
+ }
66
+ }
46
67
 
47
68
  if (outcome.error) {
48
69
  throw outcome.error;
@@ -21,35 +21,32 @@ import {
21
21
  toggleSelection,
22
22
  transitionFromSplash
23
23
  } from "./setup-state.js";
24
+ import { COCKPIT_COLORS } from "./theme.js";
25
+ import { CockpitPanel } from "./cockpit/primitives.js";
24
26
 
25
27
  const INK_COLORS = {
26
- accent: "cyan",
27
- success: "green",
28
- warning: "yellow",
29
- danger: "red",
30
- muted: "gray"
28
+ accent: COCKPIT_COLORS.primary,
29
+ success: COCKPIT_COLORS.success,
30
+ warning: COCKPIT_COLORS.warning,
31
+ danger: COCKPIT_COLORS.danger,
32
+ muted: COCKPIT_COLORS.muted
31
33
  };
32
34
 
33
35
  function Header() {
34
36
  const lines = formatInkHeaderLines();
35
37
  return React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
36
- React.createElement(Text, { bold: true, color: INK_COLORS.accent }, lines[0]),
37
- React.createElement(Text, { color: INK_COLORS.muted }, lines[1]),
38
+ React.createElement(Text, { bold: true, color: INK_COLORS.accent }, `╭─ ${lines[0]}`),
39
+ React.createElement(Text, { color: COCKPIT_COLORS.secondary }, lines[1]),
38
40
  React.createElement(Text, { dimColor: true }, lines[2])
39
41
  );
40
42
  }
41
43
 
42
44
  function Panel({ title, children }) {
43
- return React.createElement(Box, {
44
- flexDirection: "column",
45
- borderStyle: "round",
46
- borderColor: INK_COLORS.accent,
47
- paddingX: 1,
48
- marginBottom: 1
49
- },
50
- React.createElement(Text, { bold: true, color: INK_COLORS.accent }, title),
51
- children
52
- );
45
+ return React.createElement(CockpitPanel, {
46
+ title,
47
+ focused: true,
48
+ width: "100%"
49
+ }, children);
53
50
  }
54
51
 
55
52
  function Footer({ children }) {
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Pure terminal capability resolution for Ink cockpit / setup.
3
+ * Never communicates state via color alone — callers must keep text labels.
4
+ */
5
+
6
+ export const LAYOUT_MODES = {
7
+ WIDE: "wide",
8
+ COMPACT: "compact",
9
+ MINIMAL: "minimal"
10
+ };
11
+
12
+ /**
13
+ * @param {{
14
+ * columns?: number,
15
+ * rows?: number,
16
+ * env?: NodeJS.ProcessEnv | Record<string, string | undefined>,
17
+ * isTTY?: boolean,
18
+ * term?: string
19
+ * }} [options]
20
+ */
21
+ export function resolveTerminalCapabilities({
22
+ columns = 80,
23
+ rows = 24,
24
+ env = process.env,
25
+ isTTY = true,
26
+ term = env.TERM ?? ""
27
+ } = {}) {
28
+ const forceInk = env.HARNESS_INK !== "0";
29
+ const noColor = Boolean(env.NO_COLOR) || env.FORCE_COLOR === "0";
30
+ const unicode = !(
31
+ env.HARNESS_ASCII === "1"
32
+ || env.LC_ALL === "C"
33
+ || term === "dumb"
34
+ || /^(linux|vt100|vt220)$/i.test(term)
35
+ );
36
+
37
+ const safeColumns = Number.isFinite(columns) && columns > 0 ? columns : 80;
38
+ const safeRows = Number.isFinite(rows) && rows > 0 ? rows : 24;
39
+
40
+ return {
41
+ isTTY: Boolean(isTTY),
42
+ term: term || "",
43
+ columns: safeColumns,
44
+ rows: safeRows,
45
+ forceInk,
46
+ color: !noColor,
47
+ unicode,
48
+ canUseInk: Boolean(isTTY) && forceInk && term !== "dumb" && safeColumns >= 60
49
+ };
50
+ }
@@ -1,13 +1,35 @@
1
1
  import { stdin as input, stdout as output } from "node:process";
2
+ import { resolveTerminalCapabilities } from "./terminal-capabilities.js";
3
+ import { resolveLayoutMode } from "./layout.js";
4
+
5
+ export { resolveTerminalCapabilities } from "./terminal-capabilities.js";
6
+ export { resolveLayoutMode, resolveListLimit, LAYOUT_MODES } from "./layout.js";
7
+ export { windowList } from "./list-window.js";
2
8
 
3
9
  export function canUseSetupInk({
4
10
  interactive = Boolean(input.isTTY && output.isTTY),
5
11
  term = process.env.TERM ?? "",
6
12
  columns = output.columns ?? 80,
7
- forceInk = process.env.HARNESS_INK !== "0"
13
+ rows = output.rows ?? 24,
14
+ forceInk = process.env.HARNESS_INK !== "0",
15
+ env = process.env
16
+ } = {}) {
17
+ const caps = resolveTerminalCapabilities({
18
+ columns,
19
+ rows,
20
+ env: { ...env, HARNESS_INK: forceInk ? env.HARNESS_INK : "0", TERM: term },
21
+ isTTY: interactive,
22
+ term
23
+ });
24
+ return caps.canUseInk;
25
+ }
26
+
27
+ /**
28
+ * Snapshot of layout mode from live stdout dimensions.
29
+ */
30
+ export function readTerminalLayout({
31
+ columns = output.columns ?? 80,
32
+ rows = output.rows ?? 24
8
33
  } = {}) {
9
- if (!interactive || !forceInk) return false;
10
- if (term === "dumb") return false;
11
- if (columns > 0 && columns < 60) return false;
12
- return true;
34
+ return resolveLayoutMode({ columns, rows });
13
35
  }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Deep-space cockpit theme. Status always has a text label — never color alone.
3
+ */
4
+
5
+ export const COCKPIT_COLORS = {
6
+ primary: "cyan",
7
+ secondary: "magenta",
8
+ success: "green",
9
+ warning: "yellow",
10
+ danger: "red",
11
+ muted: "gray",
12
+ border: "cyan"
13
+ };
14
+
15
+ export const STATUS_LABELS = {
16
+ ready: "Ready",
17
+ warn: "Warn",
18
+ error: "Error",
19
+ offline: "Offline",
20
+ local: "Local",
21
+ online: "ONLINE",
22
+ loading: "Loading"
23
+ };
24
+
25
+ export const COCKPIT_GLYPHS = {
26
+ focus: "›",
27
+ focusAscii: ">",
28
+ bullet: "·",
29
+ bulletAscii: "-",
30
+ more: "…",
31
+ moreAscii: "..."
32
+ };
33
+
34
+ export function resolveGlyphs(unicode = true) {
35
+ if (unicode) {
36
+ return {
37
+ focus: COCKPIT_GLYPHS.focus,
38
+ bullet: COCKPIT_GLYPHS.bullet,
39
+ more: COCKPIT_GLYPHS.more
40
+ };
41
+ }
42
+ return {
43
+ focus: COCKPIT_GLYPHS.focusAscii,
44
+ bullet: COCKPIT_GLYPHS.bulletAscii,
45
+ more: COCKPIT_GLYPHS.moreAscii
46
+ };
47
+ }
48
+
49
+ export function statusColor(kind, { colorEnabled = true } = {}) {
50
+ if (!colorEnabled) return undefined;
51
+ switch (kind) {
52
+ case "ready":
53
+ case "success":
54
+ case "online":
55
+ return COCKPIT_COLORS.success;
56
+ case "warn":
57
+ case "warning":
58
+ return COCKPIT_COLORS.warning;
59
+ case "error":
60
+ case "danger":
61
+ return COCKPIT_COLORS.danger;
62
+ case "offline":
63
+ case "muted":
64
+ return COCKPIT_COLORS.muted;
65
+ default:
66
+ return COCKPIT_COLORS.primary;
67
+ }
68
+ }
69
+
70
+ export function formatStatusBadge(kind, label = STATUS_LABELS[kind] ?? String(kind)) {
71
+ return label;
72
+ }
@@ -0,0 +1,162 @@
1
+ import { useEffect, useState } from "react";
2
+ import { buildReadOnlyDiagnostics } from "../action-planner.js";
3
+ import { buildRuntimeDashboardData } from "../runtime/run-cli.js";
4
+ import { readRunEvents } from "../runtime/run-store.js";
5
+ import { startRun, stopRun } from "../runtime/run-manager.js";
6
+ import {
7
+ createLaunchDraft,
8
+ isRunCancellable,
9
+ resolveLaunchPermissions,
10
+ resolveLaunchableAgents
11
+ } from "./orchestrator-state.js";
12
+ import { LAUNCH_WIZARD_STEPS, ORCHESTRATOR_VIEWS } from "./orchestrator-state.js";
13
+
14
+ export function useOrchestratorData({
15
+ homeDir,
16
+ workspaceRoot,
17
+ packageName,
18
+ packageRoot,
19
+ cliVersion
20
+ }) {
21
+ const [loading, setLoading] = useState(true);
22
+ const [busy, setBusy] = useState(false);
23
+ const [error, setError] = useState(null);
24
+ const [dashboard, setDashboard] = useState(null);
25
+ const [diagnostics, setDiagnostics] = useState(null);
26
+ const [selectedRun, setSelectedRun] = useState(null);
27
+ const [selectedEvents, setSelectedEvents] = useState([]);
28
+ const [statusMessage, setStatusMessage] = useState(null);
29
+ const [launchAgentIndex, setLaunchAgentIndex] = useState(0);
30
+ const [launchStep, setLaunchStep] = useState(LAUNCH_WIZARD_STEPS.AGENT);
31
+ const [launchDraft, setLaunchDraft] = useState(createLaunchDraft);
32
+ const [launchPermissionIndex, setLaunchPermissionIndex] = useState(0);
33
+
34
+ const reload = async () => {
35
+ const [dash, diag] = await Promise.all([
36
+ buildRuntimeDashboardData({ homeDir, workspaceRoot, cliVersion }),
37
+ buildReadOnlyDiagnostics({ homeDir, workspaceRoot, packageName, packageRoot, cliVersion })
38
+ ]);
39
+ setDashboard(dash);
40
+ setDiagnostics(diag);
41
+ };
42
+
43
+ useEffect(() => {
44
+ let cancelled = false;
45
+ async function load() {
46
+ try {
47
+ await reload();
48
+ if (!cancelled) setLoading(false);
49
+ } catch (loadError) {
50
+ if (!cancelled) {
51
+ setError(loadError instanceof Error ? loadError.message : String(loadError));
52
+ setLoading(false);
53
+ }
54
+ }
55
+ }
56
+ load();
57
+ return () => { cancelled = true; };
58
+ }, [homeDir, workspaceRoot, packageName, packageRoot, cliVersion]);
59
+
60
+ const resetLaunchWizard = () => {
61
+ setLaunchStep(LAUNCH_WIZARD_STEPS.AGENT);
62
+ setLaunchDraft(createLaunchDraft());
63
+ setLaunchAgentIndex(0);
64
+ setLaunchPermissionIndex(0);
65
+ };
66
+
67
+ const openRunDetail = async (run, dispatch, returnView = null) => {
68
+ if (!run) return;
69
+ const events = await readRunEvents(homeDir, run.runId, { limit: 20 });
70
+ setSelectedRun(run);
71
+ setSelectedEvents(events);
72
+ dispatch({
73
+ type: "set-view",
74
+ view: ORCHESTRATOR_VIEWS.RUN_DETAIL,
75
+ returnView: returnView ?? null
76
+ });
77
+ };
78
+
79
+ const handleLaunch = async (draft, profile, dispatch) => {
80
+ if (!draft.agentId || !draft.task.trim()) {
81
+ setError("Agent and task are required.");
82
+ return;
83
+ }
84
+ setBusy(true);
85
+ setStatusMessage(`Launching ${draft.agentId}…`);
86
+ try {
87
+ const permissions = resolveLaunchPermissions({
88
+ ...draft,
89
+ permissionIndex: launchPermissionIndex
90
+ });
91
+ const { runId } = await startRun({
92
+ homeDir,
93
+ agentId: draft.agentId,
94
+ task: draft.task.trim(),
95
+ cwd: workspaceRoot,
96
+ model: draft.model.trim() || null,
97
+ permissions,
98
+ cliVersion,
99
+ profile: profile ?? null,
100
+ follow: false,
101
+ wait: false
102
+ });
103
+ await reload();
104
+ const run = (await buildRuntimeDashboardData({ homeDir, workspaceRoot, cliVersion }))
105
+ .runs.find((entry) => entry.runId === runId);
106
+ setStatusMessage(`Run started: ${runId}`);
107
+ resetLaunchWizard();
108
+ dispatch({ type: "set-view", view: ORCHESTRATOR_VIEWS.HOME });
109
+ if (run) await openRunDetail(run, dispatch);
110
+ } catch (launchError) {
111
+ setError(launchError instanceof Error ? launchError.message : String(launchError));
112
+ } finally {
113
+ setBusy(false);
114
+ }
115
+ };
116
+
117
+ const handleCancelRun = async () => {
118
+ if (!selectedRun || !isRunCancellable(selectedRun)) return;
119
+ setBusy(true);
120
+ try {
121
+ await stopRun(homeDir, selectedRun.runId);
122
+ await reload();
123
+ const refreshed = await buildRuntimeDashboardData({ homeDir, workspaceRoot, cliVersion });
124
+ const run = refreshed.runs.find((entry) => entry.runId === selectedRun.runId);
125
+ const events = await readRunEvents(homeDir, selectedRun.runId, { limit: 20 });
126
+ setSelectedRun(run ?? selectedRun);
127
+ setSelectedEvents(events);
128
+ setStatusMessage(`Cancelled ${selectedRun.runId}`);
129
+ } catch (cancelError) {
130
+ setError(cancelError instanceof Error ? cancelError.message : String(cancelError));
131
+ } finally {
132
+ setBusy(false);
133
+ }
134
+ };
135
+
136
+ return {
137
+ loading,
138
+ busy,
139
+ error,
140
+ setError,
141
+ dashboard,
142
+ diagnostics,
143
+ selectedRun,
144
+ setSelectedRun,
145
+ selectedEvents,
146
+ statusMessage,
147
+ launchAgentIndex,
148
+ setLaunchAgentIndex,
149
+ launchStep,
150
+ setLaunchStep,
151
+ launchDraft,
152
+ setLaunchDraft,
153
+ launchPermissionIndex,
154
+ setLaunchPermissionIndex,
155
+ launchableAgents: resolveLaunchableAgents(dashboard?.providers ?? []),
156
+ reload,
157
+ resetLaunchWizard,
158
+ openRunDetail,
159
+ handleLaunch,
160
+ handleCancelRun
161
+ };
162
+ }
@@ -0,0 +1,39 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useStdout } from "ink";
3
+ import { resolveLayoutMode } from "./layout.js";
4
+
5
+ /**
6
+ * Live terminal size + layout mode. Updates on stdout resize.
7
+ */
8
+ export function useTerminalSize({
9
+ initialColumns = 80,
10
+ initialRows = 24
11
+ } = {}) {
12
+ const { stdout } = useStdout();
13
+ const [size, setSize] = useState(() => ({
14
+ columns: stdout?.columns ?? initialColumns,
15
+ rows: stdout?.rows ?? initialRows
16
+ }));
17
+
18
+ useEffect(() => {
19
+ if (!stdout || typeof stdout.on !== "function") return undefined;
20
+
21
+ const sync = () => {
22
+ setSize({
23
+ columns: stdout.columns ?? initialColumns,
24
+ rows: stdout.rows ?? initialRows
25
+ });
26
+ };
27
+
28
+ sync();
29
+ stdout.on("resize", sync);
30
+ return () => {
31
+ stdout.off("resize", sync);
32
+ };
33
+ }, [stdout, initialColumns, initialRows]);
34
+
35
+ return {
36
+ ...size,
37
+ layoutMode: resolveLayoutMode(size)
38
+ };
39
+ }
@@ -2,6 +2,7 @@ import { stdin as input, stdout as output } from "node:process";
2
2
  import { resolveHomeDir } from "./paths.js";
3
3
  import { canUseOrchestratorShell } from "./ink/orchestrator-state.js";
4
4
  import { runOrchestratorInk as defaultRunOrchestratorInk } from "./ink/run-orchestrator-ink.js";
5
+ import { createFullscreenSession } from "./ink/fullscreen-session.js";
5
6
  import { formatCliCommand } from "./brand/cli.js";
6
7
  import { BRAND } from "./brand/index.js";
7
8
  import { buildReadOnlyDiagnostics, shouldExecutePlan } from "./action-planner.js";
@@ -31,7 +32,9 @@ export async function runOrchestratorShell({
31
32
  initialMode = INITIAL_EXPERIENCE.DASHBOARD,
32
33
  shellCapable = canUseOrchestratorShell({ interactive }),
33
34
  runOrchestratorInkImpl = defaultRunOrchestratorInk,
34
- runHarnessSetupImpl = defaultRunHarnessSetup
35
+ runHarnessSetupImpl = defaultRunHarnessSetup,
36
+ fullscreenSession = null,
37
+ stdout = output
35
38
  }) {
36
39
  if (!interactive) {
37
40
  throw new Error(
@@ -46,50 +49,68 @@ export async function runOrchestratorShell({
46
49
  }
47
50
 
48
51
  const homeDir = resolveHomeDir();
52
+ const ownsSession = !fullscreenSession;
53
+ const session = fullscreenSession ?? createFullscreenSession({
54
+ stdout,
55
+ enabled: Boolean(stdout?.isTTY)
56
+ });
57
+
58
+ if (ownsSession) {
59
+ session.enter();
60
+ }
61
+
49
62
  let setupOutcome = null;
50
63
 
51
- if (initialMode === INITIAL_EXPERIENCE.ONBOARDING) {
52
- setupOutcome = await runHarnessSetupImpl({
64
+ try {
65
+ if (initialMode === INITIAL_EXPERIENCE.ONBOARDING) {
66
+ setupOutcome = await runHarnessSetupImpl({
67
+ packageRoot,
68
+ packageName: packageManifest.name,
69
+ cliVersion: packageManifest.version,
70
+ homeDir,
71
+ workspaceRoot,
72
+ onboarding: true,
73
+ interactive: true,
74
+ fullscreenSession: session
75
+ });
76
+
77
+ if (setupOutcome?.cancelled) {
78
+ return {
79
+ cancelled: true,
80
+ wrote: false,
81
+ action: null,
82
+ initialMode,
83
+ setup: setupOutcome
84
+ };
85
+ }
86
+ }
87
+
88
+ const outcome = await runOrchestratorInkImpl({
89
+ homeDir,
90
+ workspaceRoot,
53
91
  packageRoot,
54
92
  packageName: packageManifest.name,
55
93
  cliVersion: packageManifest.version,
56
- homeDir,
57
- workspaceRoot,
58
- onboarding: true,
59
- interactive: true
94
+ hasGlobalState: hasConfiguredGlobalState(homeDir),
95
+ fullscreenSession: session
60
96
  });
61
97
 
62
- if (setupOutcome?.cancelled) {
63
- return {
64
- cancelled: true,
65
- wrote: false,
66
- action: null,
67
- initialMode,
68
- setup: setupOutcome
69
- };
98
+ if (outcome.error) {
99
+ throw outcome.error;
70
100
  }
71
- }
72
101
 
73
- const outcome = await runOrchestratorInkImpl({
74
- homeDir,
75
- workspaceRoot,
76
- packageRoot,
77
- packageName: packageManifest.name,
78
- cliVersion: packageManifest.version,
79
- hasGlobalState: hasConfiguredGlobalState(homeDir)
80
- });
81
-
82
- if (outcome.error) {
83
- throw outcome.error;
102
+ return {
103
+ cancelled: Boolean(outcome.cancelled),
104
+ wrote: Boolean(setupOutcome && !setupOutcome.cancelled),
105
+ action: outcome.action ?? null,
106
+ initialMode,
107
+ setup: setupOutcome
108
+ };
109
+ } finally {
110
+ if (ownsSession) {
111
+ session.leave();
112
+ }
84
113
  }
85
-
86
- return {
87
- cancelled: Boolean(outcome.cancelled),
88
- wrote: Boolean(setupOutcome && !setupOutcome.cancelled),
89
- action: outcome.action ?? null,
90
- initialMode,
91
- setup: setupOutcome
92
- };
93
114
  }
94
115
 
95
116
  export async function runOrchestratorDiagnostics({
@@ -64,7 +64,8 @@ export async function runHarnessSetup({
64
64
  createPrompt = createReadlinePrompt,
65
65
  runSetupInkImpl = defaultRunSetupInk,
66
66
  runSetupWizardImpl = defaultRunSetupWizard,
67
- inkCapable = canUseSetupInk({ interactive })
67
+ inkCapable = canUseSetupInk({ interactive }),
68
+ fullscreenSession = null
68
69
  }) {
69
70
  const routing = { interactive, simple, inkCapable, dryRun, yes, confirm, json, agents, components, noDefaultComponents };
70
71
  const useInk = evaluateSetupInk(routing);
@@ -94,7 +95,8 @@ export async function runHarnessSetup({
94
95
  preflightExplicit,
95
96
  yesExplicit,
96
97
  confirmExplicit,
97
- interactive
98
+ interactive,
99
+ fullscreenSession
98
100
  };
99
101
 
100
102
  if (useInk) {