@supatest/cli 0.0.12 → 0.0.14
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/claude-code-cli.js +1823 -1639
- package/dist/index.js +158 -80
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3872,6 +3872,7 @@ var init_project_instructions = __esm({
|
|
|
3872
3872
|
|
|
3873
3873
|
// src/core/agent.ts
|
|
3874
3874
|
import { createRequire } from "module";
|
|
3875
|
+
import { homedir } from "os";
|
|
3875
3876
|
import { dirname, join as join2 } from "path";
|
|
3876
3877
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3877
3878
|
var CoreAgent;
|
|
@@ -3932,6 +3933,8 @@ ${projectInstructions}`
|
|
|
3932
3933
|
cleanEnv[key] = value;
|
|
3933
3934
|
}
|
|
3934
3935
|
}
|
|
3936
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || join2(homedir(), ".supatest", "claude-config");
|
|
3937
|
+
cleanEnv.CLAUDE_CONFIG_DIR = claudeConfigDir;
|
|
3935
3938
|
cleanEnv.ANTHROPIC_API_KEY = config2.supatestApiKey || "";
|
|
3936
3939
|
cleanEnv.ANTHROPIC_BASE_URL = process.env.ANTHROPIC_BASE_URL || "";
|
|
3937
3940
|
cleanEnv.ANTHROPIC_AUTH_TOKEN = "";
|
|
@@ -4447,6 +4450,12 @@ var init_api_client = __esm({
|
|
|
4447
4450
|
hasApiKey() {
|
|
4448
4451
|
return !!this.apiKey;
|
|
4449
4452
|
}
|
|
4453
|
+
/**
|
|
4454
|
+
* Get the current API key (used to refresh auth during a session)
|
|
4455
|
+
*/
|
|
4456
|
+
getApiKey() {
|
|
4457
|
+
return this.apiKey;
|
|
4458
|
+
}
|
|
4450
4459
|
/**
|
|
4451
4460
|
* Create a new CLI session on the backend
|
|
4452
4461
|
* @param title - The session title
|
|
@@ -4570,13 +4579,13 @@ var init_api_client = __esm({
|
|
|
4570
4579
|
return data;
|
|
4571
4580
|
}
|
|
4572
4581
|
/**
|
|
4573
|
-
* Get
|
|
4582
|
+
* Get queries for a session
|
|
4574
4583
|
* @param sessionId - The session ID
|
|
4575
|
-
* @returns
|
|
4584
|
+
* @returns Queries for the session
|
|
4576
4585
|
*/
|
|
4577
|
-
async
|
|
4578
|
-
const url = `${this.apiUrl}/v1/sessions/${sessionId}/
|
|
4579
|
-
logger.debug(`Fetching
|
|
4586
|
+
async getSessionQueries(sessionId) {
|
|
4587
|
+
const url = `${this.apiUrl}/v1/sessions/${sessionId}/queries`;
|
|
4588
|
+
logger.debug(`Fetching queries for session: ${sessionId}`);
|
|
4580
4589
|
const response = await fetch(url, {
|
|
4581
4590
|
method: "GET",
|
|
4582
4591
|
headers: {
|
|
@@ -4589,7 +4598,7 @@ var init_api_client = __esm({
|
|
|
4589
4598
|
}
|
|
4590
4599
|
const data = await response.json();
|
|
4591
4600
|
logger.debug(
|
|
4592
|
-
`Fetched ${data.
|
|
4601
|
+
`Fetched ${data.queries.length} queries for session: ${sessionId}`
|
|
4593
4602
|
);
|
|
4594
4603
|
return data;
|
|
4595
4604
|
}
|
|
@@ -4658,7 +4667,7 @@ var CLI_VERSION;
|
|
|
4658
4667
|
var init_version = __esm({
|
|
4659
4668
|
"src/version.ts"() {
|
|
4660
4669
|
"use strict";
|
|
4661
|
-
CLI_VERSION = "0.0.
|
|
4670
|
+
CLI_VERSION = "0.0.14";
|
|
4662
4671
|
}
|
|
4663
4672
|
});
|
|
4664
4673
|
|
|
@@ -4733,7 +4742,7 @@ var init_encryption = __esm({
|
|
|
4733
4742
|
|
|
4734
4743
|
// src/utils/token-storage.ts
|
|
4735
4744
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
|
|
4736
|
-
import { homedir } from "os";
|
|
4745
|
+
import { homedir as homedir2 } from "os";
|
|
4737
4746
|
import { join as join4 } from "path";
|
|
4738
4747
|
function getTokenFilePath() {
|
|
4739
4748
|
const apiUrl = process.env.SUPATEST_API_URL || PRODUCTION_API_URL;
|
|
@@ -4808,7 +4817,7 @@ var init_token_storage = __esm({
|
|
|
4808
4817
|
"src/utils/token-storage.ts"() {
|
|
4809
4818
|
"use strict";
|
|
4810
4819
|
init_encryption();
|
|
4811
|
-
CONFIG_DIR = join4(
|
|
4820
|
+
CONFIG_DIR = join4(homedir2(), ".supatest");
|
|
4812
4821
|
PRODUCTION_API_URL = "https://code-api.supatest.ai";
|
|
4813
4822
|
STORAGE_VERSION = 2;
|
|
4814
4823
|
TOKEN_FILE = join4(CONFIG_DIR, "token.json");
|
|
@@ -5170,7 +5179,15 @@ function startCallbackServer(port, expectedState) {
|
|
|
5170
5179
|
}
|
|
5171
5180
|
});
|
|
5172
5181
|
server.on("error", (error) => {
|
|
5173
|
-
|
|
5182
|
+
if (error.code === "EADDRINUSE") {
|
|
5183
|
+
const portError = new Error(
|
|
5184
|
+
"Something went wrong. Please restart the CLI and try again."
|
|
5185
|
+
);
|
|
5186
|
+
portError.code = "EADDRINUSE";
|
|
5187
|
+
reject(portError);
|
|
5188
|
+
} else {
|
|
5189
|
+
reject(error);
|
|
5190
|
+
}
|
|
5174
5191
|
});
|
|
5175
5192
|
const timeout = setTimeout(() => {
|
|
5176
5193
|
server.close();
|
|
@@ -5424,7 +5441,13 @@ ${loginUrl}
|
|
|
5424
5441
|
console.log("\n\u2705 Login successful!\n");
|
|
5425
5442
|
return result;
|
|
5426
5443
|
} catch (error) {
|
|
5427
|
-
|
|
5444
|
+
const err = error;
|
|
5445
|
+
if (err.code === "EADDRINUSE") {
|
|
5446
|
+
console.error("\n\u274C Login failed: Something went wrong.");
|
|
5447
|
+
console.error(" Please restart the CLI and try again.\n");
|
|
5448
|
+
} else {
|
|
5449
|
+
console.error("\n\u274C Login failed:", error.message, "\n");
|
|
5450
|
+
}
|
|
5428
5451
|
throw error;
|
|
5429
5452
|
}
|
|
5430
5453
|
}
|
|
@@ -7066,6 +7089,9 @@ function highlightTreeToString(node) {
|
|
|
7066
7089
|
if (node.type === "text") {
|
|
7067
7090
|
return node.value;
|
|
7068
7091
|
}
|
|
7092
|
+
if (node.type === "root" && node.children) {
|
|
7093
|
+
return node.children.map(highlightTreeToString).join("");
|
|
7094
|
+
}
|
|
7069
7095
|
if (node.type === "element") {
|
|
7070
7096
|
const className = node.properties?.className?.[0] || "";
|
|
7071
7097
|
let content = "";
|
|
@@ -7352,7 +7378,8 @@ var init_ErrorMessage = __esm({
|
|
|
7352
7378
|
type = "error"
|
|
7353
7379
|
}) => {
|
|
7354
7380
|
const { icon, color } = getErrorStyle(type);
|
|
7355
|
-
|
|
7381
|
+
const displayMessage = type === "error" ? "Tool call failed" : message;
|
|
7382
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { color }, icon, " ", displayMessage));
|
|
7356
7383
|
};
|
|
7357
7384
|
}
|
|
7358
7385
|
});
|
|
@@ -7913,8 +7940,9 @@ var init_useOverlayEscapeGuard = __esm({
|
|
|
7913
7940
|
|
|
7914
7941
|
// src/ui/App.tsx
|
|
7915
7942
|
import { execSync as execSync3 } from "child_process";
|
|
7916
|
-
import { homedir as
|
|
7943
|
+
import { homedir as homedir3 } from "os";
|
|
7917
7944
|
import { Box as Box18, Text as Text17, useApp } from "ink";
|
|
7945
|
+
import Spinner3 from "ink-spinner";
|
|
7918
7946
|
import React20, { useEffect as useEffect7, useRef as useRef3, useState as useState6 } from "react";
|
|
7919
7947
|
var getGitBranch, getCurrentFolder, AppContent, App;
|
|
7920
7948
|
var init_App = __esm({
|
|
@@ -7938,6 +7966,7 @@ var init_App = __esm({
|
|
|
7938
7966
|
init_useModeToggle();
|
|
7939
7967
|
init_useOverlayEscapeGuard();
|
|
7940
7968
|
init_auth();
|
|
7969
|
+
init_theme();
|
|
7941
7970
|
getGitBranch = () => {
|
|
7942
7971
|
try {
|
|
7943
7972
|
return execSync3("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
|
|
@@ -7947,7 +7976,7 @@ var init_App = __esm({
|
|
|
7947
7976
|
};
|
|
7948
7977
|
getCurrentFolder = () => {
|
|
7949
7978
|
const cwd = process.cwd();
|
|
7950
|
-
const home =
|
|
7979
|
+
const home = homedir3();
|
|
7951
7980
|
if (cwd.startsWith(home)) {
|
|
7952
7981
|
return `~${cwd.slice(home.length)}`;
|
|
7953
7982
|
}
|
|
@@ -7967,6 +7996,7 @@ var init_App = __esm({
|
|
|
7967
7996
|
const inputPromptRef = useRef3(null);
|
|
7968
7997
|
const [showSessionSelector, setShowSessionSelector] = useState6(false);
|
|
7969
7998
|
const [showModelSelector, setShowModelSelector] = useState6(false);
|
|
7999
|
+
const [isLoadingSession, setIsLoadingSession] = useState6(false);
|
|
7970
8000
|
const [authState, setAuthState] = useState6(
|
|
7971
8001
|
() => config2.supatestApiKey ? "authenticated" /* Authenticated */ : "unauthenticated" /* Unauthenticated */
|
|
7972
8002
|
);
|
|
@@ -8127,15 +8157,13 @@ var init_App = __esm({
|
|
|
8127
8157
|
onSubmitTask(task);
|
|
8128
8158
|
}
|
|
8129
8159
|
};
|
|
8130
|
-
const handleSessionSelect = (session) => {
|
|
8160
|
+
const handleSessionSelect = async (session) => {
|
|
8131
8161
|
setShowSessionSelector(false);
|
|
8132
|
-
|
|
8133
|
-
type: "assistant",
|
|
8134
|
-
content: `Switching to session: ${session.title || "Untitled"} (${session.id})`
|
|
8135
|
-
});
|
|
8162
|
+
setIsLoadingSession(true);
|
|
8136
8163
|
if (onResumeSession) {
|
|
8137
|
-
onResumeSession(session);
|
|
8164
|
+
await onResumeSession(session);
|
|
8138
8165
|
}
|
|
8166
|
+
setIsLoadingSession(false);
|
|
8139
8167
|
};
|
|
8140
8168
|
const handleSessionSelectorCancel = () => {
|
|
8141
8169
|
markOverlayClosed();
|
|
@@ -8248,6 +8276,7 @@ var init_App = __esm({
|
|
|
8248
8276
|
onSelect: handleSessionSelect
|
|
8249
8277
|
}
|
|
8250
8278
|
),
|
|
8279
|
+
isLoadingSession && /* @__PURE__ */ React20.createElement(Box18, { borderColor: "cyan", borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React20.createElement(Box18, { flexDirection: "row" }, /* @__PURE__ */ React20.createElement(Box18, { width: 2 }, /* @__PURE__ */ React20.createElement(Text17, { color: theme.text.accent }, /* @__PURE__ */ React20.createElement(Spinner3, { type: "dots" }))), /* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "cyan" }, "Loading session...")), /* @__PURE__ */ React20.createElement(Text17, { color: theme.text.dim }, "Fetching queries and context")),
|
|
8251
8280
|
showModelSelector && /* @__PURE__ */ React20.createElement(
|
|
8252
8281
|
ModelSelector,
|
|
8253
8282
|
{
|
|
@@ -8262,7 +8291,7 @@ var init_App = __esm({
|
|
|
8262
8291
|
onLogin: handleLogin
|
|
8263
8292
|
}
|
|
8264
8293
|
),
|
|
8265
|
-
/* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React20.createElement(QueuedMessageDisplay, { messageQueue: queuedTasks }), !showAuthDialog && /* @__PURE__ */ React20.createElement(AuthBanner, { authState }), showInput && !showSessionSelector && !showAuthDialog && !showHelp && !showModelSelector && /* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column", marginTop: 0, width: "100%" }, exitWarning && /* @__PURE__ */ React20.createElement(Box18, { marginBottom: 0, paddingX: 1 }, /* @__PURE__ */ React20.createElement(Text17, { color: "yellow" }, exitWarning)), /* @__PURE__ */ React20.createElement(
|
|
8294
|
+
/* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React20.createElement(QueuedMessageDisplay, { messageQueue: queuedTasks }), !showAuthDialog && /* @__PURE__ */ React20.createElement(AuthBanner, { authState }), showInput && !showSessionSelector && !showAuthDialog && !showHelp && !showModelSelector && !isLoadingSession && /* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column", marginTop: 0, width: "100%" }, exitWarning && /* @__PURE__ */ React20.createElement(Box18, { marginBottom: 0, paddingX: 1 }, /* @__PURE__ */ React20.createElement(Text17, { color: "yellow" }, exitWarning)), /* @__PURE__ */ React20.createElement(
|
|
8266
8295
|
InputPrompt,
|
|
8267
8296
|
{
|
|
8268
8297
|
currentFolder,
|
|
@@ -8344,6 +8373,69 @@ function getToolDescription2(toolName, input) {
|
|
|
8344
8373
|
return toolName;
|
|
8345
8374
|
}
|
|
8346
8375
|
}
|
|
8376
|
+
function convertQueriesToUIMessages(queries) {
|
|
8377
|
+
const uiMessages = [];
|
|
8378
|
+
const sortedQueries = [...queries].sort((a, b2) => a.sequence - b2.sequence);
|
|
8379
|
+
for (const query2 of sortedQueries) {
|
|
8380
|
+
const timestamp = new Date(query2.startedAt).getTime();
|
|
8381
|
+
if (query2.content?.userMessage) {
|
|
8382
|
+
for (const block of query2.content.userMessage) {
|
|
8383
|
+
if (block.type === "text") {
|
|
8384
|
+
uiMessages.push({
|
|
8385
|
+
id: `${query2.id}-user-${uiMessages.length}`,
|
|
8386
|
+
type: "user",
|
|
8387
|
+
content: block.text,
|
|
8388
|
+
timestamp
|
|
8389
|
+
});
|
|
8390
|
+
}
|
|
8391
|
+
}
|
|
8392
|
+
}
|
|
8393
|
+
if (query2.content?.turns) {
|
|
8394
|
+
const toolResults = /* @__PURE__ */ new Map();
|
|
8395
|
+
for (const turn of query2.content.turns) {
|
|
8396
|
+
if (turn.toolResults) {
|
|
8397
|
+
for (const block of turn.toolResults) {
|
|
8398
|
+
if (block.type === "tool_result" && block.tool_use_id) {
|
|
8399
|
+
toolResults.set(block.tool_use_id, block.content);
|
|
8400
|
+
}
|
|
8401
|
+
}
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
8404
|
+
for (const turn of query2.content.turns) {
|
|
8405
|
+
for (const block of turn.assistant) {
|
|
8406
|
+
if (block.type === "text") {
|
|
8407
|
+
uiMessages.push({
|
|
8408
|
+
id: `${query2.id}-assistant-${uiMessages.length}`,
|
|
8409
|
+
type: "assistant",
|
|
8410
|
+
content: block.text,
|
|
8411
|
+
timestamp
|
|
8412
|
+
});
|
|
8413
|
+
} else if (block.type === "thinking") {
|
|
8414
|
+
uiMessages.push({
|
|
8415
|
+
id: `${query2.id}-thinking-${uiMessages.length}`,
|
|
8416
|
+
type: "thinking",
|
|
8417
|
+
content: block.thinking,
|
|
8418
|
+
timestamp
|
|
8419
|
+
});
|
|
8420
|
+
} else if (block.type === "tool_use") {
|
|
8421
|
+
const toolResult = toolResults.get(block.id);
|
|
8422
|
+
uiMessages.push({
|
|
8423
|
+
id: `${query2.id}-tool-${uiMessages.length}`,
|
|
8424
|
+
type: "tool",
|
|
8425
|
+
content: getToolDescription2(block.name, block.input),
|
|
8426
|
+
toolName: block.name,
|
|
8427
|
+
toolInput: block.input,
|
|
8428
|
+
toolResult,
|
|
8429
|
+
toolUseId: block.id,
|
|
8430
|
+
timestamp
|
|
8431
|
+
});
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
}
|
|
8435
|
+
}
|
|
8436
|
+
}
|
|
8437
|
+
return uiMessages;
|
|
8438
|
+
}
|
|
8347
8439
|
async function runInteractive(config2) {
|
|
8348
8440
|
let success = false;
|
|
8349
8441
|
let unmountFn = null;
|
|
@@ -8467,10 +8559,11 @@ var init_interactive = __esm({
|
|
|
8467
8559
|
const runAgent2 = async () => {
|
|
8468
8560
|
setIsAgentRunning(true);
|
|
8469
8561
|
try {
|
|
8562
|
+
const supatestApiKey = apiClient.getApiKey?.() || config2.supatestApiKey || "";
|
|
8470
8563
|
const proxyUrl = config2.supatestApiUrl || "https://code-api.supatest.ai";
|
|
8471
8564
|
const baseUrl = `${proxyUrl}/v1/sessions/${sessionId}/anthropic`;
|
|
8472
8565
|
process.env.ANTHROPIC_BASE_URL = baseUrl;
|
|
8473
|
-
process.env.ANTHROPIC_API_KEY =
|
|
8566
|
+
process.env.ANTHROPIC_API_KEY = supatestApiKey;
|
|
8474
8567
|
const presenter = new ReactPresenter(
|
|
8475
8568
|
{
|
|
8476
8569
|
addMessage: (msg) => {
|
|
@@ -8502,6 +8595,7 @@ var init_interactive = __esm({
|
|
|
8502
8595
|
);
|
|
8503
8596
|
const runConfig = {
|
|
8504
8597
|
...config2,
|
|
8598
|
+
supatestApiKey,
|
|
8505
8599
|
mode: agentMode,
|
|
8506
8600
|
planFilePath,
|
|
8507
8601
|
selectedModel,
|
|
@@ -8625,61 +8719,9 @@ var init_interactive = __esm({
|
|
|
8625
8719
|
});
|
|
8626
8720
|
return;
|
|
8627
8721
|
}
|
|
8628
|
-
const response = await apiClient.
|
|
8629
|
-
const
|
|
8630
|
-
const
|
|
8631
|
-
for (const msg of apiMessages) {
|
|
8632
|
-
const contentBlocks = msg.content;
|
|
8633
|
-
if (!contentBlocks) continue;
|
|
8634
|
-
for (const block of contentBlocks) {
|
|
8635
|
-
if (block.type === "tool_result" && block.tool_use_id) {
|
|
8636
|
-
let resultText = "";
|
|
8637
|
-
if (typeof block.content === "string") {
|
|
8638
|
-
resultText = block.content;
|
|
8639
|
-
} else if (Array.isArray(block.content)) {
|
|
8640
|
-
resultText = block.content.map((c2) => c2.text || "").join("\n");
|
|
8641
|
-
}
|
|
8642
|
-
toolResults.set(block.tool_use_id, resultText);
|
|
8643
|
-
}
|
|
8644
|
-
}
|
|
8645
|
-
}
|
|
8646
|
-
const uiMessages = apiMessages.flatMap((msg) => {
|
|
8647
|
-
const messages = [];
|
|
8648
|
-
const contentBlocks = msg.content;
|
|
8649
|
-
if (!contentBlocks || contentBlocks.length === 0) {
|
|
8650
|
-
return [];
|
|
8651
|
-
}
|
|
8652
|
-
for (const block of contentBlocks) {
|
|
8653
|
-
if (block.type === "text") {
|
|
8654
|
-
messages.push({
|
|
8655
|
-
id: `${msg.id}-${messages.length}`,
|
|
8656
|
-
type: msg.role,
|
|
8657
|
-
content: block.text,
|
|
8658
|
-
timestamp: new Date(msg.createdAt).getTime()
|
|
8659
|
-
});
|
|
8660
|
-
} else if (block.type === "thinking") {
|
|
8661
|
-
messages.push({
|
|
8662
|
-
id: `${msg.id}-${messages.length}`,
|
|
8663
|
-
type: "thinking",
|
|
8664
|
-
content: block.thinking,
|
|
8665
|
-
timestamp: new Date(msg.createdAt).getTime()
|
|
8666
|
-
});
|
|
8667
|
-
} else if (block.type === "tool_use") {
|
|
8668
|
-
const toolResult = toolResults.get(block.id);
|
|
8669
|
-
messages.push({
|
|
8670
|
-
id: `${msg.id}-${messages.length}`,
|
|
8671
|
-
type: "tool",
|
|
8672
|
-
content: getToolDescription2(block.name, block.input),
|
|
8673
|
-
toolName: block.name,
|
|
8674
|
-
toolInput: block.input,
|
|
8675
|
-
toolResult,
|
|
8676
|
-
toolUseId: block.id,
|
|
8677
|
-
timestamp: new Date(msg.createdAt).getTime()
|
|
8678
|
-
});
|
|
8679
|
-
}
|
|
8680
|
-
}
|
|
8681
|
-
return messages;
|
|
8682
|
-
});
|
|
8722
|
+
const response = await apiClient.getSessionQueries(session.id);
|
|
8723
|
+
const queries = response.queries;
|
|
8724
|
+
const uiMessages = convertQueriesToUIMessages(queries);
|
|
8683
8725
|
setSessionId(session.id);
|
|
8684
8726
|
setContextSessionId(session.id);
|
|
8685
8727
|
if (session.providerSessionId) {
|
|
@@ -8705,7 +8747,7 @@ var init_interactive = __esm({
|
|
|
8705
8747
|
uiMessages.push({
|
|
8706
8748
|
id: `resume-info-${Date.now()}`,
|
|
8707
8749
|
type: "error",
|
|
8708
|
-
content: `Resumed session: ${session.title || "Untitled"} (${
|
|
8750
|
+
content: `Resumed session: ${session.title || "Untitled"} (${queries.length} queries loaded)`,
|
|
8709
8751
|
errorType: "info",
|
|
8710
8752
|
timestamp: Date.now()
|
|
8711
8753
|
});
|
|
@@ -9432,6 +9474,36 @@ async function readStdin() {
|
|
|
9432
9474
|
// src/index.ts
|
|
9433
9475
|
init_token_storage();
|
|
9434
9476
|
init_version();
|
|
9477
|
+
var looksLikeAnthropicKey = (key) => !!key && key.startsWith("sk-ant-");
|
|
9478
|
+
var normalizeSupatestKey = (key, { isHeadless }) => {
|
|
9479
|
+
if (!key) return void 0;
|
|
9480
|
+
if (looksLikeAnthropicKey(key)) {
|
|
9481
|
+
const message = "Detected an Anthropic API key. Use a Supatest API key (sk_test_/sk_live_) or run `supatest login` for a CLI token.";
|
|
9482
|
+
if (isHeadless) {
|
|
9483
|
+
logger.error(message);
|
|
9484
|
+
process.exit(1);
|
|
9485
|
+
} else {
|
|
9486
|
+
logger.warn(`${message} Ignoring the provided key and prompting for login.`);
|
|
9487
|
+
return void 0;
|
|
9488
|
+
}
|
|
9489
|
+
}
|
|
9490
|
+
return key;
|
|
9491
|
+
};
|
|
9492
|
+
process.on("uncaughtException", (error) => {
|
|
9493
|
+
logger.error(`Uncaught exception: ${error.message}`);
|
|
9494
|
+
if (error.stack) {
|
|
9495
|
+
console.error(error.stack);
|
|
9496
|
+
}
|
|
9497
|
+
process.exit(1);
|
|
9498
|
+
});
|
|
9499
|
+
process.on("unhandledRejection", (reason, promise) => {
|
|
9500
|
+
const errorMessage = reason instanceof Error ? reason.message : String(reason);
|
|
9501
|
+
logger.error(`Unhandled promise rejection: ${errorMessage}`);
|
|
9502
|
+
if (reason instanceof Error && reason.stack) {
|
|
9503
|
+
console.error(reason.stack);
|
|
9504
|
+
}
|
|
9505
|
+
process.exit(1);
|
|
9506
|
+
});
|
|
9435
9507
|
var program = new Command();
|
|
9436
9508
|
program.name("supatest").description(
|
|
9437
9509
|
"AI-powered task automation CLI for CI/CD - fix tests, lint issues, and more"
|
|
@@ -9475,7 +9547,10 @@ program.name("supatest").description(
|
|
|
9475
9547
|
let supatestApiKey;
|
|
9476
9548
|
const supatestApiUrl = options.supatestApiUrl || config.supatestApiUrl;
|
|
9477
9549
|
if (isHeadlessMode) {
|
|
9478
|
-
supatestApiKey =
|
|
9550
|
+
supatestApiKey = normalizeSupatestKey(
|
|
9551
|
+
options.supatestApiKey || config.supatestApiKey,
|
|
9552
|
+
{ isHeadless: true }
|
|
9553
|
+
);
|
|
9479
9554
|
if (!supatestApiKey) {
|
|
9480
9555
|
logger.error(
|
|
9481
9556
|
"API key required in CI/headless mode. Please either:"
|
|
@@ -9489,7 +9564,10 @@ program.name("supatest").description(
|
|
|
9489
9564
|
if (cliToken) {
|
|
9490
9565
|
supatestApiKey = cliToken;
|
|
9491
9566
|
} else {
|
|
9492
|
-
supatestApiKey =
|
|
9567
|
+
supatestApiKey = normalizeSupatestKey(
|
|
9568
|
+
options.supatestApiKey || config.supatestApiKey,
|
|
9569
|
+
{ isHeadless: false }
|
|
9570
|
+
);
|
|
9493
9571
|
}
|
|
9494
9572
|
}
|
|
9495
9573
|
let selectedModel;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supatest/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Supatest CLI - AI-powered task automation for CI/CD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@anthropic-ai/claude-agent-sdk": "^0.1.
|
|
43
|
-
"@anthropic-ai/sdk": "^0.71.
|
|
42
|
+
"@anthropic-ai/claude-agent-sdk": "^0.1.61",
|
|
43
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
44
44
|
"@types/inquirer": "^9.0.0",
|
|
45
45
|
"ansi-escapes": "^7.0.0",
|
|
46
46
|
"boxen": "^8.0.1",
|