cueclaw 0.2.1 → 0.2.2

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.
@@ -268,8 +268,12 @@ var KeyPriority = {
268
268
  var KeypressContext = createContext(null);
269
269
  function KeypressProvider({ children }) {
270
270
  const handlersRef = useRef([]);
271
+ const sortHandlers = () => {
272
+ handlersRef.current.sort((a, b) => b.priority - a.priority);
273
+ };
271
274
  const register = useCallback((entry) => {
272
275
  handlersRef.current = [...handlersRef.current.filter((h) => h.id !== entry.id), entry];
276
+ sortHandlers();
273
277
  }, []);
274
278
  const unregister = useCallback((id) => {
275
279
  handlersRef.current = handlersRef.current.filter((h) => h.id !== id);
@@ -280,8 +284,8 @@ function KeypressProvider({ children }) {
280
284
  );
281
285
  }, []);
282
286
  useInput((input, key) => {
283
- const sorted = [...handlersRef.current].filter((h) => h.isActive).sort((a, b) => b.priority - a.priority);
284
- for (const entry of sorted) {
287
+ for (const entry of handlersRef.current) {
288
+ if (!entry.isActive) continue;
285
289
  const consumed = entry.handler(input, key);
286
290
  if (consumed === true) break;
287
291
  }
@@ -369,7 +373,7 @@ function DialogManager({ children }) {
369
373
  }
370
374
 
371
375
  // src/tui/app-provider.tsx
372
- import { useReducer, useCallback as useCallback7, useMemo as useMemo2, useState as useState4, useEffect as useEffect3 } from "react";
376
+ import { useReducer, useCallback as useCallback7, useMemo, useState as useState4, useEffect as useEffect3, useRef as useRef6 } from "react";
373
377
  import { useApp } from "ink";
374
378
 
375
379
  // src/tui/ui-state-context.ts
@@ -806,6 +810,8 @@ function useWorkflowExecution(workflow, db, cwd, bridgeRef, plannerSessionRef, d
806
810
  upsertWorkflow(db, confirmed);
807
811
  } catch (err) {
808
812
  logger.error({ err }, "Failed to persist workflow");
813
+ dispatch({ type: "ADD_MESSAGE", message: { type: "error", text: `Failed to save workflow: ${err instanceof Error ? err.message : String(err)}` } });
814
+ return;
809
815
  }
810
816
  const controller = new AbortController();
811
817
  abortRef.current = controller;
@@ -1131,7 +1137,7 @@ function useGlobalKeypress({
1131
1137
  }
1132
1138
 
1133
1139
  // src/tui/hooks/use-command-dispatch.ts
1134
- import React4, { useCallback as useCallback6, useMemo } from "react";
1140
+ import React4, { useCallback as useCallback6, useRef as useRef5 } from "react";
1135
1141
 
1136
1142
  // src/tui/commands/registry.ts
1137
1143
  var commands = [];
@@ -1494,7 +1500,8 @@ function useCommandDispatch({
1494
1500
  showDialog,
1495
1501
  dismissDialog
1496
1502
  }) {
1497
- const commandCtx = useMemo(() => ({
1503
+ const commandCtxRef = useRef5(null);
1504
+ commandCtxRef.current = {
1498
1505
  db,
1499
1506
  config,
1500
1507
  cwd,
@@ -1503,13 +1510,12 @@ function useCommandDispatch({
1503
1510
  clearMessages: () => dispatch({ type: "SET_MESSAGES", messages: [] }),
1504
1511
  setConfig,
1505
1512
  setThemeVersion
1506
- }), [db, config, cwd]);
1513
+ };
1507
1514
  const handleSlashCommand = useCallback6(async (text) => {
1508
1515
  if (!config) return false;
1509
1516
  const parsed = parseSlashCommand(text);
1510
1517
  if (!parsed) return false;
1511
- commandCtx.bridge = bridgeRef.current;
1512
- commandCtx.config = config;
1518
+ const commandCtx = commandCtxRef.current;
1513
1519
  dispatch({ type: "ADD_MESSAGE", message: { type: "user", text } });
1514
1520
  if (parsed.name === "cancel") {
1515
1521
  if (plannerSessionRef.current) {
@@ -1598,8 +1604,8 @@ function useCommandDispatch({
1598
1604
  dispatch({ type: "ADD_MESSAGE", message: { type: "assistant", text: `Unknown command: /${parsed.name}. Type /help for available commands.` } });
1599
1605
  }
1600
1606
  return true;
1601
- }, [config, db, commandCtx]);
1602
- return { handleSlashCommand, commandCtx };
1607
+ }, [config, db, exit, showDialog, dismissDialog]);
1608
+ return { handleSlashCommand };
1603
1609
  }
1604
1610
 
1605
1611
  // src/tui/app-provider.tsx
@@ -1628,8 +1634,10 @@ function appReducer(state, action) {
1628
1634
  return { ...state, streamingText: action.text };
1629
1635
  case "UPDATE_STEP":
1630
1636
  return { ...state, stepProgress: new Map(state.stepProgress).set(action.stepId, action.progress) };
1631
- case "ADD_OUTPUT":
1632
- return { ...state, executionOutput: [...state.executionOutput, action.line] };
1637
+ case "ADD_OUTPUT": {
1638
+ const next = [...state.executionOutput, action.line];
1639
+ return { ...state, executionOutput: next.length > 200 ? next.slice(-200) : next };
1640
+ }
1633
1641
  default:
1634
1642
  return state;
1635
1643
  }
@@ -1637,7 +1645,7 @@ function appReducer(state, action) {
1637
1645
  function AppProvider({ cwd, skipOnboarding, children }) {
1638
1646
  const { exit } = useApp();
1639
1647
  const { showDialog, dismissDialog } = useDialog();
1640
- const validation = useMemo2(() => validateConfig(), []);
1648
+ const validation = useMemo(() => validateConfig(), []);
1641
1649
  const needsSetup = !skipOnboarding && !validation.valid;
1642
1650
  const [config, setConfig] = useState4(() => {
1643
1651
  if (needsSetup) return null;
@@ -1647,7 +1655,7 @@ function AppProvider({ cwd, skipOnboarding, children }) {
1647
1655
  return null;
1648
1656
  }
1649
1657
  });
1650
- const db = useMemo2(() => initDb(), []);
1658
+ const db = useMemo(() => initDb(), []);
1651
1659
  const [themeVersion, setThemeVersion] = useState4(0);
1652
1660
  const initialState = {
1653
1661
  view: needsSetup ? "onboarding" : "chat",
@@ -1662,7 +1670,16 @@ function AppProvider({ cwd, skipOnboarding, children }) {
1662
1670
  detailRuns: [],
1663
1671
  detailStepRuns: []
1664
1672
  };
1665
- const [state, dispatch] = useReducer(appReducer, initialState);
1673
+ const msgIdRef = useRef6(0);
1674
+ const [state, rawDispatch] = useReducer(appReducer, initialState);
1675
+ const dispatch = useCallback7((action) => {
1676
+ if (action.type === "ADD_MESSAGE") {
1677
+ msgIdRef.current += 1;
1678
+ rawDispatch({ type: "ADD_MESSAGE", message: { ...action.message, id: msgIdRef.current } });
1679
+ } else {
1680
+ rawDispatch(action);
1681
+ }
1682
+ }, []);
1666
1683
  useEffect3(() => {
1667
1684
  markSessionStart();
1668
1685
  }, []);
@@ -1783,7 +1800,7 @@ function AppProvider({ cwd, skipOnboarding, children }) {
1783
1800
  execution.handleExecutionBack();
1784
1801
  }
1785
1802
  }, [state.previousView, state.workflow, db, execution.handleExecutionBack]);
1786
- const uiState = useMemo2(() => ({
1803
+ const uiState = useMemo(() => ({
1787
1804
  view: state.view,
1788
1805
  messages: state.messages,
1789
1806
  workflow: state.workflow,
@@ -1803,7 +1820,7 @@ function AppProvider({ cwd, skipOnboarding, children }) {
1803
1820
  detailRuns: state.detailRuns,
1804
1821
  detailStepRuns: state.detailStepRuns
1805
1822
  }), [state, daemonStatus, execution.isExecuting, config, cwd, footerExtra, footerHints, planner.isConversing, themeVersion]);
1806
- const uiActions = useMemo2(() => ({
1823
+ const uiActions = useMemo(() => ({
1807
1824
  handleChatSubmit,
1808
1825
  handleCancelGeneration: planner.handleCancelGeneration,
1809
1826
  handleConfirm: execution.handleConfirm,
@@ -1824,7 +1841,7 @@ function AppProvider({ cwd, skipOnboarding, children }) {
1824
1841
  }
1825
1842
 
1826
1843
  // src/tui/app-layout.tsx
1827
- import { useMemo as useMemo6 } from "react";
1844
+ import { useMemo as useMemo5 } from "react";
1828
1845
  import { Box as Box21, Static, useStdout as useStdout5 } from "ink";
1829
1846
 
1830
1847
  // src/tui/banner.tsx
@@ -1890,18 +1907,18 @@ function lerpGradient(stops, t) {
1890
1907
  import { Box as Box15 } from "ink";
1891
1908
 
1892
1909
  // src/tui/main-content.tsx
1893
- import { useState as useState6, useMemo as useMemo3, useEffect as useEffect5, useRef as useRef6, useCallback as useCallback9 } from "react";
1910
+ import { useState as useState6, useMemo as useMemo2, useCallback as useCallback9 } from "react";
1894
1911
  import { Box as Box13, Text as Text13, useStdout as useStdout2 } from "ink";
1895
1912
 
1896
1913
  // src/tui/thinking-indicator.tsx
1897
- import { useState as useState5, useEffect as useEffect4, useCallback as useCallback8, useRef as useRef5, memo as memo2 } from "react";
1914
+ import { useState as useState5, useEffect as useEffect4, useCallback as useCallback8, useRef as useRef7, memo as memo2 } from "react";
1898
1915
  import { Box as Box4, Text as Text4 } from "ink";
1899
1916
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1900
1917
  var DOTS = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1901
1918
  var ThinkingIndicator = memo2(function ThinkingIndicator2({ onCancel }) {
1902
1919
  const [elapsed, setElapsed] = useState5(0);
1903
1920
  const [frame, setFrame] = useState5(0);
1904
- const startRef = useRef5(Date.now());
1921
+ const startRef = useRef7(Date.now());
1905
1922
  useEffect4(() => {
1906
1923
  const timer = setInterval(() => {
1907
1924
  setElapsed(Math.floor((Date.now() - startRef.current) / 1e3));
@@ -1917,8 +1934,7 @@ var ThinkingIndicator = memo2(function ThinkingIndicator2({ onCancel }) {
1917
1934
  return false;
1918
1935
  }, [onCancel]));
1919
1936
  const gradient = theme.ui.gradient;
1920
- const cyclePos = Date.now() / 4e3 % 1;
1921
- const gradientIdx = Math.floor(cyclePos * gradient.length) % gradient.length;
1937
+ const gradientIdx = frame % gradient.length;
1922
1938
  const spinnerColor = gradient[gradientIdx] ?? theme.text.accent;
1923
1939
  const cancelHint = onCancel ? " (esc to cancel)" : "";
1924
1940
  return /* @__PURE__ */ jsxs4(Box4, { paddingX: 1, children: [
@@ -2057,12 +2073,6 @@ function MainContent() {
2057
2073
  const { stdout } = useStdout2();
2058
2074
  const rows = stdout?.rows ?? 24;
2059
2075
  const [scrollOffset, setScrollOffset] = useState6(0);
2060
- const prevMessageCountRef = useRef6(messages.length);
2061
- useEffect5(() => {
2062
- if (messages.length > prevMessageCountRef.current && scrollOffset === 0) {
2063
- }
2064
- prevMessageCountRef.current = messages.length;
2065
- }, [messages.length, scrollOffset]);
2066
2076
  const pageSize = Math.max(1, Math.floor(rows / 2));
2067
2077
  useKeypress("chat-scroll", KeyPriority.Normal, useCallback9((input, key) => {
2068
2078
  if (keyBindings.scrollUp(input, key)) {
@@ -2075,7 +2085,7 @@ function MainContent() {
2075
2085
  }
2076
2086
  return false;
2077
2087
  }, [pageSize, messages.length]));
2078
- const visibleMessages = useMemo3(() => {
2088
+ const visibleMessages = useMemo2(() => {
2079
2089
  if (scrollOffset === 0) return messages;
2080
2090
  const end = messages.length - scrollOffset;
2081
2091
  return messages.slice(0, Math.max(0, end));
@@ -2090,7 +2100,7 @@ function MainContent() {
2090
2100
  " (Ctrl+P/Ctrl+N)"
2091
2101
  ] }) }),
2092
2102
  /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", flexGrow: 1, marginTop: hiddenAbove > 0 ? 0 : 1, children: [
2093
- visibleMessages.map((msg, i) => /* @__PURE__ */ jsx16(Box13, { marginBottom: 1, flexDirection: "column", children: /* @__PURE__ */ jsx16(MessageDisplay, { message: msg }) }, i)),
2103
+ visibleMessages.map((msg) => /* @__PURE__ */ jsx16(Box13, { marginBottom: 1, flexDirection: "column", children: /* @__PURE__ */ jsx16(MessageDisplay, { message: msg }) }, msg.id)),
2094
2104
  streamingText && /* @__PURE__ */ jsxs12(Box13, { marginBottom: 1, paddingX: 1, children: [
2095
2105
  /* @__PURE__ */ jsx16(Box13, { width: 2, children: /* @__PURE__ */ jsx16(Text13, { color: theme.text.accent, children: "\u2726 " }) }),
2096
2106
  /* @__PURE__ */ jsx16(Box13, { flexShrink: 1, children: /* @__PURE__ */ jsx16(Text13, { color: theme.text.primary, children: streamingText }) })
@@ -2101,11 +2111,11 @@ function MainContent() {
2101
2111
  }
2102
2112
 
2103
2113
  // src/tui/composer.tsx
2104
- import { useState as useState7, useMemo as useMemo4 } from "react";
2114
+ import { useState as useState7, useMemo as useMemo3, useCallback as useCallback12 } from "react";
2105
2115
  import { Box as Box14, Text as Text15, useStdout as useStdout3 } from "ink";
2106
2116
 
2107
2117
  // src/tui/resettable-input.tsx
2108
- import { useReducer as useReducer2, useEffect as useEffect6, useRef as useRef7, useCallback as useCallback10 } from "react";
2118
+ import { useReducer as useReducer2, useEffect as useEffect5, useRef as useRef8, useCallback as useCallback10 } from "react";
2109
2119
  import { Text as Text14 } from "ink";
2110
2120
  import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
2111
2121
  function inputReducer(state, action) {
@@ -2131,13 +2141,13 @@ function inputReducer(state, action) {
2131
2141
  }
2132
2142
  function ResettableInput({ placeholder, onSubmit, onChange, isDisabled, onUpArrow, onDownArrow }) {
2133
2143
  const [state, dispatch] = useReducer2(inputReducer, { value: "", prevValue: "", cursor: 0 });
2134
- const submitRef = useRef7(null);
2135
- useEffect6(() => {
2144
+ const submitRef = useRef8(null);
2145
+ useEffect5(() => {
2136
2146
  if (state.value !== state.prevValue) {
2137
2147
  onChange?.(state.value);
2138
2148
  }
2139
2149
  }, [state.value, state.prevValue, onChange]);
2140
- useEffect6(() => {
2150
+ useEffect5(() => {
2141
2151
  if (submitRef.current !== null) {
2142
2152
  const value = submitRef.current;
2143
2153
  submitRef.current = null;
@@ -2145,7 +2155,7 @@ function ResettableInput({ placeholder, onSubmit, onChange, isDisabled, onUpArro
2145
2155
  }
2146
2156
  });
2147
2157
  useKeypress("resettable-input", KeyPriority.Normal, useCallback10((input, key) => {
2148
- if (key.ctrl && input === "c" || key.tab || key.shift && key.tab) return false;
2158
+ if (key.ctrl && input === "c" || key.tab || key.shift && key.tab || key.escape) return false;
2149
2159
  if (key.upArrow) {
2150
2160
  if (onUpArrow) {
2151
2161
  const entry = onUpArrow(state.value);
@@ -2197,11 +2207,11 @@ function ResettableInput({ placeholder, onSubmit, onChange, isDisabled, onUpArro
2197
2207
  }
2198
2208
 
2199
2209
  // src/tui/use-input-history.ts
2200
- import { useRef as useRef8, useCallback as useCallback11 } from "react";
2210
+ import { useRef as useRef9, useCallback as useCallback11 } from "react";
2201
2211
  function useInputHistory() {
2202
- const historyRef = useRef8([]);
2203
- const indexRef = useRef8(-1);
2204
- const draftRef = useRef8("");
2212
+ const historyRef = useRef9([]);
2213
+ const indexRef = useRef9(-1);
2214
+ const draftRef = useRef9("");
2205
2215
  const up = useCallback11((currentValue) => {
2206
2216
  const history = historyRef.current;
2207
2217
  if (history.length === 0) return void 0;
@@ -2268,8 +2278,8 @@ function Composer() {
2268
2278
  const cols = stdout?.columns ?? 80;
2269
2279
  const history = useInputHistory();
2270
2280
  const [currentInput, setCurrentInput] = useState7("");
2271
- const allCommands = useMemo4(() => getCommands(), []);
2272
- const matchingCommands = useMemo4(() => {
2281
+ const allCommands = useMemo3(() => getCommands(), []);
2282
+ const matchingCommands = useMemo3(() => {
2273
2283
  if (!currentInput.startsWith("/")) return [];
2274
2284
  const prefix = currentInput.toLowerCase();
2275
2285
  return allCommands.filter((c) => {
@@ -2278,6 +2288,18 @@ function Composer() {
2278
2288
  });
2279
2289
  }, [currentInput, allCommands]);
2280
2290
  const showCommandHints = currentInput.startsWith("/") && matchingCommands.length > 0 && currentInput !== "/" + matchingCommands[0]?.name;
2291
+ const handleInputChange = useCallback12((value) => {
2292
+ setCurrentInput(value);
2293
+ history.resetBrowsing();
2294
+ }, [history]);
2295
+ const handleInputSubmit = useCallback12((value) => {
2296
+ const trimmed = value.trim();
2297
+ if (trimmed) {
2298
+ history.push(trimmed);
2299
+ setCurrentInput("");
2300
+ handleChatSubmit(trimmed);
2301
+ }
2302
+ }, [history, handleChatSubmit]);
2281
2303
  const mode = modeLabel({ isExecuting, isGenerating, isConversing });
2282
2304
  const daemon = daemonLabel(daemonStatus);
2283
2305
  return /* @__PURE__ */ jsxs14(Fragment3, { children: [
@@ -2320,18 +2342,8 @@ function Composer() {
2320
2342
  ResettableInput,
2321
2343
  {
2322
2344
  placeholder: "Describe a workflow or type /help",
2323
- onChange: (value) => {
2324
- setCurrentInput(value);
2325
- history.resetBrowsing();
2326
- },
2327
- onSubmit: (value) => {
2328
- const trimmed = value.trim();
2329
- if (trimmed) {
2330
- history.push(trimmed);
2331
- setCurrentInput("");
2332
- handleChatSubmit(trimmed);
2333
- }
2334
- },
2345
+ onChange: handleInputChange,
2346
+ onSubmit: handleInputSubmit,
2335
2347
  onUpArrow: history.up,
2336
2348
  onDownArrow: history.down,
2337
2349
  isDisabled: isGenerating
@@ -2353,11 +2365,11 @@ function Chat() {
2353
2365
  }
2354
2366
 
2355
2367
  // src/tui/plan-view.tsx
2356
- import { useCallback as useCallback12, memo as memo10 } from "react";
2368
+ import { useCallback as useCallback13, memo as memo10 } from "react";
2357
2369
  import { Box as Box16, Text as Text16 } from "ink";
2358
2370
  import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
2359
2371
  function PlanView({ workflow, onConfirm, onModify, onCancel }) {
2360
- useKeypress("plan-view-actions", KeyPriority.Normal, useCallback12((input, key) => {
2372
+ useKeypress("plan-view-actions", KeyPriority.Normal, useCallback13((input, key) => {
2361
2373
  if (keyBindings.confirmPlan(input, key)) {
2362
2374
  onConfirm();
2363
2375
  return true;
@@ -2420,13 +2432,90 @@ var StepLine = memo10(function StepLine2({ step, index }) {
2420
2432
  });
2421
2433
 
2422
2434
  // src/tui/execution-view.tsx
2423
- import { useCallback as useCallback13 } from "react";
2435
+ import { useCallback as useCallback14 } from "react";
2424
2436
  import { Box as Box17, Text as Text17 } from "ink";
2437
+
2438
+ // src/tui/format-utils.ts
2439
+ function stepStatusIcon(status) {
2440
+ switch (status) {
2441
+ case "succeeded":
2442
+ return "\u2713";
2443
+ case "running":
2444
+ return "\u22B7";
2445
+ case "failed":
2446
+ return "\u2717";
2447
+ case "skipped":
2448
+ return "\u25CB";
2449
+ default:
2450
+ return "\u25CB";
2451
+ }
2452
+ }
2453
+ function stepStatusColor(status) {
2454
+ switch (status) {
2455
+ case "succeeded":
2456
+ return theme.status.success;
2457
+ case "running":
2458
+ return theme.status.warning;
2459
+ case "failed":
2460
+ return theme.status.error;
2461
+ case "skipped":
2462
+ return theme.status.muted;
2463
+ default:
2464
+ return theme.status.muted;
2465
+ }
2466
+ }
2467
+ function phaseColor2(phase) {
2468
+ switch (phase) {
2469
+ case "executing":
2470
+ return theme.status.warning;
2471
+ case "active":
2472
+ return theme.status.success;
2473
+ case "completed":
2474
+ return theme.status.success;
2475
+ case "failed":
2476
+ return theme.status.error;
2477
+ case "paused":
2478
+ return theme.status.muted;
2479
+ default:
2480
+ return theme.text.primary;
2481
+ }
2482
+ }
2483
+ function runStatusColor(status) {
2484
+ switch (status) {
2485
+ case "completed":
2486
+ return theme.status.success;
2487
+ case "running":
2488
+ return theme.status.warning;
2489
+ case "failed":
2490
+ return theme.status.error;
2491
+ default:
2492
+ return theme.text.primary;
2493
+ }
2494
+ }
2495
+ function formatDuration2(ms) {
2496
+ if (ms < 1e3) return `${ms}ms`;
2497
+ if (ms < 6e4) return `${Math.round(ms / 1e3)}s`;
2498
+ return `${Math.round(ms / 6e4)}m`;
2499
+ }
2500
+ function formatTrigger(trigger) {
2501
+ switch (trigger.type) {
2502
+ case "poll":
2503
+ return `poll every ${trigger.interval_seconds}s (${trigger.diff_mode})`;
2504
+ case "cron":
2505
+ return `cron: ${trigger.expression}${trigger.timezone ? ` (${trigger.timezone})` : ""}`;
2506
+ case "manual":
2507
+ return "manual";
2508
+ default:
2509
+ return trigger.type;
2510
+ }
2511
+ }
2512
+
2513
+ // src/tui/execution-view.tsx
2425
2514
  import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
2426
2515
  function ExecutionView({ workflow, stepProgress, output, onBack, onAbort }) {
2427
2516
  const { isExecuting } = useUIState();
2428
2517
  const isRunning = Array.from(stepProgress.values()).some((s) => s.status === "running");
2429
- useKeypress("execution-view-actions", KeyPriority.Normal, useCallback13((input, key) => {
2518
+ useKeypress("execution-view-actions", KeyPriority.Normal, useCallback14((input, key) => {
2430
2519
  if (isExecuting && onAbort && keyBindings.abortExec(input, key)) {
2431
2520
  onAbort();
2432
2521
  return true;
@@ -2454,9 +2543,9 @@ function ExecutionView({ workflow, stepProgress, output, onBack, onAbort }) {
2454
2543
  workflow.steps.map((step, i) => {
2455
2544
  const progress = stepProgress.get(step.id);
2456
2545
  const status = progress?.status ?? "pending";
2457
- const icon = statusIcon(status);
2546
+ const icon = stepStatusIcon(status);
2458
2547
  const durationText = progress?.duration ? ` (${formatDuration2(progress.duration)})` : "";
2459
- return /* @__PURE__ */ jsx21(Box17, { children: /* @__PURE__ */ jsxs17(Text17, { color: statusColor(status), children: [
2548
+ return /* @__PURE__ */ jsx21(Box17, { children: /* @__PURE__ */ jsxs17(Text17, { color: stepStatusColor(status), children: [
2460
2549
  icon,
2461
2550
  " ",
2462
2551
  i + 1,
@@ -2473,52 +2562,20 @@ function ExecutionView({ workflow, stepProgress, output, onBack, onAbort }) {
2473
2562
  /* @__PURE__ */ jsx21(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { color: theme.ui.comment, children: isExecuting ? "Press [X] to cancel" : "Press Enter, Q, or Esc to return to chat" }) })
2474
2563
  ] });
2475
2564
  }
2476
- function statusIcon(status) {
2477
- switch (status) {
2478
- case "succeeded":
2479
- return "\u2713";
2480
- case "running":
2481
- return "\u22B7";
2482
- case "failed":
2483
- return "\u2717";
2484
- case "skipped":
2485
- return "\u25CB";
2486
- default:
2487
- return "\u25CB";
2488
- }
2489
- }
2490
- function statusColor(status) {
2491
- switch (status) {
2492
- case "succeeded":
2493
- return theme.status.success;
2494
- case "running":
2495
- return theme.status.warning;
2496
- case "failed":
2497
- return theme.status.error;
2498
- case "skipped":
2499
- return theme.status.muted;
2500
- default:
2501
- return theme.status.muted;
2502
- }
2503
- }
2504
- function formatDuration2(ms) {
2505
- if (ms < 1e3) return `${ms}ms`;
2506
- return `${Math.round(ms / 1e3)}s`;
2507
- }
2508
2565
 
2509
2566
  // src/tui/workflow-detail-view.tsx
2510
- import { useState as useState8, useCallback as useCallback14, useEffect as useEffect7 } from "react";
2567
+ import { useState as useState8, useCallback as useCallback15, useEffect as useEffect6 } from "react";
2511
2568
  import { Box as Box18, Text as Text18 } from "ink";
2512
2569
  import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
2513
2570
  function WorkflowDetailView({ workflow, runs, latestStepRuns, onBack, onSelectRun, onStop }) {
2514
2571
  const [selectedRunIndex, setSelectedRunIndex] = useState8(0);
2515
2572
  const displayRuns = runs.slice(0, 5);
2516
- useEffect7(() => {
2573
+ useEffect6(() => {
2517
2574
  if (selectedRunIndex >= displayRuns.length && displayRuns.length > 0) {
2518
2575
  setSelectedRunIndex(displayRuns.length - 1);
2519
2576
  }
2520
2577
  }, [displayRuns.length, selectedRunIndex]);
2521
- useKeypress("detail-view-actions", KeyPriority.Normal, useCallback14((input, key) => {
2578
+ useKeypress("detail-view-actions", KeyPriority.Normal, useCallback15((input, key) => {
2522
2579
  if (keyBindings.escape(input, key) || keyBindings.quit(input, key)) {
2523
2580
  onBack();
2524
2581
  return true;
@@ -2580,8 +2637,8 @@ function WorkflowDetailView({ workflow, runs, latestStepRuns, onBack, onSelectRu
2580
2637
  workflow.steps.map((step, i) => {
2581
2638
  const deps = step.depends_on.length > 0 ? ` \u2192 depends on: ${step.depends_on.join(", ")}` : "";
2582
2639
  const stepRun = latestStepRuns.find((sr) => sr.step_id === step.id);
2583
- const icon = stepRun ? statusIcon2(stepRun.status) : "\u25CB";
2584
- const iconColor = stepRun ? statusColor2(stepRun.status) : theme.status.muted;
2640
+ const icon = stepRun ? stepStatusIcon(stepRun.status) : "\u25CB";
2641
+ const iconColor = stepRun ? stepStatusColor(stepRun.status) : theme.status.muted;
2585
2642
  return /* @__PURE__ */ jsxs18(Box18, { children: [
2586
2643
  /* @__PURE__ */ jsxs18(Text18, { color: iconColor, children: [
2587
2644
  icon,
@@ -2607,7 +2664,7 @@ function WorkflowDetailView({ workflow, runs, latestStepRuns, onBack, onSelectRu
2607
2664
  displayRuns.map((run, i) => /* @__PURE__ */ jsx22(Box18, { children: /* @__PURE__ */ jsxs18(Text18, { inverse: i === selectedRunIndex, children: [
2608
2665
  /* @__PURE__ */ jsx22(Text18, { color: runStatusColor(run.status), children: run.status.padEnd(14) }),
2609
2666
  /* @__PURE__ */ jsx22(Text18, { children: run.started_at.slice(0, 22).padEnd(24) }),
2610
- /* @__PURE__ */ jsx22(Text18, { children: (run.duration_ms != null ? formatDuration3(run.duration_ms) : "\u2014").padEnd(12) }),
2667
+ /* @__PURE__ */ jsx22(Text18, { children: (run.duration_ms != null ? formatDuration2(run.duration_ms) : "\u2014").padEnd(12) }),
2611
2668
  /* @__PURE__ */ jsx22(Text18, { color: theme.status.error, children: run.error ? run.error.slice(0, 40) : "" })
2612
2669
  ] }) }, run.id))
2613
2670
  ] })
@@ -2619,80 +2676,9 @@ function WorkflowDetailView({ workflow, runs, latestStepRuns, onBack, onSelectRu
2619
2676
  ] }) })
2620
2677
  ] });
2621
2678
  }
2622
- function phaseColor2(phase) {
2623
- switch (phase) {
2624
- case "executing":
2625
- return theme.status.warning;
2626
- case "active":
2627
- return theme.status.success;
2628
- case "completed":
2629
- return theme.status.success;
2630
- case "failed":
2631
- return theme.status.error;
2632
- case "paused":
2633
- return theme.status.muted;
2634
- default:
2635
- return theme.text.primary;
2636
- }
2637
- }
2638
- function runStatusColor(status) {
2639
- switch (status) {
2640
- case "completed":
2641
- return theme.status.success;
2642
- case "running":
2643
- return theme.status.warning;
2644
- case "failed":
2645
- return theme.status.error;
2646
- default:
2647
- return theme.text.primary;
2648
- }
2649
- }
2650
- function statusIcon2(status) {
2651
- switch (status) {
2652
- case "succeeded":
2653
- return "\u2713";
2654
- case "running":
2655
- return "\u22B7";
2656
- case "failed":
2657
- return "\u2717";
2658
- case "skipped":
2659
- return "\u25CB";
2660
- default:
2661
- return "\u25CB";
2662
- }
2663
- }
2664
- function statusColor2(status) {
2665
- switch (status) {
2666
- case "succeeded":
2667
- return theme.status.success;
2668
- case "running":
2669
- return theme.status.warning;
2670
- case "failed":
2671
- return theme.status.error;
2672
- case "skipped":
2673
- return theme.status.muted;
2674
- default:
2675
- return theme.status.muted;
2676
- }
2677
- }
2678
- function formatTrigger(trigger) {
2679
- switch (trigger.type) {
2680
- case "poll":
2681
- return `poll every ${trigger.interval_seconds}s (${trigger.diff_mode})`;
2682
- case "cron":
2683
- return `cron: ${trigger.expression}${trigger.timezone ? ` (${trigger.timezone})` : ""}`;
2684
- case "manual":
2685
- return "manual";
2686
- }
2687
- }
2688
- function formatDuration3(ms) {
2689
- if (ms < 1e3) return `${ms}ms`;
2690
- if (ms < 6e4) return `${Math.round(ms / 1e3)}s`;
2691
- return `${Math.round(ms / 6e4)}m`;
2692
- }
2693
2679
 
2694
2680
  // src/tui/onboarding.tsx
2695
- import { useState as useState9, useCallback as useCallback15, useMemo as useMemo5, useRef as useRef9, useEffect as useEffect8 } from "react";
2681
+ import { useState as useState9, useCallback as useCallback16, useMemo as useMemo4, useRef as useRef10, useEffect as useEffect7 } from "react";
2696
2682
  import { Box as Box19, Text as Text19, useStdout as useStdout4 } from "ink";
2697
2683
  import { TextInput, PasswordInput, ConfirmInput, Spinner, StatusMessage } from "@inkjs/ui";
2698
2684
  import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
@@ -2700,17 +2686,23 @@ function maskKey(key) {
2700
2686
  if (key.length <= 8) return "****";
2701
2687
  return key.slice(0, 4) + "****" + key.slice(-4);
2702
2688
  }
2689
+ function StepLayout({ children, input }) {
2690
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", flexGrow: 1, children: [
2691
+ /* @__PURE__ */ jsx23(Box19, { flexDirection: "column", flexGrow: 1, children }),
2692
+ /* @__PURE__ */ jsx23(Box19, { marginTop: 1, children: input })
2693
+ ] });
2694
+ }
2703
2695
  function Onboarding({ onComplete, onCancel, issues }) {
2704
2696
  const { stdout } = useStdout4();
2705
2697
  const cols = stdout?.columns ?? 80;
2706
- const existing = useMemo5(() => loadExistingConfig(), []);
2707
- const completeTimerRef = useRef9(null);
2708
- useEffect8(() => {
2698
+ const existing = useMemo4(() => loadExistingConfig(), []);
2699
+ const completeTimerRef = useRef10(null);
2700
+ useEffect7(() => {
2709
2701
  return () => {
2710
2702
  if (completeTimerRef.current) clearTimeout(completeTimerRef.current);
2711
2703
  };
2712
2704
  }, []);
2713
- const initialStep = useMemo5(() => {
2705
+ const initialStep = useMemo4(() => {
2714
2706
  if (!issues || issues.length === 0) return "welcome";
2715
2707
  const errorFields = new Set(issues.filter((i) => i.severity === "error").map((i) => i.field));
2716
2708
  if (errorFields.size === 1 && errorFields.has("claude.api_key")) {
@@ -2727,8 +2719,8 @@ function Onboarding({ onComplete, onCancel, issues }) {
2727
2719
  telegramToken: existing.telegramToken ?? "",
2728
2720
  whatsappEnabled: existing.whatsappEnabled ?? false
2729
2721
  });
2730
- const env = checkEnvironment();
2731
- useKeypress("onboarding-cancel", KeyPriority.Normal, useCallback15((input, key) => {
2722
+ const env = useMemo4(() => checkEnvironment(), []);
2723
+ useKeypress("onboarding-cancel", KeyPriority.Normal, useCallback16((input, key) => {
2732
2724
  if (onCancel && keyBindings.escape(input, key)) {
2733
2725
  if (completeTimerRef.current) clearTimeout(completeTimerRef.current);
2734
2726
  onCancel();
@@ -2736,54 +2728,37 @@ function Onboarding({ onComplete, onCancel, issues }) {
2736
2728
  }
2737
2729
  return false;
2738
2730
  }, [onCancel]));
2739
- const gotoApiKey = useCallback15(() => {
2731
+ const gotoApiKey = useCallback16(() => {
2740
2732
  setStep(existing.apiKey ? "api_key_existing" : "api_key");
2741
2733
  }, [existing]);
2742
- const gotoBaseUrl = useCallback15(() => {
2734
+ const gotoBaseUrl = useCallback16(() => {
2743
2735
  if (!isDev) return;
2744
2736
  setStep(existing.baseUrl ? "base_url_existing" : "base_url");
2745
2737
  }, [existing]);
2746
- const gotoContainer = useCallback15(() => {
2738
+ const gotoTelegram = useCallback16(() => {
2739
+ setStep(existing.telegramEnabled !== void 0 ? "telegram_existing" : "telegram");
2740
+ }, [existing]);
2741
+ const gotoContainer = useCallback16(() => {
2747
2742
  if (!(env.docker && env.dockerRunning)) {
2748
2743
  gotoTelegram();
2749
2744
  return;
2750
2745
  }
2751
2746
  setStep(existing.containerEnabled !== void 0 ? "container_existing" : "container");
2752
- }, [env, existing]);
2753
- const gotoTelegram = useCallback15(() => {
2754
- setStep(existing.telegramEnabled !== void 0 ? "telegram_existing" : "telegram");
2755
- }, [existing]);
2756
- const gotoTelegramToken = useCallback15(() => {
2747
+ }, [env, existing, gotoTelegram]);
2748
+ const gotoTelegramToken = useCallback16(() => {
2757
2749
  setStep(existing.telegramToken ? "telegram_token_existing" : "telegram_token");
2758
2750
  }, [existing]);
2759
- const gotoWhatsApp = useCallback15(() => {
2751
+ const gotoWhatsApp = useCallback16(() => {
2760
2752
  setStep(existing.whatsappEnabled !== void 0 ? "whatsapp_existing" : "whatsapp");
2761
2753
  }, [existing]);
2762
- const afterValidation = useCallback15(() => {
2754
+ const afterValidation = useCallback16(() => {
2763
2755
  if (env.docker && env.dockerRunning) {
2764
2756
  gotoContainer();
2765
2757
  } else {
2766
2758
  gotoTelegram();
2767
2759
  }
2768
2760
  }, [env, gotoContainer, gotoTelegram]);
2769
- const handleApiKeySubmit = useCallback15((value) => {
2770
- const key = value.trim();
2771
- if (!key) return;
2772
- setState((s) => ({ ...s, apiKey: key }));
2773
- if (isDev) {
2774
- gotoBaseUrl();
2775
- } else {
2776
- setStep("validating");
2777
- doValidation(key, "");
2778
- }
2779
- }, [gotoBaseUrl]);
2780
- const handleBaseUrlSubmit = useCallback15((value) => {
2781
- const url = value.trim();
2782
- setState((s) => ({ ...s, baseUrl: url }));
2783
- setStep("validating");
2784
- doValidation(state.apiKey, url);
2785
- }, [state.apiKey]);
2786
- const doValidation = useCallback15(async (apiKey, baseUrl) => {
2761
+ const doValidation = useCallback16(async (apiKey, baseUrl) => {
2787
2762
  const prevKey = process.env["ANTHROPIC_API_KEY"];
2788
2763
  const prevUrl = process.env["ANTHROPIC_BASE_URL"];
2789
2764
  process.env["ANTHROPIC_API_KEY"] = apiKey;
@@ -2812,35 +2787,44 @@ function Onboarding({ onComplete, onCancel, issues }) {
2812
2787
  else delete process.env["ANTHROPIC_BASE_URL"];
2813
2788
  }
2814
2789
  }, [afterValidation]);
2815
- const handleContainerYes = useCallback15(() => {
2790
+ const handleApiKeySubmit = useCallback16((value) => {
2791
+ const key = value.trim();
2792
+ if (!key) return;
2793
+ setState((s) => ({ ...s, apiKey: key }));
2794
+ if (isDev) {
2795
+ gotoBaseUrl();
2796
+ } else {
2797
+ setStep("validating");
2798
+ doValidation(key, "");
2799
+ }
2800
+ }, [gotoBaseUrl, doValidation]);
2801
+ const handleBaseUrlSubmit = useCallback16((value) => {
2802
+ const url = value.trim();
2803
+ setState((s) => ({ ...s, baseUrl: url }));
2804
+ setStep("validating");
2805
+ doValidation(state.apiKey, url);
2806
+ }, [state.apiKey, doValidation]);
2807
+ const handleContainerYes = useCallback16(() => {
2816
2808
  setState((s) => ({ ...s, containerEnabled: true }));
2817
2809
  gotoTelegram();
2818
2810
  }, [gotoTelegram]);
2819
- const handleContainerNo = useCallback15(() => {
2811
+ const handleContainerNo = useCallback16(() => {
2820
2812
  setState((s) => ({ ...s, containerEnabled: false }));
2821
2813
  gotoTelegram();
2822
2814
  }, [gotoTelegram]);
2823
- const handleTelegramYes = useCallback15(() => {
2815
+ const handleTelegramYes = useCallback16(() => {
2824
2816
  setState((s) => ({ ...s, telegramEnabled: true }));
2825
2817
  gotoTelegramToken();
2826
2818
  }, [gotoTelegramToken]);
2827
- const handleTelegramNo = useCallback15(() => {
2819
+ const handleTelegramNo = useCallback16(() => {
2828
2820
  setState((s) => ({ ...s, telegramEnabled: false }));
2829
2821
  gotoWhatsApp();
2830
2822
  }, [gotoWhatsApp]);
2831
- const handleTelegramTokenSubmit = useCallback15((value) => {
2823
+ const handleTelegramTokenSubmit = useCallback16((value) => {
2832
2824
  setState((s) => ({ ...s, telegramToken: value.trim() }));
2833
2825
  gotoWhatsApp();
2834
2826
  }, [gotoWhatsApp]);
2835
- const finishWithWhatsApp = useCallback15((enabled) => {
2836
- const next = { ...state, whatsappEnabled: enabled };
2837
- setState((s) => ({ ...s, whatsappEnabled: enabled }));
2838
- setStep("saving");
2839
- doSaveConfig(next);
2840
- }, [state]);
2841
- const handleWhatsAppYes = useCallback15(() => finishWithWhatsApp(true), [finishWithWhatsApp]);
2842
- const handleWhatsAppNo = useCallback15(() => finishWithWhatsApp(false), [finishWithWhatsApp]);
2843
- const doSaveConfig = useCallback15((finalState) => {
2827
+ const doSaveConfig = useCallback16((finalState) => {
2844
2828
  if (isDev) {
2845
2829
  writeEnvVar("ANTHROPIC_API_KEY", finalState.apiKey);
2846
2830
  if (finalState.baseUrl) {
@@ -2871,10 +2855,14 @@ function Onboarding({ onComplete, onCancel, issues }) {
2871
2855
  setStep("done");
2872
2856
  completeTimerRef.current = setTimeout(() => onComplete(config), 1500);
2873
2857
  }, [onComplete]);
2874
- const StepLayout = ({ children, input }) => /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", flexGrow: 1, children: [
2875
- /* @__PURE__ */ jsx23(Box19, { flexDirection: "column", flexGrow: 1, children }),
2876
- /* @__PURE__ */ jsx23(Box19, { marginTop: 1, children: input })
2877
- ] });
2858
+ const finishWithWhatsApp = useCallback16((enabled) => {
2859
+ const next = { ...state, whatsappEnabled: enabled };
2860
+ setState((s) => ({ ...s, whatsappEnabled: enabled }));
2861
+ setStep("saving");
2862
+ doSaveConfig(next);
2863
+ }, [state, doSaveConfig]);
2864
+ const handleWhatsAppYes = useCallback16(() => finishWithWhatsApp(true), [finishWithWhatsApp]);
2865
+ const handleWhatsAppNo = useCallback16(() => finishWithWhatsApp(false), [finishWithWhatsApp]);
2878
2866
  return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
2879
2867
  onCancel && /* @__PURE__ */ jsx23(Box19, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: "Press Esc to cancel" }) }),
2880
2868
  step === "welcome" && /* @__PURE__ */ jsxs19(
@@ -3127,24 +3115,24 @@ function Onboarding({ onComplete, onCancel, issues }) {
3127
3115
  }
3128
3116
 
3129
3117
  // src/tui/status.tsx
3130
- import { useState as useState10, useCallback as useCallback16, useEffect as useEffect9 } from "react";
3118
+ import { useState as useState10, useCallback as useCallback17, useEffect as useEffect8 } from "react";
3131
3119
  import { Box as Box20, Text as Text20 } from "ink";
3132
3120
  import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
3133
3121
  function Status({ workflows, onSelect, onBack, onStop, onDelete }) {
3134
3122
  const [selectedIndex, setSelectedIndex] = useState10(0);
3135
3123
  const [confirm, setConfirm] = useState10(null);
3136
3124
  const [message, setMessage] = useState10(null);
3137
- useEffect9(() => {
3125
+ useEffect8(() => {
3138
3126
  if (selectedIndex >= workflows.length && workflows.length > 0) {
3139
3127
  setSelectedIndex(workflows.length - 1);
3140
3128
  }
3141
3129
  }, [workflows.length, selectedIndex]);
3142
- useEffect9(() => {
3130
+ useEffect8(() => {
3143
3131
  if (!message) return;
3144
3132
  const timer = setTimeout(() => setMessage(null), 3e3);
3145
3133
  return () => clearTimeout(timer);
3146
3134
  }, [message]);
3147
- useKeypress("status-view", KeyPriority.Normal, useCallback16((input, key) => {
3135
+ useKeypress("status-view", KeyPriority.Normal, useCallback17((input, key) => {
3148
3136
  if (confirm) {
3149
3137
  if (keyBindings.confirmYes(input, key)) {
3150
3138
  const wf = workflows.find((w) => w.id === confirm.workflowId);
@@ -3193,22 +3181,6 @@ function Status({ workflows, onSelect, onBack, onStop, onDelete }) {
3193
3181
  }
3194
3182
  return false;
3195
3183
  }, [confirm, message, selectedIndex, workflows, onSelect, onBack, onStop, onDelete]));
3196
- const phaseColor3 = (phase) => {
3197
- switch (phase) {
3198
- case "executing":
3199
- return theme.status.warning;
3200
- case "active":
3201
- return theme.status.success;
3202
- case "completed":
3203
- return theme.status.success;
3204
- case "failed":
3205
- return theme.status.error;
3206
- case "paused":
3207
- return theme.status.muted;
3208
- default:
3209
- return theme.text.primary;
3210
- }
3211
- };
3212
3184
  return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
3213
3185
  /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", flexGrow: 1, children: [
3214
3186
  /* @__PURE__ */ jsx24(Text20, { bold: true, color: theme.border.accent, children: "Workflows" }),
@@ -3222,7 +3194,7 @@ function Status({ workflows, onSelect, onBack, onStop, onDelete }) {
3222
3194
  workflows.map((wf, i) => /* @__PURE__ */ jsx24(Box20, { children: /* @__PURE__ */ jsxs20(Text20, { inverse: i === selectedIndex, children: [
3223
3195
  /* @__PURE__ */ jsx24(Text20, { children: wf.id.slice(0, 12).padEnd(14) }),
3224
3196
  /* @__PURE__ */ jsx24(Text20, { children: wf.name.slice(0, 26).padEnd(28) }),
3225
- /* @__PURE__ */ jsx24(Text20, { color: phaseColor3(wf.phase), children: wf.phase })
3197
+ /* @__PURE__ */ jsx24(Text20, { color: phaseColor2(wf.phase), children: wf.phase })
3226
3198
  ] }) }, wf.id))
3227
3199
  ] })
3228
3200
  ] }),
@@ -3247,7 +3219,7 @@ function AppLayout({ cwd }) {
3247
3219
  const rows = stdout?.rows ?? 24;
3248
3220
  const displayPath = cwd ? cwd.replace(process.env["HOME"] ?? "", "~") : "";
3249
3221
  const versionLabel = appVersion === "dev" ? "dev" : `v${appVersion}`;
3250
- const configIssues = useMemo6(() => {
3222
+ const configIssues = useMemo5(() => {
3251
3223
  const validation = validateConfig();
3252
3224
  return validation.issues.filter((i) => i.severity === "error");
3253
3225
  }, [config]);
package/dist/cli.js CHANGED
@@ -508,7 +508,7 @@ program.command("tui").description("Start interactive TUI").option("--skip-onboa
508
508
  enableTuiLogging();
509
509
  const React = await import("react");
510
510
  const { render } = await import("ink");
511
- const { App } = await import("./app-P3ERBGJD.js");
511
+ const { App } = await import("./app-PUHQN5BJ.js");
512
512
  render(React.createElement(App, { cwd: process.cwd(), skipOnboarding: opts.skipOnboarding }), { exitOnCtrlC: false });
513
513
  } catch (err) {
514
514
  logger.error({ err }, "Failed to start TUI");
@@ -522,7 +522,7 @@ program.option("--skip-onboarding", "Skip first-run onboarding wizard").action(a
522
522
  enableTuiLogging();
523
523
  const React = await import("react");
524
524
  const { render } = await import("ink");
525
- const { App } = await import("./app-P3ERBGJD.js");
525
+ const { App } = await import("./app-PUHQN5BJ.js");
526
526
  render(React.createElement(App, { cwd: process.cwd(), skipOnboarding }), { exitOnCtrlC: false });
527
527
  } catch (err) {
528
528
  logger.error({ err }, "Failed to start TUI");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueclaw",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Orchestrate agent workflows with natural language. Natural language in, executable DAG out.",
5
5
  "type": "module",
6
6
  "bin": {