@supatest/cli 0.0.61 → 0.0.63
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 +388 -157
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5888,7 +5888,7 @@ var CLI_VERSION;
|
|
|
5888
5888
|
var init_version = __esm({
|
|
5889
5889
|
"src/version.ts"() {
|
|
5890
5890
|
"use strict";
|
|
5891
|
-
CLI_VERSION = "0.0.
|
|
5891
|
+
CLI_VERSION = "0.0.63";
|
|
5892
5892
|
}
|
|
5893
5893
|
});
|
|
5894
5894
|
|
|
@@ -7736,7 +7736,7 @@ ${projectInstructions}`,
|
|
|
7736
7736
|
return result;
|
|
7737
7737
|
}
|
|
7738
7738
|
async resolveClaudeCodePath() {
|
|
7739
|
-
const
|
|
7739
|
+
const fs5 = await import("fs/promises");
|
|
7740
7740
|
let claudeCodePath;
|
|
7741
7741
|
const require2 = createRequire(import.meta.url);
|
|
7742
7742
|
const sdkPath = require2.resolve("@anthropic-ai/claude-agent-sdk");
|
|
@@ -7747,7 +7747,7 @@ ${projectInstructions}`,
|
|
|
7747
7747
|
logger.debug(`[agent] Using SUPATEST_CLAUDE_CODE_PATH override: ${claudeCodePath}`);
|
|
7748
7748
|
}
|
|
7749
7749
|
try {
|
|
7750
|
-
await
|
|
7750
|
+
await fs5.access(claudeCodePath);
|
|
7751
7751
|
logger.debug(`[agent] Claude Code CLI found: ${claudeCodePath}`);
|
|
7752
7752
|
} catch {
|
|
7753
7753
|
const error = `Claude Code executable not found at: ${claudeCodePath}
|
|
@@ -8383,61 +8383,275 @@ var init_banner = __esm({
|
|
|
8383
8383
|
}
|
|
8384
8384
|
});
|
|
8385
8385
|
|
|
8386
|
+
// src/ui/utils/detect-terminal-theme.ts
|
|
8387
|
+
import { execSync as execSync2 } from "child_process";
|
|
8388
|
+
import * as fs3 from "fs";
|
|
8389
|
+
function parseX11Rgb(r, g, b) {
|
|
8390
|
+
const normalize = (hex) => {
|
|
8391
|
+
const val = Number.parseInt(hex, 16);
|
|
8392
|
+
switch (hex.length) {
|
|
8393
|
+
case 1:
|
|
8394
|
+
return val * 17;
|
|
8395
|
+
// 0xF -> 255
|
|
8396
|
+
case 2:
|
|
8397
|
+
return val;
|
|
8398
|
+
// 0xFF -> 255
|
|
8399
|
+
case 3:
|
|
8400
|
+
return Math.round(val / 16.06);
|
|
8401
|
+
// 0xFFF -> 255
|
|
8402
|
+
case 4:
|
|
8403
|
+
return Math.round(val / 257);
|
|
8404
|
+
// 0xFFFF -> 255
|
|
8405
|
+
default:
|
|
8406
|
+
return val;
|
|
8407
|
+
}
|
|
8408
|
+
};
|
|
8409
|
+
return { r: normalize(r), g: normalize(g), b: normalize(b) };
|
|
8410
|
+
}
|
|
8411
|
+
function luminance(r, g, b) {
|
|
8412
|
+
const [rs, gs, bs] = [r / 255, g / 255, b / 255].map(
|
|
8413
|
+
(c) => c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
|
|
8414
|
+
);
|
|
8415
|
+
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
8416
|
+
}
|
|
8417
|
+
function fromEnvOverride() {
|
|
8418
|
+
const val = process.env.SUPATEST_THEME?.toLowerCase();
|
|
8419
|
+
if (val === "dark" || val === "light") return val;
|
|
8420
|
+
return null;
|
|
8421
|
+
}
|
|
8422
|
+
function fromColorfgbg() {
|
|
8423
|
+
const val = process.env.COLORFGBG;
|
|
8424
|
+
if (!val) return null;
|
|
8425
|
+
const parts = val.split(";");
|
|
8426
|
+
const bg = Number.parseInt(parts[parts.length - 1], 10);
|
|
8427
|
+
if (Number.isNaN(bg)) return null;
|
|
8428
|
+
if (bg >= 0 && bg <= 6) return "dark";
|
|
8429
|
+
if (bg >= 9 && bg <= 15) return "light";
|
|
8430
|
+
return null;
|
|
8431
|
+
}
|
|
8432
|
+
function fromOsc11() {
|
|
8433
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
|
|
8434
|
+
if (!process.stdin.setRawMode) return null;
|
|
8435
|
+
let ttyFd = null;
|
|
8436
|
+
try {
|
|
8437
|
+
ttyFd = fs3.openSync("/dev/tty", fs3.constants.O_RDWR | fs3.constants.O_NONBLOCK);
|
|
8438
|
+
process.stdin.setRawMode(true);
|
|
8439
|
+
fs3.writeSync(ttyFd, "\x1B]11;?\x07");
|
|
8440
|
+
const buf = Buffer.alloc(64);
|
|
8441
|
+
let response = "";
|
|
8442
|
+
const startTime = Date.now();
|
|
8443
|
+
const TIMEOUT_MS = 100;
|
|
8444
|
+
while (Date.now() - startTime < TIMEOUT_MS) {
|
|
8445
|
+
try {
|
|
8446
|
+
const bytesRead = fs3.readSync(ttyFd, buf, 0, buf.length, null);
|
|
8447
|
+
if (bytesRead > 0) {
|
|
8448
|
+
response += buf.toString("utf8", 0, bytesRead);
|
|
8449
|
+
if (response.includes("\x07") || response.includes("\x1B\\")) {
|
|
8450
|
+
break;
|
|
8451
|
+
}
|
|
8452
|
+
}
|
|
8453
|
+
} catch {
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8456
|
+
process.stdin.setRawMode(false);
|
|
8457
|
+
fs3.closeSync(ttyFd);
|
|
8458
|
+
ttyFd = null;
|
|
8459
|
+
if (!response) return null;
|
|
8460
|
+
const match = response.match(/rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)/);
|
|
8461
|
+
if (!match) return null;
|
|
8462
|
+
const rgb = parseX11Rgb(match[1], match[2], match[3]);
|
|
8463
|
+
const lum = luminance(rgb.r, rgb.g, rgb.b);
|
|
8464
|
+
return lum < 0.5 ? "dark" : "light";
|
|
8465
|
+
} catch {
|
|
8466
|
+
return null;
|
|
8467
|
+
} finally {
|
|
8468
|
+
try {
|
|
8469
|
+
process.stdin.setRawMode?.(false);
|
|
8470
|
+
} catch {
|
|
8471
|
+
}
|
|
8472
|
+
if (ttyFd !== null) {
|
|
8473
|
+
try {
|
|
8474
|
+
fs3.closeSync(ttyFd);
|
|
8475
|
+
} catch {
|
|
8476
|
+
}
|
|
8477
|
+
}
|
|
8478
|
+
}
|
|
8479
|
+
}
|
|
8480
|
+
function fromMacOsDarkMode() {
|
|
8481
|
+
if (process.platform !== "darwin") return null;
|
|
8482
|
+
try {
|
|
8483
|
+
const result = execSync2("defaults read -g AppleInterfaceStyle 2>/dev/null", {
|
|
8484
|
+
encoding: "utf8",
|
|
8485
|
+
timeout: 500
|
|
8486
|
+
}).trim();
|
|
8487
|
+
return result === "Dark" ? "dark" : "light";
|
|
8488
|
+
} catch {
|
|
8489
|
+
return "light";
|
|
8490
|
+
}
|
|
8491
|
+
}
|
|
8492
|
+
function detectTerminalTheme() {
|
|
8493
|
+
return fromEnvOverride() ?? fromColorfgbg() ?? fromOsc11() ?? fromMacOsDarkMode() ?? "dark";
|
|
8494
|
+
}
|
|
8495
|
+
var init_detect_terminal_theme = __esm({
|
|
8496
|
+
"src/ui/utils/detect-terminal-theme.ts"() {
|
|
8497
|
+
"use strict";
|
|
8498
|
+
}
|
|
8499
|
+
});
|
|
8500
|
+
|
|
8386
8501
|
// src/ui/utils/theme.ts
|
|
8387
|
-
var
|
|
8502
|
+
var theme_exports = {};
|
|
8503
|
+
__export(theme_exports, {
|
|
8504
|
+
getThemeColor: () => getThemeColor,
|
|
8505
|
+
getThemeMode: () => getThemeMode,
|
|
8506
|
+
initTheme: () => initTheme,
|
|
8507
|
+
setThemeMode: () => setThemeMode,
|
|
8508
|
+
theme: () => theme
|
|
8509
|
+
});
|
|
8510
|
+
function getThemeMode() {
|
|
8511
|
+
return activeMode;
|
|
8512
|
+
}
|
|
8513
|
+
function applyPalette(palette) {
|
|
8514
|
+
for (const section of Object.keys(palette)) {
|
|
8515
|
+
const src = palette[section];
|
|
8516
|
+
const dst = theme[section];
|
|
8517
|
+
for (const key of Object.keys(src)) {
|
|
8518
|
+
dst[key] = src[key];
|
|
8519
|
+
}
|
|
8520
|
+
}
|
|
8521
|
+
}
|
|
8522
|
+
function initTheme() {
|
|
8523
|
+
activeMode = detectTerminalTheme();
|
|
8524
|
+
applyPalette(activeMode === "light" ? lightTheme : darkTheme);
|
|
8525
|
+
return activeMode;
|
|
8526
|
+
}
|
|
8527
|
+
function setThemeMode(mode) {
|
|
8528
|
+
activeMode = mode;
|
|
8529
|
+
applyPalette(mode === "light" ? lightTheme : darkTheme);
|
|
8530
|
+
}
|
|
8531
|
+
function getThemeColor(path5) {
|
|
8532
|
+
const parts = path5.split(".");
|
|
8533
|
+
let current = theme;
|
|
8534
|
+
for (const part of parts) {
|
|
8535
|
+
if (current[part] === void 0) {
|
|
8536
|
+
return theme.text.primary;
|
|
8537
|
+
}
|
|
8538
|
+
current = current[part];
|
|
8539
|
+
}
|
|
8540
|
+
return typeof current === "string" ? current : theme.text.primary;
|
|
8541
|
+
}
|
|
8542
|
+
var darkTheme, lightTheme, theme, activeMode;
|
|
8388
8543
|
var init_theme = __esm({
|
|
8389
8544
|
"src/ui/utils/theme.ts"() {
|
|
8390
8545
|
"use strict";
|
|
8391
|
-
|
|
8392
|
-
|
|
8546
|
+
init_detect_terminal_theme();
|
|
8547
|
+
darkTheme = {
|
|
8393
8548
|
text: {
|
|
8394
8549
|
primary: "#FFFFFF",
|
|
8395
8550
|
secondary: "#A0AEC0",
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
//
|
|
8399
|
-
|
|
8551
|
+
// light gray — readable body text on dark bg
|
|
8552
|
+
dim: "#718096",
|
|
8553
|
+
// medium gray — clearly softer than secondary
|
|
8554
|
+
accent: "#2DD4BF",
|
|
8555
|
+
// brighter teal — stands out for interactive elements
|
|
8400
8556
|
accentBg: "#1A6B67",
|
|
8557
|
+
// dark teal bg — white text readable on this
|
|
8401
8558
|
success: "#48BB78",
|
|
8402
|
-
error: "#
|
|
8403
|
-
|
|
8404
|
-
|
|
8559
|
+
error: "#FC8181",
|
|
8560
|
+
// slightly brighter red — easier to spot on dark bg
|
|
8561
|
+
warning: "#F6AD55",
|
|
8562
|
+
// warmer amber — better visibility on dark
|
|
8563
|
+
info: "#63B3ED"
|
|
8564
|
+
// brighter blue — pops more on dark
|
|
8405
8565
|
},
|
|
8406
|
-
// Background colors (for boxed content)
|
|
8407
8566
|
bg: {
|
|
8408
8567
|
primary: "#1A202C",
|
|
8409
8568
|
secondary: "#2D3748",
|
|
8410
8569
|
accent: "#234E52"
|
|
8411
8570
|
},
|
|
8412
|
-
// Borders
|
|
8413
8571
|
border: {
|
|
8414
|
-
default: "#
|
|
8415
|
-
|
|
8416
|
-
|
|
8572
|
+
default: "#4A5568",
|
|
8573
|
+
// darker gray — distinct from text.dim and text.secondary
|
|
8574
|
+
accent: "#2DD4BF",
|
|
8575
|
+
// match text accent
|
|
8576
|
+
error: "#FC8181"
|
|
8417
8577
|
},
|
|
8418
|
-
// Tool/action colors
|
|
8419
8578
|
tool: {
|
|
8420
|
-
read: "#
|
|
8421
|
-
//
|
|
8579
|
+
read: "#63B3ED",
|
|
8580
|
+
// brighter blue
|
|
8422
8581
|
write: "#48BB78",
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
// Pink
|
|
8582
|
+
edit: "#F6AD55",
|
|
8583
|
+
// warmer amber
|
|
8584
|
+
bash: "#4FD1C5",
|
|
8585
|
+
// lighter teal — distinct from accent
|
|
8586
|
+
search: "#B794F4",
|
|
8587
|
+
// brighter purple
|
|
8588
|
+
agent: "#F687B3"
|
|
8589
|
+
// brighter pink
|
|
8432
8590
|
},
|
|
8433
|
-
// Status colors
|
|
8434
8591
|
status: {
|
|
8435
8592
|
pending: "#A0AEC0",
|
|
8436
|
-
inProgress: "#
|
|
8593
|
+
inProgress: "#F6AD55",
|
|
8437
8594
|
completed: "#48BB78",
|
|
8438
|
-
failed: "#
|
|
8595
|
+
failed: "#FC8181"
|
|
8596
|
+
}
|
|
8597
|
+
};
|
|
8598
|
+
lightTheme = {
|
|
8599
|
+
text: {
|
|
8600
|
+
primary: "#1A202C",
|
|
8601
|
+
// near-black — high contrast on white
|
|
8602
|
+
secondary: "#2D3748",
|
|
8603
|
+
// dark gray — clearly readable
|
|
8604
|
+
dim: "#4A5568",
|
|
8605
|
+
// medium-dark gray — replaces the too-faint #718096
|
|
8606
|
+
accent: "#0F766E",
|
|
8607
|
+
// deeper teal — punchy on white/light gray
|
|
8608
|
+
accentBg: "#115E59",
|
|
8609
|
+
// dark teal bg — white text must be readable on this
|
|
8610
|
+
success: "#15803D",
|
|
8611
|
+
// dark green — readable on white
|
|
8612
|
+
error: "#B91C1C",
|
|
8613
|
+
// dark red
|
|
8614
|
+
warning: "#B45309",
|
|
8615
|
+
// dark amber
|
|
8616
|
+
info: "#1D4ED8"
|
|
8617
|
+
// dark blue
|
|
8618
|
+
},
|
|
8619
|
+
bg: {
|
|
8620
|
+
primary: "#F7FAFC",
|
|
8621
|
+
secondary: "#E2E8F0",
|
|
8622
|
+
// slightly darker so it's visible as a distinct region
|
|
8623
|
+
accent: "#CCFBF1"
|
|
8624
|
+
},
|
|
8625
|
+
border: {
|
|
8626
|
+
default: "#94A3B8",
|
|
8627
|
+
// slate-400 — visible on white without being heavy
|
|
8628
|
+
accent: "#0F766E",
|
|
8629
|
+
// match text accent
|
|
8630
|
+
error: "#B91C1C"
|
|
8631
|
+
},
|
|
8632
|
+
tool: {
|
|
8633
|
+
read: "#1D4ED8",
|
|
8634
|
+
// dark blue
|
|
8635
|
+
write: "#15803D",
|
|
8636
|
+
// dark green
|
|
8637
|
+
edit: "#B45309",
|
|
8638
|
+
// dark amber
|
|
8639
|
+
bash: "#0F766E",
|
|
8640
|
+
// deep teal
|
|
8641
|
+
search: "#6D28D9",
|
|
8642
|
+
// dark purple
|
|
8643
|
+
agent: "#BE185D"
|
|
8644
|
+
// dark pink
|
|
8645
|
+
},
|
|
8646
|
+
status: {
|
|
8647
|
+
pending: "#4A5568",
|
|
8648
|
+
inProgress: "#B45309",
|
|
8649
|
+
completed: "#15803D",
|
|
8650
|
+
failed: "#B91C1C"
|
|
8439
8651
|
}
|
|
8440
8652
|
};
|
|
8653
|
+
theme = { ...darkTheme };
|
|
8654
|
+
activeMode = "dark";
|
|
8441
8655
|
}
|
|
8442
8656
|
});
|
|
8443
8657
|
|
|
@@ -9550,16 +9764,17 @@ var init_base = __esm({
|
|
|
9550
9764
|
contextBlock = `<context>
|
|
9551
9765
|
**Before writing any test**, check .supatest/SUPATEST.md for test framework info.
|
|
9552
9766
|
|
|
9553
|
-
**Context-First Principle**:
|
|
9554
|
-
1. Read .supatest/SUPATEST.md
|
|
9555
|
-
2. Read page
|
|
9556
|
-
3.
|
|
9557
|
-
4.
|
|
9767
|
+
**Context-First Principle**: Follow this priority order \u2014 stop as soon as you have enough to write the test:
|
|
9768
|
+
1. Read .supatest/SUPATEST.md \u2014 it may point to page objects or source directories
|
|
9769
|
+
2. Read existing page objects and test spec files \u2014 if these give you enough selectors and flow, write the test
|
|
9770
|
+
3. If you still need context and SUPATEST.md references a source directory, read targeted source files \u2014 but stop as soon as you have actionable selectors or flow details. If each file you read leads to another without yielding anything concrete, you are going in circles \u2014 switch to step 4 instead of continuing
|
|
9771
|
+
4. If source files aren't available, aren't referenced, or reading them isn't yielding progress, use Agent Browser to explore the app \u2014 or ask the user to describe the functionality
|
|
9558
9772
|
|
|
9559
9773
|
If .supatest/SUPATEST.md does NOT exist, you MUST run discovery before doing anything else:
|
|
9560
9774
|
1. Read package.json to detect the framework (Playwright, WebDriverIO, Cypress, etc.)
|
|
9561
|
-
2.
|
|
9562
|
-
3.
|
|
9775
|
+
2. Find and read 2-3 existing test spec files (e.g., \`*.spec.ts\`, \`*.test.ts\`) to learn patterns
|
|
9776
|
+
3. Find and read 1-2 page object files (e.g., \`*.page.ts\`) to learn selector patterns
|
|
9777
|
+
4. Write findings to .supatest/SUPATEST.md including:
|
|
9563
9778
|
- Framework and test command
|
|
9564
9779
|
- File patterns and naming conventions
|
|
9565
9780
|
- **Selector strategy** \u2014 Document exactly what selectors the project uses (e.g., \`[data-test]\` attributes, \`getByRole\`, CSS classes). Your new tests MUST use the same selector strategy as existing tests.
|
|
@@ -9569,7 +9784,7 @@ NEVER edit existing test files or write new tests until discovery is complete an
|
|
|
9569
9784
|
</context>
|
|
9570
9785
|
|
|
9571
9786
|
<bias_to_action>
|
|
9572
|
-
Act on the user's request immediately. Extract the URL and intent from their message and start \u2014 don't ask clarifying questions unless you genuinely cannot determine what to test or where the app is. If the framework isn't detected, check package.json and node_modules yourself.
|
|
9787
|
+
Act on the user's request immediately. Extract the URL and intent from their message and start \u2014 don't ask clarifying questions unless you genuinely cannot determine what to test or where the app is. If the framework isn't detected, check package.json and node_modules yourself. Follow the Context-First priority order, then use Agent Browser if needed. Investigate before asking.
|
|
9573
9788
|
</bias_to_action>
|
|
9574
9789
|
|
|
9575
9790
|
<calibrated_confidence>
|
|
@@ -9836,7 +10051,7 @@ You are Supatest AI, an E2E testing assistant. You explore applications, create
|
|
|
9836
10051
|
**Explore** \u2014 The user wants to understand the app before writing tests. Use Agent Browser to navigate and describe what you see. Don't write test scripts during exploration. Summarize findings and offer to write tests afterward.
|
|
9837
10052
|
|
|
9838
10053
|
**Build** \u2014 The user wants test scripts created:
|
|
9839
|
-
1. **Read
|
|
10054
|
+
1. **Read in priority order**: Check SUPATEST.md \u2192 read page objects and existing test specs \u2192 if still insufficient and SUPATEST.md references a source directory, read relevant source files \u2192 if source files aren't available, use Agent Browser to explore or ask the user to describe the functionality. Stop reading as soon as you have enough to write the test.
|
|
9840
10055
|
2. Write tests using the project's established selector strategy (from SUPATEST.md). If no strategy exists, prefer semantic locators. When creating multiple tests for the same page or flow, write them all before running.
|
|
9841
10056
|
3. Run tests in headless mode. **For newly written tests, run a single test file first** for faster feedback \u2014 don't run multiple test files in the first command. If a process hangs, kill it and check for interactive flags.
|
|
9842
10057
|
4. Fix failures using the fix loop below. Max 5 attempts per test. **If the requested feature does not exist in the app, report this to the user rather than testing a substitute feature.**
|
|
@@ -12196,7 +12411,7 @@ __export(secret_storage_exports, {
|
|
|
12196
12411
|
listSecrets: () => listSecrets,
|
|
12197
12412
|
setSecret: () => setSecret
|
|
12198
12413
|
});
|
|
12199
|
-
import { promises as
|
|
12414
|
+
import { promises as fs4 } from "fs";
|
|
12200
12415
|
import { homedir as homedir7 } from "os";
|
|
12201
12416
|
import { dirname as dirname2, join as join9 } from "path";
|
|
12202
12417
|
async function getSecret(key) {
|
|
@@ -12228,11 +12443,11 @@ var init_secret_storage = __esm({
|
|
|
12228
12443
|
}
|
|
12229
12444
|
async ensureDirectoryExists() {
|
|
12230
12445
|
const dir = dirname2(this.secretFilePath);
|
|
12231
|
-
await
|
|
12446
|
+
await fs4.mkdir(dir, { recursive: true, mode: 448 });
|
|
12232
12447
|
}
|
|
12233
12448
|
async loadSecrets() {
|
|
12234
12449
|
try {
|
|
12235
|
-
const data = await
|
|
12450
|
+
const data = await fs4.readFile(this.secretFilePath, "utf-8");
|
|
12236
12451
|
const secrets = JSON.parse(data);
|
|
12237
12452
|
return new Map(Object.entries(secrets));
|
|
12238
12453
|
} catch (error) {
|
|
@@ -12241,7 +12456,7 @@ var init_secret_storage = __esm({
|
|
|
12241
12456
|
return /* @__PURE__ */ new Map();
|
|
12242
12457
|
}
|
|
12243
12458
|
try {
|
|
12244
|
-
await
|
|
12459
|
+
await fs4.unlink(this.secretFilePath);
|
|
12245
12460
|
} catch {
|
|
12246
12461
|
}
|
|
12247
12462
|
return /* @__PURE__ */ new Map();
|
|
@@ -12251,7 +12466,7 @@ var init_secret_storage = __esm({
|
|
|
12251
12466
|
await this.ensureDirectoryExists();
|
|
12252
12467
|
const data = Object.fromEntries(secrets);
|
|
12253
12468
|
const json = JSON.stringify(data, null, 2);
|
|
12254
|
-
await
|
|
12469
|
+
await fs4.writeFile(this.secretFilePath, json, { mode: 384 });
|
|
12255
12470
|
}
|
|
12256
12471
|
async getSecret(key) {
|
|
12257
12472
|
const secrets = await this.loadSecrets();
|
|
@@ -12270,7 +12485,7 @@ var init_secret_storage = __esm({
|
|
|
12270
12485
|
secrets.delete(key);
|
|
12271
12486
|
if (secrets.size === 0) {
|
|
12272
12487
|
try {
|
|
12273
|
-
await
|
|
12488
|
+
await fs4.unlink(this.secretFilePath);
|
|
12274
12489
|
} catch (error) {
|
|
12275
12490
|
const err = error;
|
|
12276
12491
|
if (err.code !== "ENOENT") {
|
|
@@ -13436,7 +13651,7 @@ function KeypressProvider({
|
|
|
13436
13651
|
config: config2,
|
|
13437
13652
|
debugKeystrokeLogging
|
|
13438
13653
|
}) {
|
|
13439
|
-
const { stdin, setRawMode } = useStdin2();
|
|
13654
|
+
const { stdin, setRawMode, internal_eventEmitter } = useStdin2();
|
|
13440
13655
|
const subscribers = useRef5(/* @__PURE__ */ new Set()).current;
|
|
13441
13656
|
const subscribe = useCallback3(
|
|
13442
13657
|
(handler) => subscribers.add(handler),
|
|
@@ -13451,8 +13666,8 @@ function KeypressProvider({
|
|
|
13451
13666
|
[subscribers]
|
|
13452
13667
|
);
|
|
13453
13668
|
useEffect4(() => {
|
|
13454
|
-
const
|
|
13455
|
-
if (
|
|
13669
|
+
const isRawModeSupported = stdin.isTTY;
|
|
13670
|
+
if (isRawModeSupported) {
|
|
13456
13671
|
setRawMode(true);
|
|
13457
13672
|
}
|
|
13458
13673
|
process.stdin.setEncoding("utf8");
|
|
@@ -13460,15 +13675,15 @@ function KeypressProvider({
|
|
|
13460
13675
|
const backslashBufferer = bufferBackslashEnter(mouseFilterer);
|
|
13461
13676
|
const pasteBufferer = bufferPaste(backslashBufferer);
|
|
13462
13677
|
const oscBufferer = bufferOSC(pasteBufferer);
|
|
13463
|
-
|
|
13464
|
-
|
|
13678
|
+
const dataListener = createDataListener(oscBufferer);
|
|
13679
|
+
internal_eventEmitter.on("input", dataListener);
|
|
13465
13680
|
return () => {
|
|
13466
|
-
|
|
13467
|
-
if (
|
|
13681
|
+
internal_eventEmitter.removeListener("input", dataListener);
|
|
13682
|
+
if (isRawModeSupported) {
|
|
13468
13683
|
setRawMode(false);
|
|
13469
13684
|
}
|
|
13470
13685
|
};
|
|
13471
|
-
}, [stdin, setRawMode, config2, debugKeystrokeLogging, broadcast]);
|
|
13686
|
+
}, [stdin, setRawMode, internal_eventEmitter, config2, debugKeystrokeLogging, broadcast]);
|
|
13472
13687
|
return /* @__PURE__ */ React17.createElement(KeypressContext.Provider, { value: { subscribe, unsubscribe } }, children);
|
|
13473
13688
|
}
|
|
13474
13689
|
var BACKSLASH_ENTER_TIMEOUT, ESC_TIMEOUT, PASTE_TIMEOUT, KEY_INFO_MAP, kUTF16SurrogateThreshold, MAC_ALT_KEY_CHARACTER_MAP, OSC_TIMEOUT, KeypressContext;
|
|
@@ -13963,7 +14178,7 @@ var init_ConflictResolver = __esm({
|
|
|
13963
14178
|
return;
|
|
13964
14179
|
}
|
|
13965
14180
|
});
|
|
13966
|
-
return /* @__PURE__ */ React19.createElement(Box16, { borderColor:
|
|
14181
|
+
return /* @__PURE__ */ React19.createElement(Box16, { borderColor: theme.text.warning, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React19.createElement(Text14, { bold: true, color: theme.text.warning }, "Assignment Conflicts"), /* @__PURE__ */ React19.createElement(Box16, { marginBottom: 1, marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text14, { color: theme.text.dim }, "These tests are already assigned:")), /* @__PURE__ */ React19.createElement(Box16, { flexDirection: "column" }, conflicts.map((conflict, index) => {
|
|
13967
14182
|
const isFocused = index === focusIndex;
|
|
13968
14183
|
const decision = decisions.get(conflict.testId) ?? "skip";
|
|
13969
14184
|
const indicator = isFocused ? "\u25B6 " : " ";
|
|
@@ -13975,7 +14190,7 @@ var init_ConflictResolver = __esm({
|
|
|
13975
14190
|
color: isFocused ? theme.text.primary : theme.text.dim
|
|
13976
14191
|
},
|
|
13977
14192
|
indicator,
|
|
13978
|
-
/* @__PURE__ */ React19.createElement(Text14, { color: decision === "takeOver" ?
|
|
14193
|
+
/* @__PURE__ */ React19.createElement(Text14, { color: decision === "takeOver" ? theme.text.success : theme.text.warning }, actionLabel),
|
|
13979
14194
|
" ",
|
|
13980
14195
|
conflict.testFile,
|
|
13981
14196
|
" - ",
|
|
@@ -13991,18 +14206,26 @@ var init_ConflictResolver = __esm({
|
|
|
13991
14206
|
// src/ui/components/ManualTestSelector.tsx
|
|
13992
14207
|
import { Box as Box17, Text as Text15, useInput as useInput2 } from "ink";
|
|
13993
14208
|
import React20, { useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
|
|
13994
|
-
var PAGE_SIZE, VISIBLE_ITEMS,
|
|
14209
|
+
var PAGE_SIZE, VISIBLE_ITEMS, getPriorityColor, ManualTestSelector;
|
|
13995
14210
|
var init_ManualTestSelector = __esm({
|
|
13996
14211
|
"src/ui/components/ManualTestSelector.tsx"() {
|
|
13997
14212
|
"use strict";
|
|
13998
14213
|
init_theme();
|
|
13999
14214
|
PAGE_SIZE = 50;
|
|
14000
14215
|
VISIBLE_ITEMS = 10;
|
|
14001
|
-
|
|
14002
|
-
|
|
14003
|
-
|
|
14004
|
-
|
|
14005
|
-
|
|
14216
|
+
getPriorityColor = (priority) => {
|
|
14217
|
+
switch (priority) {
|
|
14218
|
+
case "critical":
|
|
14219
|
+
return theme.text.error;
|
|
14220
|
+
case "high":
|
|
14221
|
+
return theme.text.warning;
|
|
14222
|
+
case "medium":
|
|
14223
|
+
return theme.text.accent;
|
|
14224
|
+
case "low":
|
|
14225
|
+
return theme.text.success;
|
|
14226
|
+
default:
|
|
14227
|
+
return theme.text.dim;
|
|
14228
|
+
}
|
|
14006
14229
|
};
|
|
14007
14230
|
ManualTestSelector = ({
|
|
14008
14231
|
apiClient,
|
|
@@ -14145,19 +14368,19 @@ var init_ManualTestSelector = __esm({
|
|
|
14145
14368
|
}
|
|
14146
14369
|
});
|
|
14147
14370
|
if (error) {
|
|
14148
|
-
return /* @__PURE__ */ React20.createElement(Box17, { borderColor:
|
|
14371
|
+
return /* @__PURE__ */ React20.createElement(Box17, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React20.createElement(Text15, { bold: true, color: theme.text.error }, "Error Loading Manual Tests"), /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, error), /* @__PURE__ */ React20.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "ESC"), " to go back")));
|
|
14149
14372
|
}
|
|
14150
14373
|
if (allTests.length === 0 && isLoading) {
|
|
14151
|
-
return /* @__PURE__ */ React20.createElement(Box17, { borderColor:
|
|
14374
|
+
return /* @__PURE__ */ React20.createElement(Box17, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React20.createElement(Text15, { bold: true, color: theme.text.accent }, "Loading Manual Tests..."), /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, "Fetching your manual test catalog"));
|
|
14152
14375
|
}
|
|
14153
14376
|
if (allTests.length === 0 && !isLoading) {
|
|
14154
|
-
return /* @__PURE__ */ React20.createElement(Box17, { borderColor:
|
|
14377
|
+
return /* @__PURE__ */ React20.createElement(Box17, { borderColor: theme.text.warning, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React20.createElement(Text15, { bold: true, color: theme.text.warning }, "No Manual Tests Found"), /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, "Create manual tests in the dashboard or via MCP first."), /* @__PURE__ */ React20.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "ESC"), " to go back")));
|
|
14155
14378
|
}
|
|
14156
14379
|
const testStartIndex = cursorIndex - 1;
|
|
14157
14380
|
const adjustedStart = isOnAutomateNext ? 0 : Math.max(0, testStartIndex - Math.floor(VISIBLE_ITEMS / 2));
|
|
14158
14381
|
const adjustedEnd = Math.min(allTests.length, adjustedStart + VISIBLE_ITEMS);
|
|
14159
14382
|
const visibleTests = allTests.slice(adjustedStart, adjustedEnd);
|
|
14160
|
-
return /* @__PURE__ */ React20.createElement(Box17, { borderColor:
|
|
14383
|
+
return /* @__PURE__ */ React20.createElement(Box17, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text15, { bold: true, color: theme.text.accent }, "Manual Tests", /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, " \u2022 ", total, " total"), searchQuery && /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.warning }, ' \u2022 search: "', searchQuery, '"'))), isSearchMode ? /* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.accent }, "Search: "), /* @__PURE__ */ React20.createElement(Text15, null, pendingSearch), /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, "\u2588")) : /* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "/"), " to search")), /* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(
|
|
14161
14384
|
Text15,
|
|
14162
14385
|
{
|
|
14163
14386
|
backgroundColor: isOnAutomateNext ? theme.text.accentBg : void 0,
|
|
@@ -14190,7 +14413,7 @@ var init_ManualTestSelector = __esm({
|
|
|
14190
14413
|
Text15,
|
|
14191
14414
|
{
|
|
14192
14415
|
backgroundColor: bgColor,
|
|
14193
|
-
color: isChecked ?
|
|
14416
|
+
color: isChecked ? theme.text.success : isSelected ? "white" : theme.text.dim
|
|
14194
14417
|
},
|
|
14195
14418
|
checkbox
|
|
14196
14419
|
), /* @__PURE__ */ React20.createElement(Text15, null, " "), /* @__PURE__ */ React20.createElement(
|
|
@@ -14204,14 +14427,14 @@ var init_ManualTestSelector = __esm({
|
|
|
14204
14427
|
Text15,
|
|
14205
14428
|
{
|
|
14206
14429
|
backgroundColor: bgColor,
|
|
14207
|
-
color: isSelected ? "white" :
|
|
14430
|
+
color: isSelected ? "white" : getPriorityColor(test.priority)
|
|
14208
14431
|
},
|
|
14209
14432
|
" ",
|
|
14210
14433
|
"[",
|
|
14211
14434
|
test.priority,
|
|
14212
14435
|
"]"
|
|
14213
14436
|
), test.tags.length > 0 && /* @__PURE__ */ React20.createElement(Text15, { backgroundColor: bgColor, color: isSelected ? "white" : theme.text.dim }, " ", test.tags.slice(0, 2).map((t) => `#${t}`).join(" ")));
|
|
14214
|
-
})), /* @__PURE__ */ React20.createElement(Box17, { flexDirection: "column", marginTop: 1 }, allTests.length > VISIBLE_ITEMS && /* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color:
|
|
14437
|
+
})), /* @__PURE__ */ React20.createElement(Box17, { flexDirection: "column", marginTop: 1 }, allTests.length > VISIBLE_ITEMS && /* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.warning }, "Showing ", adjustedStart + 1, "\u2013", adjustedEnd, " of ", allTests.length, hasMore && !isLoading && /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, " (scroll for more)"))), /* @__PURE__ */ React20.createElement(Box17, null, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.dim }, /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "\u2191\u2193"), " navigate \u2022", " ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "Space"), " toggle \u2022", " ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "a"), " all \u2022", " ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "n"), " none \u2022", " ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "/"), " search \u2022", " ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "Enter"), " automate selected \u2022", " ", /* @__PURE__ */ React20.createElement(Text15, { bold: true }, "ESC"), " cancel")), selectedTests.size > 0 && /* @__PURE__ */ React20.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.success }, selectedTests.size, " test", selectedTests.size !== 1 ? "s" : "", " selected")), isLoading && /* @__PURE__ */ React20.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text15, { color: theme.text.accent }, "Loading more tests..."))));
|
|
14215
14438
|
};
|
|
14216
14439
|
}
|
|
14217
14440
|
});
|
|
@@ -14392,7 +14615,7 @@ Press ESC to go back.`
|
|
|
14392
14615
|
description: "Start without claiming \u2014 assign later via /manage"
|
|
14393
14616
|
}
|
|
14394
14617
|
];
|
|
14395
|
-
return /* @__PURE__ */ React21.createElement(Box18, { borderColor:
|
|
14618
|
+
return /* @__PURE__ */ React21.createElement(Box18, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React21.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text16, { bold: true, color: theme.text.accent }, "Assign ", count, " test", count !== 1 ? "s" : "", " to yourself?")), /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", marginBottom: 1 }, options.map((opt, index) => {
|
|
14396
14619
|
const isSelected = index === assignPromptIndex;
|
|
14397
14620
|
return /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", key: opt.label }, /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(
|
|
14398
14621
|
Text16,
|
|
@@ -14403,11 +14626,11 @@ Press ESC to go back.`
|
|
|
14403
14626
|
},
|
|
14404
14627
|
isSelected ? "\u25B6 " : " ",
|
|
14405
14628
|
opt.label
|
|
14406
|
-
)), /* @__PURE__ */ React21.createElement(Box18, { marginLeft: 4 }, /* @__PURE__ */ React21.createElement(Text16, { color: isSelected ? theme.text.primary : theme.text.dim
|
|
14629
|
+
)), /* @__PURE__ */ React21.createElement(Box18, { marginLeft: 4 }, /* @__PURE__ */ React21.createElement(Text16, { color: isSelected ? theme.text.primary : theme.text.dim }, opt.description)));
|
|
14407
14630
|
})), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "\u2191\u2193"), " navigate \u2022 ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "Enter"), " select \u2022 ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "ESC"), " back")));
|
|
14408
14631
|
}
|
|
14409
14632
|
case "claiming-tests":
|
|
14410
|
-
return /* @__PURE__ */ React21.createElement(Box18, { borderColor:
|
|
14633
|
+
return /* @__PURE__ */ React21.createElement(Box18, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React21.createElement(Text16, { bold: true, color: theme.text.accent }, "Claiming Tests..."), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, "Assigning ", selectedTests.length, " test", selectedTests.length !== 1 ? "s" : "", " to you...")));
|
|
14411
14634
|
case "resolve-conflicts":
|
|
14412
14635
|
return /* @__PURE__ */ React21.createElement(
|
|
14413
14636
|
ConflictResolver,
|
|
@@ -14418,11 +14641,11 @@ Press ESC to go back.`
|
|
|
14418
14641
|
}
|
|
14419
14642
|
);
|
|
14420
14643
|
case "loading-details":
|
|
14421
|
-
return /* @__PURE__ */ React21.createElement(Box18, { borderColor:
|
|
14644
|
+
return /* @__PURE__ */ React21.createElement(Box18, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React21.createElement(Text16, { bold: true, color: theme.text.accent }, "Preparing Context..."), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, "Writing test specs to context file...")));
|
|
14422
14645
|
case "automating":
|
|
14423
|
-
return /* @__PURE__ */ React21.createElement(Box18, { borderColor:
|
|
14646
|
+
return /* @__PURE__ */ React21.createElement(Box18, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React21.createElement(Text16, { bold: true, color: theme.text.accent }, "Automating ", selectedTests.length, " Test", selectedTests.length !== 1 ? "s" : "", "..."), /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", marginTop: 1 }, selectedTests.slice(0, 10).map((test, i) => /* @__PURE__ */ React21.createElement(Box18, { key: test.id }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, i + 1, ". ", test.readableId, " \u2014 ", test.title, test.priority && /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, " [", test.priority, "]")))), selectedTests.length > 10 && /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, "... and ", selectedTests.length - 10, " more")), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, "The agent will analyze each test spec and write automated test code...")));
|
|
14424
14647
|
case "error":
|
|
14425
|
-
return /* @__PURE__ */ React21.createElement(Box18, { borderColor:
|
|
14648
|
+
return /* @__PURE__ */ React21.createElement(Box18, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React21.createElement(Text16, { bold: true, color: theme.text.error }, "Error"), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, loadError)), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text16, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React21.createElement(Text16, { bold: true }, "ESC"), " to go back")));
|
|
14426
14649
|
default:
|
|
14427
14650
|
return null;
|
|
14428
14651
|
}
|
|
@@ -14895,13 +15118,13 @@ var init_RunSelector = __esm({
|
|
|
14895
15118
|
}
|
|
14896
15119
|
});
|
|
14897
15120
|
if (error) {
|
|
14898
|
-
return /* @__PURE__ */ React23.createElement(Box20, { borderColor:
|
|
15121
|
+
return /* @__PURE__ */ React23.createElement(Box20, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.error }, "Error Loading Runs"), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, error), /* @__PURE__ */ React23.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React23.createElement(Text18, { bold: true }, "ESC"), " to cancel")));
|
|
14899
15122
|
}
|
|
14900
15123
|
if (allRuns.length === 0 && isLoading) {
|
|
14901
|
-
return /* @__PURE__ */ React23.createElement(Box20, { borderColor:
|
|
15124
|
+
return /* @__PURE__ */ React23.createElement(Box20, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.accent }, "Loading Runs..."), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, "Fetching test runs from the server"));
|
|
14902
15125
|
}
|
|
14903
15126
|
if (allRuns.length === 0 && !isLoading) {
|
|
14904
|
-
return /* @__PURE__ */ React23.createElement(Box20, { borderColor:
|
|
15127
|
+
return /* @__PURE__ */ React23.createElement(Box20, { borderColor: theme.text.warning, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.warning }, "No Runs Found"), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, "No test runs available. Run your tests with the Supatest reporter first."), /* @__PURE__ */ React23.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React23.createElement(Text18, { bold: true }, "ESC"), " to cancel")));
|
|
14905
15128
|
}
|
|
14906
15129
|
let startIndex;
|
|
14907
15130
|
let endIndex;
|
|
@@ -14922,7 +15145,7 @@ var init_RunSelector = __esm({
|
|
|
14922
15145
|
(run) => run.status === "errored" || (run.summary?.failed ?? 0) > 0
|
|
14923
15146
|
).length;
|
|
14924
15147
|
const runningCount = allRuns.filter((run) => run.status === "running").length;
|
|
14925
|
-
return /* @__PURE__ */ React23.createElement(Box20, { borderColor:
|
|
15148
|
+
return /* @__PURE__ */ React23.createElement(Box20, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React23.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.accent }, "Select a Run to Fix")), /* @__PURE__ */ React23.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, "Loaded ", allRuns.length, totalRuns > allRuns.length ? ` of ${totalRuns}` : "", " runs \u2022", " ", failedOrErroredCount, " with failures \u2022 ", runningCount, " running")), /* @__PURE__ */ React23.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, " "), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCell("RUN", RUN_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, " "), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCell("STATUS", STATUS_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, WIDE_GAP), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCell("BRANCH", BRANCH_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, " "), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCell("COMMIT", COMMIT_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, " "), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCellRight("PASS", PASS_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, " "), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCellRight("FAIL", FAIL_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, " "), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCellRight("FLAKY", FLAKY_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, WIDE_GAP), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCell("DURATION", DURATION_COL_WIDTH)), /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.secondary }, WIDE_GAP), /* @__PURE__ */ React23.createElement(Text18, { bold: true, color: theme.text.secondary }, formatCell("CREATED", CREATED_COL_WIDTH))), /* @__PURE__ */ React23.createElement(Box20, { flexDirection: "column" }, visibleRuns.map((run, index) => {
|
|
14926
15149
|
const actualIndex = startIndex + index;
|
|
14927
15150
|
const isSelected = actualIndex === selectedIndex;
|
|
14928
15151
|
const branch = run.git?.branch || "-";
|
|
@@ -14997,7 +15220,7 @@ var init_RunSelector = __esm({
|
|
|
14997
15220
|
formatDurationMs(run.durationMs, run.status),
|
|
14998
15221
|
DURATION_COL_WIDTH
|
|
14999
15222
|
)), /* @__PURE__ */ React23.createElement(Text18, { backgroundColor: bgColor, color: defaultColor }, WIDE_GAP), /* @__PURE__ */ React23.createElement(Text18, { backgroundColor: bgColor, color: mutedColor }, formatCell(createdAgo, CREATED_COL_WIDTH)));
|
|
15000
|
-
})), /* @__PURE__ */ React23.createElement(Box20, { flexDirection: "column", marginTop: 1 }, (allRuns.length > VISIBLE_ITEMS2 || totalRuns > allRuns.length) && /* @__PURE__ */ React23.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color:
|
|
15223
|
+
})), /* @__PURE__ */ React23.createElement(Box20, { flexDirection: "column", marginTop: 1 }, (allRuns.length > VISIBLE_ITEMS2 || totalRuns > allRuns.length) && /* @__PURE__ */ React23.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.warning }, "Showing ", startIndex + 1, "-", endIndex, " of ", totalRuns || allRuns.length, " runs", hasMore && !isLoading && /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, " \u2022 Scroll for more"))), /* @__PURE__ */ React23.createElement(Box20, null, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.dim }, "Use ", /* @__PURE__ */ React23.createElement(Text18, { bold: true }, "\u2191\u2193"), " to navigate \u2022 ", /* @__PURE__ */ React23.createElement(Text18, { bold: true }, "Enter"), " to select \u2022 ", /* @__PURE__ */ React23.createElement(Text18, { bold: true }, "ESC"), " to cancel")), isLoading && /* @__PURE__ */ React23.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text18, { color: theme.text.accent }, "Loading more runs..."))));
|
|
15001
15224
|
};
|
|
15002
15225
|
}
|
|
15003
15226
|
});
|
|
@@ -15259,13 +15482,13 @@ var init_TestSelector = __esm({
|
|
|
15259
15482
|
}
|
|
15260
15483
|
});
|
|
15261
15484
|
if (error) {
|
|
15262
|
-
return /* @__PURE__ */ React24.createElement(Box21, { borderColor:
|
|
15485
|
+
return /* @__PURE__ */ React24.createElement(Box21, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React24.createElement(Text19, { bold: true, color: theme.text.error }, "Error Loading Tests"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, error), /* @__PURE__ */ React24.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "ESC"), " to go back")));
|
|
15263
15486
|
}
|
|
15264
15487
|
if (allTests.length === 0 && isLoading) {
|
|
15265
|
-
return /* @__PURE__ */ React24.createElement(Box21, { borderColor:
|
|
15488
|
+
return /* @__PURE__ */ React24.createElement(Box21, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React24.createElement(Text19, { bold: true, color: theme.text.accent }, "Loading Failed Tests..."), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "Fetching failed tests for this run"));
|
|
15266
15489
|
}
|
|
15267
15490
|
if (allTests.length === 0 && !isLoading) {
|
|
15268
|
-
return /* @__PURE__ */ React24.createElement(Box21, { borderColor:
|
|
15491
|
+
return /* @__PURE__ */ React24.createElement(Box21, { borderColor: theme.text.success, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React24.createElement(Text19, { bold: true, color: theme.text.success }, "No Failed Tests"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "All tests passed in this run. Nothing to fix!"), /* @__PURE__ */ React24.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "ESC"), " to go back")));
|
|
15269
15492
|
}
|
|
15270
15493
|
const testStartIndex = Math.max(0, cursorIndex - 1);
|
|
15271
15494
|
const adjustedStart = isOnFixNext10 ? 0 : Math.max(0, testStartIndex - Math.floor(VISIBLE_ITEMS3 / 2));
|
|
@@ -15275,7 +15498,7 @@ var init_TestSelector = __esm({
|
|
|
15275
15498
|
const commit = run.git?.commit?.slice(0, 7) || "";
|
|
15276
15499
|
const failedCount = run.summary?.failed ?? 0;
|
|
15277
15500
|
const flakyCount = run.summary?.flaky ?? 0;
|
|
15278
|
-
return /* @__PURE__ */ React24.createElement(Box21, { borderColor:
|
|
15501
|
+
return /* @__PURE__ */ React24.createElement(Box21, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { bold: true, color: theme.text.accent }, "Run: ", branch, commit && /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " @ ", commit), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.error }, failedCount, " failed"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, flakyCount, " flaky"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.success }, availableCount, " avail"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, assignedCount, " working"))), isSearchMode ? /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.accent }, "Search: "), /* @__PURE__ */ React24.createElement(Text19, null, pendingSearch), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "\u2588 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "(Enter to confirm, ESC to clear)")) : /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "[", showAvailableOnly ? "x" : " ", "] ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "t"), " avail only", " ", "[", groupByFile ? "x" : " ", "] ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "f"), " group files", " ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "/"), " search", searchQuery ? /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, ' "', searchQuery, '"') : null)), /* @__PURE__ */ React24.createElement(Box21, { flexDirection: "column" }, /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(
|
|
15279
15502
|
Text19,
|
|
15280
15503
|
{
|
|
15281
15504
|
backgroundColor: isOnFixNext10 ? theme.text.accentBg : void 0,
|
|
@@ -15284,7 +15507,7 @@ var init_TestSelector = __esm({
|
|
|
15284
15507
|
},
|
|
15285
15508
|
isOnFixNext10 ? EXPANSION.COLLAPSED : " ",
|
|
15286
15509
|
availableCount === 0 ? /* @__PURE__ */ React24.createElement(Text19, { color: isOnFixNext10 ? "white" : theme.text.dim }, "[No Available Tests]") : `[Fix Next ${Math.min(10, availableCount)} Available Test${Math.min(10, availableCount) !== 1 ? "s" : ""}]`
|
|
15287
|
-
)), /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")), filteredTests.length === 0 && !isLoading && /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color:
|
|
15510
|
+
)), /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")), filteredTests.length === 0 && !isLoading && /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, showAvailableOnly ? `All ${allTests.length} test${allTests.length !== 1 ? "s" : ""} already assigned. Press t to show all.` : "No tests match the current filters.")), groupByFile ? (
|
|
15288
15511
|
// File Grouping Mode
|
|
15289
15512
|
fileGroups.map((group, index) => {
|
|
15290
15513
|
const itemIndex = index + 1;
|
|
@@ -15294,7 +15517,7 @@ var init_TestSelector = __esm({
|
|
|
15294
15517
|
const fileName = group.file.split("/").pop() || group.file;
|
|
15295
15518
|
const allSelected = group.availableCount > 0 && group.tests.filter((t) => !assignedTestIds.has(t.id)).every((t) => selectedTests.has(t.id));
|
|
15296
15519
|
const someSelected = group.tests.filter((t) => !assignedTestIds.has(t.id)).some((t) => selectedTests.has(t.id));
|
|
15297
|
-
return /* @__PURE__ */ React24.createElement(Box21, { flexDirection: "column", key: group.file, marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Box21, null, /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : theme.text.primary }, indicator), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, color: allSelected ? "green" : someSelected ? "yellow" : isSelected ? "white" : theme.text.dim }, "[", allSelected ? "\u2713" : someSelected ? "\u2297" : " ", "]"), /* @__PURE__ */ React24.createElement(Text19, null, " "), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : theme.text.primary }, fileName), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color:
|
|
15520
|
+
return /* @__PURE__ */ React24.createElement(Box21, { flexDirection: "column", key: group.file, marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Box21, null, /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : theme.text.primary }, indicator), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, color: allSelected ? "green" : someSelected ? "yellow" : isSelected ? "white" : theme.text.dim }, "[", allSelected ? "\u2713" : someSelected ? "\u2297" : " ", "]"), /* @__PURE__ */ React24.createElement(Text19, null, " "), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : theme.text.primary }, fileName), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.success }, group.availableCount, " available"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, group.assignedCount, " working"), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, group.tests.length, " total")), isSelected && group.tests.length <= 5 && /* @__PURE__ */ React24.createElement(Box21, { marginLeft: 2 }, group.tests.map((test) => {
|
|
15298
15521
|
const line = test.location?.line || "";
|
|
15299
15522
|
const title = test.title;
|
|
15300
15523
|
const isAssigned = assignedTestIds.has(test.id);
|
|
@@ -15317,9 +15540,9 @@ var init_TestSelector = __esm({
|
|
|
15317
15540
|
const indicator = isSelected ? EXPANSION.COLLAPSED : " ";
|
|
15318
15541
|
const bgColor = isSelected ? theme.text.accentBg : void 0;
|
|
15319
15542
|
const displayAssignee = assignment?.assignedToName || assignment?.assignedTo || "";
|
|
15320
|
-
return /* @__PURE__ */ React24.createElement(Box21, { key: test.id, marginBottom: 0 }, /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : isAssigned ? theme.text.dim : theme.text.primary }, indicator), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, color: isAssigned ? theme.text.dim : isChecked ? "green" : isSelected ? "white" : theme.text.dim }, isAssigned ? "\u{1F504}" : checkbox), /* @__PURE__ */ React24.createElement(Text19, null, " "), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : isAssigned ? theme.text.dim : theme.text.primary }, file, line && /* @__PURE__ */ React24.createElement(Text19, { color: isSelected ? "white" : theme.text.dim }, ":", line), isAssigned && /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color:
|
|
15543
|
+
return /* @__PURE__ */ React24.createElement(Box21, { key: test.id, marginBottom: 0 }, /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : isAssigned ? theme.text.dim : theme.text.primary }, indicator), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, color: isAssigned ? theme.text.dim : isChecked ? "green" : isSelected ? "white" : theme.text.dim }, isAssigned ? "\u{1F504}" : checkbox), /* @__PURE__ */ React24.createElement(Text19, null, " "), /* @__PURE__ */ React24.createElement(Text19, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : isAssigned ? theme.text.dim : theme.text.primary }, file, line && /* @__PURE__ */ React24.createElement(Text19, { color: isSelected ? "white" : theme.text.dim }, ":", line), isAssigned && /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, displayAssignee)), /* @__PURE__ */ React24.createElement(Text19, { color: isSelected ? "white" : theme.text.dim }, " - "), title));
|
|
15321
15544
|
})
|
|
15322
|
-
)), /* @__PURE__ */ React24.createElement(Box21, { flexDirection: "column", marginTop: 1 }, !groupByFile && filteredTests.length > VISIBLE_ITEMS3 && /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color:
|
|
15545
|
+
)), /* @__PURE__ */ React24.createElement(Box21, { flexDirection: "column", marginTop: 1 }, !groupByFile && filteredTests.length > VISIBLE_ITEMS3 && /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, "Showing ", adjustedStart + 1, "-", adjustedEnd, " of ", filteredTests.length, " ", showAvailableOnly ? "available" : "", " tests", hasMore && !isLoading && /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, " (scroll for more)"))), groupByFile && /* @__PURE__ */ React24.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.warning }, "Showing ", fileGroups.length, " file", fileGroups.length !== 1 ? "s" : "", " \u2022 ", filteredTests.length, " total test", filteredTests.length !== 1 ? "s" : "")), /* @__PURE__ */ React24.createElement(Box21, null, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.dim }, /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "\u2191\u2193"), " navigate \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "Space"), " toggle \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "n"), " none \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "s"), " next 10 \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "/"), " search \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "f"), " group files \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "t"), " filter \u2022 ", /* @__PURE__ */ React24.createElement(Text19, { bold: true }, "Enter"), " fix selected")), selectedTests.size > 0 && /* @__PURE__ */ React24.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.success }, selectedTests.size, " test", selectedTests.size !== 1 ? "s" : "", " selected")), isLoading && /* @__PURE__ */ React24.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React24.createElement(Text19, { color: theme.text.accent }, "Loading more tests..."))));
|
|
15323
15546
|
};
|
|
15324
15547
|
}
|
|
15325
15548
|
});
|
|
@@ -15670,7 +15893,7 @@ Press ESC to go back and try again.`);
|
|
|
15670
15893
|
case "select-tests":
|
|
15671
15894
|
if (!selectedRun) return null;
|
|
15672
15895
|
if (!assignmentsLoaded) {
|
|
15673
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15896
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.accent }, "Loading..."), /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "Fetching assignment data for this run"));
|
|
15674
15897
|
}
|
|
15675
15898
|
return /* @__PURE__ */ React25.createElement(
|
|
15676
15899
|
TestSelector,
|
|
@@ -15697,7 +15920,7 @@ Press ESC to go back and try again.`);
|
|
|
15697
15920
|
description: "Agent fixes everything automatically"
|
|
15698
15921
|
}
|
|
15699
15922
|
];
|
|
15700
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15923
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.accent }, branch, commit && /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, " @ ", commit), /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, " \u2022 "), /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.success }, testCount, " test", testCount !== 1 ? "s" : "", " selected"))), /* @__PURE__ */ React25.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.primary }, "Which mode would you like to proceed with?")), /* @__PURE__ */ React25.createElement(Box22, { flexDirection: "column", marginBottom: 1 }, modes.map((mode, index) => {
|
|
15701
15924
|
const isSelected = index === modeSelectionIndex;
|
|
15702
15925
|
const indicator = isSelected ? EXPANSION.COLLAPSED : " ";
|
|
15703
15926
|
return /* @__PURE__ */ React25.createElement(Box22, { flexDirection: "column", gap: 0, key: mode.label }, /* @__PURE__ */ React25.createElement(Box22, null, /* @__PURE__ */ React25.createElement(
|
|
@@ -15712,8 +15935,7 @@ Press ESC to go back and try again.`);
|
|
|
15712
15935
|
)), /* @__PURE__ */ React25.createElement(Box22, { marginLeft: 4 }, /* @__PURE__ */ React25.createElement(
|
|
15713
15936
|
Text20,
|
|
15714
15937
|
{
|
|
15715
|
-
color: isSelected ? theme.text.primary : theme.text.dim
|
|
15716
|
-
dimColor: !isSelected
|
|
15938
|
+
color: isSelected ? theme.text.primary : theme.text.dim
|
|
15717
15939
|
},
|
|
15718
15940
|
mode.description
|
|
15719
15941
|
)));
|
|
@@ -15731,7 +15953,7 @@ Press ESC to go back and try again.`);
|
|
|
15731
15953
|
description: "Fix without claiming \u2014 you can assign later via /manage"
|
|
15732
15954
|
}
|
|
15733
15955
|
];
|
|
15734
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15956
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.accent }, "Assign these tests to yourself?")), /* @__PURE__ */ React25.createElement(Box22, { flexDirection: "column", marginBottom: 1 }, assignOptions.map((option, index) => {
|
|
15735
15957
|
const isSelected = index === assignPromptIndex;
|
|
15736
15958
|
const indicator = isSelected ? EXPANSION.COLLAPSED : " ";
|
|
15737
15959
|
return /* @__PURE__ */ React25.createElement(Box22, { flexDirection: "column", gap: 0, key: option.label }, /* @__PURE__ */ React25.createElement(Box22, null, /* @__PURE__ */ React25.createElement(
|
|
@@ -15746,15 +15968,14 @@ Press ESC to go back and try again.`);
|
|
|
15746
15968
|
)), /* @__PURE__ */ React25.createElement(Box22, { marginLeft: 4 }, /* @__PURE__ */ React25.createElement(
|
|
15747
15969
|
Text20,
|
|
15748
15970
|
{
|
|
15749
|
-
color: isSelected ? theme.text.primary : theme.text.dim
|
|
15750
|
-
dimColor: !isSelected
|
|
15971
|
+
color: isSelected ? theme.text.primary : theme.text.dim
|
|
15751
15972
|
},
|
|
15752
15973
|
option.description
|
|
15753
15974
|
)));
|
|
15754
15975
|
})), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, /* @__PURE__ */ React25.createElement(Text20, { bold: true }, "\u2191\u2193"), " navigate \u2022 ", /* @__PURE__ */ React25.createElement(Text20, { bold: true }, "Enter"), " select \u2022 ", /* @__PURE__ */ React25.createElement(Text20, { bold: true }, "ESC"), " back")));
|
|
15755
15976
|
}
|
|
15756
15977
|
case "claiming-tests":
|
|
15757
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15978
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.accent }, "Claiming Tests..."), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "Assigning ", selectedTests.length, " test", selectedTests.length !== 1 ? "s" : "", " to you...")));
|
|
15758
15979
|
case "resolve-conflicts":
|
|
15759
15980
|
return /* @__PURE__ */ React25.createElement(
|
|
15760
15981
|
ConflictResolver,
|
|
@@ -15766,17 +15987,17 @@ Press ESC to go back and try again.`);
|
|
|
15766
15987
|
);
|
|
15767
15988
|
case "loading-details":
|
|
15768
15989
|
if (loadError) {
|
|
15769
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15990
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.error }, "Error Loading Test Details"), /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, loadError), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React25.createElement(Text20, { bold: true }, "ESC"), " to go back")));
|
|
15770
15991
|
}
|
|
15771
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15992
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.accent }, "Loading Test Details..."), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "Fetching error messages, stack traces, and execution steps...")), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.warning }, loadingProgress.current, " / ", loadingProgress.total, " tests loaded")));
|
|
15772
15993
|
case "error":
|
|
15773
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15994
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.error }, "Error"), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, loadError)), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React25.createElement(Text20, { bold: true }, "ESC"), " to go back")));
|
|
15774
15995
|
case "fixing": {
|
|
15775
15996
|
const modeLabel = workflowMode === "fix" ? "Analyzing & Fixing" : "Fixing";
|
|
15776
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
15997
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.accent }, modeLabel, " ", selectedTests.length, " Test", selectedTests.length !== 1 ? "s" : "", "..."), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, selectedTests.slice(0, 10).map((test, index) => /* @__PURE__ */ React25.createElement(Box22, { key: test.id }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, index + 1, ". ", test.file.split("/").pop(), ":", test.location?.line || "", " - ", test.title))), selectedTests.length > 10 && /* @__PURE__ */ React25.createElement(Box22, null, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "... and ", selectedTests.length - 10, " more"))), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, workflowMode === "fix" ? "The agent will analyze all failures, present findings, and guide you through fixing..." : "The agent will now analyze and fix each test...")));
|
|
15777
15998
|
}
|
|
15778
15999
|
case "complete":
|
|
15779
|
-
return /* @__PURE__ */ React25.createElement(Box22, { borderColor:
|
|
16000
|
+
return /* @__PURE__ */ React25.createElement(Box22, { borderColor: theme.text.success, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: theme.text.success }, "Tests Marked as Complete"), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "\u2713 ", selectedTests.length, " test", selectedTests.length !== 1 ? "s have" : " has", " been marked as fixed")), /* @__PURE__ */ React25.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: theme.text.dim }, "Press any key to continue...")));
|
|
15780
16001
|
default:
|
|
15781
16002
|
return null;
|
|
15782
16003
|
}
|
|
@@ -16030,26 +16251,26 @@ var init_ModelSelector = __esm({
|
|
|
16030
16251
|
});
|
|
16031
16252
|
|
|
16032
16253
|
// src/ui/components/InputPrompt.tsx
|
|
16254
|
+
import { execSync as execSync6 } from "child_process";
|
|
16033
16255
|
import path4 from "path";
|
|
16034
|
-
import { execSync as execSync5 } from "child_process";
|
|
16035
16256
|
import chalk5 from "chalk";
|
|
16036
16257
|
import { Box as Box24, Text as Text23 } from "ink";
|
|
16037
16258
|
import React28, { forwardRef, memo as memo3, useEffect as useEffect11, useImperativeHandle, useRef as useRef9, useState as useState14 } from "react";
|
|
16038
16259
|
function readClipboard() {
|
|
16039
16260
|
try {
|
|
16040
16261
|
if (process.platform === "win32") {
|
|
16041
|
-
return
|
|
16262
|
+
return execSync6('powershell.exe -NoProfile -Command "Get-Clipboard"', {
|
|
16042
16263
|
encoding: "utf8",
|
|
16043
16264
|
timeout: 2e3
|
|
16044
16265
|
}).replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\n$/, "");
|
|
16045
16266
|
}
|
|
16046
16267
|
if (process.platform === "darwin") {
|
|
16047
|
-
return
|
|
16268
|
+
return execSync6("pbpaste", { encoding: "utf8", timeout: 2e3 });
|
|
16048
16269
|
}
|
|
16049
16270
|
try {
|
|
16050
|
-
return
|
|
16271
|
+
return execSync6("xclip -selection clipboard -o", { encoding: "utf8", timeout: 2e3 });
|
|
16051
16272
|
} catch {
|
|
16052
|
-
return
|
|
16273
|
+
return execSync6("xsel --clipboard --output", { encoding: "utf8", timeout: 2e3 });
|
|
16053
16274
|
}
|
|
16054
16275
|
} catch {
|
|
16055
16276
|
return null;
|
|
@@ -16914,7 +17135,7 @@ var init_ManageFlow = __esm({
|
|
|
16914
17135
|
};
|
|
16915
17136
|
switch (step) {
|
|
16916
17137
|
case "menu":
|
|
16917
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17138
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Work Management"), /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "column", marginBottom: 1, marginTop: 1 }, MANAGE_MENU_OPTIONS.map((option, index) => {
|
|
16918
17139
|
const isSelected = index === menuIndex;
|
|
16919
17140
|
const indicator = isSelected ? EXPANSION.COLLAPSED : " ";
|
|
16920
17141
|
return /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "column", key: option.label }, /* @__PURE__ */ React29.createElement(
|
|
@@ -16930,12 +17151,12 @@ var init_ManageFlow = __esm({
|
|
|
16930
17151
|
})), /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "\u2191\u2193"), " navigate \u2022 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "Enter"), " select \u2022 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " close"));
|
|
16931
17152
|
case "my-work":
|
|
16932
17153
|
if (myWorkLoading) {
|
|
16933
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17154
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Loading..."));
|
|
16934
17155
|
}
|
|
16935
17156
|
if (!myWorkData || myWorkData.assignments.length === 0) {
|
|
16936
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17157
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "My Work"), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "No active assignments")), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " to go back")));
|
|
16937
17158
|
}
|
|
16938
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17159
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "My Work"), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, myWorkData.stats.assigned, " assigned | ", myWorkData.stats.completed, " completed | ", myWorkData.stats.failed, " failed")), /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "column", marginTop: 1 }, myWorkData.assignments.map((a) => /* @__PURE__ */ React29.createElement(Box25, { key: a.id }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.primary }, a.test.file, " - ", a.test.title, " ", /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, formatTimeAgo(a.assignedAt)))))), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " to go back")));
|
|
16939
17160
|
case "assign-run":
|
|
16940
17161
|
return /* @__PURE__ */ React29.createElement(
|
|
16941
17162
|
RunSelector,
|
|
@@ -16961,13 +17182,13 @@ var init_ManageFlow = __esm({
|
|
|
16961
17182
|
);
|
|
16962
17183
|
case "assign-to": {
|
|
16963
17184
|
if (assigneesLoading) {
|
|
16964
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17185
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Loading team members..."));
|
|
16965
17186
|
}
|
|
16966
17187
|
const options = assignees.map((a) => ({
|
|
16967
17188
|
label: a.name || a.email,
|
|
16968
17189
|
description: `${a.email} (${a.activeTests} active)`
|
|
16969
17190
|
}));
|
|
16970
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17191
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Assign to whom?"), /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "column", marginBottom: 1, marginTop: 1 }, options.map((opt, index) => {
|
|
16971
17192
|
const isSelected = index === assigneeIndex;
|
|
16972
17193
|
const indicator = isSelected ? EXPANSION.COLLAPSED : " ";
|
|
16973
17194
|
return /* @__PURE__ */ React29.createElement(Box25, { key: opt.label }, /* @__PURE__ */ React29.createElement(
|
|
@@ -16992,15 +17213,15 @@ var init_ManageFlow = __esm({
|
|
|
16992
17213
|
}
|
|
16993
17214
|
);
|
|
16994
17215
|
case "assign-done":
|
|
16995
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17216
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.text.success, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.success }, "Done"), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.primary }, assignMessage)), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "Enter"), " or ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " to return to menu")));
|
|
16996
17217
|
case "unassign-list": {
|
|
16997
17218
|
if (unassignLoading) {
|
|
16998
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17219
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Loading assignments..."));
|
|
16999
17220
|
}
|
|
17000
17221
|
if (allAssignments.length === 0) {
|
|
17001
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17222
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Unassign"), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "No active assignments")), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " to go back")));
|
|
17002
17223
|
}
|
|
17003
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17224
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.accent }, "Active Assignments (", allAssignments.length, ")"), /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "column", marginTop: 1 }, allAssignments.map((a, index) => {
|
|
17004
17225
|
const isFocused = index === unassignIndex;
|
|
17005
17226
|
const isSelected = unassignSelections.has(index);
|
|
17006
17227
|
const indicator = isFocused ? EXPANSION.COLLAPSED : " ";
|
|
@@ -17023,7 +17244,7 @@ var init_ManageFlow = __esm({
|
|
|
17023
17244
|
})), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "Space"), " toggle \u2022 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "Enter"), " release selected \u2022 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " back")));
|
|
17024
17245
|
}
|
|
17025
17246
|
case "unassign-done":
|
|
17026
|
-
return /* @__PURE__ */ React29.createElement(Box25, { borderColor:
|
|
17247
|
+
return /* @__PURE__ */ React29.createElement(Box25, { borderColor: theme.text.success, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: theme.text.success }, "Done"), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.primary }, unassignMessage)), /* @__PURE__ */ React29.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "Enter"), " or ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "ESC"), " to return to menu")));
|
|
17027
17248
|
default:
|
|
17028
17249
|
return null;
|
|
17029
17250
|
}
|
|
@@ -17365,8 +17586,7 @@ var init_PlanApprovalSelector = __esm({
|
|
|
17365
17586
|
)), /* @__PURE__ */ React33.createElement(Box29, { marginLeft: 4 }, /* @__PURE__ */ React33.createElement(
|
|
17366
17587
|
Text28,
|
|
17367
17588
|
{
|
|
17368
|
-
color: isSelected ? theme.text.primary : theme.text.dim
|
|
17369
|
-
dimColor: !isSelected
|
|
17589
|
+
color: isSelected ? theme.text.primary : theme.text.dim
|
|
17370
17590
|
},
|
|
17371
17591
|
option.description
|
|
17372
17592
|
)));
|
|
@@ -17435,15 +17655,15 @@ var init_ProjectSelector = __esm({
|
|
|
17435
17655
|
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.accent }, "Loading projects..."));
|
|
17436
17656
|
}
|
|
17437
17657
|
if (error) {
|
|
17438
|
-
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Text29, { color:
|
|
17658
|
+
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.error }, "Failed to load projects: ", error), /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.dim }, "Press Esc to cancel"));
|
|
17439
17659
|
}
|
|
17440
17660
|
if (projects.length === 0) {
|
|
17441
|
-
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Text29, { color:
|
|
17661
|
+
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.warning }, "No projects found. Create one at your dashboard first."), /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.dim }, "Press Esc to cancel"));
|
|
17442
17662
|
}
|
|
17443
|
-
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Box30, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text29, { bold: true, color: theme.text.accent }, "Select a project"), /* @__PURE__ */ React34.createElement(Text29, {
|
|
17663
|
+
return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React34.createElement(Box30, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text29, { bold: true, color: theme.text.accent }, "Select a project"), /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.dim }, " (\u2191\u2193 navigate, Enter select, Esc cancel)")), projects.map((project, index) => {
|
|
17444
17664
|
const isSelected = index === selectedIndex;
|
|
17445
17665
|
const isCurrent = project.id === currentProjectId;
|
|
17446
|
-
return /* @__PURE__ */ React34.createElement(Box30, { key: project.id }, /* @__PURE__ */ React34.createElement(Text29, { color: isSelected ? theme.text.accent : void 0 }, isSelected ? "\u276F " : " "), /* @__PURE__ */ React34.createElement(Text29, { bold: isSelected, color: isSelected ? theme.text.accent : void 0 }, project.name), /* @__PURE__ */ React34.createElement(Text29, {
|
|
17666
|
+
return /* @__PURE__ */ React34.createElement(Box30, { key: project.id }, /* @__PURE__ */ React34.createElement(Text29, { color: isSelected ? theme.text.accent : void 0 }, isSelected ? "\u276F " : " "), /* @__PURE__ */ React34.createElement(Text29, { bold: isSelected, color: isSelected ? theme.text.accent : void 0 }, project.name), /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.dim }, " (", project.slug, ")"), isCurrent && /* @__PURE__ */ React34.createElement(Text29, { color: theme.text.success }, " \u2713"));
|
|
17447
17667
|
}));
|
|
17448
17668
|
};
|
|
17449
17669
|
}
|
|
@@ -17633,8 +17853,7 @@ var init_QuestionSelector = __esm({
|
|
|
17633
17853
|
)), /* @__PURE__ */ React36.createElement(Box31, { marginLeft: multiSelect ? 6 : 4 }, /* @__PURE__ */ React36.createElement(
|
|
17634
17854
|
Text31,
|
|
17635
17855
|
{
|
|
17636
|
-
color: isSelected ? theme.text.primary : theme.text.dim
|
|
17637
|
-
dimColor: !isSelected
|
|
17856
|
+
color: isSelected ? theme.text.primary : theme.text.dim
|
|
17638
17857
|
},
|
|
17639
17858
|
option.description
|
|
17640
17859
|
)));
|
|
@@ -17717,13 +17936,13 @@ var init_SessionSelector = __esm({
|
|
|
17717
17936
|
}
|
|
17718
17937
|
});
|
|
17719
17938
|
if (error) {
|
|
17720
|
-
return /* @__PURE__ */ React37.createElement(Box32, { borderColor:
|
|
17939
|
+
return /* @__PURE__ */ React37.createElement(Box32, { borderColor: theme.border.error, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: theme.text.error }, "Error Loading Sessions"), /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, error), /* @__PURE__ */ React37.createElement(Box32, { marginTop: 1 }, /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React37.createElement(Text32, { bold: true }, "ESC"), " to cancel")));
|
|
17721
17940
|
}
|
|
17722
17941
|
if (allSessions.length === 0 && isLoading) {
|
|
17723
|
-
return /* @__PURE__ */ React37.createElement(Box32, { borderColor:
|
|
17942
|
+
return /* @__PURE__ */ React37.createElement(Box32, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: theme.text.accent }, "Loading Sessions..."), /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, "Fetching your sessions from the server"));
|
|
17724
17943
|
}
|
|
17725
17944
|
if (allSessions.length === 0 && !isLoading) {
|
|
17726
|
-
return /* @__PURE__ */ React37.createElement(Box32, { borderColor:
|
|
17945
|
+
return /* @__PURE__ */ React37.createElement(Box32, { borderColor: theme.text.warning, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: theme.text.warning }, "No Sessions Found"), /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, "No previous sessions available. Start a new session!"), /* @__PURE__ */ React37.createElement(Box32, { marginTop: 1 }, /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, "Press ", /* @__PURE__ */ React37.createElement(Text32, { bold: true }, "ESC"), " to cancel")));
|
|
17727
17946
|
}
|
|
17728
17947
|
const VISIBLE_ITEMS4 = 10;
|
|
17729
17948
|
let startIndex;
|
|
@@ -17743,7 +17962,7 @@ var init_SessionSelector = __esm({
|
|
|
17743
17962
|
const visibleSessions = allSessions.slice(startIndex, endIndex);
|
|
17744
17963
|
const MAX_TITLE_WIDTH = 50;
|
|
17745
17964
|
const PREFIX_WIDTH = 6;
|
|
17746
|
-
return /* @__PURE__ */ React37.createElement(Box32, { borderColor:
|
|
17965
|
+
return /* @__PURE__ */ React37.createElement(Box32, { borderColor: theme.border.accent, borderStyle: "round", flexDirection: "column", padding: 1 }, /* @__PURE__ */ React37.createElement(Box32, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: theme.text.accent }, "Select a Session to Resume")), /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column" }, visibleSessions.map((item, index) => {
|
|
17747
17966
|
const actualIndex = startIndex + index;
|
|
17748
17967
|
const isSelected = actualIndex === selectedIndex;
|
|
17749
17968
|
const title = item.session.title || "Untitled session";
|
|
@@ -17764,11 +17983,11 @@ var init_SessionSelector = __esm({
|
|
|
17764
17983
|
dateStr = `${sessionDate.toLocaleDateString([], { month: "numeric", day: "numeric" })} ${sessionDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" })}`;
|
|
17765
17984
|
}
|
|
17766
17985
|
const prefix = item.prefix.padEnd(PREFIX_WIDTH, " ");
|
|
17767
|
-
const prefixColor = item.prefix === "[Me]" ?
|
|
17986
|
+
const prefixColor = item.prefix === "[Me]" ? theme.text.accent : theme.text.warning;
|
|
17768
17987
|
const indicator = isSelected ? EXPANSION.COLLAPSED : " ";
|
|
17769
17988
|
const bgColor = isSelected ? theme.text.accentBg : void 0;
|
|
17770
17989
|
return /* @__PURE__ */ React37.createElement(Box32, { key: item.session.id, width: "100%" }, /* @__PURE__ */ React37.createElement(Text32, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : theme.text.primary }, indicator), /* @__PURE__ */ React37.createElement(Text32, { backgroundColor: bgColor, bold: isSelected, color: prefixColor }, prefix), /* @__PURE__ */ React37.createElement(Text32, { backgroundColor: bgColor, bold: isSelected, color: isSelected ? "white" : theme.text.primary }, displayTitle), /* @__PURE__ */ React37.createElement(Text32, { backgroundColor: bgColor, color: theme.text.dim }, "(", dateStr, ")"));
|
|
17771
|
-
})), /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column", marginTop: 1 }, (allSessions.length > VISIBLE_ITEMS4 || totalSessions > allSessions.length) && /* @__PURE__ */ React37.createElement(Box32, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text32, { color:
|
|
17990
|
+
})), /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column", marginTop: 1 }, (allSessions.length > VISIBLE_ITEMS4 || totalSessions > allSessions.length) && /* @__PURE__ */ React37.createElement(Box32, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.warning }, "Showing ", startIndex + 1, "-", endIndex, " of ", totalSessions || allSessions.length, " sessions", hasMore && !isLoading && /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, " \u2022 Scroll for more"))), /* @__PURE__ */ React37.createElement(Box32, null, /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.dim }, "Use ", /* @__PURE__ */ React37.createElement(Text32, { bold: true }, "\u2191\u2193"), " to navigate \u2022 ", /* @__PURE__ */ React37.createElement(Text32, { bold: true }, "Enter"), " to select \u2022 ", /* @__PURE__ */ React37.createElement(Text32, { bold: true }, "ESC"), " to cancel")), isLoading && /* @__PURE__ */ React37.createElement(Box32, { marginTop: 1 }, /* @__PURE__ */ React37.createElement(Text32, { color: theme.text.accent }, "Loading more sessions..."))));
|
|
17772
17991
|
};
|
|
17773
17992
|
}
|
|
17774
17993
|
});
|
|
@@ -17817,7 +18036,7 @@ var init_useOverlayEscapeGuard = __esm({
|
|
|
17817
18036
|
});
|
|
17818
18037
|
|
|
17819
18038
|
// src/ui/App.tsx
|
|
17820
|
-
import { execSync as
|
|
18039
|
+
import { execSync as execSync7 } from "child_process";
|
|
17821
18040
|
import { homedir as homedir9 } from "os";
|
|
17822
18041
|
import { Box as Box33, Text as Text33, useApp as useApp2, useStdout as useStdout2 } from "ink";
|
|
17823
18042
|
import Spinner4 from "ink-spinner";
|
|
@@ -17863,7 +18082,7 @@ var init_App = __esm({
|
|
|
17863
18082
|
init_theme();
|
|
17864
18083
|
getGitBranch2 = () => {
|
|
17865
18084
|
try {
|
|
17866
|
-
return
|
|
18085
|
+
return execSync7("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
|
|
17867
18086
|
} catch {
|
|
17868
18087
|
return "";
|
|
17869
18088
|
}
|
|
@@ -17958,8 +18177,7 @@ var init_App = __esm({
|
|
|
17958
18177
|
config2.projectId = project.id;
|
|
17959
18178
|
apiClient.setProjectId(project.id);
|
|
17960
18179
|
saveSupatestSettings(config2.cwd || process.cwd(), {
|
|
17961
|
-
projectId: project.slug
|
|
17962
|
-
projectName: project.name
|
|
18180
|
+
projectId: project.slug
|
|
17963
18181
|
});
|
|
17964
18182
|
} else if (result.projects.length > 1) {
|
|
17965
18183
|
addMessage({
|
|
@@ -18056,8 +18274,7 @@ var init_App = __esm({
|
|
|
18056
18274
|
setSavedProjectSlug(void 0);
|
|
18057
18275
|
config2.projectId = void 0;
|
|
18058
18276
|
saveSupatestSettings(config2.cwd || process.cwd(), {
|
|
18059
|
-
projectId: void 0
|
|
18060
|
-
projectName: void 0
|
|
18277
|
+
projectId: void 0
|
|
18061
18278
|
});
|
|
18062
18279
|
setAuthState("unauthenticated" /* Unauthenticated */);
|
|
18063
18280
|
addMessage({
|
|
@@ -18491,8 +18708,7 @@ Make sure the file exists and is a valid image (png, jpg, gif, webp, bmp, svg).`
|
|
|
18491
18708
|
apiClient.setProjectId(project.id);
|
|
18492
18709
|
}
|
|
18493
18710
|
saveSupatestSettings(config2.cwd || process.cwd(), {
|
|
18494
|
-
projectId: project.slug
|
|
18495
|
-
projectName: project.name
|
|
18711
|
+
projectId: project.slug
|
|
18496
18712
|
});
|
|
18497
18713
|
addMessage({
|
|
18498
18714
|
type: "assistant",
|
|
@@ -19041,7 +19257,7 @@ Make sure the file exists and is a valid image (png, jpg, gif, webp, bmp, svg).`
|
|
|
19041
19257
|
onInputChange: handleInputChange,
|
|
19042
19258
|
onSubmit: stableHandleSubmitTask,
|
|
19043
19259
|
placeholder: "Enter your task...",
|
|
19044
|
-
projectName: currentProject?.
|
|
19260
|
+
projectName: currentProject?.slug,
|
|
19045
19261
|
ref: inputPromptRef,
|
|
19046
19262
|
selectedModel,
|
|
19047
19263
|
setSelectedModel
|
|
@@ -19684,13 +19900,13 @@ await init_agent();
|
|
|
19684
19900
|
init_react();
|
|
19685
19901
|
init_MessageList();
|
|
19686
19902
|
init_SessionContext();
|
|
19687
|
-
import { execSync as
|
|
19903
|
+
import { execSync as execSync3 } from "child_process";
|
|
19688
19904
|
import { homedir as homedir5 } from "os";
|
|
19689
19905
|
import { Box as Box13, useApp } from "ink";
|
|
19690
19906
|
import React14, { useEffect as useEffect2, useRef as useRef4, useState as useState3 } from "react";
|
|
19691
19907
|
var getGitBranch = () => {
|
|
19692
19908
|
try {
|
|
19693
|
-
return
|
|
19909
|
+
return execSync3("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
|
|
19694
19910
|
} catch {
|
|
19695
19911
|
return "";
|
|
19696
19912
|
}
|
|
@@ -19948,10 +20164,13 @@ async function runAgent(config2) {
|
|
|
19948
20164
|
});
|
|
19949
20165
|
}
|
|
19950
20166
|
|
|
20167
|
+
// src/index.ts
|
|
20168
|
+
init_theme();
|
|
20169
|
+
|
|
19951
20170
|
// src/utils/auto-update.ts
|
|
19952
20171
|
init_version();
|
|
19953
20172
|
init_error_logger();
|
|
19954
|
-
import { execSync as
|
|
20173
|
+
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
19955
20174
|
import latestVersion from "latest-version";
|
|
19956
20175
|
import { gt } from "semver";
|
|
19957
20176
|
var UPDATE_CHECK_TIMEOUT = 3e3;
|
|
@@ -19977,7 +20196,7 @@ async function checkAndAutoUpdate() {
|
|
|
19977
20196
|
Updating Supatest CLI ${CLI_VERSION} \u2192 ${latest}...`);
|
|
19978
20197
|
try {
|
|
19979
20198
|
try {
|
|
19980
|
-
const npmPrefix =
|
|
20199
|
+
const npmPrefix = execSync4("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
19981
20200
|
if (process.platform === "win32") {
|
|
19982
20201
|
const { rmSync, readdirSync: readdirSync2 } = await import("fs");
|
|
19983
20202
|
const modulesDir = `${npmPrefix}\\node_modules\\@supatest`;
|
|
@@ -19986,24 +20205,24 @@ Updating Supatest CLI ${CLI_VERSION} \u2192 ${latest}...`);
|
|
|
19986
20205
|
rmSync(`${modulesDir}\\${entry}`, { recursive: true, force: true });
|
|
19987
20206
|
}
|
|
19988
20207
|
} else {
|
|
19989
|
-
|
|
20208
|
+
execSync4(`rm -rf ${npmPrefix}/lib/node_modules/@supatest/.cli-* 2>/dev/null || true`);
|
|
19990
20209
|
}
|
|
19991
20210
|
} catch {
|
|
19992
20211
|
}
|
|
19993
20212
|
try {
|
|
19994
|
-
|
|
20213
|
+
execSync4("npm update -g @supatest/cli", {
|
|
19995
20214
|
stdio: "inherit",
|
|
19996
20215
|
timeout: INSTALL_TIMEOUT
|
|
19997
20216
|
});
|
|
19998
20217
|
} catch {
|
|
19999
|
-
|
|
20218
|
+
execSync4("npm install -g @supatest/cli@latest --force", {
|
|
20000
20219
|
stdio: "inherit",
|
|
20001
20220
|
timeout: INSTALL_TIMEOUT
|
|
20002
20221
|
});
|
|
20003
20222
|
}
|
|
20004
20223
|
let updateVerified = false;
|
|
20005
20224
|
try {
|
|
20006
|
-
const installedVersion =
|
|
20225
|
+
const installedVersion = execSync4("npm ls -g @supatest/cli --json 2>/dev/null", {
|
|
20007
20226
|
encoding: "utf-8"
|
|
20008
20227
|
});
|
|
20009
20228
|
const parsed = JSON.parse(installedVersion);
|
|
@@ -20049,7 +20268,7 @@ init_logger();
|
|
|
20049
20268
|
|
|
20050
20269
|
// src/utils/node-version.ts
|
|
20051
20270
|
init_logger();
|
|
20052
|
-
import { execSync as
|
|
20271
|
+
import { execSync as execSync5 } from "child_process";
|
|
20053
20272
|
var MINIMUM_NODE_VERSION2 = 18;
|
|
20054
20273
|
function parseVersion2(versionString) {
|
|
20055
20274
|
const cleaned = versionString.trim().replace(/^v/, "");
|
|
@@ -20066,7 +20285,7 @@ function parseVersion2(versionString) {
|
|
|
20066
20285
|
}
|
|
20067
20286
|
function getNodeVersion2() {
|
|
20068
20287
|
try {
|
|
20069
|
-
const versionOutput =
|
|
20288
|
+
const versionOutput = execSync5("node --version", {
|
|
20070
20289
|
encoding: "utf-8",
|
|
20071
20290
|
stdio: ["ignore", "pipe", "ignore"]
|
|
20072
20291
|
});
|
|
@@ -20189,9 +20408,18 @@ program.name("supatest").description(
|
|
|
20189
20408
|
).option(
|
|
20190
20409
|
"--claude-max-iterations <number>",
|
|
20191
20410
|
"[Deprecated] Alias for --max-iterations"
|
|
20192
|
-
).option("--supatest-api-key <key>", "Supatest API key (or use SUPATEST_API_KEY env)").option("--supatest-api-url <url>", "Supatest API URL (or use SUPATEST_API_URL env, defaults to https://code-api.supatest.ai)").option("--headless", "Run in headless mode (for CI/CD, minimal output)").option("--mode <mode>", "Agent mode for headless: fix (default), build, plan, test-feature, or report").option("--verbose", "Enable verbose logging").option("--model <model>", "Model to use (or use ANTHROPIC_MODEL_NAME env). Use 'small', 'medium', or 'premium' for tier-based selection").action(async (task, options) => {
|
|
20411
|
+
).option("--supatest-api-key <key>", "Supatest API key (or use SUPATEST_API_KEY env)").option("--supatest-api-url <url>", "Supatest API URL (or use SUPATEST_API_URL env, defaults to https://code-api.supatest.ai)").option("--theme <mode>", "Color theme: auto (default), dark, or light", "auto").option("--headless", "Run in headless mode (for CI/CD, minimal output)").option("--mode <mode>", "Agent mode for headless: fix (default), build, plan, test-feature, or report").option("--project-id <id>", "Project ID to scope queries (or use SUPATEST_PROJECT_ID env)").option("--verbose", "Enable verbose logging").option("--model <model>", "Model to use (or use ANTHROPIC_MODEL_NAME env). Use 'small', 'medium', or 'premium' for tier-based selection").action(async (task, options) => {
|
|
20193
20412
|
try {
|
|
20194
20413
|
checkNodeVersion2();
|
|
20414
|
+
if (options.theme && options.theme !== "auto") {
|
|
20415
|
+
const mode = options.theme;
|
|
20416
|
+
const { setThemeMode: setThemeMode2 } = await Promise.resolve().then(() => (init_theme(), theme_exports));
|
|
20417
|
+
setThemeMode2(mode);
|
|
20418
|
+
logger.debug(`Terminal theme set via --theme flag: ${mode}`);
|
|
20419
|
+
} else {
|
|
20420
|
+
const detectedTheme = initTheme();
|
|
20421
|
+
logger.debug(`Terminal theme detected: ${detectedTheme}`);
|
|
20422
|
+
}
|
|
20195
20423
|
await checkAndAutoUpdate();
|
|
20196
20424
|
const isHeadlessMode = options.headless || process.stdin.isTTY === false;
|
|
20197
20425
|
if (options.verbose) {
|
|
@@ -20210,9 +20438,9 @@ program.name("supatest").description(
|
|
|
20210
20438
|
logs = stdinContent;
|
|
20211
20439
|
}
|
|
20212
20440
|
if (options.logs) {
|
|
20213
|
-
const
|
|
20441
|
+
const fs5 = await import("fs/promises");
|
|
20214
20442
|
try {
|
|
20215
|
-
logs = await
|
|
20443
|
+
logs = await fs5.readFile(options.logs, "utf-8");
|
|
20216
20444
|
} catch (error) {
|
|
20217
20445
|
logger.error(`Failed to read log file: ${options.logs}`);
|
|
20218
20446
|
process.exit(1);
|
|
@@ -20252,6 +20480,7 @@ program.name("supatest").description(
|
|
|
20252
20480
|
);
|
|
20253
20481
|
}
|
|
20254
20482
|
}
|
|
20483
|
+
const projectId = options.projectId || process.env.SUPATEST_PROJECT_ID;
|
|
20255
20484
|
let selectedModel;
|
|
20256
20485
|
const modelOption = options.model || "medium";
|
|
20257
20486
|
if (modelOption && isValidModelId(modelOption)) {
|
|
@@ -20275,7 +20504,7 @@ program.name("supatest").description(
|
|
|
20275
20504
|
process.exit(1);
|
|
20276
20505
|
}
|
|
20277
20506
|
const headlessAgentMode = headlessMode;
|
|
20278
|
-
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "
|
|
20507
|
+
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "500";
|
|
20279
20508
|
const parsedMaxIterations = Number.parseInt(rawMaxIterations, 10);
|
|
20280
20509
|
if (Number.isNaN(parsedMaxIterations) || parsedMaxIterations < 1) {
|
|
20281
20510
|
logger.error(
|
|
@@ -20314,13 +20543,14 @@ ${prompt}`;
|
|
|
20314
20543
|
),
|
|
20315
20544
|
selectedModel,
|
|
20316
20545
|
oauthToken,
|
|
20546
|
+
projectId,
|
|
20317
20547
|
mode: headlessMode === "plan" ? "plan" : "build",
|
|
20318
20548
|
allowInteractivePrompts: false
|
|
20319
20549
|
});
|
|
20320
20550
|
process.exit(result.success ? 0 : 1);
|
|
20321
20551
|
} else {
|
|
20322
20552
|
const { runInteractive: runInteractive2 } = await init_interactive().then(() => interactive_exports);
|
|
20323
|
-
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "
|
|
20553
|
+
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "500";
|
|
20324
20554
|
const parsedMaxIterations = Number.parseInt(rawMaxIterations, 10);
|
|
20325
20555
|
if (Number.isNaN(parsedMaxIterations) || parsedMaxIterations < 1) {
|
|
20326
20556
|
logger.error(
|
|
@@ -20340,6 +20570,7 @@ ${prompt}`;
|
|
|
20340
20570
|
systemPromptAppend: getSystemPromptForMode("build"),
|
|
20341
20571
|
selectedModel,
|
|
20342
20572
|
oauthToken,
|
|
20573
|
+
projectId,
|
|
20343
20574
|
allowInteractivePrompts: true
|
|
20344
20575
|
});
|
|
20345
20576
|
}
|