@dmrlzz/davecode 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +33 -2
- package/bin/davecode.js +2 -0
- package/dist/ChatApp-FO5SABXB.js +893 -0
- package/dist/ChatApp-FO5SABXB.js.map +1 -0
- package/dist/RunnerView-DLVR7C22.js +18 -0
- package/dist/RunnerView-DLVR7C22.js.map +1 -0
- package/dist/accounts-MTMGYKEP.js +724 -0
- package/dist/accounts-MTMGYKEP.js.map +1 -0
- package/dist/budget-RBHCEDPP.js +115 -0
- package/dist/budget-RBHCEDPP.js.map +1 -0
- package/dist/chat-ZDXX3N6X.js +95 -0
- package/dist/chat-ZDXX3N6X.js.map +1 -0
- package/dist/chunk-23KTE7IK.js +114 -0
- package/dist/chunk-23KTE7IK.js.map +1 -0
- package/dist/chunk-7XVXEO7U.js +23 -0
- package/dist/chunk-7XVXEO7U.js.map +1 -0
- package/dist/chunk-BOLFK3BH.js +20 -0
- package/dist/chunk-BOLFK3BH.js.map +1 -0
- package/dist/chunk-C7FDRA3U.js +9087 -0
- package/dist/chunk-C7FDRA3U.js.map +1 -0
- package/dist/chunk-DYQ56FBT.js +47 -0
- package/dist/chunk-DYQ56FBT.js.map +1 -0
- package/dist/chunk-FRFSJMN4.js +79 -0
- package/dist/chunk-FRFSJMN4.js.map +1 -0
- package/dist/chunk-IC3TDONV.js +12 -0
- package/dist/chunk-IC3TDONV.js.map +1 -0
- package/dist/chunk-IVZHKUCD.js +180 -0
- package/dist/chunk-IVZHKUCD.js.map +1 -0
- package/dist/chunk-MSLLH5XP.js +213 -0
- package/dist/chunk-MSLLH5XP.js.map +1 -0
- package/dist/chunk-OXRMGR72.js +20 -0
- package/dist/chunk-OXRMGR72.js.map +1 -0
- package/dist/chunk-OYEYNDOO.js +200 -0
- package/dist/chunk-OYEYNDOO.js.map +1 -0
- package/dist/chunk-PIIJ3RSI.js +1610 -0
- package/dist/chunk-PIIJ3RSI.js.map +1 -0
- package/dist/chunk-SF5ZEAP4.js +105 -0
- package/dist/chunk-SF5ZEAP4.js.map +1 -0
- package/dist/chunk-VVCXGQMY.js +107 -0
- package/dist/chunk-VVCXGQMY.js.map +1 -0
- package/dist/config-FRMY5OHG.js +158 -0
- package/dist/config-FRMY5OHG.js.map +1 -0
- package/dist/dashboard/assets/Accounts-BR3ZfVk4.js +1 -0
- package/dist/dashboard/assets/Badge-B-qzNRrZ.js +55 -0
- package/dist/dashboard/assets/Callout-B9g_wPDi.js +1 -0
- package/dist/dashboard/assets/Field-BfabPEcY.js +1 -0
- package/dist/dashboard/assets/Goals-BsV-6m94.js +1 -0
- package/dist/dashboard/assets/Library-CEA9P1m-.js +1 -0
- package/dist/dashboard/assets/Markdown-ClRsddnB.js +69 -0
- package/dist/dashboard/assets/Panel-B9tSgX6l.js +1 -0
- package/dist/dashboard/assets/RoutesPage-Dh-BJ3ir.js +4 -0
- package/dist/dashboard/assets/Runner-C_e9l5l2.js +1 -0
- package/dist/dashboard/assets/Settings-C6Yc1Gjg.js +1 -0
- package/dist/dashboard/assets/Switch-CUpOJjUT.js +1 -0
- package/dist/dashboard/assets/Tasks-CTku0rR3.js +2 -0
- package/dist/dashboard/assets/Traffic-CE6wZSMr.js +1 -0
- package/dist/dashboard/assets/Workspace-CxFxvkA6.js +1 -0
- package/dist/dashboard/assets/arrow-up-DL3CuFOO.js +1 -0
- package/dist/dashboard/assets/forms-D6UIYgC5.js +1 -0
- package/dist/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/dashboard/assets/index-1iH716Xy.css +2 -0
- package/dist/dashboard/assets/index-BMWr9EKo.js +104 -0
- package/dist/dashboard/assets/task-errors-CE4oEr8H.js +1 -0
- package/dist/dashboard/assets/trash-CWqeZ7eg.js +1 -0
- package/dist/dashboard/favicon.svg +7 -0
- package/dist/dashboard/github.svg +1 -0
- package/dist/dashboard/index.html +31 -0
- package/dist/dist-ZPXEVBEC.js +357 -0
- package/dist/dist-ZPXEVBEC.js.map +1 -0
- package/dist/doctor-7RUD4D3A.js +279 -0
- package/dist/doctor-7RUD4D3A.js.map +1 -0
- package/dist/goal-JFRNPBSD.js +302 -0
- package/dist/goal-JFRNPBSD.js.map +1 -0
- package/dist/index.js +381 -0
- package/dist/index.js.map +1 -0
- package/dist/init-NFYNO3A3.js +194 -0
- package/dist/init-NFYNO3A3.js.map +1 -0
- package/dist/prompts-L37J72YW.js +215 -0
- package/dist/prompts-L37J72YW.js.map +1 -0
- package/dist/run-ARUPXFFB.js +376 -0
- package/dist/run-ARUPXFFB.js.map +1 -0
- package/dist/runner-state-QFU3LJVJ.js +17 -0
- package/dist/runner-state-QFU3LJVJ.js.map +1 -0
- package/dist/start-CFPOVIAR.js +285 -0
- package/dist/start-CFPOVIAR.js.map +1 -0
- package/dist/status-E4EACVE2.js +25 -0
- package/dist/status-E4EACVE2.js.map +1 -0
- package/dist/tasks-ZIK6BVEX.js +184 -0
- package/dist/tasks-ZIK6BVEX.js.map +1 -0
- package/package.json +68 -4
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PIPELINE,
|
|
3
|
+
isTerminal,
|
|
4
|
+
pipelineIndex,
|
|
5
|
+
runnerReducer
|
|
6
|
+
} from "./chunk-FRFSJMN4.js";
|
|
7
|
+
import {
|
|
8
|
+
Spinner
|
|
9
|
+
} from "./chunk-BOLFK3BH.js";
|
|
10
|
+
import {
|
|
11
|
+
ThemeProvider,
|
|
12
|
+
useTheme
|
|
13
|
+
} from "./chunk-OXRMGR72.js";
|
|
14
|
+
import {
|
|
15
|
+
bar,
|
|
16
|
+
truncate
|
|
17
|
+
} from "./chunk-SF5ZEAP4.js";
|
|
18
|
+
|
|
19
|
+
// src/tui/RunnerView.tsx
|
|
20
|
+
import { Box, Text, useApp, useInput, useWindowSize } from "ink";
|
|
21
|
+
import { useEffect, useReducer, useRef, useState } from "react";
|
|
22
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
23
|
+
var IDLE_STATES = ["idle", "paused", "stopped", "error"];
|
|
24
|
+
function pipelineText(theme, state, repairCycle) {
|
|
25
|
+
const current = pipelineIndex(state);
|
|
26
|
+
const arrow = theme.dim(` ${theme.glyph.arrow} `);
|
|
27
|
+
return PIPELINE.map((step, i) => {
|
|
28
|
+
let label = step;
|
|
29
|
+
if (step === "validating" && state === "repairing") {
|
|
30
|
+
label = `repairing${repairCycle ? ` #${repairCycle}` : ""}`;
|
|
31
|
+
}
|
|
32
|
+
if (current === -1) return theme.dim(label);
|
|
33
|
+
if (i < current) return theme.ok(label);
|
|
34
|
+
if (i === current) return theme.bold(theme.accent(label));
|
|
35
|
+
return theme.dim(label);
|
|
36
|
+
}).join(arrow);
|
|
37
|
+
}
|
|
38
|
+
function logColor(theme, line) {
|
|
39
|
+
if (line.level === "error") return theme.error;
|
|
40
|
+
if (line.level === "warn") return theme.warn;
|
|
41
|
+
if (line.level === "debug") return theme.dim;
|
|
42
|
+
return (t) => t;
|
|
43
|
+
}
|
|
44
|
+
function logText(theme, line, width) {
|
|
45
|
+
const time = new Date(line.ts).toTimeString().slice(0, 8);
|
|
46
|
+
const prefix = `${time} `;
|
|
47
|
+
return `${theme.dim(prefix)}${logColor(theme, line)(truncate(line.message.replace(/\s*\n\s*/g, " "), Math.max(10, width - prefix.length)))}`;
|
|
48
|
+
}
|
|
49
|
+
function RunnerView({
|
|
50
|
+
state,
|
|
51
|
+
maxRepairCycles,
|
|
52
|
+
projectName,
|
|
53
|
+
width,
|
|
54
|
+
logLines,
|
|
55
|
+
notice
|
|
56
|
+
}) {
|
|
57
|
+
const theme = useTheme();
|
|
58
|
+
const { status } = state;
|
|
59
|
+
const task = status.taskId ? state.tasks[status.taskId] : void 0;
|
|
60
|
+
const busy = !IDLE_STATES.includes(status.state);
|
|
61
|
+
const cycle = status.repairCycle ?? 0;
|
|
62
|
+
const stateColor = status.state === "error" ? theme.ink.error : status.state === "paused" || status.state === "stopped" ? theme.ink.warn : theme.ink.accent;
|
|
63
|
+
const rule = theme.dim(theme.glyph.rule.repeat(Math.max(10, width)));
|
|
64
|
+
const tail = state.logs.slice(-logLines);
|
|
65
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width, children: [
|
|
66
|
+
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
|
|
67
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
68
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.ink.accent, children: "DaveCode runner" }),
|
|
69
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: theme.ink.dim, children: [
|
|
70
|
+
" \xB7 ",
|
|
71
|
+
projectName
|
|
72
|
+
] })
|
|
73
|
+
] }),
|
|
74
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: theme.ink.dim, children: [
|
|
75
|
+
state.done.success,
|
|
76
|
+
" done \xB7 ",
|
|
77
|
+
state.done.failed,
|
|
78
|
+
" failed"
|
|
79
|
+
] })
|
|
80
|
+
] }),
|
|
81
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
|
|
82
|
+
busy ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(Text, { color: stateColor, children: theme.glyph.dot }),
|
|
83
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: stateColor, children: [
|
|
84
|
+
" ",
|
|
85
|
+
status.state
|
|
86
|
+
] }),
|
|
87
|
+
status.startedAt ? /* @__PURE__ */ jsxs(Text, { dimColor: theme.ink.dim, children: [
|
|
88
|
+
" since ",
|
|
89
|
+
status.startedAt.slice(11, 19)
|
|
90
|
+
] }) : null
|
|
91
|
+
] }),
|
|
92
|
+
/* @__PURE__ */ jsx(Text, { wrap: "truncate-end", children: pipelineText(theme, status.state, status.repairCycle) }),
|
|
93
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
|
|
94
|
+
/* @__PURE__ */ jsxs(Text, { wrap: "truncate-end", children: [
|
|
95
|
+
/* @__PURE__ */ jsx(Text, { dimColor: theme.ink.dim, children: "task " }),
|
|
96
|
+
task ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
97
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: task.id }),
|
|
98
|
+
" ",
|
|
99
|
+
task.title,
|
|
100
|
+
task.attempts ? /* @__PURE__ */ jsxs(Text, { dimColor: theme.ink.dim, children: [
|
|
101
|
+
" \xB7 attempt ",
|
|
102
|
+
task.attempts
|
|
103
|
+
] }) : null
|
|
104
|
+
] }) : status.taskId ? /* @__PURE__ */ jsx(Text, { bold: true, children: status.taskId }) : /* @__PURE__ */ jsx(Text, { dimColor: theme.ink.dim, children: "none" })
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
107
|
+
/* @__PURE__ */ jsx(Text, { dimColor: theme.ink.dim, children: "repair " }),
|
|
108
|
+
bar(
|
|
109
|
+
theme,
|
|
110
|
+
maxRepairCycles > 0 ? cycle / maxRepairCycles : 0,
|
|
111
|
+
Math.max(1, maxRepairCycles * 2)
|
|
112
|
+
),
|
|
113
|
+
" ",
|
|
114
|
+
cycle,
|
|
115
|
+
"/",
|
|
116
|
+
maxRepairCycles
|
|
117
|
+
] }),
|
|
118
|
+
status.lastError ? /* @__PURE__ */ jsxs(Text, { color: theme.ink.error, wrap: "truncate-end", children: [
|
|
119
|
+
theme.glyph.fail,
|
|
120
|
+
" ",
|
|
121
|
+
status.lastError
|
|
122
|
+
] }) : null
|
|
123
|
+
] }),
|
|
124
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
|
|
125
|
+
/* @__PURE__ */ jsx(Text, { children: rule }),
|
|
126
|
+
tail.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: theme.ink.dim, children: "waiting for runner output\u2026" }) : null,
|
|
127
|
+
tail.map((line, i) => (
|
|
128
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: log lines are append-only
|
|
129
|
+
/* @__PURE__ */ jsx(Text, { wrap: "truncate-end", children: logText(theme, line, width) }, `${line.ts}-${i}`)
|
|
130
|
+
)),
|
|
131
|
+
/* @__PURE__ */ jsx(Text, { children: rule })
|
|
132
|
+
] }),
|
|
133
|
+
/* @__PURE__ */ jsx(Text, { dimColor: theme.ink.dim, children: notice ?? "q or Ctrl+C stop safely \xB7 p pause/resume" })
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
function RunnerScreen(props) {
|
|
137
|
+
const { exit } = useApp();
|
|
138
|
+
const { columns, rows } = useWindowSize();
|
|
139
|
+
const [state, dispatch] = useReducer(runnerReducer, props.initial);
|
|
140
|
+
const [notice, setNotice] = useState();
|
|
141
|
+
const stopping = useRef(false);
|
|
142
|
+
const sawActive = useRef(!isTerminal(props.initial.status.state));
|
|
143
|
+
useEffect(() => props.subscribe(dispatch), [props.subscribe]);
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
if (!isTerminal(state.status.state)) {
|
|
146
|
+
sawActive.current = true;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (sawActive.current || stopping.current) {
|
|
150
|
+
const timer = setTimeout(() => exit(), 50);
|
|
151
|
+
return () => clearTimeout(timer);
|
|
152
|
+
}
|
|
153
|
+
}, [state.status.state, exit]);
|
|
154
|
+
const requestStop = () => {
|
|
155
|
+
if (stopping.current) {
|
|
156
|
+
exit();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
stopping.current = true;
|
|
160
|
+
setNotice("Stopping safely (the task goes back to PENDING)\u2026 press again to quit now");
|
|
161
|
+
props.stop().then(
|
|
162
|
+
() => exit(),
|
|
163
|
+
(err) => {
|
|
164
|
+
setNotice(`stop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
+
setTimeout(() => exit(), 500);
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
useInput((input, key) => {
|
|
170
|
+
if (key.ctrl && input === "c" || input === "q") return requestStop();
|
|
171
|
+
if (input === "p") {
|
|
172
|
+
if (state.status.state === "paused") void props.resume?.();
|
|
173
|
+
else void props.pause?.();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
const width = Math.max(30, columns);
|
|
177
|
+
const logLines = Math.max(3, Math.min(30, rows - 14));
|
|
178
|
+
return /* @__PURE__ */ jsx(
|
|
179
|
+
RunnerView,
|
|
180
|
+
{
|
|
181
|
+
state,
|
|
182
|
+
maxRepairCycles: props.maxRepairCycles,
|
|
183
|
+
projectName: props.projectName,
|
|
184
|
+
width,
|
|
185
|
+
logLines,
|
|
186
|
+
...notice ? { notice } : {}
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
function RunnerApp(props) {
|
|
191
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { theme: props.theme, children: /* @__PURE__ */ jsx(RunnerScreen, { ...props }) });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
pipelineText,
|
|
196
|
+
logText,
|
|
197
|
+
RunnerView,
|
|
198
|
+
RunnerApp
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=chunk-OYEYNDOO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tui/RunnerView.tsx"],"sourcesContent":["import type { DaveEvent, RunnerState } from '@davecode/core';\nimport { Box, Text, useApp, useInput, useWindowSize } from 'ink';\nimport { useEffect, useReducer, useRef, useState } from 'react';\nimport { bar, truncate } from '../ui/format';\nimport type { Theme } from '../ui/theme';\nimport { Spinner } from './components/Spinner';\nimport {\n isTerminal,\n type LogLine,\n PIPELINE,\n pipelineIndex,\n type RunnerViewState,\n runnerReducer,\n} from './runner-state';\nimport { ThemeProvider, useTheme } from './theme-context';\n\nconst IDLE_STATES: readonly RunnerState[] = ['idle', 'paused', 'stopped', 'error'];\n\n/** `selecting → preparing → implementing → …` with the current step highlighted. */\nexport function pipelineText(theme: Theme, state: RunnerState, repairCycle?: number): string {\n const current = pipelineIndex(state);\n const arrow = theme.dim(` ${theme.glyph.arrow} `);\n return PIPELINE.map((step, i) => {\n let label: string = step;\n if (step === 'validating' && state === 'repairing') {\n label = `repairing${repairCycle ? ` #${repairCycle}` : ''}`;\n }\n if (current === -1) return theme.dim(label);\n if (i < current) return theme.ok(label);\n if (i === current) return theme.bold(theme.accent(label));\n return theme.dim(label);\n }).join(arrow);\n}\n\nfunction logColor(theme: Theme, line: LogLine): (text: string) => string {\n if (line.level === 'error') return theme.error;\n if (line.level === 'warn') return theme.warn;\n if (line.level === 'debug') return theme.dim;\n return (t) => t;\n}\n\nexport function logText(theme: Theme, line: LogLine, width: number): string {\n const time = new Date(line.ts).toTimeString().slice(0, 8);\n const prefix = `${time} `;\n return `${theme.dim(prefix)}${logColor(theme, line)(truncate(line.message.replace(/\\s*\\n\\s*/g, ' '), Math.max(10, width - prefix.length)))}`;\n}\n\nexport interface RunnerViewProps {\n state: RunnerViewState;\n maxRepairCycles: number;\n projectName: string;\n width: number;\n /** Number of log lines to show. */\n logLines: number;\n notice?: string;\n}\n\n/** Stateless runner dashboard: state machine position, current task, repair cycle, log tail. */\nexport function RunnerView({\n state,\n maxRepairCycles,\n projectName,\n width,\n logLines,\n notice,\n}: RunnerViewProps) {\n const theme = useTheme();\n const { status } = state;\n const task = status.taskId ? state.tasks[status.taskId] : undefined;\n const busy = !IDLE_STATES.includes(status.state);\n const cycle = status.repairCycle ?? 0;\n const stateColor =\n status.state === 'error'\n ? theme.ink.error\n : status.state === 'paused' || status.state === 'stopped'\n ? theme.ink.warn\n : theme.ink.accent;\n const rule = theme.dim(theme.glyph.rule.repeat(Math.max(10, width)));\n const tail = state.logs.slice(-logLines);\n\n return (\n <Box flexDirection=\"column\" width={width}>\n <Box justifyContent=\"space-between\">\n <Text>\n <Text bold color={theme.ink.accent}>\n DaveCode runner\n </Text>\n <Text dimColor={theme.ink.dim}> · {projectName}</Text>\n </Text>\n <Text dimColor={theme.ink.dim}>\n {state.done.success} done · {state.done.failed} failed\n </Text>\n </Box>\n <Box marginTop={1}>\n {busy ? <Spinner /> : <Text color={stateColor}>{theme.glyph.dot}</Text>}\n <Text bold color={stateColor}>\n {' '}\n {status.state}\n </Text>\n {status.startedAt ? (\n <Text dimColor={theme.ink.dim}> since {status.startedAt.slice(11, 19)}</Text>\n ) : null}\n </Box>\n <Text wrap=\"truncate-end\">{pipelineText(theme, status.state, status.repairCycle)}</Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text wrap=\"truncate-end\">\n <Text dimColor={theme.ink.dim}>{'task '}</Text>\n {task ? (\n <Text>\n <Text bold>{task.id}</Text> {task.title}\n {task.attempts ? (\n <Text dimColor={theme.ink.dim}> · attempt {task.attempts}</Text>\n ) : null}\n </Text>\n ) : status.taskId ? (\n <Text bold>{status.taskId}</Text>\n ) : (\n <Text dimColor={theme.ink.dim}>none</Text>\n )}\n </Text>\n <Text>\n <Text dimColor={theme.ink.dim}>{'repair '}</Text>\n {bar(\n theme,\n maxRepairCycles > 0 ? cycle / maxRepairCycles : 0,\n Math.max(1, maxRepairCycles * 2),\n )}{' '}\n {cycle}/{maxRepairCycles}\n </Text>\n {status.lastError ? (\n <Text color={theme.ink.error} wrap=\"truncate-end\">\n {theme.glyph.fail} {status.lastError}\n </Text>\n ) : null}\n </Box>\n <Box marginTop={1} flexDirection=\"column\">\n <Text>{rule}</Text>\n {tail.length === 0 ? (\n <Text dimColor={theme.ink.dim}>waiting for runner output…</Text>\n ) : null}\n {tail.map((line, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: log lines are append-only\n <Text key={`${line.ts}-${i}`} wrap=\"truncate-end\">\n {logText(theme, line, width)}\n </Text>\n ))}\n <Text>{rule}</Text>\n </Box>\n <Text dimColor={theme.ink.dim}>{notice ?? 'q or Ctrl+C stop safely · p pause/resume'}</Text>\n </Box>\n );\n}\n\nexport interface RunnerAppProps {\n theme: Theme;\n initial: RunnerViewState;\n /** Subscribe to events (in-process bus or `/api/events`); returns an unsubscribe function. */\n subscribe: (onEvent: (event: DaveEvent) => void) => () => void;\n maxRepairCycles: number;\n projectName: string;\n stop: () => Promise<void>;\n pause?: () => void | Promise<void>;\n resume?: () => void | Promise<void>;\n}\n\nfunction RunnerScreen(props: RunnerAppProps) {\n const { exit } = useApp();\n const { columns, rows } = useWindowSize();\n const [state, dispatch] = useReducer(runnerReducer, props.initial);\n const [notice, setNotice] = useState<string | undefined>();\n const stopping = useRef(false);\n const sawActive = useRef(!isTerminal(props.initial.status.state));\n\n useEffect(() => props.subscribe(dispatch), [props.subscribe]);\n\n // Leave once the runner comes to rest on its own (fatal error) or after our stop().\n useEffect(() => {\n if (!isTerminal(state.status.state)) {\n sawActive.current = true;\n return;\n }\n if (sawActive.current || stopping.current) {\n const timer = setTimeout(() => exit(), 50);\n return () => clearTimeout(timer);\n }\n }, [state.status.state, exit]);\n\n const requestStop = () => {\n if (stopping.current) {\n exit();\n return;\n }\n stopping.current = true;\n setNotice('Stopping safely (the task goes back to PENDING)… press again to quit now');\n props.stop().then(\n () => exit(),\n (err: unknown) => {\n setNotice(`stop failed: ${err instanceof Error ? err.message : String(err)}`);\n setTimeout(() => exit(), 500);\n },\n );\n };\n\n useInput((input, key) => {\n if ((key.ctrl && input === 'c') || input === 'q') return requestStop();\n if (input === 'p') {\n if (state.status.state === 'paused') void props.resume?.();\n else void props.pause?.();\n }\n });\n\n const width = Math.max(30, columns);\n const logLines = Math.max(3, Math.min(30, rows - 14));\n return (\n <RunnerView\n state={state}\n maxRepairCycles={props.maxRepairCycles}\n projectName={props.projectName}\n width={width}\n logLines={logLines}\n {...(notice ? { notice } : {})}\n />\n );\n}\n\n/** Live runner view. Render with `exitOnCtrlC: false` so Ctrl+C stops the runner safely. */\nexport function RunnerApp(props: RunnerAppProps) {\n return (\n <ThemeProvider theme={props.theme}>\n <RunnerScreen {...props} />\n </ThemeProvider>\n );\n}\n"],"mappings":"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","names":[]}
|