executant 1.8.0 → 1.9.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 (2) hide show
  1. package/dist/index.js +215 -111
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -863,7 +863,7 @@ init_update();
863
863
 
864
864
  // src/ui/App.tsx
865
865
  import { useEffect as useEffect2, useReducer, useState } from "react";
866
- import { Box as Box4, Text as Text4, useApp, useStdin } from "ink";
866
+ import { Box as Box5, Text as Text5, useApp, useStdin } from "ink";
867
867
 
868
868
  // src/ui/KeyboardHandler.tsx
869
869
  import { useInput } from "ink";
@@ -931,45 +931,70 @@ function reducer(state, event) {
931
931
  status: "running",
932
932
  startTime: Date.now()
933
933
  });
934
- case "step:complete":
934
+ case "step:complete": {
935
+ const prev = state.tasks[event.index]?.iterationHistory;
936
+ const iterationHistory = prev?.length ? prev.map(
937
+ (r) => r.status === "running" ? { ...r, status: "complete", endTime: Date.now() } : r
938
+ ) : void 0;
935
939
  return {
936
940
  ...updateTask(state, event.index, {
937
941
  status: "complete",
938
- endTime: Date.now()
942
+ endTime: Date.now(),
943
+ ...iterationHistory ? { iterationHistory } : {}
939
944
  }),
940
945
  currentIndex: event.index + 1
941
946
  };
942
- case "step:error":
947
+ }
948
+ case "step:error": {
949
+ const prev = state.tasks[event.index]?.iterationHistory;
950
+ const iterationHistory = prev?.length ? prev.map(
951
+ (r) => r.status === "running" ? { ...r, status: "error", endTime: Date.now() } : r
952
+ ) : void 0;
943
953
  return {
944
954
  ...updateTask(state, event.index, {
945
955
  status: "error",
946
956
  endTime: Date.now(),
947
- error: event.error
957
+ error: event.error,
958
+ ...iterationHistory ? { iterationHistory } : {}
948
959
  }),
949
960
  currentIndex: event.index + 1
950
961
  };
962
+ }
951
963
  case "step:skip":
952
964
  return {
953
965
  ...updateTask(state, event.index, { status: "skipped" }),
954
966
  currentIndex: event.index + 1
955
967
  };
956
- case "step:iteration":
957
- return updateTask(state, event.index, {
958
- iteration: {
959
- current: event.iteration,
960
- total: event.total,
961
- item: event.item
962
- },
963
- inner: void 0
964
- });
965
- case "step:inner":
968
+ case "step:iteration": {
969
+ const prev = (state.tasks[event.index]?.iterationHistory ?? []).map(
970
+ (r) => r.status === "running" ? { ...r, status: "complete", endTime: Date.now() } : r
971
+ );
966
972
  return updateTask(state, event.index, {
967
- inner: {
968
- index: event.innerIndex,
969
- total: event.innerTotal,
970
- name: event.name
971
- }
973
+ iterationHistory: [
974
+ ...prev,
975
+ {
976
+ item: event.item,
977
+ iteration: event.iteration,
978
+ total: event.total,
979
+ status: "running",
980
+ startTime: Date.now()
981
+ }
982
+ ]
972
983
  });
984
+ }
985
+ case "step:inner": {
986
+ const iterationHistory = (state.tasks[event.index]?.iterationHistory ?? []).map(
987
+ (r) => r.status === "running" ? {
988
+ ...r,
989
+ inner: {
990
+ index: event.innerIndex,
991
+ total: event.innerTotal,
992
+ name: event.name
993
+ }
994
+ } : r
995
+ );
996
+ return updateTask(state, event.index, { iterationHistory });
997
+ }
973
998
  case "output:text": {
974
999
  const idx = event.index;
975
1000
  if (idx >= state.tasks.length) return state;
@@ -1024,20 +1049,6 @@ function appendLine(state, index, line) {
1024
1049
  // src/ui/TaskRow.tsx
1025
1050
  import { Box, Text } from "ink";
1026
1051
 
1027
- // src/ui/utils.ts
1028
- var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1029
- var EXIT_DELAY_MS = 300;
1030
- function formatHeaderElapsed(start, end) {
1031
- const ms = (end ?? Date.now()) - start;
1032
- return ms < 1e3 ? `${ms}ms` : `${(ms / 1e3).toFixed(1)}s`;
1033
- }
1034
- function formatTaskElapsed(start, end, status) {
1035
- if (!start) return "";
1036
- const ms = (end ?? Date.now()) - start;
1037
- if (status === "running" || status === "complete" || status === "error") return `${(ms / 1e3).toFixed(1)}s`;
1038
- return "";
1039
- }
1040
-
1041
1052
  // src/ui/theme.ts
1042
1053
  import { createRequire } from "node:module";
1043
1054
  import { oklchToHex } from "@coston/design-tokens";
@@ -1066,6 +1077,32 @@ var theme = {
1066
1077
  // log pane border
1067
1078
  };
1068
1079
 
1080
+ // src/ui/utils.ts
1081
+ var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1082
+ var STATUS_ICON = {
1083
+ complete: "\u2713",
1084
+ error: "\u2717",
1085
+ skipped: "\u2298",
1086
+ pending: "\xB7"
1087
+ };
1088
+ var STATUS_COLOR = {
1089
+ complete: theme.success,
1090
+ error: theme.error,
1091
+ pending: theme.muted
1092
+ };
1093
+ var EXIT_DELAY_MS = 300;
1094
+ function formatHeaderElapsed(start, end) {
1095
+ const ms = (end ?? Date.now()) - start;
1096
+ return ms < 1e3 ? `${ms}ms` : `${(ms / 1e3).toFixed(1)}s`;
1097
+ }
1098
+ function formatTaskElapsed(start, end, status) {
1099
+ if (!start) return "";
1100
+ const ms = (end ?? Date.now()) - start;
1101
+ if (status === "running" || status === "complete" || status === "error")
1102
+ return `${(ms / 1e3).toFixed(1)}s`;
1103
+ return "";
1104
+ }
1105
+
1069
1106
  // src/ui/TaskRow.tsx
1070
1107
  import { jsx, jsxs } from "react/jsx-runtime";
1071
1108
  function TaskRow({ taskState, isActive, index, tick }) {
@@ -1073,9 +1110,8 @@ function TaskRow({ taskState, isActive, index, tick }) {
1073
1110
  const icon = statusIcon(status, tick);
1074
1111
  const color = statusColor(status, isActive);
1075
1112
  const elapsed = formatTaskElapsed(startTime, endTime, status);
1076
- const iterInfo = taskState.iteration ? ` (${taskState.iteration.current}/${taskState.iteration.total}) ${taskState.iteration.item}` : "";
1077
- const innerInfo = taskState.inner ? ` \u2014 ${taskState.inner.name} [${taskState.inner.index + 1}/${taskState.inner.total}]` : "";
1078
- const label = `${index + 1}. ${task.name}${iterInfo}${innerInfo}`;
1113
+ const iterInfo = formatIterCount(taskState.iterationHistory);
1114
+ const label = `${index + 1}. ${task.name}${iterInfo}`;
1079
1115
  return /* @__PURE__ */ jsxs(Box, { children: [
1080
1116
  /* @__PURE__ */ jsxs(Text, { color, children: [
1081
1117
  icon,
@@ -1088,17 +1124,6 @@ function TaskRow({ taskState, isActive, index, tick }) {
1088
1124
  ] })
1089
1125
  ] });
1090
1126
  }
1091
- var STATUS_ICON = {
1092
- complete: "\u2713",
1093
- error: "\u2717",
1094
- skipped: "\u2298",
1095
- pending: "\xB7"
1096
- };
1097
- var STATUS_COLOR = {
1098
- complete: theme.success,
1099
- error: theme.error,
1100
- pending: theme.muted
1101
- };
1102
1127
  function statusIcon(status, tick) {
1103
1128
  return status === "running" ? SPINNER[tick % SPINNER.length] : STATUS_ICON[status] ?? "\xB7";
1104
1129
  }
@@ -1106,16 +1131,74 @@ function statusColor(status, isActive) {
1106
1131
  if (isActive && status === "running") return theme.primary;
1107
1132
  return STATUS_COLOR[status] ?? theme.foreground;
1108
1133
  }
1134
+ function formatIterCount(history) {
1135
+ if (!history?.length) return "";
1136
+ const total = history[0].total;
1137
+ const running = history.find((r) => r.status === "running");
1138
+ const current = running?.iteration ?? history.length;
1139
+ return ` (${current}/${total})`;
1140
+ }
1109
1141
 
1110
- // src/ui/LogPane.tsx
1142
+ // src/ui/IterationRow.tsx
1111
1143
  import { Box as Box2, Text as Text2 } from "ink";
1112
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1144
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1145
+ function IterationRow({ record, tick }) {
1146
+ const icon = record.status === "running" ? SPINNER[tick % SPINNER.length] : STATUS_ICON[record.status] ?? "\xB7";
1147
+ const color = STATUS_COLOR[record.status] ?? theme.primary;
1148
+ const innerText = record.inner ? ` \u2014 ${stripItem(record.inner.name, record.item)} [${record.inner.index + 1}/${record.inner.total}]` : "";
1149
+ const ms = (record.endTime ?? Date.now()) - record.startTime;
1150
+ const elapsed = `${(ms / 1e3).toFixed(1)}s`;
1151
+ return /* @__PURE__ */ jsxs2(Box2, { children: [
1152
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " " }),
1153
+ /* @__PURE__ */ jsx2(Text2, { color, children: icon }),
1154
+ /* @__PURE__ */ jsx2(Text2, { children: " " }),
1155
+ /* @__PURE__ */ jsxs2(
1156
+ Text2,
1157
+ {
1158
+ color: record.status === "running" ? theme.foreground : theme.muted,
1159
+ children: [
1160
+ record.item,
1161
+ innerText
1162
+ ]
1163
+ }
1164
+ ),
1165
+ /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
1166
+ " ",
1167
+ elapsed
1168
+ ] })
1169
+ ] });
1170
+ }
1171
+ function stripItem(name, item) {
1172
+ if (!name.includes(item)) return name;
1173
+ const stripped = name.replace(item, "").replace(/\s{2,}/g, " ").replace(/^[\s\-—–]+/, "").replace(/[\s\-—–]+$/, "").trim();
1174
+ return stripped || name;
1175
+ }
1176
+ function isRepeatStyle(history) {
1177
+ return history.every((r) => r.item === String(r.iteration));
1178
+ }
1179
+ function IterationList({
1180
+ iterationHistory,
1181
+ tick,
1182
+ maxVisible
1183
+ }) {
1184
+ if (isRepeatStyle(iterationHistory)) return null;
1185
+ const hidden = iterationHistory.length - maxVisible;
1186
+ const visible = iterationHistory.slice(-maxVisible);
1187
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
1188
+ hidden > 0 && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: ` \u2026 ${hidden} earlier` }),
1189
+ visible.map((record) => /* @__PURE__ */ jsx2(IterationRow, { record, tick }, record.iteration))
1190
+ ] });
1191
+ }
1192
+
1193
+ // src/ui/LogPane.tsx
1194
+ import { Box as Box3, Text as Text3 } from "ink";
1195
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1113
1196
  function LogPane({ lines, isActive = false, maxLines = 15 }) {
1114
1197
  const visible = lines.slice(-maxLines);
1115
1198
  if (visible.length === 0) {
1116
- return /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: isActive ? "\u2838 waiting for output\u2026" : "\u2014 no output yet \u2014" }) });
1199
+ return /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: isActive ? "\u2838 waiting for output\u2026" : "\u2014 no output yet \u2014" }) });
1117
1200
  }
1118
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginTop: 1, borderStyle: "single", borderColor: theme.border, paddingX: 1, children: visible.map((line, i) => /* @__PURE__ */ jsx2(
1201
+ return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", marginTop: 1, borderStyle: "single", borderColor: theme.border, paddingX: 1, children: visible.map((line, i) => /* @__PURE__ */ jsx3(
1119
1202
  LogLine,
1120
1203
  {
1121
1204
  text: line,
@@ -1125,29 +1208,29 @@ function LogPane({ lines, isActive = false, maxLines = 15 }) {
1125
1208
  )) });
1126
1209
  }
1127
1210
  function LogLine({ text, cursor }) {
1128
- const suffix = cursor ? /* @__PURE__ */ jsx2(Text2, { color: theme.primary, children: " \u258C" }) : null;
1211
+ const suffix = cursor ? /* @__PURE__ */ jsx3(Text3, { color: theme.primary, children: " \u258C" }) : null;
1129
1212
  if (/^\[[\w:]+\]/.test(text)) {
1130
1213
  const bracket = text.match(/^\[[\w:]+\]/)?.[0] ?? "";
1131
1214
  const rest = text.slice(bracket.length);
1132
- return /* @__PURE__ */ jsxs2(Text2, { children: [
1133
- /* @__PURE__ */ jsx2(Text2, { color: theme.primary, children: bracket }),
1134
- /* @__PURE__ */ jsx2(Text2, { children: rest }),
1215
+ return /* @__PURE__ */ jsxs3(Text3, { children: [
1216
+ /* @__PURE__ */ jsx3(Text3, { color: theme.primary, children: bracket }),
1217
+ /* @__PURE__ */ jsx3(Text3, { children: rest }),
1135
1218
  suffix
1136
1219
  ] });
1137
1220
  }
1138
- if (/^\s*\$\s/.test(text)) return /* @__PURE__ */ jsxs2(Text2, { color: theme.warning, children: [
1221
+ if (/^\s*\$\s/.test(text)) return /* @__PURE__ */ jsxs3(Text3, { color: theme.warning, children: [
1139
1222
  text,
1140
1223
  suffix
1141
1224
  ] });
1142
- if (text.startsWith("[warn]")) return /* @__PURE__ */ jsxs2(Text2, { color: theme.warning, children: [
1225
+ if (text.startsWith("[warn]")) return /* @__PURE__ */ jsxs3(Text3, { color: theme.warning, children: [
1143
1226
  text,
1144
1227
  suffix
1145
1228
  ] });
1146
- if (text.startsWith("[error]")) return /* @__PURE__ */ jsxs2(Text2, { color: theme.error, children: [
1229
+ if (text.startsWith("[error]")) return /* @__PURE__ */ jsxs3(Text3, { color: theme.error, children: [
1147
1230
  text,
1148
1231
  suffix
1149
1232
  ] });
1150
- return /* @__PURE__ */ jsxs2(Text2, { children: [
1233
+ return /* @__PURE__ */ jsxs3(Text3, { children: [
1151
1234
  text,
1152
1235
  suffix
1153
1236
  ] });
@@ -1167,8 +1250,8 @@ function useInterval(callback, delayMs) {
1167
1250
  }
1168
1251
 
1169
1252
  // src/ui/BrandMark.tsx
1170
- import { Box as Box3, Text as Text3 } from "ink";
1171
- import { jsx as jsx3 } from "react/jsx-runtime";
1253
+ import { Box as Box4, Text as Text4 } from "ink";
1254
+ import { jsx as jsx4 } from "react/jsx-runtime";
1172
1255
  var BRAND = "Executant";
1173
1256
  var SWEEP_TICKS = BRAND.length * 2;
1174
1257
  var GAP_TICKS = 30;
@@ -1181,11 +1264,12 @@ function charColor(charIndex, tick, isActive) {
1181
1264
  return charIndex === charPos ? theme.primaryLight : theme.primary;
1182
1265
  }
1183
1266
  function BrandMark({ tick, isActive }) {
1184
- return /* @__PURE__ */ jsx3(Box3, { children: [...BRAND].map((char, i) => /* @__PURE__ */ jsx3(Text3, { color: charColor(i, tick, isActive), bold: true, children: char }, i)) });
1267
+ return /* @__PURE__ */ jsx4(Box4, { children: [...BRAND].map((char, i) => /* @__PURE__ */ jsx4(Text4, { color: charColor(i, tick, isActive), bold: true, children: char }, i)) });
1185
1268
  }
1186
1269
 
1187
1270
  // src/ui/App.tsx
1188
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1271
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1272
+ var MAX_VISIBLE_ITERATIONS = 8;
1189
1273
  function App({ workflow: workflow2, events: events2, options: options2, updateCheck: updateCheck2 }) {
1190
1274
  const { exit } = useApp();
1191
1275
  const [state, dispatch] = useReducer(reducer, buildInitialState(workflow2));
@@ -1203,7 +1287,10 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
1203
1287
  } catch (err) {
1204
1288
  if (!active) return;
1205
1289
  dispatch({ type: "log", level: "error", text: getErrorMessage(err) });
1206
- setTimeout(() => exit(err instanceof Error ? err : new Error(getErrorMessage(err))), EXIT_DELAY_MS);
1290
+ setTimeout(
1291
+ () => exit(err instanceof Error ? err : new Error(getErrorMessage(err))),
1292
+ EXIT_DELAY_MS
1293
+ );
1207
1294
  }
1208
1295
  })();
1209
1296
  return () => {
@@ -1223,14 +1310,16 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
1223
1310
  }, [updateCheck2]);
1224
1311
  const elapsed = formatHeaderElapsed(state.startTime, state.endTime);
1225
1312
  const activeTask = state.tasks[state.currentIndex];
1226
- const completedCount = state.tasks.filter((t) => t.status === "complete").length;
1313
+ const completedCount = state.tasks.filter(
1314
+ (t) => t.status === "complete"
1315
+ ).length;
1227
1316
  const totalCount = state.tasks.length;
1228
1317
  const filterInfo = options2?.stepFilter ? ` [step: ${options2.stepFilter}]` : options2?.fromStep ? ` [from step: ${options2.fromStep}]` : "";
1229
- return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, children: [
1230
- /* @__PURE__ */ jsx4(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx4(BrandMark, { tick, isActive: !state.endTime }) }),
1231
- /* @__PURE__ */ jsxs3(Box4, { marginBottom: 1, children: [
1232
- /* @__PURE__ */ jsx4(Text4, { bold: true, color: theme.primary, children: workflow2.goal }),
1233
- /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
1318
+ return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", padding: 1, children: [
1319
+ /* @__PURE__ */ jsx5(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx5(BrandMark, { tick, isActive: !state.endTime }) }),
1320
+ /* @__PURE__ */ jsxs4(Box5, { marginBottom: 1, children: [
1321
+ /* @__PURE__ */ jsx5(Text5, { bold: true, color: theme.primary, children: workflow2.goal }),
1322
+ /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
1234
1323
  " ",
1235
1324
  completedCount,
1236
1325
  "/",
@@ -1240,33 +1329,48 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
1240
1329
  filterInfo
1241
1330
  ] })
1242
1331
  ] }),
1243
- /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginBottom: 1, children: state.tasks.map((taskState, i) => /* @__PURE__ */ jsx4(
1244
- TaskRow,
1332
+ /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginBottom: 1, children: state.tasks.map((taskState, i) => /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
1333
+ /* @__PURE__ */ jsx5(
1334
+ TaskRow,
1335
+ {
1336
+ index: i,
1337
+ tick,
1338
+ taskState,
1339
+ isActive: i === state.currentIndex
1340
+ }
1341
+ ),
1342
+ taskState.status === "running" && taskState.iterationHistory?.length ? /* @__PURE__ */ jsx5(
1343
+ IterationList,
1344
+ {
1345
+ iterationHistory: taskState.iterationHistory,
1346
+ tick,
1347
+ maxVisible: MAX_VISIBLE_ITERATIONS
1348
+ }
1349
+ ) : null
1350
+ ] }, taskState.task.name)) }),
1351
+ activeTask && /* @__PURE__ */ jsx5(
1352
+ LogPane,
1245
1353
  {
1246
- index: i,
1247
- tick,
1248
- taskState,
1249
- isActive: i === state.currentIndex
1250
- },
1251
- taskState.task.name
1252
- )) }),
1253
- activeTask && /* @__PURE__ */ jsx4(LogPane, { lines: activeTask.lines, isActive: activeTask.status === "running" }),
1254
- state.endTime !== void 0 && state.writtenFiles.length > 0 && /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", marginTop: 1, children: [
1255
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "files written:" }),
1256
- state.writtenFiles.map((f) => /* @__PURE__ */ jsxs3(Text4, { color: theme.primary, children: [
1354
+ lines: activeTask.lines,
1355
+ isActive: activeTask.status === "running"
1356
+ }
1357
+ ),
1358
+ state.endTime !== void 0 && state.writtenFiles.length > 0 && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
1359
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "files written:" }),
1360
+ state.writtenFiles.map((f) => /* @__PURE__ */ jsxs4(Text5, { color: theme.primary, children: [
1257
1361
  " ",
1258
1362
  f
1259
1363
  ] }, f))
1260
1364
  ] }),
1261
- /* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
1262
- updateVersion && /* @__PURE__ */ jsxs3(Text4, { color: theme.warning, children: [
1365
+ /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, flexDirection: "column", children: [
1366
+ updateVersion && /* @__PURE__ */ jsxs4(Text5, { color: theme.warning, children: [
1263
1367
  "v",
1264
1368
  updateVersion,
1265
1369
  " available \u2014 run: executant update"
1266
1370
  ] }),
1267
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "press q to quit" })
1371
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "press q to quit" })
1268
1372
  ] }),
1269
- isRawModeSupported && /* @__PURE__ */ jsx4(KeyboardHandler, { onExit: exit })
1373
+ isRawModeSupported && /* @__PURE__ */ jsx5(KeyboardHandler, { onExit: exit })
1270
1374
  ] });
1271
1375
  }
1272
1376
 
@@ -1672,8 +1776,8 @@ ${issues}`
1672
1776
 
1673
1777
  // src/ui/PlanApp.tsx
1674
1778
  import { useEffect as useEffect3, useReducer as useReducer2, useState as useState2 } from "react";
1675
- import { Box as Box5, Text as Text5, useApp as useApp2, useStdin as useStdin2 } from "ink";
1676
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1779
+ import { Box as Box6, Text as Text6, useApp as useApp2, useStdin as useStdin2 } from "ink";
1780
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1677
1781
  var truncate = (str, max) => str.length > max ? str.slice(0, max - 3) + "..." : str;
1678
1782
  function buildInitial(description) {
1679
1783
  return {
@@ -1749,7 +1853,7 @@ function StageProgress({ stage, totalStages, stageNames, tick, isActive, status
1749
1853
  }
1750
1854
  return { icon, color, name, bold, dim };
1751
1855
  });
1752
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginBottom: 1, children: rows.map(({ icon, color, name, bold, dim }, i) => /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsxs4(Text5, { color, dimColor: dim, bold, children: [
1856
+ return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginBottom: 1, children: rows.map(({ icon, color, name, bold, dim }, i) => /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsxs5(Text6, { color, dimColor: dim, bold, children: [
1753
1857
  " ",
1754
1858
  icon,
1755
1859
  name ? ` ${name}` : ""
@@ -1782,19 +1886,19 @@ function PlanApp({ description, events: events2 }) {
1782
1886
  const elapsed = formatHeaderElapsed(state.startTime);
1783
1887
  const icon = isActive ? SPINNER[tick % SPINNER.length] : state.status === "complete" ? "\u2713" : "\u2717";
1784
1888
  const iconColor = state.status === "complete" ? theme.success : state.status === "error" ? theme.error : theme.primary;
1785
- return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", padding: 1, children: [
1786
- /* @__PURE__ */ jsx5(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx5(BrandMark, { tick, isActive }) }),
1787
- /* @__PURE__ */ jsxs4(Box5, { marginBottom: 1, children: [
1788
- /* @__PURE__ */ jsxs4(Text5, { color: iconColor, children: [
1889
+ return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", padding: 1, children: [
1890
+ /* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(BrandMark, { tick, isActive }) }),
1891
+ /* @__PURE__ */ jsxs5(Box6, { marginBottom: 1, children: [
1892
+ /* @__PURE__ */ jsxs5(Text6, { color: iconColor, children: [
1789
1893
  icon,
1790
1894
  " "
1791
1895
  ] }),
1792
- /* @__PURE__ */ jsx5(Text5, { bold: true, color: theme.primary, children: "Generating plan" }),
1793
- /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
1896
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.primary, children: "Generating plan" }),
1897
+ /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
1794
1898
  " ",
1795
1899
  elapsed
1796
1900
  ] }),
1797
- state.status === "retrying" && /* @__PURE__ */ jsxs4(Text5, { color: theme.warning, children: [
1901
+ state.status === "retrying" && /* @__PURE__ */ jsxs5(Text6, { color: theme.warning, children: [
1798
1902
  " ",
1799
1903
  "(attempt ",
1800
1904
  state.attempt,
@@ -1803,11 +1907,11 @@ function PlanApp({ description, events: events2 }) {
1803
1907
  ")"
1804
1908
  ] })
1805
1909
  ] }),
1806
- /* @__PURE__ */ jsxs4(Box5, { marginBottom: 1, children: [
1807
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " " }),
1808
- /* @__PURE__ */ jsx5(Text5, { children: truncate(state.description, 80) })
1910
+ /* @__PURE__ */ jsxs5(Box6, { marginBottom: 1, children: [
1911
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " " }),
1912
+ /* @__PURE__ */ jsx6(Text6, { children: truncate(state.description, 80) })
1809
1913
  ] }),
1810
- /* @__PURE__ */ jsx5(
1914
+ /* @__PURE__ */ jsx6(
1811
1915
  StageProgress,
1812
1916
  {
1813
1917
  stage: state.stage,
@@ -1818,23 +1922,23 @@ function PlanApp({ description, events: events2 }) {
1818
1922
  status: state.status
1819
1923
  }
1820
1924
  ),
1821
- state.lines.length > 0 && /* @__PURE__ */ jsx5(LogPane, { lines: state.lines, isActive, maxLines: 10 }),
1822
- state.status === "complete" && state.taskFile && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
1823
- /* @__PURE__ */ jsxs4(Text5, { color: theme.success, children: [
1925
+ state.lines.length > 0 && /* @__PURE__ */ jsx6(LogPane, { lines: state.lines, isActive, maxLines: 10 }),
1926
+ state.status === "complete" && state.taskFile && /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", marginTop: 1, children: [
1927
+ /* @__PURE__ */ jsxs5(Text6, { color: theme.success, children: [
1824
1928
  "\u2705 Task plan saved: ",
1825
1929
  state.taskFile
1826
1930
  ] }),
1827
- state.preview && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
1828
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Preview:" }),
1829
- /* @__PURE__ */ jsx5(Text5, { children: state.preview })
1931
+ state.preview && /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", marginTop: 1, children: [
1932
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Preview:" }),
1933
+ /* @__PURE__ */ jsx6(Text6, { children: state.preview })
1830
1934
  ] })
1831
1935
  ] }),
1832
- state.status === "error" && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text5, { color: theme.error, children: [
1936
+ state.status === "error" && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsxs5(Text6, { color: theme.error, children: [
1833
1937
  "Error: ",
1834
1938
  state.errorMessage
1835
1939
  ] }) }),
1836
- isActive && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "press q to quit" }) }),
1837
- isRawModeSupported && /* @__PURE__ */ jsx5(KeyboardHandler, { onExit: exit })
1940
+ isActive && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "press q to quit" }) }),
1941
+ isRawModeSupported && /* @__PURE__ */ jsx6(KeyboardHandler, { onExit: exit })
1838
1942
  ] });
1839
1943
  }
1840
1944
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "executant",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Harness for YAML-defined workflows that enables stepping through Claude sessions and bash commands",
5
5
  "repository": {
6
6
  "type": "git",