executant 1.14.0 → 1.15.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 +14 -0
- package/dist/index.js +251 -135
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,6 +121,20 @@ steps:
|
|
|
121
121
|
- **`self_healing: true`** — on script failure, Claude diagnoses and repairs the command, then re-runs it, up to 5×
|
|
122
122
|
- **`self_improve: true`** — after the workflow finishes, Claude analyzes execution highlights and saves an improved YAML to `tasks/backlog/`
|
|
123
123
|
|
|
124
|
+
## Interjection
|
|
125
|
+
|
|
126
|
+
While a workflow is running, press **`i`** to open a text input at the bottom of the TUI. Type a correction and press **Enter** to send it; **Esc** cancels.
|
|
127
|
+
|
|
128
|
+
The message is queued and prepended to the **next Claude step's prompt** as `[User correction from a previous step]`. Claude sees your note before it starts and incorporates it into its work. If you interject while a script step is running, the correction waits for the next Claude step in the workflow.
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
press i → ▷ don't delete that file, use git revert▌ esc to cancel
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**What it's good for:** steering the next Claude step while watching the current one run — leaving a note for the step that's about to start.
|
|
135
|
+
|
|
136
|
+
**What it can't do:** interrupt a Claude step mid-execution. The Claude CLI processes each invocation as a complete unit; there's no mechanism to inject a message partway through. To abort a runaway step immediately, press `q`.
|
|
137
|
+
|
|
124
138
|
## Examples
|
|
125
139
|
|
|
126
140
|
| File | Demonstrates |
|
package/dist/index.js
CHANGED
|
@@ -406,12 +406,11 @@ import { execSync, spawn as spawn2 } from "node:child_process";
|
|
|
406
406
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
407
407
|
var METHODOLOGY = loadPrompt("development-methodology");
|
|
408
408
|
var DEFAULT_TOOLS = ["Read", "Edit", "Write", "Bash", "Glob", "Grep"];
|
|
409
|
-
function buildClaudeArgs(task) {
|
|
409
|
+
function buildClaudeArgs(task, interactive = false) {
|
|
410
410
|
const allowedTools = task.allowedTools ?? DEFAULT_TOOLS;
|
|
411
411
|
const permissionMode = task.permissionMode ?? "bypassPermissions";
|
|
412
412
|
return [
|
|
413
|
-
"--print",
|
|
414
|
-
task.prompt,
|
|
413
|
+
...interactive ? [] : ["--print", task.prompt],
|
|
415
414
|
"--output-format",
|
|
416
415
|
"stream-json",
|
|
417
416
|
"--verbose",
|
|
@@ -433,7 +432,7 @@ function resolveClaudePath() {
|
|
|
433
432
|
);
|
|
434
433
|
}
|
|
435
434
|
}
|
|
436
|
-
async function* runClaude(task) {
|
|
435
|
+
async function* runClaude(task, _channel) {
|
|
437
436
|
yield {
|
|
438
437
|
type: "log",
|
|
439
438
|
level: "info",
|
|
@@ -562,7 +561,7 @@ function shouldSkipStep(stepNumber, name, options2) {
|
|
|
562
561
|
}
|
|
563
562
|
return options2.fromStep !== void 0 && stepNumber < options2.fromStep[0];
|
|
564
563
|
}
|
|
565
|
-
async function* runWorkflow(workflow2, options2 = {}) {
|
|
564
|
+
async function* runWorkflow(workflow2, options2 = {}, channel2) {
|
|
566
565
|
const workflowStart = Date.now();
|
|
567
566
|
yield { type: "workflow:start", workflow: workflow2 };
|
|
568
567
|
for (const [i, task] of workflow2.tasks.entries()) {
|
|
@@ -575,7 +574,7 @@ async function* runWorkflow(workflow2, options2 = {}) {
|
|
|
575
574
|
yield { type: "step:start", index: i, name: task.name };
|
|
576
575
|
const from = options2.fromStep && options2.fromStep[0] === stepNumber ? options2.fromStep.slice(1) : void 0;
|
|
577
576
|
try {
|
|
578
|
-
for await (const event of runStep(task, from)) {
|
|
577
|
+
for await (const event of runStep(task, from, channel2)) {
|
|
579
578
|
if (event.type === "step:iteration" || event.type === "step:inner" || event.type === "output:text" || event.type === "output:tool") {
|
|
580
579
|
yield { ...event, index: i };
|
|
581
580
|
} else {
|
|
@@ -600,7 +599,7 @@ async function* runWorkflow(workflow2, options2 = {}) {
|
|
|
600
599
|
durationMs: Date.now() - workflowStart
|
|
601
600
|
};
|
|
602
601
|
}
|
|
603
|
-
async function* runStep(task, from) {
|
|
602
|
+
async function* runStep(task, from, channel2) {
|
|
604
603
|
switch (task.type) {
|
|
605
604
|
case "log":
|
|
606
605
|
yield* runLog(task);
|
|
@@ -619,11 +618,20 @@ async function* runStep(task, from) {
|
|
|
619
618
|
}
|
|
620
619
|
case "claude": {
|
|
621
620
|
const expanded = expandContext(task);
|
|
622
|
-
|
|
621
|
+
const queued = channel2?.consumeQueue() ?? [];
|
|
622
|
+
const enriched = queued.length > 0 ? {
|
|
623
|
+
...expanded,
|
|
624
|
+
prompt: `[User correction from a previous step]
|
|
625
|
+
${queued.join("\n")}
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
${expanded.prompt}`
|
|
629
|
+
} : expanded;
|
|
630
|
+
yield* enriched.llmAsJudge ? runClaudeWithJudge(enriched, channel2) : runClaude(enriched, channel2);
|
|
623
631
|
break;
|
|
624
632
|
}
|
|
625
633
|
case "forEach":
|
|
626
|
-
yield* runForEach(task, from);
|
|
634
|
+
yield* runForEach(task, from, channel2);
|
|
627
635
|
break;
|
|
628
636
|
default: {
|
|
629
637
|
const _ = task;
|
|
@@ -634,7 +642,7 @@ async function* runStep(task, from) {
|
|
|
634
642
|
async function* runLog(task) {
|
|
635
643
|
yield { type: "output:text", index: -1, text: task.message };
|
|
636
644
|
}
|
|
637
|
-
async function* runForEach(task, from) {
|
|
645
|
+
async function* runForEach(task, from, channel2) {
|
|
638
646
|
const items = await resolveItems(task.forEach);
|
|
639
647
|
const total = items.length;
|
|
640
648
|
const innerTotal = task.inner.length;
|
|
@@ -669,7 +677,7 @@ async function* runForEach(task, from) {
|
|
|
669
677
|
}
|
|
670
678
|
const childFrom = childIdx === startChild ? iterFrom?.slice(1) : void 0;
|
|
671
679
|
try {
|
|
672
|
-
for await (const event of runStep(substituted, childFrom)) {
|
|
680
|
+
for await (const event of runStep(substituted, childFrom, channel2)) {
|
|
673
681
|
if (event.type !== "step:iteration" && event.type !== "step:inner") {
|
|
674
682
|
yield event;
|
|
675
683
|
}
|
|
@@ -803,14 +811,14 @@ async function* runCommandWithHealing(task) {
|
|
|
803
811
|
}
|
|
804
812
|
}
|
|
805
813
|
}
|
|
806
|
-
async function* runClaudeWithJudge(task) {
|
|
814
|
+
async function* runClaudeWithJudge(task, channel2) {
|
|
807
815
|
let judgeContext = "";
|
|
808
816
|
for (let attempt = 0; attempt < MAX_JUDGE_RETRIES; attempt++) {
|
|
809
817
|
const prompt = attempt === 0 ? task.prompt : `${task.prompt}
|
|
810
818
|
|
|
811
819
|
${fillTemplate(JUDGE_RETRY_CONTEXT, { FEEDBACK: judgeContext })}`;
|
|
812
820
|
const lines = [];
|
|
813
|
-
yield* collectLines(runClaude({ ...task, prompt }), lines);
|
|
821
|
+
yield* collectLines(runClaude({ ...task, prompt }, channel2), lines);
|
|
814
822
|
yield {
|
|
815
823
|
type: "log",
|
|
816
824
|
level: "info",
|
|
@@ -918,18 +926,86 @@ ${blocks.join("\n\n")}`;
|
|
|
918
926
|
init_update();
|
|
919
927
|
|
|
920
928
|
// src/ui/App.tsx
|
|
921
|
-
import { useEffect as useEffect2, useReducer, useState } from "react";
|
|
922
|
-
import { Box as
|
|
929
|
+
import { useEffect as useEffect2, useReducer, useState as useState2 } from "react";
|
|
930
|
+
import { Box as Box6, Text as Text6, useApp, useStdin, useStdout } from "ink";
|
|
923
931
|
|
|
924
932
|
// src/ui/KeyboardHandler.tsx
|
|
925
933
|
import { useInput } from "ink";
|
|
926
|
-
function KeyboardHandler({
|
|
934
|
+
function KeyboardHandler({
|
|
935
|
+
onExit,
|
|
936
|
+
onInterject,
|
|
937
|
+
isInterjecting
|
|
938
|
+
}) {
|
|
927
939
|
useInput((input, key) => {
|
|
940
|
+
if (isInterjecting) return;
|
|
928
941
|
if (input === "q" || key.ctrl && input === "c") onExit();
|
|
942
|
+
if (input === "i" && onInterject) onInterject();
|
|
929
943
|
});
|
|
930
944
|
return null;
|
|
931
945
|
}
|
|
932
946
|
|
|
947
|
+
// src/ui/InterjectInput.tsx
|
|
948
|
+
import { useState } from "react";
|
|
949
|
+
import { Box, Text, useInput as useInput2 } from "ink";
|
|
950
|
+
|
|
951
|
+
// src/ui/theme.ts
|
|
952
|
+
import { createRequire } from "node:module";
|
|
953
|
+
import { oklchToHex } from "@coston/design-tokens";
|
|
954
|
+
var THEME_NAME = "purple-dark";
|
|
955
|
+
var _require = createRequire(import.meta.url);
|
|
956
|
+
var { themes } = _require("@coston/design-tokens/tokens.json");
|
|
957
|
+
function hex(key) {
|
|
958
|
+
return oklchToHex(themes[THEME_NAME][key]);
|
|
959
|
+
}
|
|
960
|
+
var theme = {
|
|
961
|
+
foreground: hex("foreground"),
|
|
962
|
+
// primary text
|
|
963
|
+
muted: hex("muted-foreground"),
|
|
964
|
+
// dimmed / inactive text and borders
|
|
965
|
+
primary: hex("primary"),
|
|
966
|
+
// tool calls, cursor, active
|
|
967
|
+
primaryLight: hex("secondary-foreground"),
|
|
968
|
+
// lighter tint of primary (same hue, higher lightness)
|
|
969
|
+
success: hex("success"),
|
|
970
|
+
// completed steps
|
|
971
|
+
error: hex("destructive"),
|
|
972
|
+
// errors
|
|
973
|
+
warning: hex("warning"),
|
|
974
|
+
// warnings, retries, updates
|
|
975
|
+
border: hex("border")
|
|
976
|
+
// log pane border
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
// src/ui/InterjectInput.tsx
|
|
980
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
981
|
+
function InterjectInput({ onSubmit, onCancel }) {
|
|
982
|
+
const [value, setValue] = useState("");
|
|
983
|
+
useInput2((input, key) => {
|
|
984
|
+
if (key.escape) {
|
|
985
|
+
onCancel();
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
if (key.return) {
|
|
989
|
+
if (value.trim()) onSubmit(value.trim());
|
|
990
|
+
else onCancel();
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
if (key.backspace || key.delete) {
|
|
994
|
+
setValue((v) => v.slice(0, -1));
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
if (input && !key.ctrl && !key.meta) {
|
|
998
|
+
setValue((v) => v + input);
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
return /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "row", children: [
|
|
1002
|
+
/* @__PURE__ */ jsx(Text, { color: theme.primary, bold: true, children: "\u25B7 " }),
|
|
1003
|
+
/* @__PURE__ */ jsx(Text, { children: value }),
|
|
1004
|
+
/* @__PURE__ */ jsx(Text, { color: theme.primary, children: "\u258C" }),
|
|
1005
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " esc to cancel" })
|
|
1006
|
+
] });
|
|
1007
|
+
}
|
|
1008
|
+
|
|
933
1009
|
// src/ui/formatTool.ts
|
|
934
1010
|
function formatToolCall2(tool, input) {
|
|
935
1011
|
switch (tool) {
|
|
@@ -1081,6 +1157,11 @@ function reducer(state, event) {
|
|
|
1081
1157
|
if (idx >= state.tasks.length) return state;
|
|
1082
1158
|
return appendLines(state, idx, `[${event.level}] ${event.text}`);
|
|
1083
1159
|
}
|
|
1160
|
+
case "step:interjection": {
|
|
1161
|
+
const idx = event.index;
|
|
1162
|
+
if (idx >= state.tasks.length) return state;
|
|
1163
|
+
return appendLines(state, idx, `[interjection] ${event.message}`);
|
|
1164
|
+
}
|
|
1084
1165
|
default: {
|
|
1085
1166
|
const _ = event;
|
|
1086
1167
|
void _;
|
|
@@ -1116,35 +1197,7 @@ function appendLines(state, index, text) {
|
|
|
1116
1197
|
}
|
|
1117
1198
|
|
|
1118
1199
|
// src/ui/TaskRow.tsx
|
|
1119
|
-
import { Box, Text } from "ink";
|
|
1120
|
-
|
|
1121
|
-
// src/ui/theme.ts
|
|
1122
|
-
import { createRequire } from "node:module";
|
|
1123
|
-
import { oklchToHex } from "@coston/design-tokens";
|
|
1124
|
-
var THEME_NAME = "purple-dark";
|
|
1125
|
-
var _require = createRequire(import.meta.url);
|
|
1126
|
-
var { themes } = _require("@coston/design-tokens/tokens.json");
|
|
1127
|
-
function hex(key) {
|
|
1128
|
-
return oklchToHex(themes[THEME_NAME][key]);
|
|
1129
|
-
}
|
|
1130
|
-
var theme = {
|
|
1131
|
-
foreground: hex("foreground"),
|
|
1132
|
-
// primary text
|
|
1133
|
-
muted: hex("muted-foreground"),
|
|
1134
|
-
// dimmed / inactive text and borders
|
|
1135
|
-
primary: hex("primary"),
|
|
1136
|
-
// tool calls, cursor, active
|
|
1137
|
-
primaryLight: hex("secondary-foreground"),
|
|
1138
|
-
// lighter tint of primary (same hue, higher lightness)
|
|
1139
|
-
success: hex("success"),
|
|
1140
|
-
// completed steps
|
|
1141
|
-
error: hex("destructive"),
|
|
1142
|
-
// errors
|
|
1143
|
-
warning: hex("warning"),
|
|
1144
|
-
// warnings, retries, updates
|
|
1145
|
-
border: hex("border")
|
|
1146
|
-
// log pane border
|
|
1147
|
-
};
|
|
1200
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
1148
1201
|
|
|
1149
1202
|
// src/ui/utils.ts
|
|
1150
1203
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -1182,7 +1235,7 @@ function formatTaskElapsed(start, end, status) {
|
|
|
1182
1235
|
}
|
|
1183
1236
|
|
|
1184
1237
|
// src/ui/TaskRow.tsx
|
|
1185
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1238
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1186
1239
|
function TaskRow({ taskState, isActive, index, tick }) {
|
|
1187
1240
|
const { task, status, startTime, endTime } = taskState;
|
|
1188
1241
|
const icon = statusIcon(status, tick);
|
|
@@ -1190,13 +1243,13 @@ function TaskRow({ taskState, isActive, index, tick }) {
|
|
|
1190
1243
|
const elapsed = formatTaskElapsed(startTime, endTime, status);
|
|
1191
1244
|
const iterInfo = formatIterCount(taskState.iterationHistory);
|
|
1192
1245
|
const label = `${index + 1}. ${task.name}${iterInfo}`;
|
|
1193
|
-
return /* @__PURE__ */
|
|
1194
|
-
/* @__PURE__ */
|
|
1246
|
+
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
1247
|
+
/* @__PURE__ */ jsxs2(Text2, { color, children: [
|
|
1195
1248
|
icon,
|
|
1196
1249
|
" "
|
|
1197
1250
|
] }),
|
|
1198
|
-
/* @__PURE__ */
|
|
1199
|
-
/* @__PURE__ */
|
|
1251
|
+
/* @__PURE__ */ jsx2(Text2, { color: isActive ? theme.foreground : theme.muted, bold: isActive, children: label }),
|
|
1252
|
+
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
1200
1253
|
" ",
|
|
1201
1254
|
elapsed
|
|
1202
1255
|
] })
|
|
@@ -1215,22 +1268,22 @@ function formatIterCount(history) {
|
|
|
1215
1268
|
}
|
|
1216
1269
|
|
|
1217
1270
|
// src/ui/IterationRow.tsx
|
|
1218
|
-
import { Box as
|
|
1219
|
-
import { Fragment, jsx as
|
|
1271
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
1272
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1220
1273
|
function IterationRow({ record, tick }) {
|
|
1221
1274
|
const icon = statusIcon(record.status, tick);
|
|
1222
1275
|
const color = STATUS_COLOR[record.status] ?? theme.primary;
|
|
1223
1276
|
const innerText = record.inner ? ` \u2014 ${stripItem(record.inner.name, record.item)} [${record.inner.index + 1}/${record.inner.total}]` : "";
|
|
1224
1277
|
const ms = (record.endTime ?? Date.now()) - record.startTime;
|
|
1225
1278
|
const elapsed = `${(ms / 1e3).toFixed(1)}s`;
|
|
1226
|
-
return /* @__PURE__ */
|
|
1227
|
-
/* @__PURE__ */
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1230
|
-
/* @__PURE__ */
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
|
|
1279
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
1280
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: " " }),
|
|
1281
|
+
/* @__PURE__ */ jsx3(Text3, { color, children: icon }),
|
|
1282
|
+
/* @__PURE__ */ jsx3(Text3, { children: " " }),
|
|
1283
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: `[${record.iteration}/${record.total}]` }),
|
|
1284
|
+
/* @__PURE__ */ jsx3(Text3, { children: " " }),
|
|
1285
|
+
/* @__PURE__ */ jsxs3(
|
|
1286
|
+
Text3,
|
|
1234
1287
|
{
|
|
1235
1288
|
color: record.status === "running" ? theme.foreground : theme.muted,
|
|
1236
1289
|
children: [
|
|
@@ -1239,7 +1292,7 @@ function IterationRow({ record, tick }) {
|
|
|
1239
1292
|
]
|
|
1240
1293
|
}
|
|
1241
1294
|
),
|
|
1242
|
-
/* @__PURE__ */
|
|
1295
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
1243
1296
|
" ",
|
|
1244
1297
|
elapsed
|
|
1245
1298
|
] })
|
|
@@ -1261,29 +1314,29 @@ function IterationList({
|
|
|
1261
1314
|
if (isRepeatStyle(iterationHistory)) return null;
|
|
1262
1315
|
const hidden = iterationHistory.length - maxVisible;
|
|
1263
1316
|
const visible = iterationHistory.slice(-maxVisible);
|
|
1264
|
-
return /* @__PURE__ */
|
|
1265
|
-
hidden > 0 && /* @__PURE__ */
|
|
1266
|
-
visible.map((record) => /* @__PURE__ */
|
|
1317
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1318
|
+
hidden > 0 && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: ` \u2026 ${hidden} earlier` }),
|
|
1319
|
+
visible.map((record) => /* @__PURE__ */ jsx3(IterationRow, { record, tick }, record.iteration))
|
|
1267
1320
|
] });
|
|
1268
1321
|
}
|
|
1269
1322
|
|
|
1270
1323
|
// src/ui/LogPane.tsx
|
|
1271
|
-
import { Box as
|
|
1272
|
-
import { jsx as
|
|
1324
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
1325
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1273
1326
|
function LogPane({ lines, isActive = false, maxLines = 15 }) {
|
|
1274
1327
|
const visible = lines.slice(-maxLines);
|
|
1275
1328
|
if (visible.length === 0) {
|
|
1276
|
-
return /* @__PURE__ */
|
|
1329
|
+
return /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: isActive ? "\u2838 waiting for output\u2026" : "\u2014 no output yet \u2014" }) });
|
|
1277
1330
|
}
|
|
1278
|
-
return /* @__PURE__ */
|
|
1279
|
-
|
|
1331
|
+
return /* @__PURE__ */ jsx4(
|
|
1332
|
+
Box4,
|
|
1280
1333
|
{
|
|
1281
1334
|
flexDirection: "column",
|
|
1282
1335
|
marginTop: 1,
|
|
1283
1336
|
borderStyle: "single",
|
|
1284
1337
|
borderColor: theme.border,
|
|
1285
1338
|
paddingX: 1,
|
|
1286
|
-
children: visible.map((line, i) => /* @__PURE__ */
|
|
1339
|
+
children: visible.map((line, i) => /* @__PURE__ */ jsx4(
|
|
1287
1340
|
LogLine,
|
|
1288
1341
|
{
|
|
1289
1342
|
text: line,
|
|
@@ -1295,52 +1348,52 @@ function LogPane({ lines, isActive = false, maxLines = 15 }) {
|
|
|
1295
1348
|
);
|
|
1296
1349
|
}
|
|
1297
1350
|
function LogLine({ text, cursor }) {
|
|
1298
|
-
const suffix = cursor ? /* @__PURE__ */
|
|
1351
|
+
const suffix = cursor ? /* @__PURE__ */ jsx4(Text4, { color: theme.primary, children: " \u258C" }) : null;
|
|
1299
1352
|
if (/^\[[\w:]+\]/.test(text)) {
|
|
1300
1353
|
const bracket = text.match(/^\[[\w:]+\]/)?.[0] ?? "";
|
|
1301
1354
|
const rest = text.slice(bracket.length);
|
|
1302
|
-
return /* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
/* @__PURE__ */
|
|
1355
|
+
return /* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1356
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.primary, children: bracket }),
|
|
1357
|
+
/* @__PURE__ */ jsx4(Text4, { children: rest }),
|
|
1305
1358
|
suffix
|
|
1306
1359
|
] });
|
|
1307
1360
|
}
|
|
1308
1361
|
if (/^\s*\$\s/.test(text))
|
|
1309
|
-
return /* @__PURE__ */
|
|
1362
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.warning, children: [
|
|
1310
1363
|
text,
|
|
1311
1364
|
suffix
|
|
1312
1365
|
] });
|
|
1313
1366
|
if (text.startsWith("[warn]"))
|
|
1314
|
-
return /* @__PURE__ */
|
|
1367
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.warning, children: [
|
|
1315
1368
|
text,
|
|
1316
1369
|
suffix
|
|
1317
1370
|
] });
|
|
1318
1371
|
if (text.startsWith("[error]"))
|
|
1319
|
-
return /* @__PURE__ */
|
|
1372
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.error, children: [
|
|
1320
1373
|
text,
|
|
1321
1374
|
suffix
|
|
1322
1375
|
] });
|
|
1323
1376
|
if (/^[\s]*(✓|✔|✅|done|success|compiled|built|passed)/i.test(text) && !/\b(error|fail|failed|warn|warning)\b/i.test(text))
|
|
1324
|
-
return /* @__PURE__ */
|
|
1377
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.success, children: [
|
|
1325
1378
|
text,
|
|
1326
1379
|
suffix
|
|
1327
1380
|
] });
|
|
1328
1381
|
if (/\b(error|failed|fail)\b/i.test(text))
|
|
1329
|
-
return /* @__PURE__ */
|
|
1382
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.error, children: [
|
|
1330
1383
|
text,
|
|
1331
1384
|
suffix
|
|
1332
1385
|
] });
|
|
1333
1386
|
if (/\b(warn|warning)\b/i.test(text))
|
|
1334
|
-
return /* @__PURE__ */
|
|
1387
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.warning, children: [
|
|
1335
1388
|
text,
|
|
1336
1389
|
suffix
|
|
1337
1390
|
] });
|
|
1338
1391
|
if (/^[·…⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/.test(text))
|
|
1339
|
-
return /* @__PURE__ */
|
|
1392
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.muted, children: [
|
|
1340
1393
|
text,
|
|
1341
1394
|
suffix
|
|
1342
1395
|
] });
|
|
1343
|
-
return /* @__PURE__ */
|
|
1396
|
+
return /* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1344
1397
|
text,
|
|
1345
1398
|
suffix
|
|
1346
1399
|
] });
|
|
@@ -1360,8 +1413,8 @@ function useInterval(callback, delayMs) {
|
|
|
1360
1413
|
}
|
|
1361
1414
|
|
|
1362
1415
|
// src/ui/BrandMark.tsx
|
|
1363
|
-
import { Box as
|
|
1364
|
-
import { jsx as
|
|
1416
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
1417
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1365
1418
|
var BRAND = "Executant";
|
|
1366
1419
|
var SWEEP_TICKS = BRAND.length * 2;
|
|
1367
1420
|
var GAP_TICKS = 30;
|
|
@@ -1374,15 +1427,22 @@ function charColor(charIndex, tick, isActive) {
|
|
|
1374
1427
|
return charIndex === charPos ? theme.primaryLight : theme.primary;
|
|
1375
1428
|
}
|
|
1376
1429
|
function BrandMark({ tick, isActive }) {
|
|
1377
|
-
return /* @__PURE__ */
|
|
1430
|
+
return /* @__PURE__ */ jsx5(Box5, { children: [...BRAND].map((char, i) => /* @__PURE__ */ jsx5(Text5, { color: charColor(i, tick, isActive), bold: true, children: char }, i)) });
|
|
1378
1431
|
}
|
|
1379
1432
|
|
|
1380
1433
|
// src/ui/App.tsx
|
|
1381
|
-
import { jsx as
|
|
1434
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1382
1435
|
var MAX_VISIBLE_ITERATIONS = 8;
|
|
1383
|
-
function App({
|
|
1436
|
+
function App({
|
|
1437
|
+
workflow: workflow2,
|
|
1438
|
+
events: events2,
|
|
1439
|
+
options: options2,
|
|
1440
|
+
updateCheck: updateCheck2,
|
|
1441
|
+
interjectChannel
|
|
1442
|
+
}) {
|
|
1384
1443
|
const { exit } = useApp();
|
|
1385
1444
|
const [state, dispatch] = useReducer(reducer, buildInitialState(workflow2));
|
|
1445
|
+
const [isInterjecting, setIsInterjecting] = useState2(false);
|
|
1386
1446
|
useEffect2(() => {
|
|
1387
1447
|
let active = true;
|
|
1388
1448
|
(async () => {
|
|
@@ -1411,11 +1471,11 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1411
1471
|
}, [events2, exit]);
|
|
1412
1472
|
const { isRawModeSupported } = useStdin();
|
|
1413
1473
|
const { stdout } = useStdout();
|
|
1414
|
-
const [updateVersion, setUpdateVersion] =
|
|
1474
|
+
const [updateVersion, setUpdateVersion] = useState2(null);
|
|
1415
1475
|
useEffect2(() => {
|
|
1416
1476
|
updateCheck2.then(setUpdateVersion);
|
|
1417
1477
|
}, [updateCheck2]);
|
|
1418
|
-
const [tick, setTick] =
|
|
1478
|
+
const [tick, setTick] = useState2(0);
|
|
1419
1479
|
useInterval(() => {
|
|
1420
1480
|
if (!state.endTime) setTick((t) => t + 1);
|
|
1421
1481
|
}, 100);
|
|
@@ -1426,7 +1486,7 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1426
1486
|
runningTask?.iterationHistory,
|
|
1427
1487
|
MAX_VISIBLE_ITERATIONS
|
|
1428
1488
|
);
|
|
1429
|
-
const FIXED_OVERHEAD = 12 + (updateVersion ? 1 : 0);
|
|
1489
|
+
const FIXED_OVERHEAD = 12 + (updateVersion ? 1 : 0) + (isInterjecting ? 1 : 0);
|
|
1430
1490
|
const availableForTaskSection = Math.max(
|
|
1431
1491
|
1,
|
|
1432
1492
|
terminalRows - FIXED_OVERHEAD - LOG_PANE_MIN - iterationRowCount
|
|
@@ -1446,11 +1506,11 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1446
1506
|
).length;
|
|
1447
1507
|
const totalCount = state.tasks.length;
|
|
1448
1508
|
const filterInfo = options2?.stepFilter ? ` [step: ${options2.stepFilter}]` : options2?.fromStep ? ` [from step: ${options2.fromStep}]` : "";
|
|
1449
|
-
return /* @__PURE__ */
|
|
1450
|
-
/* @__PURE__ */
|
|
1451
|
-
/* @__PURE__ */
|
|
1452
|
-
/* @__PURE__ */
|
|
1453
|
-
/* @__PURE__ */
|
|
1509
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", padding: 1, children: [
|
|
1510
|
+
/* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(BrandMark, { tick, isActive: !state.endTime }) }),
|
|
1511
|
+
/* @__PURE__ */ jsxs5(Box6, { marginBottom: 1, children: [
|
|
1512
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.primary, children: workflow2.goal }),
|
|
1513
|
+
/* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
1454
1514
|
" ",
|
|
1455
1515
|
completedCount,
|
|
1456
1516
|
"/",
|
|
@@ -1460,8 +1520,8 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1460
1520
|
filterInfo
|
|
1461
1521
|
] })
|
|
1462
1522
|
] }),
|
|
1463
|
-
/* @__PURE__ */
|
|
1464
|
-
hiddenTaskCount > 0 && /* @__PURE__ */
|
|
1523
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", marginBottom: 1, children: [
|
|
1524
|
+
hiddenTaskCount > 0 && /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
1465
1525
|
" ",
|
|
1466
1526
|
"\xB7\xB7\xB7 ",
|
|
1467
1527
|
hiddenTaskCount,
|
|
@@ -1469,8 +1529,8 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1469
1529
|
] }),
|
|
1470
1530
|
taskSlice.map((taskState, i) => {
|
|
1471
1531
|
const globalIndex = hiddenTaskCount + i;
|
|
1472
|
-
return /* @__PURE__ */
|
|
1473
|
-
/* @__PURE__ */
|
|
1532
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
1533
|
+
/* @__PURE__ */ jsx6(
|
|
1474
1534
|
TaskRow,
|
|
1475
1535
|
{
|
|
1476
1536
|
index: globalIndex,
|
|
@@ -1479,7 +1539,7 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1479
1539
|
isActive: globalIndex === state.currentIndex
|
|
1480
1540
|
}
|
|
1481
1541
|
),
|
|
1482
|
-
taskState.status === "running" && taskState.iterationHistory?.length ? /* @__PURE__ */
|
|
1542
|
+
taskState.status === "running" && taskState.iterationHistory?.length ? /* @__PURE__ */ jsx6(
|
|
1483
1543
|
IterationList,
|
|
1484
1544
|
{
|
|
1485
1545
|
iterationHistory: taskState.iterationHistory,
|
|
@@ -1490,7 +1550,7 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1490
1550
|
] }, globalIndex);
|
|
1491
1551
|
})
|
|
1492
1552
|
] }),
|
|
1493
|
-
activeTask && /* @__PURE__ */
|
|
1553
|
+
activeTask && /* @__PURE__ */ jsx6(
|
|
1494
1554
|
LogPane,
|
|
1495
1555
|
{
|
|
1496
1556
|
lines: activeTask.lines,
|
|
@@ -1498,22 +1558,44 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1498
1558
|
maxLines: logPaneMaxLines
|
|
1499
1559
|
}
|
|
1500
1560
|
),
|
|
1501
|
-
state.endTime !== void 0 && state.writtenFiles.length > 0 && /* @__PURE__ */
|
|
1502
|
-
/* @__PURE__ */
|
|
1503
|
-
state.writtenFiles.map((f) => /* @__PURE__ */
|
|
1561
|
+
state.endTime !== void 0 && state.writtenFiles.length > 0 && /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
1562
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "files written:" }),
|
|
1563
|
+
state.writtenFiles.map((f) => /* @__PURE__ */ jsxs5(Text6, { color: theme.primary, children: [
|
|
1504
1564
|
" ",
|
|
1505
1565
|
f
|
|
1506
1566
|
] }, f))
|
|
1507
1567
|
] }),
|
|
1508
|
-
/* @__PURE__ */
|
|
1509
|
-
|
|
1568
|
+
isInterjecting && interjectChannel && /* @__PURE__ */ jsx6(
|
|
1569
|
+
InterjectInput,
|
|
1570
|
+
{
|
|
1571
|
+
onSubmit: (msg) => {
|
|
1572
|
+
interjectChannel.interject(msg);
|
|
1573
|
+
dispatch({
|
|
1574
|
+
type: "step:interjection",
|
|
1575
|
+
index: state.currentIndex,
|
|
1576
|
+
message: msg
|
|
1577
|
+
});
|
|
1578
|
+
setIsInterjecting(false);
|
|
1579
|
+
},
|
|
1580
|
+
onCancel: () => setIsInterjecting(false)
|
|
1581
|
+
}
|
|
1582
|
+
),
|
|
1583
|
+
/* @__PURE__ */ jsxs5(Box6, { marginTop: 1, flexDirection: "column", children: [
|
|
1584
|
+
updateVersion && /* @__PURE__ */ jsxs5(Text6, { color: theme.warning, children: [
|
|
1510
1585
|
"v",
|
|
1511
1586
|
updateVersion,
|
|
1512
1587
|
" available \u2014 run: executant update"
|
|
1513
1588
|
] }),
|
|
1514
|
-
/* @__PURE__ */
|
|
1589
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: isInterjecting ? "typing interjection\u2026" : "press q to quit \xB7 i to interject" })
|
|
1515
1590
|
] }),
|
|
1516
|
-
isRawModeSupported && /* @__PURE__ */
|
|
1591
|
+
isRawModeSupported && /* @__PURE__ */ jsx6(
|
|
1592
|
+
KeyboardHandler,
|
|
1593
|
+
{
|
|
1594
|
+
onExit: exit,
|
|
1595
|
+
onInterject: interjectChannel ? () => setIsInterjecting(true) : void 0,
|
|
1596
|
+
isInterjecting
|
|
1597
|
+
}
|
|
1598
|
+
)
|
|
1517
1599
|
] });
|
|
1518
1600
|
}
|
|
1519
1601
|
|
|
@@ -1922,9 +2004,9 @@ ${issues}`
|
|
|
1922
2004
|
}
|
|
1923
2005
|
|
|
1924
2006
|
// src/ui/PlanApp.tsx
|
|
1925
|
-
import { useEffect as useEffect3, useReducer as useReducer2, useState as
|
|
1926
|
-
import { Box as
|
|
1927
|
-
import { jsx as
|
|
2007
|
+
import { useEffect as useEffect3, useReducer as useReducer2, useState as useState3 } from "react";
|
|
2008
|
+
import { Box as Box7, Text as Text7, useApp as useApp2, useStdin as useStdin2 } from "ink";
|
|
2009
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1928
2010
|
var truncate = (str, max) => str.length > max ? str.slice(0, max - 3) + "..." : str;
|
|
1929
2011
|
function buildInitial(description) {
|
|
1930
2012
|
return {
|
|
@@ -2000,7 +2082,7 @@ function StageProgress({ stage, totalStages, stageNames, tick, isActive, status
|
|
|
2000
2082
|
}
|
|
2001
2083
|
return { icon, color, name, bold, dim };
|
|
2002
2084
|
});
|
|
2003
|
-
return /* @__PURE__ */
|
|
2085
|
+
return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", marginBottom: 1, children: rows.map(({ icon, color, name, bold, dim }, i) => /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs6(Text7, { color, dimColor: dim, bold, children: [
|
|
2004
2086
|
" ",
|
|
2005
2087
|
icon,
|
|
2006
2088
|
name ? ` ${name}` : ""
|
|
@@ -2025,7 +2107,7 @@ function PlanApp({ description, events: events2 }) {
|
|
|
2025
2107
|
};
|
|
2026
2108
|
}, [events2, exit]);
|
|
2027
2109
|
const { isRawModeSupported } = useStdin2();
|
|
2028
|
-
const [tick, setTick] =
|
|
2110
|
+
const [tick, setTick] = useState3(0);
|
|
2029
2111
|
const isActive = state.status === "running" || state.status === "retrying";
|
|
2030
2112
|
useInterval(() => {
|
|
2031
2113
|
if (isActive) setTick((t) => t + 1);
|
|
@@ -2033,19 +2115,19 @@ function PlanApp({ description, events: events2 }) {
|
|
|
2033
2115
|
const elapsed = formatHeaderElapsed(state.startTime);
|
|
2034
2116
|
const icon = isActive ? SPINNER[tick % SPINNER.length] : state.status === "complete" ? "\u2713" : "\u2717";
|
|
2035
2117
|
const iconColor = state.status === "complete" ? theme.success : state.status === "error" ? theme.error : theme.primary;
|
|
2036
|
-
return /* @__PURE__ */
|
|
2037
|
-
/* @__PURE__ */
|
|
2038
|
-
/* @__PURE__ */
|
|
2039
|
-
/* @__PURE__ */
|
|
2118
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", padding: 1, children: [
|
|
2119
|
+
/* @__PURE__ */ jsx7(Box7, { marginBottom: 1, children: /* @__PURE__ */ jsx7(BrandMark, { tick, isActive }) }),
|
|
2120
|
+
/* @__PURE__ */ jsxs6(Box7, { marginBottom: 1, children: [
|
|
2121
|
+
/* @__PURE__ */ jsxs6(Text7, { color: iconColor, children: [
|
|
2040
2122
|
icon,
|
|
2041
2123
|
" "
|
|
2042
2124
|
] }),
|
|
2043
|
-
/* @__PURE__ */
|
|
2044
|
-
/* @__PURE__ */
|
|
2125
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.primary, children: "Generating plan" }),
|
|
2126
|
+
/* @__PURE__ */ jsxs6(Text7, { dimColor: true, children: [
|
|
2045
2127
|
" ",
|
|
2046
2128
|
elapsed
|
|
2047
2129
|
] }),
|
|
2048
|
-
state.status === "retrying" && /* @__PURE__ */
|
|
2130
|
+
state.status === "retrying" && /* @__PURE__ */ jsxs6(Text7, { color: theme.warning, children: [
|
|
2049
2131
|
" ",
|
|
2050
2132
|
"(attempt ",
|
|
2051
2133
|
state.attempt,
|
|
@@ -2054,11 +2136,11 @@ function PlanApp({ description, events: events2 }) {
|
|
|
2054
2136
|
")"
|
|
2055
2137
|
] })
|
|
2056
2138
|
] }),
|
|
2057
|
-
/* @__PURE__ */
|
|
2058
|
-
/* @__PURE__ */
|
|
2059
|
-
/* @__PURE__ */
|
|
2139
|
+
/* @__PURE__ */ jsxs6(Box7, { marginBottom: 1, children: [
|
|
2140
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " }),
|
|
2141
|
+
/* @__PURE__ */ jsx7(Text7, { children: truncate(state.description, 80) })
|
|
2060
2142
|
] }),
|
|
2061
|
-
/* @__PURE__ */
|
|
2143
|
+
/* @__PURE__ */ jsx7(
|
|
2062
2144
|
StageProgress,
|
|
2063
2145
|
{
|
|
2064
2146
|
stage: state.stage,
|
|
@@ -2069,23 +2151,23 @@ function PlanApp({ description, events: events2 }) {
|
|
|
2069
2151
|
status: state.status
|
|
2070
2152
|
}
|
|
2071
2153
|
),
|
|
2072
|
-
state.lines.length > 0 && /* @__PURE__ */
|
|
2073
|
-
state.status === "complete" && state.taskFile && /* @__PURE__ */
|
|
2074
|
-
/* @__PURE__ */
|
|
2154
|
+
state.lines.length > 0 && /* @__PURE__ */ jsx7(LogPane, { lines: state.lines, isActive, maxLines: 10 }),
|
|
2155
|
+
state.status === "complete" && state.taskFile && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
2156
|
+
/* @__PURE__ */ jsxs6(Text7, { color: theme.success, children: [
|
|
2075
2157
|
"\u2705 Task plan saved: ",
|
|
2076
2158
|
state.taskFile
|
|
2077
2159
|
] }),
|
|
2078
|
-
state.preview && /* @__PURE__ */
|
|
2079
|
-
/* @__PURE__ */
|
|
2080
|
-
/* @__PURE__ */
|
|
2160
|
+
state.preview && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
2161
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Preview:" }),
|
|
2162
|
+
/* @__PURE__ */ jsx7(Text7, { children: state.preview })
|
|
2081
2163
|
] })
|
|
2082
2164
|
] }),
|
|
2083
|
-
state.status === "error" && /* @__PURE__ */
|
|
2165
|
+
state.status === "error" && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsxs6(Text7, { color: theme.error, children: [
|
|
2084
2166
|
"Error: ",
|
|
2085
2167
|
state.errorMessage
|
|
2086
2168
|
] }) }),
|
|
2087
|
-
isActive && /* @__PURE__ */
|
|
2088
|
-
isRawModeSupported && /* @__PURE__ */
|
|
2169
|
+
isActive && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "press q to quit" }) }),
|
|
2170
|
+
isRawModeSupported && /* @__PURE__ */ jsx7(KeyboardHandler, { onExit: exit })
|
|
2089
2171
|
] });
|
|
2090
2172
|
}
|
|
2091
2173
|
|
|
@@ -2586,6 +2668,33 @@ function extractJson(text) {
|
|
|
2586
2668
|
return text.slice(start, end + 1);
|
|
2587
2669
|
}
|
|
2588
2670
|
|
|
2671
|
+
// src/types.ts
|
|
2672
|
+
var InterjectChannel = class {
|
|
2673
|
+
sender = null;
|
|
2674
|
+
_queue = [];
|
|
2675
|
+
/** Called by runClaude when a Claude step starts to activate direct delivery. */
|
|
2676
|
+
register(sender) {
|
|
2677
|
+
this.sender = sender;
|
|
2678
|
+
for (const msg of this._queue) sender(msg);
|
|
2679
|
+
this._queue = [];
|
|
2680
|
+
}
|
|
2681
|
+
/** Called by runClaude when a Claude step ends. */
|
|
2682
|
+
unregister() {
|
|
2683
|
+
this.sender = null;
|
|
2684
|
+
}
|
|
2685
|
+
/** Called by the TUI. Delivers immediately if a Claude step is running, else queues. */
|
|
2686
|
+
interject(message) {
|
|
2687
|
+
if (this.sender) this.sender(message);
|
|
2688
|
+
else this._queue.push(message);
|
|
2689
|
+
}
|
|
2690
|
+
/** Drains and returns any queued messages (for non-Claude steps to consume). */
|
|
2691
|
+
consumeQueue() {
|
|
2692
|
+
const q = this._queue.slice();
|
|
2693
|
+
this._queue = [];
|
|
2694
|
+
return q;
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
|
|
2589
2698
|
// src/index.ts
|
|
2590
2699
|
var CURRENT_VERSION = JSON.parse(
|
|
2591
2700
|
readFileSync6(
|
|
@@ -2740,7 +2849,8 @@ try {
|
|
|
2740
2849
|
process.exit(1);
|
|
2741
2850
|
}
|
|
2742
2851
|
var options = { stepFilter, fromStep };
|
|
2743
|
-
var
|
|
2852
|
+
var channel = new InterjectChannel();
|
|
2853
|
+
var rawEvents = runWorkflow(workflow, options, channel);
|
|
2744
2854
|
var logger = createLogger(resolveLogDir(filePath), workflow.goal);
|
|
2745
2855
|
var events = withLogger(rawEvents, logger);
|
|
2746
2856
|
var updateCheck = checkForUpdate(CURRENT_VERSION);
|
|
@@ -2780,7 +2890,13 @@ if (ciMode) {
|
|
|
2780
2890
|
});
|
|
2781
2891
|
} else {
|
|
2782
2892
|
const inkApp = render(
|
|
2783
|
-
React3.createElement(App, {
|
|
2893
|
+
React3.createElement(App, {
|
|
2894
|
+
workflow,
|
|
2895
|
+
events,
|
|
2896
|
+
options,
|
|
2897
|
+
updateCheck,
|
|
2898
|
+
interjectChannel: channel
|
|
2899
|
+
})
|
|
2784
2900
|
);
|
|
2785
2901
|
if (workflow.selfImprove) {
|
|
2786
2902
|
inkApp.waitUntilExit().then(() => maybeRunRetrospective(filePath, workflow, logger)).catch(() => {
|