agent-oven 0.1.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.
Files changed (146) hide show
  1. package/CLAUDE.md +164 -0
  2. package/LICENSE +21 -0
  3. package/README.md +447 -0
  4. package/dist/cli/commands/add.d.ts +6 -0
  5. package/dist/cli/commands/add.d.ts.map +1 -0
  6. package/dist/cli/commands/add.js +150 -0
  7. package/dist/cli/commands/add.js.map +1 -0
  8. package/dist/cli/commands/daemon.d.ts +6 -0
  9. package/dist/cli/commands/daemon.d.ts.map +1 -0
  10. package/dist/cli/commands/daemon.js +97 -0
  11. package/dist/cli/commands/daemon.js.map +1 -0
  12. package/dist/cli/commands/delete.d.ts +6 -0
  13. package/dist/cli/commands/delete.d.ts.map +1 -0
  14. package/dist/cli/commands/delete.js +34 -0
  15. package/dist/cli/commands/delete.js.map +1 -0
  16. package/dist/cli/commands/down.d.ts +6 -0
  17. package/dist/cli/commands/down.d.ts.map +1 -0
  18. package/dist/cli/commands/down.js +53 -0
  19. package/dist/cli/commands/down.js.map +1 -0
  20. package/dist/cli/commands/list.d.ts +6 -0
  21. package/dist/cli/commands/list.d.ts.map +1 -0
  22. package/dist/cli/commands/list.js +41 -0
  23. package/dist/cli/commands/list.js.map +1 -0
  24. package/dist/cli/commands/logs.d.ts +6 -0
  25. package/dist/cli/commands/logs.d.ts.map +1 -0
  26. package/dist/cli/commands/logs.js +124 -0
  27. package/dist/cli/commands/logs.js.map +1 -0
  28. package/dist/cli/commands/run.d.ts +6 -0
  29. package/dist/cli/commands/run.d.ts.map +1 -0
  30. package/dist/cli/commands/run.js +45 -0
  31. package/dist/cli/commands/run.js.map +1 -0
  32. package/dist/cli/commands/scheduler-tick.d.ts +8 -0
  33. package/dist/cli/commands/scheduler-tick.d.ts.map +1 -0
  34. package/dist/cli/commands/scheduler-tick.js +25 -0
  35. package/dist/cli/commands/scheduler-tick.js.map +1 -0
  36. package/dist/cli/commands/show.d.ts +6 -0
  37. package/dist/cli/commands/show.d.ts.map +1 -0
  38. package/dist/cli/commands/show.js +81 -0
  39. package/dist/cli/commands/show.js.map +1 -0
  40. package/dist/cli/commands/status.d.ts +6 -0
  41. package/dist/cli/commands/status.d.ts.map +1 -0
  42. package/dist/cli/commands/status.js +63 -0
  43. package/dist/cli/commands/status.js.map +1 -0
  44. package/dist/cli/commands/toggle.d.ts +6 -0
  45. package/dist/cli/commands/toggle.d.ts.map +1 -0
  46. package/dist/cli/commands/toggle.js +24 -0
  47. package/dist/cli/commands/toggle.js.map +1 -0
  48. package/dist/cli/commands/up.d.ts +6 -0
  49. package/dist/cli/commands/up.d.ts.map +1 -0
  50. package/dist/cli/commands/up.js +48 -0
  51. package/dist/cli/commands/up.js.map +1 -0
  52. package/dist/cli/utils/errors.d.ts +17 -0
  53. package/dist/cli/utils/errors.d.ts.map +1 -0
  54. package/dist/cli/utils/errors.js +37 -0
  55. package/dist/cli/utils/errors.js.map +1 -0
  56. package/dist/cli/utils/output.d.ts +17 -0
  57. package/dist/cli/utils/output.d.ts.map +1 -0
  58. package/dist/cli/utils/output.js +52 -0
  59. package/dist/cli/utils/output.js.map +1 -0
  60. package/dist/cli/utils/prompts.d.ts +8 -0
  61. package/dist/cli/utils/prompts.d.ts.map +1 -0
  62. package/dist/cli/utils/prompts.js +27 -0
  63. package/dist/cli/utils/prompts.js.map +1 -0
  64. package/dist/cli.d.ts +8 -0
  65. package/dist/cli.d.ts.map +1 -0
  66. package/dist/cli.js +71 -0
  67. package/dist/cli.js.map +1 -0
  68. package/dist/core/auth.d.ts +40 -0
  69. package/dist/core/auth.d.ts.map +1 -0
  70. package/dist/core/auth.js +114 -0
  71. package/dist/core/auth.js.map +1 -0
  72. package/dist/core/config.d.ts +43 -0
  73. package/dist/core/config.d.ts.map +1 -0
  74. package/dist/core/config.js +179 -0
  75. package/dist/core/config.js.map +1 -0
  76. package/dist/core/docker.d.ts +60 -0
  77. package/dist/core/docker.d.ts.map +1 -0
  78. package/dist/core/docker.js +507 -0
  79. package/dist/core/docker.js.map +1 -0
  80. package/dist/core/index.d.ts +10 -0
  81. package/dist/core/index.d.ts.map +1 -0
  82. package/dist/core/index.js +10 -0
  83. package/dist/core/index.js.map +1 -0
  84. package/dist/core/jobs.d.ts +53 -0
  85. package/dist/core/jobs.d.ts.map +1 -0
  86. package/dist/core/jobs.js +264 -0
  87. package/dist/core/jobs.js.map +1 -0
  88. package/dist/core/scheduler-runner.d.ts +15 -0
  89. package/dist/core/scheduler-runner.d.ts.map +1 -0
  90. package/dist/core/scheduler-runner.js +230 -0
  91. package/dist/core/scheduler-runner.js.map +1 -0
  92. package/dist/core/scheduler.d.ts +41 -0
  93. package/dist/core/scheduler.d.ts.map +1 -0
  94. package/dist/core/scheduler.js +373 -0
  95. package/dist/core/scheduler.js.map +1 -0
  96. package/dist/core/setup.d.ts +84 -0
  97. package/dist/core/setup.d.ts.map +1 -0
  98. package/dist/core/setup.js +315 -0
  99. package/dist/core/setup.js.map +1 -0
  100. package/dist/core/types.d.ts +181 -0
  101. package/dist/core/types.d.ts.map +1 -0
  102. package/dist/core/types.js +12 -0
  103. package/dist/core/types.js.map +1 -0
  104. package/dist/tui/App.d.ts +7 -0
  105. package/dist/tui/App.d.ts.map +1 -0
  106. package/dist/tui/App.js +103 -0
  107. package/dist/tui/App.js.map +1 -0
  108. package/dist/tui/components/Dashboard.d.ts +9 -0
  109. package/dist/tui/components/Dashboard.d.ts.map +1 -0
  110. package/dist/tui/components/Dashboard.js +70 -0
  111. package/dist/tui/components/Dashboard.js.map +1 -0
  112. package/dist/tui/components/InitWizard.d.ts +2 -0
  113. package/dist/tui/components/InitWizard.d.ts.map +1 -0
  114. package/dist/tui/components/InitWizard.js +522 -0
  115. package/dist/tui/components/InitWizard.js.map +1 -0
  116. package/dist/tui/components/JobDetail.d.ts +12 -0
  117. package/dist/tui/components/JobDetail.d.ts.map +1 -0
  118. package/dist/tui/components/JobDetail.js +137 -0
  119. package/dist/tui/components/JobDetail.js.map +1 -0
  120. package/dist/tui/components/JobForm.d.ts +10 -0
  121. package/dist/tui/components/JobForm.d.ts.map +1 -0
  122. package/dist/tui/components/JobForm.js +183 -0
  123. package/dist/tui/components/JobForm.js.map +1 -0
  124. package/dist/tui/components/JobList.d.ts +11 -0
  125. package/dist/tui/components/JobList.d.ts.map +1 -0
  126. package/dist/tui/components/JobList.js +136 -0
  127. package/dist/tui/components/JobList.js.map +1 -0
  128. package/dist/tui/components/LogViewer.d.ts +10 -0
  129. package/dist/tui/components/LogViewer.d.ts.map +1 -0
  130. package/dist/tui/components/LogViewer.js +184 -0
  131. package/dist/tui/components/LogViewer.js.map +1 -0
  132. package/dist/tui/index.d.ts +11 -0
  133. package/dist/tui/index.d.ts.map +1 -0
  134. package/dist/tui/index.js +11 -0
  135. package/dist/tui/index.js.map +1 -0
  136. package/dist/tui/types.d.ts +21 -0
  137. package/dist/tui/types.d.ts.map +1 -0
  138. package/dist/tui/types.js +5 -0
  139. package/dist/tui/types.js.map +1 -0
  140. package/images/base-tasks/Dockerfile +33 -0
  141. package/images/node-tasks/Dockerfile +36 -0
  142. package/images/pipeline-runner/Dockerfile +43 -0
  143. package/images/pipeline-runner/entrypoint.sh +60 -0
  144. package/images/python-tasks/Dockerfile +43 -0
  145. package/package.json +91 -0
  146. package/scheduler.sh +522 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard.d.ts","sourceRoot":"","sources":["../../../src/tui/components/Dashboard.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,cAAc,2CA8G/D"}
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { Box, Text } from 'ink';
4
+ import Spinner from 'ink-spinner';
5
+ import { getSystemStatus } from '../../core/docker.js';
6
+ import { formatRelativeTime } from '../../core/scheduler.js';
7
+ export function Dashboard({ config, onNavigate }) {
8
+ const [status, setStatus] = useState(null);
9
+ const [loading, setLoading] = useState(true);
10
+ const [error, setError] = useState(null);
11
+ // Load status on mount
12
+ useEffect(() => {
13
+ const loadStatus = async () => {
14
+ try {
15
+ const s = await getSystemStatus(config);
16
+ setStatus(s);
17
+ setError(null);
18
+ }
19
+ catch (err) {
20
+ setError(err instanceof Error ? err.message : 'Failed to load status');
21
+ }
22
+ finally {
23
+ setLoading(false);
24
+ }
25
+ };
26
+ loadStatus();
27
+ // Refresh every 10 seconds
28
+ const interval = setInterval(loadStatus, 10000);
29
+ return () => clearInterval(interval);
30
+ }, [config]);
31
+ if (loading && !status) {
32
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Loading status..." })] })] }));
33
+ }
34
+ if (error && !status) {
35
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }), _jsx(Shortcuts, {})] }));
36
+ }
37
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { bold: true, children: "Status: " }), _jsx(StatusIndicator, { running: status?.colima.running ?? false, label: "Colima" }), _jsx(Text, { children: " " }), _jsx(StatusIndicator, { running: status?.scheduler.loaded ?? false, label: "Scheduler" })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { bold: true, children: "Jobs: " }), _jsxs(Text, { children: [status?.jobs.total ?? 0, " total"] }), _jsx(Text, { dimColor: true, children: " | " }), _jsxs(Text, { children: [status?.jobs.cron ?? 0, " cron"] }), _jsx(Text, { dimColor: true, children: " | " }), _jsxs(Text, { children: [status?.jobs.oncePending ?? 0, " pending one-time"] })] }), status?.runningContainers && status.runningContainers.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, underline: true, children: "Running Jobs" }), status.runningContainers.map((container) => (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: container.jobId || container.name }), _jsxs(Text, { dimColor: true, children: [" - ", container.status] })] }, container.name)))] })), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, underline: true, children: "Recent Runs" }), _jsx(Box, { borderStyle: "single", flexDirection: "column", paddingX: 1, children: (!status?.recentExecutions || status.recentExecutions.length === 0) ? (_jsx(Text, { dimColor: true, children: "No recent executions" })) : (status.recentExecutions.slice(0, 5).map((exec) => (_jsx(RecentExecution, { execution: exec }, `${exec.jobId}-${exec.timestamp}`)))) })] }), _jsx(Shortcuts, {})] }));
38
+ }
39
+ function Header() {
40
+ return (_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "magenta", children: "Agent Oven" }), _jsx(Text, { dimColor: true, children: " - Job Scheduler" })] }));
41
+ }
42
+ function StatusIndicator({ running, label }) {
43
+ return (_jsxs(Text, { children: [_jsx(Text, { color: running ? 'green' : 'red', children: running ? '●' : '○' }), _jsxs(Text, { children: [" ", label, " ", running ? 'running' : 'stopped'] })] }));
44
+ }
45
+ function RecentExecution({ execution }) {
46
+ const { jobId, timestamp, exitCode } = execution;
47
+ // Parse timestamp (format: YYYYMMDD-HHMMSS)
48
+ let timeAgo = timestamp;
49
+ try {
50
+ const year = timestamp.slice(0, 4);
51
+ const month = timestamp.slice(4, 6);
52
+ const day = timestamp.slice(6, 8);
53
+ const hour = timestamp.slice(9, 11);
54
+ const minute = timestamp.slice(11, 13);
55
+ const date = new Date(`${year}-${month}-${day}T${hour}:${minute}:00`);
56
+ if (!isNaN(date.getTime())) {
57
+ timeAgo = formatRelativeTime(date);
58
+ }
59
+ }
60
+ catch {
61
+ // Keep original timestamp
62
+ }
63
+ const isRunning = exitCode === 'running';
64
+ const isSuccess = exitCode === 0;
65
+ return (_jsxs(Box, { children: [_jsx(Text, { color: isRunning ? 'cyan' : isSuccess ? 'green' : 'red', children: isRunning ? '◐' : isSuccess ? '✓' : '✗' }), _jsx(Text, { children: " " }), _jsx(Text, { children: jobId.padEnd(20) }), _jsx(Text, { dimColor: true, children: timeAgo.padEnd(15) }), _jsx(Text, { dimColor: true, children: isRunning ? 'running' : `exit ${exitCode}` })] }));
66
+ }
67
+ function Shortcuts() {
68
+ return (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[j] Jobs [a] Add Job [l] Logs [q] Quit" }) }));
69
+ }
70
+ //# sourceMappingURL=Dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard.js","sourceRoot":"","sources":["../../../src/tui/components/Dashboard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function InitWizard(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=InitWizard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InitWizard.d.ts","sourceRoot":"","sources":["../../../src/tui/components/InitWizard.tsx"],"names":[],"mappings":"AAyCA,wBAAgB,UAAU,4CAmiBzB"}
@@ -0,0 +1,522 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useCallback } from 'react';
3
+ import { Box, Text, useApp, useInput } from 'ink';
4
+ import TextInput from 'ink-text-input';
5
+ import Spinner from 'ink-spinner';
6
+ import { checkHomebrew, checkDependency, brewInstall, setupFiles, discoverImages, buildImage, detectTimezone, installLaunchd, verifyDocker, getColimaStatus, startColima, buildConfig, } from '../../core/setup.js';
7
+ export function InitWizard() {
8
+ const { exit } = useApp();
9
+ const [step, setStep] = useState('welcome');
10
+ const [error, setError] = useState(null);
11
+ // Collected config values
12
+ const [projectDir] = useState(process.cwd());
13
+ const [cpu, setCpu] = useState('2');
14
+ const [memory, setMemory] = useState('4');
15
+ const [disk, setDisk] = useState('20');
16
+ const [timezone, setTimezone] = useState('');
17
+ const [editTimezone, setEditTimezone] = useState(false);
18
+ // Prerequisites state
19
+ const [prereqs, setPrereqs] = useState([]);
20
+ const [prereqsDone, setPrereqsDone] = useState(false);
21
+ const [missingDeps, setMissingDeps] = useState([]);
22
+ // Dependencies install state
23
+ const [depStatuses, setDepStatuses] = useState({});
24
+ const [depOutput, setDepOutput] = useState('');
25
+ const [depsDone, setDepsDone] = useState(false);
26
+ // Colima state
27
+ const [colimaRunning, setColimaRunning] = useState(false);
28
+ const [colimaStatus, setColimaStatus] = useState('pending');
29
+ // Docker verify state
30
+ const [dockerStatus, setDockerStatus] = useState('pending');
31
+ const [dockerVersion, setDockerVersion] = useState('');
32
+ // Files setup state
33
+ const [filesResult, setFilesResult] = useState(null);
34
+ // Image state
35
+ const [availableImages, setAvailableImages] = useState([]);
36
+ const [selectedImages, setSelectedImages] = useState(new Set());
37
+ const [imageCursor, setImageCursor] = useState(0);
38
+ // Image build state
39
+ const [buildStatuses, setBuildStatuses] = useState({});
40
+ const [buildOutput, setBuildOutput] = useState('');
41
+ const [buildsDone, setBuildsDone] = useState(false);
42
+ // Launchd state
43
+ const [launchdStatus, setLaunchdStatus] = useState('pending');
44
+ // Active field for colima-config form
45
+ const [configField, setConfigField] = useState('cpu');
46
+ // Summary items
47
+ const [summaryItems, setSummaryItems] = useState([]);
48
+ // --- Step: prerequisites ---
49
+ useEffect(() => {
50
+ if (step !== 'prerequisites')
51
+ return;
52
+ let cancelled = false;
53
+ const run = async () => {
54
+ const results = [];
55
+ const homebrew = await checkHomebrew();
56
+ if (cancelled)
57
+ return;
58
+ results.push({ name: 'homebrew', status: homebrew });
59
+ setPrereqs([...results]);
60
+ if (!homebrew.installed) {
61
+ setError('Homebrew is required. Install it from https://brew.sh');
62
+ setPrereqsDone(true);
63
+ return;
64
+ }
65
+ for (const dep of ['colima', 'docker', 'jq']) {
66
+ const status = await checkDependency(dep);
67
+ if (cancelled)
68
+ return;
69
+ results.push({ name: dep, status });
70
+ setPrereqs([...results]);
71
+ }
72
+ const missing = results
73
+ .filter((r) => r.name !== 'homebrew' && !r.status.installed)
74
+ .map((r) => r.name);
75
+ setMissingDeps(missing);
76
+ setPrereqsDone(true);
77
+ };
78
+ run();
79
+ return () => { cancelled = true; };
80
+ }, [step]);
81
+ // --- Step: dependencies ---
82
+ useEffect(() => {
83
+ if (step !== 'dependencies')
84
+ return;
85
+ let cancelled = false;
86
+ const run = async () => {
87
+ const statuses = {};
88
+ for (const dep of missingDeps) {
89
+ statuses[dep] = 'pending';
90
+ }
91
+ setDepStatuses({ ...statuses });
92
+ for (const dep of missingDeps) {
93
+ if (cancelled)
94
+ return;
95
+ statuses[dep] = 'running';
96
+ setDepStatuses({ ...statuses });
97
+ setDepOutput('');
98
+ const result = await brewInstall(dep, (line) => {
99
+ if (!cancelled)
100
+ setDepOutput(line);
101
+ });
102
+ if (cancelled)
103
+ return;
104
+ statuses[dep] = result === 'failed' ? 'failed' : 'done';
105
+ setDepStatuses({ ...statuses });
106
+ if (result === 'failed') {
107
+ setError(`Failed to install ${dep} via Homebrew.`);
108
+ return;
109
+ }
110
+ }
111
+ setDepsDone(true);
112
+ };
113
+ run();
114
+ return () => { cancelled = true; };
115
+ }, [step, missingDeps]);
116
+ // --- Step: colima-start ---
117
+ useEffect(() => {
118
+ if (step !== 'colima-start')
119
+ return;
120
+ let cancelled = false;
121
+ const run = async () => {
122
+ setColimaStatus('running');
123
+ // Check if already running
124
+ const status = await getColimaStatus();
125
+ if (cancelled)
126
+ return;
127
+ if (status.running) {
128
+ setColimaRunning(true);
129
+ setColimaStatus('done');
130
+ return;
131
+ }
132
+ try {
133
+ const config = {
134
+ projectDir,
135
+ colima: { cpu: parseInt(cpu, 10), memory: parseInt(memory, 10), disk: parseInt(disk, 10) },
136
+ docker: { defaultCpus: 1, defaultMemory: '512m' },
137
+ timezone: timezone || detectTimezone(),
138
+ };
139
+ await startColima(config);
140
+ if (cancelled)
141
+ return;
142
+ setColimaRunning(true);
143
+ setColimaStatus('done');
144
+ }
145
+ catch (err) {
146
+ if (cancelled)
147
+ return;
148
+ setColimaStatus('failed');
149
+ setError(err instanceof Error ? err.message : 'Failed to start Colima');
150
+ }
151
+ };
152
+ run();
153
+ return () => { cancelled = true; };
154
+ }, [step, projectDir, cpu, memory, disk, timezone]);
155
+ // --- Step: docker-verify ---
156
+ useEffect(() => {
157
+ if (step !== 'docker-verify')
158
+ return;
159
+ let cancelled = false;
160
+ const run = async () => {
161
+ setDockerStatus('running');
162
+ const result = await verifyDocker();
163
+ if (cancelled)
164
+ return;
165
+ if (result.available) {
166
+ setDockerVersion(result.version ?? 'unknown');
167
+ setDockerStatus('done');
168
+ }
169
+ else {
170
+ setDockerStatus('failed');
171
+ setError('Docker is not responding. Check Colima status.');
172
+ }
173
+ };
174
+ run();
175
+ return () => { cancelled = true; };
176
+ }, [step]);
177
+ // --- Step: files-setup ---
178
+ useEffect(() => {
179
+ if (step !== 'files-setup')
180
+ return;
181
+ try {
182
+ const result = setupFiles(projectDir);
183
+ setFilesResult(result);
184
+ }
185
+ catch (err) {
186
+ setError(err instanceof Error ? err.message : 'Failed to create files');
187
+ }
188
+ }, [step, projectDir]);
189
+ // --- Step: image-select ---
190
+ useEffect(() => {
191
+ if (step !== 'image-select')
192
+ return;
193
+ const images = discoverImages(projectDir);
194
+ setAvailableImages(images);
195
+ setSelectedImages(new Set(images)); // Select all by default
196
+ }, [step, projectDir]);
197
+ // --- Step: image-build ---
198
+ useEffect(() => {
199
+ if (step !== 'image-build')
200
+ return;
201
+ let cancelled = false;
202
+ const run = async () => {
203
+ const images = Array.from(selectedImages);
204
+ const statuses = {};
205
+ for (const img of images) {
206
+ statuses[img] = 'pending';
207
+ }
208
+ setBuildStatuses({ ...statuses });
209
+ for (const img of images) {
210
+ if (cancelled)
211
+ return;
212
+ statuses[img] = 'running';
213
+ setBuildStatuses({ ...statuses });
214
+ setBuildOutput('');
215
+ const result = await buildImage(projectDir, img, (line) => {
216
+ if (!cancelled)
217
+ setBuildOutput(line);
218
+ });
219
+ if (cancelled)
220
+ return;
221
+ statuses[img] = result.success ? 'done' : 'failed';
222
+ setBuildStatuses({ ...statuses });
223
+ if (!result.success) {
224
+ setError(`Failed to build ${img}: ${result.error}`);
225
+ }
226
+ }
227
+ setBuildsDone(true);
228
+ };
229
+ run();
230
+ return () => { cancelled = true; };
231
+ }, [step, selectedImages, projectDir]);
232
+ // --- Step: timezone ---
233
+ useEffect(() => {
234
+ if (step !== 'timezone')
235
+ return;
236
+ setTimezone(detectTimezone());
237
+ }, [step]);
238
+ // --- Step: launchd ---
239
+ useEffect(() => {
240
+ if (step !== 'launchd')
241
+ return;
242
+ let cancelled = false;
243
+ const run = async () => {
244
+ setLaunchdStatus('running');
245
+ const result = await installLaunchd(projectDir);
246
+ if (cancelled)
247
+ return;
248
+ if (result.success) {
249
+ setLaunchdStatus('done');
250
+ }
251
+ else {
252
+ setLaunchdStatus('failed');
253
+ setError(result.error ?? 'Failed to install launchd agent');
254
+ }
255
+ };
256
+ run();
257
+ return () => { cancelled = true; };
258
+ }, [step, projectDir]);
259
+ // --- Step: summary ---
260
+ useEffect(() => {
261
+ if (step !== 'summary')
262
+ return;
263
+ // Save config
264
+ const tz = timezone || detectTimezone();
265
+ buildConfig({
266
+ projectDir,
267
+ cpu: parseInt(cpu, 10),
268
+ memory: parseInt(memory, 10),
269
+ disk: parseInt(disk, 10),
270
+ timezone: tz,
271
+ });
272
+ setSummaryItems([
273
+ { label: 'Project directory', value: projectDir, ok: true },
274
+ { label: 'Colima VM', value: `${cpu} CPU, ${memory}GB RAM, ${disk}GB disk`, ok: colimaRunning },
275
+ { label: 'Docker', value: dockerVersion || 'connected', ok: dockerStatus === 'done' },
276
+ { label: 'Images built', value: `${Array.from(selectedImages).length} images`, ok: buildsDone },
277
+ { label: 'Timezone', value: tz, ok: true },
278
+ { label: 'Scheduler daemon', value: 'launchd agent', ok: launchdStatus === 'done' },
279
+ ]);
280
+ }, [step, projectDir, cpu, memory, disk, timezone, colimaRunning, dockerVersion, dockerStatus, selectedImages, buildsDone, launchdStatus]);
281
+ // --- Navigation helpers ---
282
+ const advance = useCallback(() => {
283
+ setError(null);
284
+ const steps = [
285
+ 'welcome', 'prerequisites', 'dependencies', 'colima-config',
286
+ 'colima-start', 'docker-verify', 'files-setup', 'image-select',
287
+ 'image-build', 'timezone', 'launchd', 'summary',
288
+ ];
289
+ const idx = steps.indexOf(step);
290
+ // Skip dependencies step if nothing to install
291
+ if (step === 'prerequisites' && missingDeps.length === 0) {
292
+ setStep('colima-config');
293
+ return;
294
+ }
295
+ // Skip image-build if no images selected
296
+ if (step === 'image-select' && selectedImages.size === 0) {
297
+ setStep('timezone');
298
+ return;
299
+ }
300
+ if (idx < steps.length - 1) {
301
+ setStep(steps[idx + 1]);
302
+ }
303
+ }, [step, missingDeps, selectedImages]);
304
+ const retry = useCallback(() => {
305
+ setError(null);
306
+ // Re-trigger the current step by toggling
307
+ const current = step;
308
+ setStep('welcome');
309
+ setTimeout(() => setStep(current), 0);
310
+ }, [step]);
311
+ // --- Input handling ---
312
+ useInput((input, key) => {
313
+ if (key.ctrl && input === 'c') {
314
+ exit();
315
+ return;
316
+ }
317
+ // Error state: retry / skip / quit
318
+ if (error && step !== 'prerequisites') {
319
+ if (input === 'r') {
320
+ retry();
321
+ return;
322
+ }
323
+ if (input === 's' && step !== 'dependencies' && step !== 'colima-config') {
324
+ setError(null);
325
+ advance();
326
+ return;
327
+ }
328
+ if (input === 'q') {
329
+ exit();
330
+ return;
331
+ }
332
+ return;
333
+ }
334
+ // Step-specific input handling
335
+ switch (step) {
336
+ case 'welcome':
337
+ if (key.return)
338
+ advance();
339
+ if (input === 'q')
340
+ exit();
341
+ break;
342
+ case 'prerequisites':
343
+ if (prereqsDone && !error) {
344
+ if (key.return)
345
+ advance();
346
+ }
347
+ if (prereqsDone && error) {
348
+ if (input === 'q')
349
+ exit();
350
+ }
351
+ break;
352
+ case 'dependencies':
353
+ if (depsDone) {
354
+ if (key.return)
355
+ advance();
356
+ }
357
+ break;
358
+ case 'colima-config':
359
+ if (key.tab || (key.return && configField !== 'disk')) {
360
+ if (configField === 'cpu')
361
+ setConfigField('memory');
362
+ else if (configField === 'memory')
363
+ setConfigField('disk');
364
+ }
365
+ else if (key.return && configField === 'disk') {
366
+ const cpuValue = parsePositiveInt(cpu);
367
+ const memoryValue = parsePositiveInt(memory);
368
+ const diskValue = parsePositiveInt(disk);
369
+ if (!cpuValue || !memoryValue || !diskValue) {
370
+ setError('Colima CPU, memory, and disk must be positive whole numbers.');
371
+ return;
372
+ }
373
+ advance();
374
+ }
375
+ break;
376
+ case 'colima-start':
377
+ if (colimaStatus === 'done') {
378
+ if (key.return)
379
+ advance();
380
+ }
381
+ break;
382
+ case 'docker-verify':
383
+ if (dockerStatus === 'done') {
384
+ if (key.return)
385
+ advance();
386
+ }
387
+ break;
388
+ case 'files-setup':
389
+ if (filesResult) {
390
+ if (key.return)
391
+ advance();
392
+ }
393
+ break;
394
+ case 'image-select':
395
+ if (availableImages.length === 0) {
396
+ if (key.return)
397
+ advance();
398
+ break;
399
+ }
400
+ if (key.upArrow || input === 'k') {
401
+ setImageCursor((c) => Math.max(0, c - 1));
402
+ }
403
+ else if (key.downArrow || input === 'j') {
404
+ setImageCursor((c) => Math.min(availableImages.length - 1, c + 1));
405
+ }
406
+ else if (input === ' ') {
407
+ setSelectedImages((prev) => {
408
+ const next = new Set(prev);
409
+ const img = availableImages[imageCursor];
410
+ if (next.has(img))
411
+ next.delete(img);
412
+ else
413
+ next.add(img);
414
+ return next;
415
+ });
416
+ }
417
+ else if (key.return) {
418
+ advance();
419
+ }
420
+ break;
421
+ case 'image-build':
422
+ if (buildsDone) {
423
+ if (key.return)
424
+ advance();
425
+ }
426
+ break;
427
+ case 'timezone':
428
+ if (!editTimezone) {
429
+ if (input === 'e') {
430
+ setEditTimezone(true);
431
+ }
432
+ else if (key.return) {
433
+ advance();
434
+ }
435
+ }
436
+ else if (editTimezone && key.return) {
437
+ setEditTimezone(false);
438
+ }
439
+ break;
440
+ case 'launchd':
441
+ if (launchdStatus === 'done') {
442
+ if (key.return)
443
+ advance();
444
+ }
445
+ break;
446
+ case 'summary':
447
+ if (key.return || input === 'q') {
448
+ exit();
449
+ }
450
+ break;
451
+ }
452
+ });
453
+ return (_jsxs(Box, { flexDirection: "column", children: [step === 'welcome' && _jsx(WelcomeStep, {}), step === 'prerequisites' && (_jsx(PrerequisitesStep, { prereqs: prereqs, done: prereqsDone, error: error })), step === 'dependencies' && (_jsx(DependenciesStep, { deps: missingDeps, statuses: depStatuses, output: depOutput, done: depsDone })), step === 'colima-config' && (_jsx(ColimaConfigStep, { cpu: cpu, memory: memory, disk: disk, onCpuChange: setCpu, onMemoryChange: setMemory, onDiskChange: setDisk, activeField: configField })), step === 'colima-start' && (_jsx(ColimaStartStep, { status: colimaStatus, alreadyRunning: colimaRunning, error: error })), step === 'docker-verify' && (_jsx(DockerVerifyStep, { status: dockerStatus, version: dockerVersion, error: error })), step === 'files-setup' && (_jsx(FilesSetupStep, { result: filesResult })), step === 'image-select' && (_jsx(ImageSelectStep, { images: availableImages, selected: selectedImages, cursor: imageCursor })), step === 'image-build' && (_jsx(ImageBuildStep, { statuses: buildStatuses, output: buildOutput, done: buildsDone })), step === 'timezone' && (_jsx(TimezoneStep, { timezone: timezone, editing: editTimezone, onTimezoneChange: setTimezone })), step === 'launchd' && (_jsx(LaunchdStep, { status: launchdStatus, error: error })), step === 'summary' && _jsx(SummaryStep, { items: summaryItems }), error && step !== 'prerequisites' && step !== 'summary' && (_jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: "red", children: ["Error: ", error] }), _jsx(Text, { dimColor: true, children: step === 'dependencies' || step === 'colima-config'
454
+ ? ' [r] Retry [q] Quit'
455
+ : ' [r] Retry [s] Skip [q] Quit' })] }))] }));
456
+ }
457
+ function parsePositiveInt(value) {
458
+ const parsed = Number.parseInt(value, 10);
459
+ if (!Number.isFinite(parsed) || parsed <= 0)
460
+ return null;
461
+ return parsed;
462
+ }
463
+ // --- Step components ---
464
+ function WelcomeStep() {
465
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "magenta", children: "Agent Oven" }), _jsx(Text, { dimColor: true, children: " - Setup Wizard" })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { children: "Welcome to Agent Oven setup. This wizard will:" }), _jsx(Text, { dimColor: true, children: " 1. Check and install prerequisites (Colima, Docker, jq)" }), _jsx(Text, { dimColor: true, children: " 2. Configure and start the Colima VM" }), _jsx(Text, { dimColor: true, children: " 3. Create directories and build Docker images" }), _jsx(Text, { dimColor: true, children: " 4. Install the scheduler daemon" })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Start [q] Quit" }) })] }));
466
+ }
467
+ function PrerequisitesStep({ prereqs, done, error, }) {
468
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Checking Prerequisites", step: 1 }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [prereqs.map((p) => (_jsxs(Box, { children: [_jsx(Text, { color: p.status.installed ? 'green' : 'red', children: p.status.installed ? '●' : '○' }), _jsxs(Text, { children: [" ", p.name] }), p.status.version && _jsxs(Text, { dimColor: true, children: [" (", p.status.version, ")"] }), !p.status.installed && _jsx(Text, { color: "red", children: " not found" })] }, p.name))), !done && prereqs.length < 4 && (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Checking..." })] }))] }), done && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) })), done && error && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "red", children: error }), _jsx(Text, { dimColor: true, children: " [q] Quit" })] }))] }));
469
+ }
470
+ function DependenciesStep({ deps, statuses, output, done, }) {
471
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Installing Dependencies", step: 2 }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: deps.map((dep) => (_jsxs(Box, { children: [_jsx(StatusIcon, { status: statuses[dep] ?? 'pending' }), _jsxs(Text, { children: [" brew install ", dep] })] }, dep))) }), output && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: output }) })), done && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) }))] }));
472
+ }
473
+ function ColimaConfigStep({ cpu, memory, disk, onCpuChange, onMemoryChange, onDiskChange, activeField, }) {
474
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Colima VM Configuration", step: 3 }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: activeField === 'cpu' ? 'cyan' : undefined, children: 'CPU cores '.padEnd(12) }), _jsx(TextInput, { value: cpu, onChange: onCpuChange, focus: activeField === 'cpu', placeholder: "2" })] }), _jsxs(Box, { children: [_jsx(Text, { color: activeField === 'memory' ? 'cyan' : undefined, children: 'Memory GB '.padEnd(12) }), _jsx(TextInput, { value: memory, onChange: onMemoryChange, focus: activeField === 'memory', placeholder: "4" })] }), _jsxs(Box, { children: [_jsx(Text, { color: activeField === 'disk' ? 'cyan' : undefined, children: 'Disk GB '.padEnd(12) }), _jsx(TextInput, { value: disk, onChange: onDiskChange, focus: activeField === 'disk', placeholder: "20" })] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[tab] Next field [enter] Continue" }) })] }));
475
+ }
476
+ function ColimaStartStep({ status, alreadyRunning, error, }) {
477
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Starting Colima", step: 4 }), _jsxs(Box, { marginTop: 1, children: [_jsx(StatusIcon, { status: status }), _jsxs(Text, { children: [status === 'running' ? ' Starting Colima VM...' : '', status === 'done' && alreadyRunning ? ' Colima is already running' : '', status === 'done' && !alreadyRunning ? ' Colima started successfully' : '', status === 'failed' ? ' Failed to start Colima' : ''] })] }), status === 'done' && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) }))] }));
478
+ }
479
+ function DockerVerifyStep({ status, version, error, }) {
480
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Verifying Docker", step: 5 }), _jsxs(Box, { marginTop: 1, children: [_jsx(StatusIcon, { status: status }), _jsxs(Text, { children: [status === 'running' ? ' Checking Docker connection...' : '', status === 'done' ? ` Docker ${version} is available` : '', status === 'failed' ? ' Docker is not responding' : ''] })] }), status === 'done' && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) }))] }));
481
+ }
482
+ function FilesSetupStep({ result }) {
483
+ if (!result) {
484
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Setting Up Files", step: 6 }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Creating directories..." })] })] }));
485
+ }
486
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Setting Up Files", step: 6 }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [result.created.map((f) => (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: "+" }), _jsxs(Text, { children: [" Created ", f] })] }, f))), result.existed.map((f) => (_jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["- Already exists ", f] }) }, f)))] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) })] }));
487
+ }
488
+ function ImageSelectStep({ images, selected, cursor, }) {
489
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Select Docker Images to Build", step: 7 }), images.length === 0 ? (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "No images found in images/ directory" }) })) : (_jsx(Box, { flexDirection: "column", marginTop: 1, children: images.map((img, i) => (_jsx(Box, { children: _jsxs(Text, { color: i === cursor ? 'cyan' : undefined, children: [i === cursor ? '>' : ' ', " [", selected.has(img) ? 'x' : ' ', "] agent-oven/", img] }) }, img))) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[space] Toggle [j/k] Navigate [enter] Continue" }) })] }));
490
+ }
491
+ function ImageBuildStep({ statuses, output, done, }) {
492
+ const entries = Object.entries(statuses);
493
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Building Docker Images", step: 8 }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: entries.map(([name, status]) => (_jsxs(Box, { children: [_jsx(StatusIcon, { status: status }), _jsxs(Text, { children: [" agent-oven/", name] })] }, name))) }), output && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: output }) })), done && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) }))] }));
494
+ }
495
+ function TimezoneStep({ timezone, editing, onTimezoneChange, }) {
496
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Timezone", step: 9 }), _jsx(Box, { marginTop: 1, children: editing ? (_jsxs(Box, { children: [_jsx(Text, { children: "Timezone: " }), _jsx(TextInput, { value: timezone, onChange: onTimezoneChange, focus: true })] })) : (_jsxs(Box, { children: [_jsx(Text, { children: "Detected: " }), _jsx(Text, { color: "cyan", children: timezone })] })) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: editing ? '[enter] Confirm' : '[e] Edit [enter] Accept' }) })] }));
497
+ }
498
+ function LaunchdStep({ status, error, }) {
499
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Installing Scheduler Daemon", step: 10 }), _jsxs(Box, { marginTop: 1, children: [_jsx(StatusIcon, { status: status }), _jsxs(Text, { children: [status === 'running' ? ' Installing launchd agent...' : '', status === 'done' ? ' Scheduler daemon installed and loaded' : '', status === 'failed' ? ' Failed to install daemon' : ''] })] }), status === 'done' && !error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Continue" }) }))] }));
500
+ }
501
+ function SummaryStep({ items }) {
502
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "magenta", children: "Agent Oven" }), _jsx(Text, { dimColor: true, children: " - Setup Complete" })] }), _jsx(Box, { flexDirection: "column", marginTop: 1, borderStyle: "single", paddingX: 1, children: items.map((item) => (_jsxs(Box, { children: [_jsx(Text, { color: item.ok ? 'green' : 'red', children: item.ok ? '●' : '○' }), _jsxs(Text, { children: [" ", item.label.padEnd(22)] }), _jsx(Text, { color: "cyan", children: item.value })] }, item.label))) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, children: "Next steps:" }), _jsx(Text, { dimColor: true, children: " Run " }), _jsx(Text, { color: "cyan", children: " npm start" }), _jsx(Text, { dimColor: true, children: " to open the TUI and manage your jobs." })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[enter] Exit" }) })] }));
503
+ }
504
+ // --- Shared sub-components ---
505
+ function StepHeader({ title, step }) {
506
+ return (_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "magenta", children: title }), _jsxs(Text, { dimColor: true, children: [" (step ", step, "/10)"] })] }));
507
+ }
508
+ function StatusIcon({ status }) {
509
+ switch (status) {
510
+ case 'running':
511
+ return _jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) });
512
+ case 'done':
513
+ return _jsx(Text, { color: "green", children: "\u25CF" });
514
+ case 'failed':
515
+ return _jsx(Text, { color: "red", children: "\u25CF" });
516
+ case 'skipped':
517
+ return _jsx(Text, { dimColor: true, children: "\u25CB" });
518
+ default:
519
+ return _jsx(Text, { dimColor: true, children: "\u25CB" });
520
+ }
521
+ }
522
+ //# sourceMappingURL=InitWizard.js.map