@supatest/cli 0.0.37 → 0.0.39

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 +112 -87
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5891,7 +5891,7 @@ var CLI_VERSION;
5891
5891
  var init_version = __esm({
5892
5892
  "src/version.ts"() {
5893
5893
  "use strict";
5894
- CLI_VERSION = "0.0.37";
5894
+ CLI_VERSION = "0.0.39";
5895
5895
  }
5896
5896
  });
5897
5897
 
@@ -5963,7 +5963,7 @@ var init_error_logger = __esm({
5963
5963
  "src/utils/error-logger.ts"() {
5964
5964
  "use strict";
5965
5965
  init_version();
5966
- SUPATEST_DIR = path2.join(os2.homedir(), ".supatest");
5966
+ SUPATEST_DIR = process.platform === "win32" ? path2.join(os2.tmpdir(), ".supatest") : path2.join(os2.homedir(), ".supatest");
5967
5967
  LOGS_DIR = path2.join(SUPATEST_DIR, "logs");
5968
5968
  ERROR_LOG_FILE = path2.join(LOGS_DIR, "error.log");
5969
5969
  MAX_LOG_SIZE = 5 * 1024 * 1024;
@@ -7527,7 +7527,7 @@ var init_react = __esm({
7527
7527
  });
7528
7528
 
7529
7529
  // src/ui/contexts/SessionContext.tsx
7530
- import React, { createContext, useCallback, useContext, useMemo, useState } from "react";
7530
+ import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
7531
7531
  var SessionContext, SessionProvider, useSession;
7532
7532
  var init_SessionContext = __esm({
7533
7533
  "src/ui/contexts/SessionContext.tsx"() {
@@ -7573,12 +7573,25 @@ var init_SessionContext = __esm({
7573
7573
  },
7574
7574
  [allToolsExpanded]
7575
7575
  );
7576
+ const pendingUpdateRef = useRef(null);
7577
+ const updateScheduledRef = useRef(false);
7576
7578
  const updateLastMessage = useCallback((updates) => {
7577
- setMessages((prev) => {
7578
- if (prev.length === 0) return prev;
7579
- const last = prev[prev.length - 1];
7580
- return [...prev.slice(0, -1), { ...last, ...updates }];
7581
- });
7579
+ pendingUpdateRef.current = pendingUpdateRef.current ? { ...pendingUpdateRef.current, ...updates } : updates;
7580
+ if (!updateScheduledRef.current) {
7581
+ updateScheduledRef.current = true;
7582
+ setTimeout(() => {
7583
+ updateScheduledRef.current = false;
7584
+ const pending = pendingUpdateRef.current;
7585
+ pendingUpdateRef.current = null;
7586
+ if (pending) {
7587
+ setMessages((prev) => {
7588
+ if (prev.length === 0) return prev;
7589
+ const last = prev[prev.length - 1];
7590
+ return [...prev.slice(0, -1), { ...last, ...pending }];
7591
+ });
7592
+ }
7593
+ }, 0);
7594
+ }
7582
7595
  }, []);
7583
7596
  const updateMessageById = useCallback((id, updates) => {
7584
7597
  setMessages((prev) => {
@@ -8248,48 +8261,36 @@ var init_ErrorMessage = __esm({
8248
8261
  // src/ui/components/messages/LoadingMessage.tsx
8249
8262
  import { Box as Box5, Text as Text5 } from "ink";
8250
8263
  import Spinner2 from "ink-spinner";
8251
- import React6, { useEffect, useState as useState2 } from "react";
8252
- var LOADING_MESSAGES, SHIMMER_INTERVAL_MS, TEXT_ROTATION_INTERVAL_MS, LoadingMessage;
8264
+ import React6, { memo, useEffect, useRef as useRef2, useState as useState2 } from "react";
8265
+ var LOADING_MESSAGES, TEXT_ROTATION_INTERVAL_MS, LoadingMessage;
8253
8266
  var init_LoadingMessage = __esm({
8254
8267
  "src/ui/components/messages/LoadingMessage.tsx"() {
8255
8268
  "use strict";
8256
8269
  init_theme();
8257
8270
  LOADING_MESSAGES = [
8258
- "Brainstorming...",
8259
- "Brewing coffee...",
8260
- "Sipping espresso...",
8261
- "Testing theories...",
8262
- "Making magic...",
8263
- "Multiplying matrices..."
8271
+ "Thinking...",
8272
+ "Working...",
8273
+ "Processing..."
8264
8274
  ];
8265
- SHIMMER_INTERVAL_MS = 80;
8266
- TEXT_ROTATION_INTERVAL_MS = 2e3;
8267
- LoadingMessage = ({ headless = false }) => {
8275
+ TEXT_ROTATION_INTERVAL_MS = 3e3;
8276
+ LoadingMessage = memo(({ headless = false }) => {
8268
8277
  const [messageIndex, setMessageIndex] = useState2(0);
8269
- const [shimmerPosition, setShimmerPosition] = useState2(0);
8278
+ const intervalRef = useRef2(null);
8270
8279
  const message = LOADING_MESSAGES[messageIndex];
8271
8280
  useEffect(() => {
8272
- const rotationInterval = setInterval(() => {
8281
+ intervalRef.current = setInterval(() => {
8273
8282
  setMessageIndex((prev) => (prev + 1) % LOADING_MESSAGES.length);
8274
- setShimmerPosition(0);
8275
8283
  }, TEXT_ROTATION_INTERVAL_MS);
8276
8284
  return () => {
8277
- clearInterval(rotationInterval);
8285
+ if (intervalRef.current) {
8286
+ clearInterval(intervalRef.current);
8287
+ intervalRef.current = null;
8288
+ }
8278
8289
  };
8279
8290
  }, []);
8280
- useEffect(() => {
8281
- const shimmerInterval = setInterval(() => {
8282
- setShimmerPosition((prev) => (prev + 1) % (message.length + 1));
8283
- }, SHIMMER_INTERVAL_MS);
8284
- return () => {
8285
- clearInterval(shimmerInterval);
8286
- };
8287
- }, [message.length]);
8288
- const before = message.slice(0, shimmerPosition);
8289
- const current = message[shimmerPosition] || "";
8290
- const after = message.slice(shimmerPosition + 1);
8291
- return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React6.createElement(Box5, { width: 2 }, /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.accent }, /* @__PURE__ */ React6.createElement(Spinner2, { type: "dots" }))), /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React6.createElement(Text5, null, /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.primary }, before), /* @__PURE__ */ React6.createElement(Text5, { bold: true, color: theme.text.accent }, current), /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.primary }, after), !headless && /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.primary }, " (esc to interrupt)"))));
8292
- };
8291
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React6.createElement(Box5, { width: 2 }, /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.accent }, /* @__PURE__ */ React6.createElement(Spinner2, { type: "dots" }))), /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React6.createElement(Text5, null, /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.primary }, message), !headless && /* @__PURE__ */ React6.createElement(Text5, { color: theme.text.dim }, " (esc to interrupt)"))));
8292
+ });
8293
+ LoadingMessage.displayName = "LoadingMessage";
8293
8294
  }
8294
8295
  });
8295
8296
 
@@ -8620,7 +8621,7 @@ var init_QueuedMessageDisplay = __esm({
8620
8621
 
8621
8622
  // src/ui/components/MessageList.tsx
8622
8623
  import { Box as Box12, Static } from "ink";
8623
- import React13, { useMemo as useMemo4, useRef } from "react";
8624
+ import React13, { memo as memo2, useCallback as useCallback2, useMemo as useMemo3, useRef as useRef3 } from "react";
8624
8625
  var MessageList;
8625
8626
  var init_MessageList = __esm({
8626
8627
  "src/ui/components/MessageList.tsx"() {
@@ -8636,9 +8637,12 @@ var init_MessageList = __esm({
8636
8637
  init_ToolMessage();
8637
8638
  init_UserMessage();
8638
8639
  init_QueuedMessageDisplay();
8639
- MessageList = ({ terminalWidth, currentFolder, gitBranch, headless = false, queuedTasks = [] }) => {
8640
+ MessageList = memo2(({ terminalWidth, currentFolder, gitBranch, headless = false, queuedTasks = [] }) => {
8640
8641
  const { messages, updateMessageById, isAgentRunning, staticRemountKey, toolGroupsExpanded, toggleToolGroups } = useSession();
8641
- const renderMessage = (message, isInGroup = false) => {
8642
+ const handleToggle = useCallback2((id, currentExpanded) => {
8643
+ updateMessageById(id, { isExpanded: !currentExpanded });
8644
+ }, [updateMessageById]);
8645
+ const renderMessage = useCallback2((message, isInGroup = false) => {
8642
8646
  switch (message.type) {
8643
8647
  case "user":
8644
8648
  return /* @__PURE__ */ React13.createElement(UserMessage, { key: message.id, text: message.content });
@@ -8662,7 +8666,7 @@ var init_MessageList = __esm({
8662
8666
  input: message.toolInput,
8663
8667
  isExpanded: message.isExpanded,
8664
8668
  key: message.id,
8665
- onToggle: (id) => updateMessageById(id, { isExpanded: !message.isExpanded }),
8669
+ onToggle: (id) => handleToggle(id, message.isExpanded),
8666
8670
  result: message.toolResult,
8667
8671
  toolName: message.toolName || "Unknown"
8668
8672
  }
@@ -8676,7 +8680,7 @@ var init_MessageList = __esm({
8676
8680
  input: message.toolInput,
8677
8681
  isExpanded: message.isExpanded,
8678
8682
  key: message.id,
8679
- onToggle: (id) => updateMessageById(id, { isExpanded: !message.isExpanded }),
8683
+ onToggle: (id) => handleToggle(id, message.isExpanded),
8680
8684
  result: message.toolResult,
8681
8685
  toolName: message.toolName || "Unknown"
8682
8686
  }
@@ -8689,7 +8693,7 @@ var init_MessageList = __esm({
8689
8693
  id: message.id,
8690
8694
  isExpanded: message.isExpanded,
8691
8695
  key: message.id,
8692
- onToggle: (id) => updateMessageById(id, { isExpanded: !message.isExpanded })
8696
+ onToggle: (id) => handleToggle(id, message.isExpanded)
8693
8697
  }
8694
8698
  );
8695
8699
  case "error":
@@ -8706,8 +8710,8 @@ var init_MessageList = __esm({
8706
8710
  default:
8707
8711
  return null;
8708
8712
  }
8709
- };
8710
- const renderGroupedMessage = (group) => {
8713
+ }, [terminalWidth, handleToggle]);
8714
+ const renderGroupedMessage = useCallback2((group) => {
8711
8715
  if (group.type === "group") {
8712
8716
  return /* @__PURE__ */ React13.createElement(
8713
8717
  ToolGroup,
@@ -8718,7 +8722,7 @@ var init_MessageList = __esm({
8718
8722
  onToggleTool: (id) => {
8719
8723
  const msg = group.messages.find((m) => m.id === id);
8720
8724
  if (msg) {
8721
- updateMessageById(id, { isExpanded: !msg.isExpanded });
8725
+ handleToggle(id, msg.isExpanded);
8722
8726
  }
8723
8727
  },
8724
8728
  tools: group.messages.map((msg) => ({
@@ -8733,8 +8737,8 @@ var init_MessageList = __esm({
8733
8737
  );
8734
8738
  }
8735
8739
  return renderMessage(group.messages[0]);
8736
- };
8737
- const lastUserMessageIndex = useMemo4(() => {
8740
+ }, [toolGroupsExpanded, toggleToolGroups, handleToggle, renderMessage]);
8741
+ const lastUserMessageIndex = useMemo3(() => {
8738
8742
  for (let i = messages.length - 1; i >= 0; i--) {
8739
8743
  if (messages[i].type === "user") {
8740
8744
  return i;
@@ -8742,12 +8746,12 @@ var init_MessageList = __esm({
8742
8746
  }
8743
8747
  return -1;
8744
8748
  }, [messages]);
8745
- const hasPendingAssistant = useMemo4(
8749
+ const hasPendingAssistant = useMemo3(
8746
8750
  () => messages.some((m) => m.type === "assistant" && m.isPending),
8747
8751
  [messages]
8748
8752
  );
8749
- const completedBoundaryRef = useRef(-1);
8750
- const completedBoundaryKey = useMemo4(() => {
8753
+ const completedBoundaryRef = useRef3(-1);
8754
+ const completedBoundaryKey = useMemo3(() => {
8751
8755
  const currentBoundary = lastUserMessageIndex;
8752
8756
  if (currentBoundary !== completedBoundaryRef.current) {
8753
8757
  completedBoundaryRef.current = currentBoundary;
@@ -8755,7 +8759,7 @@ var init_MessageList = __esm({
8755
8759
  }
8756
8760
  return `boundary-${completedBoundaryRef.current}`;
8757
8761
  }, [lastUserMessageIndex]);
8758
- const { completedGroups, currentTurnGroups } = useMemo4(() => {
8762
+ const { completedGroups, currentTurnGroups } = useMemo3(() => {
8759
8763
  const completed = [];
8760
8764
  const currentTurn = [];
8761
8765
  const processTurn = (turnMessages2, targetArray) => {
@@ -8798,7 +8802,7 @@ var init_MessageList = __esm({
8798
8802
  processTurn(currentTurnMessages, currentTurn);
8799
8803
  return { completedGroups: completed, currentTurnGroups: currentTurn };
8800
8804
  }, [messages, lastUserMessageIndex, completedBoundaryKey]);
8801
- const staticItems = useMemo4(() => [
8805
+ const staticItems = useMemo3(() => [
8802
8806
  { id: "header", type: "header" },
8803
8807
  ...completedGroups.map((group, idx) => {
8804
8808
  if (group.type === "group") {
@@ -8807,7 +8811,7 @@ var init_MessageList = __esm({
8807
8811
  return { ...group.messages[0], _isMessage: true };
8808
8812
  })
8809
8813
  ], [completedGroups]);
8810
- return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Static, { items: staticItems, key: `${staticRemountKey}-${toolGroupsExpanded ? "expanded" : "collapsed"}` }, (item) => {
8814
+ return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Static, { items: staticItems, key: staticRemountKey }, (item) => {
8811
8815
  if (item.type === "header") {
8812
8816
  return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", key: "header" }, /* @__PURE__ */ React13.createElement(Header, { currentFolder, gitBranch, headless }));
8813
8817
  }
@@ -8830,7 +8834,8 @@ var init_MessageList = __esm({
8830
8834
  }
8831
8835
  return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", key: group.type === "group" ? `current-group-${idx}` : group.messages[0].id, width: "100%" }, content);
8832
8836
  }), /* @__PURE__ */ React13.createElement(QueuedMessageDisplay, { messageQueue: queuedTasks }), isAgentRunning && !hasPendingAssistant && /* @__PURE__ */ React13.createElement(LoadingMessage, { headless, key: "loading" }), /* @__PURE__ */ React13.createElement(Box12, { height: 1 }));
8833
- };
8837
+ });
8838
+ MessageList.displayName = "MessageList";
8834
8839
  }
8835
8840
  });
8836
8841
 
@@ -10121,10 +10126,10 @@ var init_mouse = __esm({
10121
10126
  import { useStdin as useStdin2 } from "ink";
10122
10127
  import React17, {
10123
10128
  createContext as createContext2,
10124
- useCallback as useCallback2,
10129
+ useCallback as useCallback3,
10125
10130
  useContext as useContext2,
10126
10131
  useEffect as useEffect4,
10127
- useRef as useRef3
10132
+ useRef as useRef5
10128
10133
  } from "react";
10129
10134
  function charLengthAt(str, i) {
10130
10135
  if (str.length <= i) {
@@ -10411,16 +10416,16 @@ function KeypressProvider({
10411
10416
  debugKeystrokeLogging
10412
10417
  }) {
10413
10418
  const { stdin, setRawMode } = useStdin2();
10414
- const subscribers = useRef3(/* @__PURE__ */ new Set()).current;
10415
- const subscribe = useCallback2(
10419
+ const subscribers = useRef5(/* @__PURE__ */ new Set()).current;
10420
+ const subscribe = useCallback3(
10416
10421
  (handler) => subscribers.add(handler),
10417
10422
  [subscribers]
10418
10423
  );
10419
- const unsubscribe = useCallback2(
10424
+ const unsubscribe = useCallback3(
10420
10425
  (handler) => subscribers.delete(handler),
10421
10426
  [subscribers]
10422
10427
  );
10423
- const broadcast = useCallback2(
10428
+ const broadcast = useCallback3(
10424
10429
  (key) => subscribers.forEach((handler) => handler(key)),
10425
10430
  [subscribers]
10426
10431
  );
@@ -11426,8 +11431,8 @@ var init_ModelSelector = __esm({
11426
11431
  import path5 from "path";
11427
11432
  import chalk4 from "chalk";
11428
11433
  import { Box as Box21, Text as Text19 } from "ink";
11429
- import React24, { forwardRef, useEffect as useEffect9, useImperativeHandle, useState as useState10 } from "react";
11430
- var InputPrompt;
11434
+ import React24, { forwardRef, memo as memo3, useEffect as useEffect9, useImperativeHandle, useState as useState10 } from "react";
11435
+ var InputPromptInner, InputPrompt;
11431
11436
  var init_InputPrompt = __esm({
11432
11437
  "src/ui/components/InputPrompt.tsx"() {
11433
11438
  "use strict";
@@ -11438,7 +11443,7 @@ var init_InputPrompt = __esm({
11438
11443
  init_file_completion();
11439
11444
  init_theme();
11440
11445
  init_ModelSelector();
11441
- InputPrompt = forwardRef(({
11446
+ InputPromptInner = forwardRef(({
11442
11447
  onSubmit,
11443
11448
  placeholder = "Enter your task (press Enter to submit, Shift+Enter for new line)...",
11444
11449
  disabled = false,
@@ -11449,7 +11454,7 @@ var init_InputPrompt = __esm({
11449
11454
  onInputChange,
11450
11455
  isClaudeMax = false
11451
11456
  }, ref) => {
11452
- const { messages, agentMode, selectedModel, setSelectedModel, isAgentRunning, usageStats } = useSession();
11457
+ const { agentMode, selectedModel, setSelectedModel, isAgentRunning, usageStats } = useSession();
11453
11458
  const [value, setValue] = useState10("");
11454
11459
  const [cursorOffset, setCursorOffset] = useState10(0);
11455
11460
  const [allFiles, setAllFiles] = useState10([]);
@@ -11733,6 +11738,8 @@ var init_InputPrompt = __esm({
11733
11738
  })), !hasContent && disabled && /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim, italic: true }, "Waiting for agent to complete...")))
11734
11739
  ), /* @__PURE__ */ React24.createElement(Box21, { justifyContent: "space-between", paddingX: 1 }, /* @__PURE__ */ React24.createElement(Box21, { gap: 2 }, /* @__PURE__ */ React24.createElement(Box21, null, /* @__PURE__ */ React24.createElement(Text19, { color: agentMode === "plan" ? theme.status.inProgress : theme.text.dim }, agentMode === "plan" ? "\u23F8 plan" : "\u25B6 build"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " (shift+tab)")), /* @__PURE__ */ React24.createElement(Box21, null, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "model:"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.info }, getModelDisplayName(selectedModel)), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " (Cost: "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.info }, getModelCostLabel(selectedModel)), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, ") (shift+m)"))), /* @__PURE__ */ React24.createElement(Box21, null, /* @__PURE__ */ React24.createElement(Text19, { color: usageStats && usageStats.contextPct >= 90 ? theme.text.error : usageStats && usageStats.contextPct >= 75 ? theme.text.warning : theme.text.dim }, usageStats?.contextPct ?? 0, "% context used"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " ", "(", usageStats ? usageStats.inputTokens >= 1e3 ? `${(usageStats.inputTokens / 1e3).toFixed(1)}K` : usageStats.inputTokens : 0, " / ", usageStats ? usageStats.contextWindow >= 1e3 ? `${(usageStats.contextWindow / 1e3).toFixed(0)}K` : usageStats.contextWindow : "200K", ")"))));
11735
11740
  });
11741
+ InputPromptInner.displayName = "InputPromptInner";
11742
+ InputPrompt = memo3(InputPromptInner);
11736
11743
  InputPrompt.displayName = "InputPrompt";
11737
11744
  }
11738
11745
  });
@@ -12228,18 +12235,18 @@ var init_useModeToggle = __esm({
12228
12235
  });
12229
12236
 
12230
12237
  // src/ui/hooks/useOverlayEscapeGuard.ts
12231
- import { useCallback as useCallback3, useMemo as useMemo5, useRef as useRef4 } from "react";
12238
+ import { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef6 } from "react";
12232
12239
  var useOverlayEscapeGuard;
12233
12240
  var init_useOverlayEscapeGuard = __esm({
12234
12241
  "src/ui/hooks/useOverlayEscapeGuard.ts"() {
12235
12242
  "use strict";
12236
12243
  useOverlayEscapeGuard = ({ overlays, suppressionMs = 250 }) => {
12237
- const suppressUntilRef = useRef4(0);
12238
- const markOverlayClosed = useCallback3(() => {
12244
+ const suppressUntilRef = useRef6(0);
12245
+ const markOverlayClosed = useCallback4(() => {
12239
12246
  suppressUntilRef.current = Date.now() + suppressionMs;
12240
12247
  }, [suppressionMs]);
12241
- const isCancelSuppressed = useCallback3(() => Date.now() < suppressUntilRef.current, []);
12242
- const isOverlayOpen = useMemo5(() => overlays.some(Boolean), [overlays]);
12248
+ const isCancelSuppressed = useCallback4(() => Date.now() < suppressUntilRef.current, []);
12249
+ const isOverlayOpen = useMemo4(() => overlays.some(Boolean), [overlays]);
12243
12250
  return { isOverlayOpen, isCancelSuppressed, markOverlayClosed };
12244
12251
  };
12245
12252
  }
@@ -12250,7 +12257,7 @@ import { execSync as execSync6 } from "child_process";
12250
12257
  import { homedir as homedir8 } from "os";
12251
12258
  import { Box as Box27, Text as Text25, useApp as useApp2, useStdout as useStdout2 } from "ink";
12252
12259
  import Spinner4 from "ink-spinner";
12253
- import React30, { useEffect as useEffect13, useRef as useRef5, useState as useState16 } from "react";
12260
+ import React30, { useCallback as useCallback5, useEffect as useEffect13, useRef as useRef7, useState as useState16 } from "react";
12254
12261
  var getGitBranch2, getCurrentFolder2, AppContent, App;
12255
12262
  var init_App = __esm({
12256
12263
  "src/ui/App.tsx"() {
@@ -12302,15 +12309,15 @@ var init_App = __esm({
12302
12309
  AppContent = ({ config: config2, sessionId, webUrl, queuedTasks = [], onExit, onSubmitTask, apiClient, onResumeSession, onClearSession }) => {
12303
12310
  const { exit } = useApp2();
12304
12311
  const { stdout } = useStdout2();
12305
- const { addMessage, clearMessages, isAgentRunning, messages, setSessionId, setWebUrl, setShouldInterruptAgent, setIsAgentRunning, toggleAllToolOutputs, allToolsExpanded, selectedModel, setSelectedModel, refreshStatic, toggleToolGroups, llmProvider, setLlmProvider } = useSession();
12312
+ const { addMessage, clearMessages, isAgentRunning, setSessionId, setWebUrl, setShouldInterruptAgent, setIsAgentRunning, toggleAllToolOutputs, allToolsExpanded, selectedModel, setSelectedModel, refreshStatic, toggleToolGroups, llmProvider, setLlmProvider } = useSession();
12306
12313
  useModeToggle();
12307
12314
  const [terminalWidth, setTerminalWidth] = useState16(process.stdout.columns || 80);
12308
12315
  const [showInput, setShowInput] = useState16(true);
12309
12316
  const [gitBranch] = useState16(() => getGitBranch2());
12310
12317
  const [currentFolder] = useState16(() => getCurrentFolder2(config2.cwd));
12311
- const [hasInputContent, setHasInputContent] = useState16(false);
12318
+ const hasInputContentRef = useRef7(false);
12312
12319
  const [exitWarning, setExitWarning] = useState16(null);
12313
- const inputPromptRef = useRef5(null);
12320
+ const inputPromptRef = useRef7(null);
12314
12321
  const [showSessionSelector, setShowSessionSelector] = useState16(false);
12315
12322
  const [showModelSelector, setShowModelSelector] = useState16(false);
12316
12323
  const [showProviderSelector, setShowProviderSelector] = useState16(false);
@@ -12560,7 +12567,7 @@ var init_App = __esm({
12560
12567
  setShowAuthDialog(true);
12561
12568
  return;
12562
12569
  }
12563
- setHasInputContent(false);
12570
+ hasInputContentRef.current = false;
12564
12571
  setExitWarning(null);
12565
12572
  if (!isAgentRunning) {
12566
12573
  addMessage({
@@ -12573,6 +12580,9 @@ var init_App = __esm({
12573
12580
  onSubmitTask(task);
12574
12581
  }
12575
12582
  };
12583
+ const handleInputChange = useCallback5((val) => {
12584
+ hasInputContentRef.current = val.trim().length > 0;
12585
+ }, []);
12576
12586
  const handleSessionSelect = async (session) => {
12577
12587
  setShowSessionSelector(false);
12578
12588
  setIsLoadingSession(true);
@@ -12790,7 +12800,7 @@ var init_App = __esm({
12790
12800
  markOverlayClosed();
12791
12801
  setShowMcpServers(true);
12792
12802
  };
12793
- const isInitialMount = useRef5(true);
12803
+ const isInitialMount = useRef7(true);
12794
12804
  useEffect13(() => {
12795
12805
  const handleResize = () => {
12796
12806
  setTerminalWidth(process.stdout.columns || 80);
@@ -12839,8 +12849,9 @@ var init_App = __esm({
12839
12849
  } else if (exitWarning) {
12840
12850
  exit();
12841
12851
  onExit(true);
12842
- } else if (showInput && hasInputContent) {
12852
+ } else if (showInput && hasInputContentRef.current) {
12843
12853
  inputPromptRef.current?.clear();
12854
+ hasInputContentRef.current = false;
12844
12855
  setExitWarning("Press Ctrl+C again to exit");
12845
12856
  setTimeout(() => setExitWarning(null), 1500);
12846
12857
  } else {
@@ -12953,7 +12964,7 @@ var init_App = __esm({
12953
12964
  cwd: config2.cwd,
12954
12965
  gitBranch,
12955
12966
  isClaudeMax: !!config2.oauthToken,
12956
- onInputChange: (val) => setHasInputContent(val.trim().length > 0),
12967
+ onInputChange: handleInputChange,
12957
12968
  onSubmit: handleSubmitTask,
12958
12969
  placeholder: "Enter your task...",
12959
12970
  ref: inputPromptRef
@@ -12998,7 +13009,7 @@ __export(interactive_exports, {
12998
13009
  runInteractive: () => runInteractive
12999
13010
  });
13000
13011
  import { render as render2 } from "ink";
13001
- import React31, { useEffect as useEffect15, useRef as useRef6 } from "react";
13012
+ import React31, { useEffect as useEffect15, useRef as useRef8 } from "react";
13002
13013
  function getToolDescription2(toolName, input) {
13003
13014
  switch (toolName) {
13004
13015
  case "Read":
@@ -13149,7 +13160,9 @@ async function runInteractive(config2) {
13149
13160
  stdin: process.stdin,
13150
13161
  alternateBuffer: false,
13151
13162
  // Like Gemini CLI - allows terminal to handle scroll & selection
13152
- exitOnCtrlC: false
13163
+ exitOnCtrlC: false,
13164
+ // Reduce flickering by using incremental updates (only changed lines, not entire screen)
13165
+ incrementalRendering: true
13153
13166
  }
13154
13167
  );
13155
13168
  unmountFn = unmount;
@@ -13208,7 +13221,7 @@ var init_interactive = __esm({
13208
13221
  selectedModel,
13209
13222
  llmProvider
13210
13223
  } = useSession();
13211
- const agentRef = useRef6(null);
13224
+ const agentRef = useRef8(null);
13212
13225
  useEffect15(() => {
13213
13226
  if (shouldInterruptAgent && agentRef.current) {
13214
13227
  agentRef.current.abort();
@@ -13531,7 +13544,7 @@ init_SessionContext();
13531
13544
  import { execSync as execSync2 } from "child_process";
13532
13545
  import { homedir as homedir4 } from "os";
13533
13546
  import { Box as Box13, useApp } from "ink";
13534
- import React14, { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
13547
+ import React14, { useEffect as useEffect2, useRef as useRef4, useState as useState3 } from "react";
13535
13548
  var getGitBranch = () => {
13536
13549
  try {
13537
13550
  return execSync2("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
@@ -13557,7 +13570,7 @@ var HeadlessAgentRunner = ({ config: config2, sessionId, apiClient, onComplete }
13557
13570
  setTodos,
13558
13571
  setUsageStats
13559
13572
  } = useSession();
13560
- const agentRef = useRef2(null);
13573
+ const agentRef = useRef4(null);
13561
13574
  useEffect2(() => {
13562
13575
  let isMounted = true;
13563
13576
  const runAgent2 = async () => {
@@ -13645,7 +13658,7 @@ var HeadlessAppContent = ({
13645
13658
  const [gitBranch] = useState3(() => getGitBranch());
13646
13659
  const [currentFolder] = useState3(() => getCurrentFolder());
13647
13660
  const [terminalWidth, setTerminalWidth] = useState3(process.stdout.columns || 80);
13648
- const hasCompletedRef = useRef2(false);
13661
+ const hasCompletedRef = useRef4(false);
13649
13662
  useEffect2(() => {
13650
13663
  setSessionId(sessionId);
13651
13664
  if (webUrl) {
@@ -13813,10 +13826,22 @@ async function checkAndAutoUpdate() {
13813
13826
  console.log(`
13814
13827
  Updating Supatest CLI ${CLI_VERSION} \u2192 ${latest}...`);
13815
13828
  try {
13816
- execSync3("npm install -g @supatest/cli@latest", {
13817
- stdio: "inherit",
13818
- timeout: INSTALL_TIMEOUT
13819
- });
13829
+ try {
13830
+ const npmPrefix = execSync3("npm config get prefix", { encoding: "utf-8" }).trim();
13831
+ execSync3(`rm -rf ${npmPrefix}/lib/node_modules/@supatest/.cli-* 2>/dev/null || true`);
13832
+ } catch {
13833
+ }
13834
+ try {
13835
+ execSync3("npm update -g @supatest/cli", {
13836
+ stdio: "inherit",
13837
+ timeout: INSTALL_TIMEOUT
13838
+ });
13839
+ } catch {
13840
+ execSync3("npm install -g @supatest/cli@latest --force", {
13841
+ stdio: "inherit",
13842
+ timeout: INSTALL_TIMEOUT
13843
+ });
13844
+ }
13820
13845
  console.log("\u2713 Updated successfully\n");
13821
13846
  const child = spawn(process.argv[0], process.argv.slice(1), {
13822
13847
  stdio: "inherit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supatest/cli",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "description": "Supatest CLI - AI-powered task automation for CI/CD",
5
5
  "type": "module",
6
6
  "bin": {