@supatest/cli 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +188 -138
- 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.
|
|
5894
|
+
CLI_VERSION = "0.0.40";
|
|
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,11 +7527,12 @@ 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";
|
|
7531
|
-
var SessionContext, SessionProvider, useSession;
|
|
7530
|
+
import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
|
|
7531
|
+
var UsageStatsContext, SessionContext, SessionProvider, useSession, useUsageStats;
|
|
7532
7532
|
var init_SessionContext = __esm({
|
|
7533
7533
|
"src/ui/contexts/SessionContext.tsx"() {
|
|
7534
7534
|
"use strict";
|
|
7535
|
+
UsageStatsContext = createContext(null);
|
|
7535
7536
|
SessionContext = createContext(null);
|
|
7536
7537
|
SessionProvider = ({
|
|
7537
7538
|
children,
|
|
@@ -7573,12 +7574,25 @@ var init_SessionContext = __esm({
|
|
|
7573
7574
|
},
|
|
7574
7575
|
[allToolsExpanded]
|
|
7575
7576
|
);
|
|
7577
|
+
const pendingUpdateRef = useRef(null);
|
|
7578
|
+
const updateScheduledRef = useRef(false);
|
|
7576
7579
|
const updateLastMessage = useCallback((updates) => {
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7580
|
+
pendingUpdateRef.current = pendingUpdateRef.current ? { ...pendingUpdateRef.current, ...updates } : updates;
|
|
7581
|
+
if (!updateScheduledRef.current) {
|
|
7582
|
+
updateScheduledRef.current = true;
|
|
7583
|
+
setTimeout(() => {
|
|
7584
|
+
updateScheduledRef.current = false;
|
|
7585
|
+
const pending = pendingUpdateRef.current;
|
|
7586
|
+
pendingUpdateRef.current = null;
|
|
7587
|
+
if (pending) {
|
|
7588
|
+
setMessages((prev) => {
|
|
7589
|
+
if (prev.length === 0) return prev;
|
|
7590
|
+
const last = prev[prev.length - 1];
|
|
7591
|
+
return [...prev.slice(0, -1), { ...last, ...pending }];
|
|
7592
|
+
});
|
|
7593
|
+
}
|
|
7594
|
+
}, 0);
|
|
7595
|
+
}
|
|
7582
7596
|
}, []);
|
|
7583
7597
|
const updateMessageById = useCallback((id, updates) => {
|
|
7584
7598
|
setMessages((prev) => {
|
|
@@ -7658,8 +7672,6 @@ var init_SessionContext = __esm({
|
|
|
7658
7672
|
setTodos,
|
|
7659
7673
|
stats,
|
|
7660
7674
|
updateStats,
|
|
7661
|
-
usageStats,
|
|
7662
|
-
setUsageStats,
|
|
7663
7675
|
isAgentRunning,
|
|
7664
7676
|
setIsAgentRunning,
|
|
7665
7677
|
shouldInterruptAgent,
|
|
@@ -7693,7 +7705,6 @@ var init_SessionContext = __esm({
|
|
|
7693
7705
|
todos,
|
|
7694
7706
|
stats,
|
|
7695
7707
|
updateStats,
|
|
7696
|
-
usageStats,
|
|
7697
7708
|
isAgentRunning,
|
|
7698
7709
|
shouldInterruptAgent,
|
|
7699
7710
|
sessionId,
|
|
@@ -7705,7 +7716,11 @@ var init_SessionContext = __esm({
|
|
|
7705
7716
|
staticRemountKey,
|
|
7706
7717
|
refreshStatic
|
|
7707
7718
|
]);
|
|
7708
|
-
|
|
7719
|
+
const usageStatsValue = useMemo(() => ({
|
|
7720
|
+
usageStats,
|
|
7721
|
+
setUsageStats
|
|
7722
|
+
}), [usageStats]);
|
|
7723
|
+
return /* @__PURE__ */ React.createElement(SessionContext.Provider, { value }, /* @__PURE__ */ React.createElement(UsageStatsContext.Provider, { value: usageStatsValue }, children));
|
|
7709
7724
|
};
|
|
7710
7725
|
useSession = () => {
|
|
7711
7726
|
const context = useContext(SessionContext);
|
|
@@ -7714,6 +7729,13 @@ var init_SessionContext = __esm({
|
|
|
7714
7729
|
}
|
|
7715
7730
|
return context;
|
|
7716
7731
|
};
|
|
7732
|
+
useUsageStats = () => {
|
|
7733
|
+
const context = useContext(UsageStatsContext);
|
|
7734
|
+
if (!context) {
|
|
7735
|
+
throw new Error("useUsageStats must be used within SessionProvider");
|
|
7736
|
+
}
|
|
7737
|
+
return context;
|
|
7738
|
+
};
|
|
7717
7739
|
}
|
|
7718
7740
|
});
|
|
7719
7741
|
|
|
@@ -8248,48 +8270,36 @@ var init_ErrorMessage = __esm({
|
|
|
8248
8270
|
// src/ui/components/messages/LoadingMessage.tsx
|
|
8249
8271
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
8250
8272
|
import Spinner2 from "ink-spinner";
|
|
8251
|
-
import React6, { useEffect, useState as useState2 } from "react";
|
|
8252
|
-
var LOADING_MESSAGES,
|
|
8273
|
+
import React6, { memo, useEffect, useRef as useRef2, useState as useState2 } from "react";
|
|
8274
|
+
var LOADING_MESSAGES, TEXT_ROTATION_INTERVAL_MS, LoadingMessage;
|
|
8253
8275
|
var init_LoadingMessage = __esm({
|
|
8254
8276
|
"src/ui/components/messages/LoadingMessage.tsx"() {
|
|
8255
8277
|
"use strict";
|
|
8256
8278
|
init_theme();
|
|
8257
8279
|
LOADING_MESSAGES = [
|
|
8258
|
-
"
|
|
8259
|
-
"
|
|
8260
|
-
"
|
|
8261
|
-
"Testing theories...",
|
|
8262
|
-
"Making magic...",
|
|
8263
|
-
"Multiplying matrices..."
|
|
8280
|
+
"Thinking...",
|
|
8281
|
+
"Working...",
|
|
8282
|
+
"Processing..."
|
|
8264
8283
|
];
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
LoadingMessage = ({ headless = false }) => {
|
|
8284
|
+
TEXT_ROTATION_INTERVAL_MS = 3e3;
|
|
8285
|
+
LoadingMessage = memo(({ headless = false }) => {
|
|
8268
8286
|
const [messageIndex, setMessageIndex] = useState2(0);
|
|
8269
|
-
const
|
|
8287
|
+
const intervalRef = useRef2(null);
|
|
8270
8288
|
const message = LOADING_MESSAGES[messageIndex];
|
|
8271
8289
|
useEffect(() => {
|
|
8272
|
-
|
|
8290
|
+
intervalRef.current = setInterval(() => {
|
|
8273
8291
|
setMessageIndex((prev) => (prev + 1) % LOADING_MESSAGES.length);
|
|
8274
|
-
setShimmerPosition(0);
|
|
8275
8292
|
}, TEXT_ROTATION_INTERVAL_MS);
|
|
8276
8293
|
return () => {
|
|
8277
|
-
|
|
8294
|
+
if (intervalRef.current) {
|
|
8295
|
+
clearInterval(intervalRef.current);
|
|
8296
|
+
intervalRef.current = null;
|
|
8297
|
+
}
|
|
8278
8298
|
};
|
|
8279
8299
|
}, []);
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
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
|
-
};
|
|
8300
|
+
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)"))));
|
|
8301
|
+
});
|
|
8302
|
+
LoadingMessage.displayName = "LoadingMessage";
|
|
8293
8303
|
}
|
|
8294
8304
|
});
|
|
8295
8305
|
|
|
@@ -8620,8 +8630,8 @@ var init_QueuedMessageDisplay = __esm({
|
|
|
8620
8630
|
|
|
8621
8631
|
// src/ui/components/MessageList.tsx
|
|
8622
8632
|
import { Box as Box12, Static } from "ink";
|
|
8623
|
-
import React13, {
|
|
8624
|
-
var MessageList;
|
|
8633
|
+
import React13, { memo as memo2, useCallback as useCallback2, useMemo as useMemo3 } from "react";
|
|
8634
|
+
var StaticHeader, MessageList;
|
|
8625
8635
|
var init_MessageList = __esm({
|
|
8626
8636
|
"src/ui/components/MessageList.tsx"() {
|
|
8627
8637
|
"use strict";
|
|
@@ -8636,9 +8646,17 @@ var init_MessageList = __esm({
|
|
|
8636
8646
|
init_ToolMessage();
|
|
8637
8647
|
init_UserMessage();
|
|
8638
8648
|
init_QueuedMessageDisplay();
|
|
8639
|
-
|
|
8649
|
+
StaticHeader = memo2(({ currentFolder, gitBranch, headless, staticRemountKey }) => {
|
|
8650
|
+
const headerItems = useMemo3(() => [{ id: "header" }], []);
|
|
8651
|
+
return /* @__PURE__ */ React13.createElement(Static, { items: headerItems, key: `header-${staticRemountKey}` }, () => /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", key: "header" }, /* @__PURE__ */ React13.createElement(Header, { currentFolder, gitBranch, headless })));
|
|
8652
|
+
});
|
|
8653
|
+
StaticHeader.displayName = "StaticHeader";
|
|
8654
|
+
MessageList = memo2(({ terminalWidth, currentFolder, gitBranch, headless = false, queuedTasks = [] }) => {
|
|
8640
8655
|
const { messages, updateMessageById, isAgentRunning, staticRemountKey, toolGroupsExpanded, toggleToolGroups } = useSession();
|
|
8641
|
-
const
|
|
8656
|
+
const handleToggle = useCallback2((id, currentExpanded) => {
|
|
8657
|
+
updateMessageById(id, { isExpanded: !currentExpanded });
|
|
8658
|
+
}, [updateMessageById]);
|
|
8659
|
+
const renderMessage = useCallback2((message, isInGroup = false) => {
|
|
8642
8660
|
switch (message.type) {
|
|
8643
8661
|
case "user":
|
|
8644
8662
|
return /* @__PURE__ */ React13.createElement(UserMessage, { key: message.id, text: message.content });
|
|
@@ -8662,7 +8680,7 @@ var init_MessageList = __esm({
|
|
|
8662
8680
|
input: message.toolInput,
|
|
8663
8681
|
isExpanded: message.isExpanded,
|
|
8664
8682
|
key: message.id,
|
|
8665
|
-
onToggle: (id) =>
|
|
8683
|
+
onToggle: (id) => handleToggle(id, message.isExpanded),
|
|
8666
8684
|
result: message.toolResult,
|
|
8667
8685
|
toolName: message.toolName || "Unknown"
|
|
8668
8686
|
}
|
|
@@ -8676,7 +8694,7 @@ var init_MessageList = __esm({
|
|
|
8676
8694
|
input: message.toolInput,
|
|
8677
8695
|
isExpanded: message.isExpanded,
|
|
8678
8696
|
key: message.id,
|
|
8679
|
-
onToggle: (id) =>
|
|
8697
|
+
onToggle: (id) => handleToggle(id, message.isExpanded),
|
|
8680
8698
|
result: message.toolResult,
|
|
8681
8699
|
toolName: message.toolName || "Unknown"
|
|
8682
8700
|
}
|
|
@@ -8689,7 +8707,7 @@ var init_MessageList = __esm({
|
|
|
8689
8707
|
id: message.id,
|
|
8690
8708
|
isExpanded: message.isExpanded,
|
|
8691
8709
|
key: message.id,
|
|
8692
|
-
onToggle: (id) =>
|
|
8710
|
+
onToggle: (id) => handleToggle(id, message.isExpanded)
|
|
8693
8711
|
}
|
|
8694
8712
|
);
|
|
8695
8713
|
case "error":
|
|
@@ -8706,8 +8724,8 @@ var init_MessageList = __esm({
|
|
|
8706
8724
|
default:
|
|
8707
8725
|
return null;
|
|
8708
8726
|
}
|
|
8709
|
-
};
|
|
8710
|
-
const renderGroupedMessage = (group) => {
|
|
8727
|
+
}, [terminalWidth, handleToggle]);
|
|
8728
|
+
const renderGroupedMessage = useCallback2((group) => {
|
|
8711
8729
|
if (group.type === "group") {
|
|
8712
8730
|
return /* @__PURE__ */ React13.createElement(
|
|
8713
8731
|
ToolGroup,
|
|
@@ -8718,7 +8736,7 @@ var init_MessageList = __esm({
|
|
|
8718
8736
|
onToggleTool: (id) => {
|
|
8719
8737
|
const msg = group.messages.find((m) => m.id === id);
|
|
8720
8738
|
if (msg) {
|
|
8721
|
-
|
|
8739
|
+
handleToggle(id, msg.isExpanded);
|
|
8722
8740
|
}
|
|
8723
8741
|
},
|
|
8724
8742
|
tools: group.messages.map((msg) => ({
|
|
@@ -8733,32 +8751,30 @@ var init_MessageList = __esm({
|
|
|
8733
8751
|
);
|
|
8734
8752
|
}
|
|
8735
8753
|
return renderMessage(group.messages[0]);
|
|
8736
|
-
};
|
|
8737
|
-
const
|
|
8738
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8739
|
-
if (messages[i].type === "user") {
|
|
8740
|
-
return i;
|
|
8741
|
-
}
|
|
8742
|
-
}
|
|
8743
|
-
return -1;
|
|
8744
|
-
}, [messages]);
|
|
8745
|
-
const hasPendingAssistant = useMemo4(
|
|
8754
|
+
}, [toolGroupsExpanded, toggleToolGroups, handleToggle, renderMessage]);
|
|
8755
|
+
const hasPendingAssistant = useMemo3(
|
|
8746
8756
|
() => messages.some((m) => m.type === "assistant" && m.isPending),
|
|
8747
8757
|
[messages]
|
|
8748
8758
|
);
|
|
8749
|
-
const
|
|
8750
|
-
const completedBoundaryKey = useMemo4(() => {
|
|
8751
|
-
const currentBoundary = lastUserMessageIndex;
|
|
8752
|
-
if (currentBoundary !== completedBoundaryRef.current) {
|
|
8753
|
-
completedBoundaryRef.current = currentBoundary;
|
|
8754
|
-
return `boundary-${currentBoundary}`;
|
|
8755
|
-
}
|
|
8756
|
-
return `boundary-${completedBoundaryRef.current}`;
|
|
8757
|
-
}, [lastUserMessageIndex]);
|
|
8758
|
-
const { completedGroups, currentTurnGroups } = useMemo4(() => {
|
|
8759
|
+
const { completedGroups, currentTurnGroups } = useMemo3(() => {
|
|
8759
8760
|
const completed = [];
|
|
8760
8761
|
const currentTurn = [];
|
|
8761
|
-
const
|
|
8762
|
+
const isMessageComplete = (msg) => {
|
|
8763
|
+
switch (msg.type) {
|
|
8764
|
+
case "user":
|
|
8765
|
+
case "error":
|
|
8766
|
+
case "todo":
|
|
8767
|
+
case "thinking":
|
|
8768
|
+
return true;
|
|
8769
|
+
case "tool":
|
|
8770
|
+
return msg.toolResult !== void 0;
|
|
8771
|
+
case "assistant":
|
|
8772
|
+
return !msg.isPending;
|
|
8773
|
+
default:
|
|
8774
|
+
return true;
|
|
8775
|
+
}
|
|
8776
|
+
};
|
|
8777
|
+
const processTurn = (turnMessages, targetArray) => {
|
|
8762
8778
|
let currentToolGroup = [];
|
|
8763
8779
|
const flushToolGroup = () => {
|
|
8764
8780
|
if (currentToolGroup.length === 0) return;
|
|
@@ -8769,7 +8785,7 @@ var init_MessageList = __esm({
|
|
|
8769
8785
|
}
|
|
8770
8786
|
currentToolGroup = [];
|
|
8771
8787
|
};
|
|
8772
|
-
for (const msg of
|
|
8788
|
+
for (const msg of turnMessages) {
|
|
8773
8789
|
if (msg.type === "tool") {
|
|
8774
8790
|
currentToolGroup.push(msg);
|
|
8775
8791
|
} else {
|
|
@@ -8779,38 +8795,46 @@ var init_MessageList = __esm({
|
|
|
8779
8795
|
}
|
|
8780
8796
|
flushToolGroup();
|
|
8781
8797
|
};
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
if (msg
|
|
8786
|
-
|
|
8787
|
-
turnMessages = [];
|
|
8788
|
-
completed.push({ type: "single", messages: [msg] });
|
|
8798
|
+
const completeMessages = [];
|
|
8799
|
+
const inProgressMessages = [];
|
|
8800
|
+
for (const msg of messages) {
|
|
8801
|
+
if (isMessageComplete(msg)) {
|
|
8802
|
+
completeMessages.push(msg);
|
|
8789
8803
|
} else {
|
|
8790
|
-
|
|
8804
|
+
inProgressMessages.push(msg);
|
|
8791
8805
|
}
|
|
8792
8806
|
}
|
|
8793
|
-
|
|
8794
|
-
|
|
8795
|
-
|
|
8807
|
+
let splitIndex = messages.length;
|
|
8808
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8809
|
+
if (isMessageComplete(messages[i])) {
|
|
8810
|
+
splitIndex = i + 1;
|
|
8811
|
+
break;
|
|
8812
|
+
}
|
|
8796
8813
|
}
|
|
8797
|
-
const
|
|
8798
|
-
|
|
8814
|
+
const finalCompleteMessages = messages.slice(0, splitIndex);
|
|
8815
|
+
const finalInProgressMessages = messages.slice(splitIndex);
|
|
8816
|
+
processTurn(finalCompleteMessages, completed);
|
|
8817
|
+
processTurn(finalInProgressMessages, currentTurn);
|
|
8799
8818
|
return { completedGroups: completed, currentTurnGroups: currentTurn };
|
|
8800
|
-
}, [messages
|
|
8801
|
-
const staticItems =
|
|
8802
|
-
|
|
8803
|
-
...completedGroups.map((group, idx) => {
|
|
8819
|
+
}, [messages]);
|
|
8820
|
+
const staticItems = useMemo3(
|
|
8821
|
+
() => completedGroups.map((group, idx) => {
|
|
8804
8822
|
if (group.type === "group") {
|
|
8805
|
-
return { ...group, _isGroup: true, id: `group-${idx}` };
|
|
8823
|
+
return { ...group, _isGroup: true, id: `group-${group.messages[0]?.id || idx}` };
|
|
8806
8824
|
}
|
|
8807
8825
|
return { ...group.messages[0], _isMessage: true };
|
|
8808
|
-
})
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8826
|
+
}),
|
|
8827
|
+
[completedGroups]
|
|
8828
|
+
);
|
|
8829
|
+
return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(
|
|
8830
|
+
StaticHeader,
|
|
8831
|
+
{
|
|
8832
|
+
currentFolder,
|
|
8833
|
+
gitBranch,
|
|
8834
|
+
headless,
|
|
8835
|
+
staticRemountKey
|
|
8813
8836
|
}
|
|
8837
|
+
), staticItems.length > 0 && /* @__PURE__ */ React13.createElement(Static, { items: staticItems, key: `messages-${staticRemountKey}-${toolGroupsExpanded}` }, (item) => {
|
|
8814
8838
|
if (item._isGroup) {
|
|
8815
8839
|
const content2 = renderGroupedMessage(item);
|
|
8816
8840
|
if (!content2) {
|
|
@@ -8830,7 +8854,8 @@ var init_MessageList = __esm({
|
|
|
8830
8854
|
}
|
|
8831
8855
|
return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", key: group.type === "group" ? `current-group-${idx}` : group.messages[0].id, width: "100%" }, content);
|
|
8832
8856
|
}), /* @__PURE__ */ React13.createElement(QueuedMessageDisplay, { messageQueue: queuedTasks }), isAgentRunning && !hasPendingAssistant && /* @__PURE__ */ React13.createElement(LoadingMessage, { headless, key: "loading" }), /* @__PURE__ */ React13.createElement(Box12, { height: 1 }));
|
|
8833
|
-
};
|
|
8857
|
+
});
|
|
8858
|
+
MessageList.displayName = "MessageList";
|
|
8834
8859
|
}
|
|
8835
8860
|
});
|
|
8836
8861
|
|
|
@@ -10121,10 +10146,10 @@ var init_mouse = __esm({
|
|
|
10121
10146
|
import { useStdin as useStdin2 } from "ink";
|
|
10122
10147
|
import React17, {
|
|
10123
10148
|
createContext as createContext2,
|
|
10124
|
-
useCallback as
|
|
10149
|
+
useCallback as useCallback3,
|
|
10125
10150
|
useContext as useContext2,
|
|
10126
10151
|
useEffect as useEffect4,
|
|
10127
|
-
useRef as
|
|
10152
|
+
useRef as useRef5
|
|
10128
10153
|
} from "react";
|
|
10129
10154
|
function charLengthAt(str, i) {
|
|
10130
10155
|
if (str.length <= i) {
|
|
@@ -10411,16 +10436,16 @@ function KeypressProvider({
|
|
|
10411
10436
|
debugKeystrokeLogging
|
|
10412
10437
|
}) {
|
|
10413
10438
|
const { stdin, setRawMode } = useStdin2();
|
|
10414
|
-
const subscribers =
|
|
10415
|
-
const subscribe =
|
|
10439
|
+
const subscribers = useRef5(/* @__PURE__ */ new Set()).current;
|
|
10440
|
+
const subscribe = useCallback3(
|
|
10416
10441
|
(handler) => subscribers.add(handler),
|
|
10417
10442
|
[subscribers]
|
|
10418
10443
|
);
|
|
10419
|
-
const unsubscribe =
|
|
10444
|
+
const unsubscribe = useCallback3(
|
|
10420
10445
|
(handler) => subscribers.delete(handler),
|
|
10421
10446
|
[subscribers]
|
|
10422
10447
|
);
|
|
10423
|
-
const broadcast =
|
|
10448
|
+
const broadcast = useCallback3(
|
|
10424
10449
|
(key) => subscribers.forEach((handler) => handler(key)),
|
|
10425
10450
|
[subscribers]
|
|
10426
10451
|
);
|
|
@@ -11037,7 +11062,8 @@ var init_TestSelector = __esm({
|
|
|
11037
11062
|
// Only fetch failed tests
|
|
11038
11063
|
});
|
|
11039
11064
|
setTotalTests(result.total);
|
|
11040
|
-
|
|
11065
|
+
const loadedCount = allTests.length + result.tests.length;
|
|
11066
|
+
setHasMore(result.tests.length === PAGE_SIZE2 && loadedCount < result.total);
|
|
11041
11067
|
setAllTests((prev) => [...prev, ...result.tests]);
|
|
11042
11068
|
} catch (err) {
|
|
11043
11069
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -11149,7 +11175,7 @@ var init_TestSelector = __esm({
|
|
|
11149
11175
|
const indicator = isSelected ? "\u25B6 " : " ";
|
|
11150
11176
|
const bgColor = isSelected ? theme.text.accent : void 0;
|
|
11151
11177
|
return /* @__PURE__ */ React21.createElement(Box18, { key: test.id, marginBottom: 0 }, /* @__PURE__ */ React21.createElement(Text16, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "black" : theme.text.primary }, indicator), /* @__PURE__ */ React21.createElement(Text16, { backgroundColor: bgColor, color: isChecked ? "green" : isSelected ? "black" : theme.text.dim }, checkbox), /* @__PURE__ */ React21.createElement(Text16, null, " "), /* @__PURE__ */ React21.createElement(Text16, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "black" : theme.text.primary }, file, line && /* @__PURE__ */ React21.createElement(Text16, { color: isSelected ? "black" : theme.text.dim }, ":", line), /* @__PURE__ */ React21.createElement(Text16, { color: isSelected ? "black" : theme.text.dim }, " - "), title));
|
|
11152
|
-
})), /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", marginTop: 1 }, allTests.length > VISIBLE_ITEMS2 && /* @__PURE__ */ React21.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: "yellow" }, "Showing ", adjustedStart + 1, "-", adjustedEnd, " of ",
|
|
11178
|
+
})), /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", marginTop: 1 }, allTests.length > VISIBLE_ITEMS2 && /* @__PURE__ */ React21.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: "yellow" }, "Showing ", adjustedStart + 1, "-", adjustedEnd, " of ", allTests.length, " failed tests", hasMore && !isLoading && /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, " (scroll for more)"))), /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "\u2191\u2193"), " navigate \u2022 ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "Space"), " toggle \u2022 ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "a"), " all \u2022 ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "n"), " none \u2022 ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "Enter"), " fix selected")), selectedTests.size > 0 && /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: "green" }, selectedTests.size, " test", selectedTests.size !== 1 ? "s" : "", " selected")), isLoading && /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: "cyan" }, "Loading more tests..."))));
|
|
11153
11179
|
};
|
|
11154
11180
|
}
|
|
11155
11181
|
});
|
|
@@ -11426,8 +11452,8 @@ var init_ModelSelector = __esm({
|
|
|
11426
11452
|
import path5 from "path";
|
|
11427
11453
|
import chalk4 from "chalk";
|
|
11428
11454
|
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;
|
|
11455
|
+
import React24, { forwardRef, memo as memo3, useEffect as useEffect9, useImperativeHandle, useState as useState10 } from "react";
|
|
11456
|
+
var InputPromptInner, InputPrompt;
|
|
11431
11457
|
var init_InputPrompt = __esm({
|
|
11432
11458
|
"src/ui/components/InputPrompt.tsx"() {
|
|
11433
11459
|
"use strict";
|
|
@@ -11438,7 +11464,7 @@ var init_InputPrompt = __esm({
|
|
|
11438
11464
|
init_file_completion();
|
|
11439
11465
|
init_theme();
|
|
11440
11466
|
init_ModelSelector();
|
|
11441
|
-
|
|
11467
|
+
InputPromptInner = forwardRef(({
|
|
11442
11468
|
onSubmit,
|
|
11443
11469
|
placeholder = "Enter your task (press Enter to submit, Shift+Enter for new line)...",
|
|
11444
11470
|
disabled = false,
|
|
@@ -11449,7 +11475,8 @@ var init_InputPrompt = __esm({
|
|
|
11449
11475
|
onInputChange,
|
|
11450
11476
|
isClaudeMax = false
|
|
11451
11477
|
}, ref) => {
|
|
11452
|
-
const {
|
|
11478
|
+
const { agentMode, selectedModel, setSelectedModel, isAgentRunning } = useSession();
|
|
11479
|
+
const { usageStats } = useUsageStats();
|
|
11453
11480
|
const [value, setValue] = useState10("");
|
|
11454
11481
|
const [cursorOffset, setCursorOffset] = useState10(0);
|
|
11455
11482
|
const [allFiles, setAllFiles] = useState10([]);
|
|
@@ -11733,6 +11760,8 @@ var init_InputPrompt = __esm({
|
|
|
11733
11760
|
})), !hasContent && disabled && /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim, italic: true }, "Waiting for agent to complete...")))
|
|
11734
11761
|
), /* @__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
11762
|
});
|
|
11763
|
+
InputPromptInner.displayName = "InputPromptInner";
|
|
11764
|
+
InputPrompt = memo3(InputPromptInner);
|
|
11736
11765
|
InputPrompt.displayName = "InputPrompt";
|
|
11737
11766
|
}
|
|
11738
11767
|
});
|
|
@@ -12228,18 +12257,18 @@ var init_useModeToggle = __esm({
|
|
|
12228
12257
|
});
|
|
12229
12258
|
|
|
12230
12259
|
// src/ui/hooks/useOverlayEscapeGuard.ts
|
|
12231
|
-
import { useCallback as
|
|
12260
|
+
import { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef6 } from "react";
|
|
12232
12261
|
var useOverlayEscapeGuard;
|
|
12233
12262
|
var init_useOverlayEscapeGuard = __esm({
|
|
12234
12263
|
"src/ui/hooks/useOverlayEscapeGuard.ts"() {
|
|
12235
12264
|
"use strict";
|
|
12236
12265
|
useOverlayEscapeGuard = ({ overlays, suppressionMs = 250 }) => {
|
|
12237
|
-
const suppressUntilRef =
|
|
12238
|
-
const markOverlayClosed =
|
|
12266
|
+
const suppressUntilRef = useRef6(0);
|
|
12267
|
+
const markOverlayClosed = useCallback4(() => {
|
|
12239
12268
|
suppressUntilRef.current = Date.now() + suppressionMs;
|
|
12240
12269
|
}, [suppressionMs]);
|
|
12241
|
-
const isCancelSuppressed =
|
|
12242
|
-
const isOverlayOpen =
|
|
12270
|
+
const isCancelSuppressed = useCallback4(() => Date.now() < suppressUntilRef.current, []);
|
|
12271
|
+
const isOverlayOpen = useMemo4(() => overlays.some(Boolean), [overlays]);
|
|
12243
12272
|
return { isOverlayOpen, isCancelSuppressed, markOverlayClosed };
|
|
12244
12273
|
};
|
|
12245
12274
|
}
|
|
@@ -12250,7 +12279,7 @@ import { execSync as execSync6 } from "child_process";
|
|
|
12250
12279
|
import { homedir as homedir8 } from "os";
|
|
12251
12280
|
import { Box as Box27, Text as Text25, useApp as useApp2, useStdout as useStdout2 } from "ink";
|
|
12252
12281
|
import Spinner4 from "ink-spinner";
|
|
12253
|
-
import React30, { useEffect as useEffect13, useRef as
|
|
12282
|
+
import React30, { useCallback as useCallback5, useEffect as useEffect13, useRef as useRef7, useState as useState16 } from "react";
|
|
12254
12283
|
var getGitBranch2, getCurrentFolder2, AppContent, App;
|
|
12255
12284
|
var init_App = __esm({
|
|
12256
12285
|
"src/ui/App.tsx"() {
|
|
@@ -12302,15 +12331,15 @@ var init_App = __esm({
|
|
|
12302
12331
|
AppContent = ({ config: config2, sessionId, webUrl, queuedTasks = [], onExit, onSubmitTask, apiClient, onResumeSession, onClearSession }) => {
|
|
12303
12332
|
const { exit } = useApp2();
|
|
12304
12333
|
const { stdout } = useStdout2();
|
|
12305
|
-
const { addMessage, clearMessages, isAgentRunning,
|
|
12334
|
+
const { addMessage, clearMessages, isAgentRunning, setSessionId, setWebUrl, setShouldInterruptAgent, setIsAgentRunning, toggleAllToolOutputs, allToolsExpanded, selectedModel, setSelectedModel, refreshStatic, toggleToolGroups, llmProvider, setLlmProvider } = useSession();
|
|
12306
12335
|
useModeToggle();
|
|
12307
12336
|
const [terminalWidth, setTerminalWidth] = useState16(process.stdout.columns || 80);
|
|
12308
12337
|
const [showInput, setShowInput] = useState16(true);
|
|
12309
12338
|
const [gitBranch] = useState16(() => getGitBranch2());
|
|
12310
12339
|
const [currentFolder] = useState16(() => getCurrentFolder2(config2.cwd));
|
|
12311
|
-
const
|
|
12340
|
+
const hasInputContentRef = useRef7(false);
|
|
12312
12341
|
const [exitWarning, setExitWarning] = useState16(null);
|
|
12313
|
-
const inputPromptRef =
|
|
12342
|
+
const inputPromptRef = useRef7(null);
|
|
12314
12343
|
const [showSessionSelector, setShowSessionSelector] = useState16(false);
|
|
12315
12344
|
const [showModelSelector, setShowModelSelector] = useState16(false);
|
|
12316
12345
|
const [showProviderSelector, setShowProviderSelector] = useState16(false);
|
|
@@ -12560,7 +12589,7 @@ var init_App = __esm({
|
|
|
12560
12589
|
setShowAuthDialog(true);
|
|
12561
12590
|
return;
|
|
12562
12591
|
}
|
|
12563
|
-
|
|
12592
|
+
hasInputContentRef.current = false;
|
|
12564
12593
|
setExitWarning(null);
|
|
12565
12594
|
if (!isAgentRunning) {
|
|
12566
12595
|
addMessage({
|
|
@@ -12573,6 +12602,9 @@ var init_App = __esm({
|
|
|
12573
12602
|
onSubmitTask(task);
|
|
12574
12603
|
}
|
|
12575
12604
|
};
|
|
12605
|
+
const handleInputChange = useCallback5((val) => {
|
|
12606
|
+
hasInputContentRef.current = val.trim().length > 0;
|
|
12607
|
+
}, []);
|
|
12576
12608
|
const handleSessionSelect = async (session) => {
|
|
12577
12609
|
setShowSessionSelector(false);
|
|
12578
12610
|
setIsLoadingSession(true);
|
|
@@ -12790,7 +12822,7 @@ var init_App = __esm({
|
|
|
12790
12822
|
markOverlayClosed();
|
|
12791
12823
|
setShowMcpServers(true);
|
|
12792
12824
|
};
|
|
12793
|
-
const isInitialMount =
|
|
12825
|
+
const isInitialMount = useRef7(true);
|
|
12794
12826
|
useEffect13(() => {
|
|
12795
12827
|
const handleResize = () => {
|
|
12796
12828
|
setTerminalWidth(process.stdout.columns || 80);
|
|
@@ -12839,8 +12871,9 @@ var init_App = __esm({
|
|
|
12839
12871
|
} else if (exitWarning) {
|
|
12840
12872
|
exit();
|
|
12841
12873
|
onExit(true);
|
|
12842
|
-
} else if (showInput &&
|
|
12874
|
+
} else if (showInput && hasInputContentRef.current) {
|
|
12843
12875
|
inputPromptRef.current?.clear();
|
|
12876
|
+
hasInputContentRef.current = false;
|
|
12844
12877
|
setExitWarning("Press Ctrl+C again to exit");
|
|
12845
12878
|
setTimeout(() => setExitWarning(null), 1500);
|
|
12846
12879
|
} else {
|
|
@@ -12953,7 +12986,7 @@ var init_App = __esm({
|
|
|
12953
12986
|
cwd: config2.cwd,
|
|
12954
12987
|
gitBranch,
|
|
12955
12988
|
isClaudeMax: !!config2.oauthToken,
|
|
12956
|
-
onInputChange:
|
|
12989
|
+
onInputChange: handleInputChange,
|
|
12957
12990
|
onSubmit: handleSubmitTask,
|
|
12958
12991
|
placeholder: "Enter your task...",
|
|
12959
12992
|
ref: inputPromptRef
|
|
@@ -12998,7 +13031,7 @@ __export(interactive_exports, {
|
|
|
12998
13031
|
runInteractive: () => runInteractive
|
|
12999
13032
|
});
|
|
13000
13033
|
import { render as render2 } from "ink";
|
|
13001
|
-
import React31, { useEffect as useEffect15, useRef as
|
|
13034
|
+
import React31, { useEffect as useEffect15, useRef as useRef8 } from "react";
|
|
13002
13035
|
function getToolDescription2(toolName, input) {
|
|
13003
13036
|
switch (toolName) {
|
|
13004
13037
|
case "Read":
|
|
@@ -13147,9 +13180,14 @@ async function runInteractive(config2) {
|
|
|
13147
13180
|
stdout: inkStdout,
|
|
13148
13181
|
stderr: inkStderr,
|
|
13149
13182
|
stdin: process.stdin,
|
|
13183
|
+
// Keep alternateBuffer: false for native terminal scrollback and text selection
|
|
13150
13184
|
alternateBuffer: false,
|
|
13151
|
-
|
|
13152
|
-
|
|
13185
|
+
exitOnCtrlC: false,
|
|
13186
|
+
// Disable incrementalRendering - it doesn't work well without alternateBuffer
|
|
13187
|
+
// and can cause more flickering issues
|
|
13188
|
+
incrementalRendering: false,
|
|
13189
|
+
// Prevent Ink from patching console methods
|
|
13190
|
+
patchConsole: false
|
|
13153
13191
|
}
|
|
13154
13192
|
);
|
|
13155
13193
|
unmountFn = unmount;
|
|
@@ -13199,7 +13237,6 @@ var init_interactive = __esm({
|
|
|
13199
13237
|
setIsAgentRunning,
|
|
13200
13238
|
updateStats,
|
|
13201
13239
|
setTodos,
|
|
13202
|
-
setUsageStats,
|
|
13203
13240
|
shouldInterruptAgent,
|
|
13204
13241
|
setShouldInterruptAgent,
|
|
13205
13242
|
agentMode,
|
|
@@ -13208,7 +13245,8 @@ var init_interactive = __esm({
|
|
|
13208
13245
|
selectedModel,
|
|
13209
13246
|
llmProvider
|
|
13210
13247
|
} = useSession();
|
|
13211
|
-
const
|
|
13248
|
+
const { setUsageStats } = useUsageStats();
|
|
13249
|
+
const agentRef = useRef8(null);
|
|
13212
13250
|
useEffect15(() => {
|
|
13213
13251
|
if (shouldInterruptAgent && agentRef.current) {
|
|
13214
13252
|
agentRef.current.abort();
|
|
@@ -13320,9 +13358,9 @@ var init_interactive = __esm({
|
|
|
13320
13358
|
addMessage,
|
|
13321
13359
|
loadMessages,
|
|
13322
13360
|
setSessionId: setContextSessionId,
|
|
13323
|
-
setIsAgentRunning
|
|
13324
|
-
setUsageStats
|
|
13361
|
+
setIsAgentRunning
|
|
13325
13362
|
} = useSession();
|
|
13363
|
+
const { setUsageStats } = useUsageStats();
|
|
13326
13364
|
const [sessionId, setSessionId] = React31.useState(initialSessionId);
|
|
13327
13365
|
const [currentTask, setCurrentTask] = React31.useState(config2.task);
|
|
13328
13366
|
const [taskId, setTaskId] = React31.useState(0);
|
|
@@ -13531,7 +13569,7 @@ init_SessionContext();
|
|
|
13531
13569
|
import { execSync as execSync2 } from "child_process";
|
|
13532
13570
|
import { homedir as homedir4 } from "os";
|
|
13533
13571
|
import { Box as Box13, useApp } from "ink";
|
|
13534
|
-
import React14, { useEffect as useEffect2, useRef as
|
|
13572
|
+
import React14, { useEffect as useEffect2, useRef as useRef4, useState as useState3 } from "react";
|
|
13535
13573
|
var getGitBranch = () => {
|
|
13536
13574
|
try {
|
|
13537
13575
|
return execSync2("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
|
|
@@ -13554,10 +13592,10 @@ var HeadlessAgentRunner = ({ config: config2, sessionId, apiClient, onComplete }
|
|
|
13554
13592
|
updateMessageByToolId,
|
|
13555
13593
|
setIsAgentRunning,
|
|
13556
13594
|
updateStats,
|
|
13557
|
-
setTodos
|
|
13558
|
-
setUsageStats
|
|
13595
|
+
setTodos
|
|
13559
13596
|
} = useSession();
|
|
13560
|
-
const
|
|
13597
|
+
const { setUsageStats } = useUsageStats();
|
|
13598
|
+
const agentRef = useRef4(null);
|
|
13561
13599
|
useEffect2(() => {
|
|
13562
13600
|
let isMounted = true;
|
|
13563
13601
|
const runAgent2 = async () => {
|
|
@@ -13645,7 +13683,7 @@ var HeadlessAppContent = ({
|
|
|
13645
13683
|
const [gitBranch] = useState3(() => getGitBranch());
|
|
13646
13684
|
const [currentFolder] = useState3(() => getCurrentFolder());
|
|
13647
13685
|
const [terminalWidth, setTerminalWidth] = useState3(process.stdout.columns || 80);
|
|
13648
|
-
const hasCompletedRef =
|
|
13686
|
+
const hasCompletedRef = useRef4(false);
|
|
13649
13687
|
useEffect2(() => {
|
|
13650
13688
|
setSessionId(sessionId);
|
|
13651
13689
|
if (webUrl) {
|
|
@@ -13813,10 +13851,22 @@ async function checkAndAutoUpdate() {
|
|
|
13813
13851
|
console.log(`
|
|
13814
13852
|
Updating Supatest CLI ${CLI_VERSION} \u2192 ${latest}...`);
|
|
13815
13853
|
try {
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
}
|
|
13854
|
+
try {
|
|
13855
|
+
const npmPrefix = execSync3("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
13856
|
+
execSync3(`rm -rf ${npmPrefix}/lib/node_modules/@supatest/.cli-* 2>/dev/null || true`);
|
|
13857
|
+
} catch {
|
|
13858
|
+
}
|
|
13859
|
+
try {
|
|
13860
|
+
execSync3("npm update -g @supatest/cli", {
|
|
13861
|
+
stdio: "inherit",
|
|
13862
|
+
timeout: INSTALL_TIMEOUT
|
|
13863
|
+
});
|
|
13864
|
+
} catch {
|
|
13865
|
+
execSync3("npm install -g @supatest/cli@latest --force", {
|
|
13866
|
+
stdio: "inherit",
|
|
13867
|
+
timeout: INSTALL_TIMEOUT
|
|
13868
|
+
});
|
|
13869
|
+
}
|
|
13820
13870
|
console.log("\u2713 Updated successfully\n");
|
|
13821
13871
|
const child = spawn(process.argv[0], process.argv.slice(1), {
|
|
13822
13872
|
stdio: "inherit",
|