@saga-ai/cli 2.17.0 → 2.17.1
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/cli.cjs
CHANGED
|
@@ -26,11 +26,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/cli.ts
|
|
27
27
|
var import_node_fs9 = require("node:fs");
|
|
28
28
|
var import_node_path15 = require("node:path");
|
|
29
|
-
var
|
|
29
|
+
var import_node_process11 = __toESM(require("node:process"), 1);
|
|
30
30
|
var import_commander = require("commander");
|
|
31
31
|
|
|
32
32
|
// src/commands/dashboard.ts
|
|
33
|
-
var
|
|
33
|
+
var import_node_process4 = __toESM(require("node:process"), 1);
|
|
34
34
|
|
|
35
35
|
// src/server/index.ts
|
|
36
36
|
var import_node_http = require("node:http");
|
|
@@ -385,6 +385,7 @@ async function parseJournal(journalPath) {
|
|
|
385
385
|
entries.push({
|
|
386
386
|
timestamp,
|
|
387
387
|
type: "session",
|
|
388
|
+
title: `Session ${timestamp}`,
|
|
388
389
|
content: sectionContent
|
|
389
390
|
});
|
|
390
391
|
} else if (headerLine.toLowerCase().startsWith("blocker:")) {
|
|
@@ -393,9 +394,8 @@ async function parseJournal(journalPath) {
|
|
|
393
394
|
timestamp: "",
|
|
394
395
|
// Blockers may not have timestamps
|
|
395
396
|
type: "blocker",
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
${sectionContent}`.trim()
|
|
397
|
+
title,
|
|
398
|
+
content: sectionContent
|
|
399
399
|
});
|
|
400
400
|
} else if (headerLine.toLowerCase().startsWith("resolution:")) {
|
|
401
401
|
const title = headerLine.substring("resolution:".length).trim();
|
|
@@ -403,9 +403,8 @@ ${sectionContent}`.trim()
|
|
|
403
403
|
timestamp: "",
|
|
404
404
|
// Resolutions may not have timestamps
|
|
405
405
|
type: "resolution",
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
${sectionContent}`.trim()
|
|
406
|
+
title,
|
|
407
|
+
content: sectionContent
|
|
409
408
|
});
|
|
410
409
|
}
|
|
411
410
|
}
|
|
@@ -1199,12 +1198,16 @@ var LogStreamManager = class {
|
|
|
1199
1198
|
// src/server/watcher.ts
|
|
1200
1199
|
var import_node_events = require("node:events");
|
|
1201
1200
|
var import_node_path6 = require("node:path");
|
|
1201
|
+
var import_node_process2 = __toESM(require("node:process"), 1);
|
|
1202
1202
|
var import_chokidar2 = __toESM(require("chokidar"), 1);
|
|
1203
1203
|
var MIN_PATH_PARTS = 4;
|
|
1204
1204
|
var ARCHIVE_STORY_PARTS = 5;
|
|
1205
1205
|
var EPIC_FILE_PARTS = 4;
|
|
1206
1206
|
var STORY_FILE_PARTS = 6;
|
|
1207
1207
|
var DEBOUNCE_DELAY_MS = 100;
|
|
1208
|
+
function shouldUsePolling() {
|
|
1209
|
+
return import_node_process2.default.env.SAGA_USE_POLLING === "1";
|
|
1210
|
+
}
|
|
1208
1211
|
function isStoryMarkdownFile(fileName) {
|
|
1209
1212
|
return fileName === "story.md" || fileName === "journal.md";
|
|
1210
1213
|
}
|
|
@@ -1327,17 +1330,18 @@ function createDebounceKey(parsed) {
|
|
|
1327
1330
|
function createChokidarWatcher(sagaRoot) {
|
|
1328
1331
|
const epicsDir = (0, import_node_path6.join)(sagaRoot, ".saga", "epics");
|
|
1329
1332
|
const archiveDir = (0, import_node_path6.join)(sagaRoot, ".saga", "archive");
|
|
1333
|
+
const usePolling = shouldUsePolling();
|
|
1330
1334
|
return import_chokidar2.default.watch([epicsDir, archiveDir], {
|
|
1331
1335
|
persistent: true,
|
|
1332
1336
|
ignoreInitial: true,
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
//
|
|
1337
|
-
awaitWriteFinish: {
|
|
1337
|
+
// Use polling for tests (reliable) or native watching for production (fast)
|
|
1338
|
+
usePolling,
|
|
1339
|
+
interval: usePolling ? DEBOUNCE_DELAY_MS : void 0,
|
|
1340
|
+
// Wait for writes to finish when polling
|
|
1341
|
+
awaitWriteFinish: usePolling ? {
|
|
1338
1342
|
stabilityThreshold: 50,
|
|
1339
1343
|
pollInterval: 50
|
|
1340
|
-
}
|
|
1344
|
+
} : false
|
|
1341
1345
|
});
|
|
1342
1346
|
}
|
|
1343
1347
|
async function createSagaWatcher(sagaRoot) {
|
|
@@ -1734,9 +1738,9 @@ async function startServer(config) {
|
|
|
1734
1738
|
// src/utils/project-discovery.ts
|
|
1735
1739
|
var import_node_fs4 = require("node:fs");
|
|
1736
1740
|
var import_node_path9 = require("node:path");
|
|
1737
|
-
var
|
|
1741
|
+
var import_node_process3 = __toESM(require("node:process"), 1);
|
|
1738
1742
|
function findProjectRoot(startDir) {
|
|
1739
|
-
let currentDir = startDir ??
|
|
1743
|
+
let currentDir = startDir ?? import_node_process3.default.cwd();
|
|
1740
1744
|
while (true) {
|
|
1741
1745
|
const sagaDir = (0, import_node_path9.join)(currentDir, ".saga");
|
|
1742
1746
|
if ((0, import_node_fs4.existsSync)(sagaDir)) {
|
|
@@ -1776,7 +1780,7 @@ async function dashboardCommand(options) {
|
|
|
1776
1780
|
projectPath = resolveProjectPath(options.path);
|
|
1777
1781
|
} catch (error) {
|
|
1778
1782
|
console.error(error instanceof Error ? error.message : "Failed to resolve SAGA project path");
|
|
1779
|
-
|
|
1783
|
+
import_node_process4.default.exit(1);
|
|
1780
1784
|
}
|
|
1781
1785
|
try {
|
|
1782
1786
|
const server = await startServer({
|
|
@@ -1785,21 +1789,21 @@ async function dashboardCommand(options) {
|
|
|
1785
1789
|
});
|
|
1786
1790
|
console.log(`SAGA Dashboard server running on http://localhost:${server.port}`);
|
|
1787
1791
|
console.log(`Project: ${projectPath}`);
|
|
1788
|
-
|
|
1792
|
+
import_node_process4.default.on("SIGINT", async () => {
|
|
1789
1793
|
await server.close();
|
|
1790
|
-
|
|
1794
|
+
import_node_process4.default.exit(0);
|
|
1791
1795
|
});
|
|
1792
|
-
|
|
1796
|
+
import_node_process4.default.on("SIGTERM", async () => {
|
|
1793
1797
|
await server.close();
|
|
1794
|
-
|
|
1798
|
+
import_node_process4.default.exit(0);
|
|
1795
1799
|
});
|
|
1796
1800
|
} catch (_error) {
|
|
1797
|
-
|
|
1801
|
+
import_node_process4.default.exit(1);
|
|
1798
1802
|
}
|
|
1799
1803
|
}
|
|
1800
1804
|
|
|
1801
1805
|
// src/commands/find.ts
|
|
1802
|
-
var
|
|
1806
|
+
var import_node_process5 = __toESM(require("node:process"), 1);
|
|
1803
1807
|
|
|
1804
1808
|
// src/utils/finder.ts
|
|
1805
1809
|
var import_node_fs5 = require("node:fs");
|
|
@@ -1959,7 +1963,7 @@ async function findCommand(query, options) {
|
|
|
1959
1963
|
try {
|
|
1960
1964
|
projectPath = resolveProjectPath(options.path);
|
|
1961
1965
|
} catch (_error) {
|
|
1962
|
-
|
|
1966
|
+
import_node_process5.default.exit(1);
|
|
1963
1967
|
}
|
|
1964
1968
|
const type = options.type ?? "story";
|
|
1965
1969
|
let result;
|
|
@@ -1970,7 +1974,7 @@ async function findCommand(query, options) {
|
|
|
1970
1974
|
}
|
|
1971
1975
|
console.log(JSON.stringify(result, null, 2));
|
|
1972
1976
|
if (!result.found) {
|
|
1973
|
-
|
|
1977
|
+
import_node_process5.default.exit(1);
|
|
1974
1978
|
}
|
|
1975
1979
|
}
|
|
1976
1980
|
|
|
@@ -1978,7 +1982,7 @@ async function findCommand(query, options) {
|
|
|
1978
1982
|
var import_node_child_process2 = require("node:child_process");
|
|
1979
1983
|
var import_node_fs6 = require("node:fs");
|
|
1980
1984
|
var import_node_path11 = require("node:path");
|
|
1981
|
-
var
|
|
1985
|
+
var import_node_process6 = __toESM(require("node:process"), 1);
|
|
1982
1986
|
var DEFAULT_MAX_CYCLES = 10;
|
|
1983
1987
|
var DEFAULT_MAX_TIME = 60;
|
|
1984
1988
|
var DEFAULT_MODEL = "opus";
|
|
@@ -2436,19 +2440,19 @@ function spawnWorkerAsync(prompt, model, settings, workingDir) {
|
|
|
2436
2440
|
if (line.trim()) {
|
|
2437
2441
|
const formatted = formatStreamLine(line);
|
|
2438
2442
|
if (formatted) {
|
|
2439
|
-
|
|
2443
|
+
import_node_process6.default.stdout.write(formatted);
|
|
2440
2444
|
}
|
|
2441
2445
|
}
|
|
2442
2446
|
}
|
|
2443
2447
|
});
|
|
2444
2448
|
child.stderr.on("data", (chunk) => {
|
|
2445
|
-
|
|
2449
|
+
import_node_process6.default.stderr.write(chunk);
|
|
2446
2450
|
});
|
|
2447
2451
|
child.on("error", (err) => {
|
|
2448
2452
|
reject(new Error(`Failed to spawn worker: ${err.message}`));
|
|
2449
2453
|
});
|
|
2450
2454
|
child.on("close", (_code) => {
|
|
2451
|
-
|
|
2455
|
+
import_node_process6.default.stdout.write("\n");
|
|
2452
2456
|
try {
|
|
2453
2457
|
const result = parseStreamingResult(buffer);
|
|
2454
2458
|
resolve2(result);
|
|
@@ -2612,7 +2616,7 @@ function buildDetachedCommand(storySlug, projectPath, options) {
|
|
|
2612
2616
|
function handleDryRun(storyInfo, projectPath, pluginRoot) {
|
|
2613
2617
|
const dryRunResult = runDryRun(storyInfo, projectPath, pluginRoot);
|
|
2614
2618
|
printDryRunResults(dryRunResult);
|
|
2615
|
-
|
|
2619
|
+
import_node_process6.default.exit(dryRunResult.success ? 0 : 1);
|
|
2616
2620
|
}
|
|
2617
2621
|
async function handleDetachedMode(storySlug, storyInfo, projectPath, options) {
|
|
2618
2622
|
const detachedCommand = buildDetachedCommand(storySlug, projectPath, {
|
|
@@ -2631,7 +2635,7 @@ async function handleDetachedMode(storySlug, storyInfo, projectPath, options) {
|
|
|
2631
2635
|
console.error(
|
|
2632
2636
|
`Error creating session: ${error instanceof Error ? error.message : String(error)}`
|
|
2633
2637
|
);
|
|
2634
|
-
|
|
2638
|
+
import_node_process6.default.exit(1);
|
|
2635
2639
|
}
|
|
2636
2640
|
}
|
|
2637
2641
|
async function handleInternalSession(storyInfo, projectPath, pluginRoot, options) {
|
|
@@ -2653,7 +2657,7 @@ async function handleInternalSession(storyInfo, projectPath, pluginRoot, options
|
|
|
2653
2657
|
);
|
|
2654
2658
|
if (result.status === "ERROR") {
|
|
2655
2659
|
console.error(`Error: ${result.summary}`);
|
|
2656
|
-
|
|
2660
|
+
import_node_process6.default.exit(1);
|
|
2657
2661
|
}
|
|
2658
2662
|
console.log(`
|
|
2659
2663
|
Implementation ${result.status}: ${result.summary}`);
|
|
@@ -2664,28 +2668,28 @@ async function implementCommand(storySlug, options) {
|
|
|
2664
2668
|
projectPath = resolveProjectPath(options.path);
|
|
2665
2669
|
} catch (_error) {
|
|
2666
2670
|
console.error("Error: SAGA project not found. Run saga init first or use --path option.");
|
|
2667
|
-
|
|
2671
|
+
import_node_process6.default.exit(1);
|
|
2668
2672
|
}
|
|
2669
2673
|
const storyInfo = await findStory2(projectPath, storySlug);
|
|
2670
2674
|
if (!storyInfo) {
|
|
2671
2675
|
console.error(`Error: Story '${storySlug}' not found in project.`);
|
|
2672
2676
|
console.error("Use /generate-stories to create stories for an epic first.");
|
|
2673
|
-
|
|
2677
|
+
import_node_process6.default.exit(1);
|
|
2674
2678
|
}
|
|
2675
|
-
const pluginRoot =
|
|
2679
|
+
const pluginRoot = import_node_process6.default.env.SAGA_PLUGIN_ROOT;
|
|
2676
2680
|
if (options.dryRun) {
|
|
2677
2681
|
handleDryRun(storyInfo, projectPath, pluginRoot);
|
|
2678
2682
|
}
|
|
2679
2683
|
if (!pluginRoot) {
|
|
2680
2684
|
console.error("Error: SAGA_PLUGIN_ROOT environment variable is not set.");
|
|
2681
2685
|
console.error("This is required to find the worker prompt template.");
|
|
2682
|
-
|
|
2686
|
+
import_node_process6.default.exit(1);
|
|
2683
2687
|
}
|
|
2684
2688
|
if (!(0, import_node_fs6.existsSync)(storyInfo.worktreePath)) {
|
|
2685
2689
|
console.error(`Error: Worktree not found at ${storyInfo.worktreePath}`);
|
|
2686
|
-
|
|
2690
|
+
import_node_process6.default.exit(1);
|
|
2687
2691
|
}
|
|
2688
|
-
const isInternalSession =
|
|
2692
|
+
const isInternalSession = import_node_process6.default.env.SAGA_INTERNAL_SESSION === "1";
|
|
2689
2693
|
if (isInternalSession) {
|
|
2690
2694
|
await handleInternalSession(storyInfo, projectPath, pluginRoot, options);
|
|
2691
2695
|
} else {
|
|
@@ -2696,7 +2700,7 @@ async function implementCommand(storySlug, options) {
|
|
|
2696
2700
|
// src/commands/init.ts
|
|
2697
2701
|
var import_node_fs7 = require("node:fs");
|
|
2698
2702
|
var import_node_path12 = require("node:path");
|
|
2699
|
-
var
|
|
2703
|
+
var import_node_process7 = __toESM(require("node:process"), 1);
|
|
2700
2704
|
var WORKTREES_PATTERN = ".saga/worktrees/";
|
|
2701
2705
|
function runInitDryRun(targetPath) {
|
|
2702
2706
|
const sagaDir = (0, import_node_path12.join)(targetPath, ".saga");
|
|
@@ -2760,7 +2764,7 @@ function resolveTargetPath(explicitPath) {
|
|
|
2760
2764
|
if (existingRoot) {
|
|
2761
2765
|
return existingRoot;
|
|
2762
2766
|
}
|
|
2763
|
-
return
|
|
2767
|
+
return import_node_process7.default.cwd();
|
|
2764
2768
|
}
|
|
2765
2769
|
function createDirectoryStructure(projectRoot) {
|
|
2766
2770
|
const sagaDir = (0, import_node_path12.join)(projectRoot, ".saga");
|
|
@@ -2795,11 +2799,11 @@ function initCommand(options) {
|
|
|
2795
2799
|
if (options.path) {
|
|
2796
2800
|
if (!(0, import_node_fs7.existsSync)(options.path)) {
|
|
2797
2801
|
console.error(`Error: Path does not exist: ${options.path}`);
|
|
2798
|
-
|
|
2802
|
+
import_node_process7.default.exit(1);
|
|
2799
2803
|
}
|
|
2800
2804
|
if (!(0, import_node_fs7.statSync)(options.path).isDirectory()) {
|
|
2801
2805
|
console.error(`Error: Path is not a directory: ${options.path}`);
|
|
2802
|
-
|
|
2806
|
+
import_node_process7.default.exit(1);
|
|
2803
2807
|
}
|
|
2804
2808
|
}
|
|
2805
2809
|
const targetPath = resolveTargetPath(options.path);
|
|
@@ -2815,7 +2819,7 @@ function initCommand(options) {
|
|
|
2815
2819
|
|
|
2816
2820
|
// src/commands/scope-validator.ts
|
|
2817
2821
|
var import_node_path13 = require("node:path");
|
|
2818
|
-
var
|
|
2822
|
+
var import_node_process8 = __toESM(require("node:process"), 1);
|
|
2819
2823
|
var FILE_PATH_WIDTH = 50;
|
|
2820
2824
|
var EPIC_STORY_WIDTH = 43;
|
|
2821
2825
|
var REASON_WIDTH = 56;
|
|
@@ -2884,19 +2888,19 @@ function printScopeViolation(filePath, epicSlug, storySlug, worktreePath, reason
|
|
|
2884
2888
|
"\u2570\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F",
|
|
2885
2889
|
""
|
|
2886
2890
|
].join("\n");
|
|
2887
|
-
|
|
2891
|
+
import_node_process8.default.stderr.write(message);
|
|
2888
2892
|
}
|
|
2889
2893
|
async function readStdinInput() {
|
|
2890
2894
|
const chunks = [];
|
|
2891
|
-
for await (const chunk of
|
|
2895
|
+
for await (const chunk of import_node_process8.default.stdin) {
|
|
2892
2896
|
chunks.push(chunk);
|
|
2893
2897
|
}
|
|
2894
2898
|
return Buffer.concat(chunks).toString("utf-8");
|
|
2895
2899
|
}
|
|
2896
2900
|
function getScopeEnvironment() {
|
|
2897
|
-
const worktreePath =
|
|
2898
|
-
const epicSlug =
|
|
2899
|
-
const storySlug =
|
|
2901
|
+
const worktreePath = import_node_process8.default.env.SAGA_PROJECT_DIR || "";
|
|
2902
|
+
const epicSlug = import_node_process8.default.env.SAGA_EPIC_SLUG || "";
|
|
2903
|
+
const storySlug = import_node_process8.default.env.SAGA_STORY_SLUG || "";
|
|
2900
2904
|
if (!(worktreePath && epicSlug && storySlug)) {
|
|
2901
2905
|
return null;
|
|
2902
2906
|
}
|
|
@@ -2918,23 +2922,23 @@ function validatePath(filePath, worktreePath, epicSlug, storySlug) {
|
|
|
2918
2922
|
async function scopeValidatorCommand() {
|
|
2919
2923
|
const env = getScopeEnvironment();
|
|
2920
2924
|
if (!env) {
|
|
2921
|
-
|
|
2925
|
+
import_node_process8.default.exit(2);
|
|
2922
2926
|
}
|
|
2923
2927
|
const toolInput = await readStdinInput();
|
|
2924
2928
|
const filePath = getFilePathFromInput(toolInput);
|
|
2925
2929
|
if (!filePath) {
|
|
2926
|
-
|
|
2930
|
+
import_node_process8.default.exit(0);
|
|
2927
2931
|
}
|
|
2928
2932
|
const violation = validatePath(filePath, env.worktreePath, env.epicSlug, env.storySlug);
|
|
2929
2933
|
if (violation) {
|
|
2930
2934
|
printScopeViolation(filePath, env.epicSlug, env.storySlug, env.worktreePath, violation);
|
|
2931
|
-
|
|
2935
|
+
import_node_process8.default.exit(2);
|
|
2932
2936
|
}
|
|
2933
|
-
|
|
2937
|
+
import_node_process8.default.exit(0);
|
|
2934
2938
|
}
|
|
2935
2939
|
|
|
2936
2940
|
// src/commands/sessions/index.ts
|
|
2937
|
-
var
|
|
2941
|
+
var import_node_process9 = __toESM(require("node:process"), 1);
|
|
2938
2942
|
async function sessionsListCommand() {
|
|
2939
2943
|
const sessions = await listSessions();
|
|
2940
2944
|
console.log(JSON.stringify(sessions, null, 2));
|
|
@@ -2948,7 +2952,7 @@ async function sessionsLogsCommand(sessionName) {
|
|
|
2948
2952
|
await streamLogs(sessionName);
|
|
2949
2953
|
} catch (error) {
|
|
2950
2954
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
2951
|
-
|
|
2955
|
+
import_node_process9.default.exit(1);
|
|
2952
2956
|
}
|
|
2953
2957
|
}
|
|
2954
2958
|
async function sessionsKillCommand(sessionName) {
|
|
@@ -2960,7 +2964,7 @@ async function sessionsKillCommand(sessionName) {
|
|
|
2960
2964
|
var import_node_child_process3 = require("node:child_process");
|
|
2961
2965
|
var import_node_fs8 = require("node:fs");
|
|
2962
2966
|
var import_node_path14 = require("node:path");
|
|
2963
|
-
var
|
|
2967
|
+
var import_node_process10 = __toESM(require("node:process"), 1);
|
|
2964
2968
|
function runGitCommand(args, cwd) {
|
|
2965
2969
|
try {
|
|
2966
2970
|
const output = (0, import_node_child_process3.execSync)(`git ${args.join(" ")}`, {
|
|
@@ -3041,12 +3045,12 @@ function worktreeCommand(epicSlug, storySlug, options) {
|
|
|
3041
3045
|
error: error instanceof Error ? error.message : String(error)
|
|
3042
3046
|
};
|
|
3043
3047
|
console.log(JSON.stringify(result2, null, 2));
|
|
3044
|
-
|
|
3048
|
+
import_node_process10.default.exit(1);
|
|
3045
3049
|
}
|
|
3046
3050
|
const result = createWorktree(projectPath, epicSlug, storySlug);
|
|
3047
3051
|
console.log(JSON.stringify(result, null, 2));
|
|
3048
3052
|
if (!result.success) {
|
|
3049
|
-
|
|
3053
|
+
import_node_process10.default.exit(1);
|
|
3050
3054
|
}
|
|
3051
3055
|
}
|
|
3052
3056
|
|
|
@@ -3109,6 +3113,6 @@ sessionsCommand.command("kill <name>").description("Terminate a session").action
|
|
|
3109
3113
|
});
|
|
3110
3114
|
program.on("command:*", (operands) => {
|
|
3111
3115
|
console.error(`error: unknown command '${operands[0]}'`);
|
|
3112
|
-
|
|
3116
|
+
import_node_process11.default.exit(1);
|
|
3113
3117
|
});
|
|
3114
3118
|
program.parse();
|
|
@@ -11,5 +11,5 @@ Error generating stack: `+a.message+`
|
|
|
11
11
|
`);return c.length>Xm?c.slice(-Xm):c}function Kb({truncatedOutput:u,outputAvailable:r}){const c=_.useRef(null);return _.useLayoutEffect(()=>{u&&c.current&&(c.current.scrollTop=c.current.scrollHeight)},[u]),r?u?f.jsx("pre",{ref:c,className:"font-mono bg-bg-dark text-xs p-2 rounded max-h-24 overflow-y-auto whitespace-pre-wrap",role:"presentation",children:u}):null:f.jsx("div",{className:"text-text-muted text-sm italic",children:"Output unavailable"})}function Jb({session:u}){const[r,c]=_.useState(()=>{const m=new Date(u.startTime).getTime(),g=Date.now();return Math.floor((g-m)/Lm)}),o=kb(u.outputPreview);return _.useEffect(()=>{const m=setInterval(()=>{const g=new Date(u.startTime).getTime(),v=Date.now();c(Math.floor((v-g)/Lm))},Zb);return()=>clearInterval(m)},[u.startTime]),f.jsx(il,{to:`/epic/${u.epicSlug}/story/${u.storySlug}?tab=sessions`,className:"block",children:f.jsxs(ne,{className:"hover:border-primary/50 transition-colors cursor-pointer",children:[f.jsxs(ye,{className:"pb-2",children:[f.jsx(sa,{className:"text-base",children:u.storySlug}),f.jsx("div",{className:"text-sm text-text-muted",children:u.epicSlug})]}),f.jsxs(Ae,{className:"space-y-2",children:[f.jsx("div",{className:"text-sm text-text-muted",children:eo(r)}),f.jsx(Kb,{truncatedOutput:o,outputAvailable:u.outputAvailable})]})]})})}function kc(){return f.jsxs(ne,{className:"animate-pulse min-w-[300px] flex-shrink-0","data-testid":"session-card-skeleton",children:[f.jsxs(ye,{className:"pb-2",children:[f.jsx("div",{className:"h-5 w-32 bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-20 bg-bg-light rounded mt-1"})]}),f.jsx(Ae,{children:f.jsx("div",{className:"h-16 w-full bg-bg-light rounded"})})]})}function Wb(){const{sessions:u,setSessions:r}=ua(),[c,o]=_.useState(!0);_.useEffect(()=>{(async()=>{try{const v=await fetch("/api/sessions?status=running");if(v.ok){const E=await v.json();r(E)}}catch{r([])}finally{o(!1)}})()},[r]);const m=_.useMemo(()=>u.filter(g=>g.status==="running"),[u]);return c?f.jsx($b,{}):m.length===0?null:f.jsxs("section",{"data-testid":"active-sessions",className:"space-y-4",children:[f.jsx("h2",{className:"text-xl font-semibold text-text",children:"Active Sessions"}),f.jsx("div",{className:"flex gap-4 overflow-x-auto pb-2",children:m.map(g=>f.jsx("div",{className:"min-w-[300px] flex-shrink-0",children:f.jsx(Jb,{session:g})},g.name))})]})}function $b(){return f.jsxs("section",{"data-testid":"active-sessions-skeleton",className:"space-y-4",children:[f.jsx("h2",{className:"text-xl font-semibold text-text",children:"Active Sessions"}),f.jsxs("div",{className:"flex gap-4 overflow-x-auto pb-2",children:[f.jsx(kc,{}),f.jsx(kc,{}),f.jsx(kc,{})]})]})}const Fb=100;function Kc(){return f.jsxs(ne,{className:"animate-pulse","data-testid":"epic-card-skeleton",children:[f.jsx(ye,{children:f.jsx("div",{className:"h-6 w-48 bg-bg-light rounded"})}),f.jsxs(Ae,{className:"space-y-4",children:[f.jsx("div",{className:"h-4 w-full bg-bg-light rounded"}),f.jsxs("div",{className:"flex gap-2",children:[f.jsx("div",{className:"h-6 w-16 bg-bg-light rounded-full"}),f.jsx("div",{className:"h-6 w-16 bg-bg-light rounded-full"}),f.jsx("div",{className:"h-6 w-16 bg-bg-light rounded-full"})]})]})]})}function hu({status:u,count:r}){const c={ready:"bg-text-muted/20 text-text-muted",inProgress:"bg-primary/20 text-primary",blocked:"bg-danger/20 text-danger",completed:"bg-success/20 text-success"},o={ready:"Ready",inProgress:"In Progress",blocked:"Blocked",completed:"Completed"};return f.jsxs(wl,{className:c[u],children:[o[u],": ",r]})}function Ib({epic:u}){const{storyCounts:r}=u,c=r.total>0?Math.round(r.completed/r.total*Fb):0;return f.jsx(il,{to:`/epic/${u.slug}`,className:"block",children:f.jsxs(ne,{className:"hover:border-primary/50 transition-colors cursor-pointer",children:[f.jsx(ye,{children:f.jsx(sa,{className:"text-lg",children:u.title})}),f.jsxs(Ae,{className:"space-y-4",children:[f.jsxs("div",{className:"space-y-2",children:[f.jsxs("div",{className:"flex justify-between text-sm",children:[f.jsx("span",{className:"text-text-muted",children:"Progress"}),f.jsxs("span",{className:"text-text-muted",children:[r.completed,"/",r.total," stories"]})]}),f.jsx(go,{value:c})]}),f.jsxs("div",{className:"flex flex-wrap gap-2",children:[r.ready>0&&f.jsx(hu,{status:"ready",count:r.ready}),r.inProgress>0&&f.jsx(hu,{status:"inProgress",count:r.inProgress}),r.blocked>0&&f.jsx(hu,{status:"blocked",count:r.blocked}),r.completed>0&&f.jsx(hu,{status:"completed",count:r.completed})]})]})]})})}function Pb(){const{epics:u,setEpics:r}=ua(),[c,o]=_.useState(!1),[m,g]=_.useState(!0);_.useEffect(()=>{(async()=>{try{const R=await fetch("/api/epics");if(R.ok){const C=await R.json();r(C)}}catch(R){const C=R instanceof Error?R.message:"Unknown error";ro("/api/epics",C)}finally{g(!1)}})()},[r]);const v=m,E=u.filter(M=>c?!0:!M.isArchived),j=u.some(M=>M.isArchived);return f.jsxs("div",{className:"space-y-6",children:[f.jsx(Wb,{}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("h1",{className:"text-2xl font-bold text-text",children:"Epics"}),j&&f.jsxs("label",{className:"flex items-center gap-2 text-sm text-text-muted cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:c,onChange:M=>o(M.target.checked),className:"rounded border-border"}),"Show archived"]})]}),v&&f.jsxs("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:[f.jsx(Kc,{}),f.jsx(Kc,{}),f.jsx(Kc,{})]}),!v&&E.length===0&&f.jsxs("div",{className:"text-center py-12",children:[f.jsx("p",{className:"text-text-muted text-lg",children:"No epics found."}),f.jsxs("p",{className:"text-text-muted",children:["Run ",f.jsx("code",{className:"text-primary",children:"/create-epic"})," to get started."]})]}),!v&&E.length>0&&f.jsx("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:E.map(M=>f.jsx(Ib,{epic:M},M.slug))})]})}const t0=uo("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input bg-background hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3",lg:"h-11 rounded-md px-8",icon:"h-10 w-10"}},defaultVariants:{variant:"default",size:"default"}}),Eh=_.forwardRef(({className:u,variant:r,size:c,asChild:o=!1,...m},g)=>{const v=o?fp:"button";return f.jsx(v,{className:Ht(t0({variant:r,size:c,className:u})),ref:g,...m})});Eh.displayName="Button";function Ka(u,r,c){let o=c.initialDeps??[],m,g=!0;function v(){var E,j,M;let R;c.key&&((E=c.debug)!=null&&E.call(c))&&(R=Date.now());const C=u();if(!(C.length!==o.length||C.some((Z,G)=>o[G]!==Z)))return m;o=C;let k;if(c.key&&((j=c.debug)!=null&&j.call(c))&&(k=Date.now()),m=r(...C),c.key&&((M=c.debug)!=null&&M.call(c))){const Z=Math.round((Date.now()-R)*100)/100,G=Math.round((Date.now()-k)*100)/100,J=G/16,gt=(St,Et)=>{for(St=String(St);St.length<Et;)St=" "+St;return St};console.info(`%c⏱ ${gt(G,5)} /${gt(Z,5)} ms`,`
|
|
12
12
|
font-size: .6rem;
|
|
13
13
|
font-weight: bold;
|
|
14
|
-
color: hsl(${Math.max(0,Math.min(120-120*J,120))}deg 100% 31%);`,c?.key)}return c?.onChange&&!(g&&c.skipInitialOnChange)&&c.onChange(m),g=!1,m}return v.updateDeps=E=>{o=E},v}function Vm(u,r){if(u===void 0)throw new Error("Unexpected undefined");return u}const e0=(u,r)=>Math.abs(u-r)<1.01,l0=(u,r,c)=>{let o;return function(...m){u.clearTimeout(o),o=u.setTimeout(()=>r.apply(this,m),c)}},Qm=u=>{const{offsetWidth:r,offsetHeight:c}=u;return{width:r,height:c}},a0=u=>u,n0=u=>{const r=Math.max(u.startIndex-u.overscan,0),c=Math.min(u.endIndex+u.overscan,u.count-1),o=[];for(let m=r;m<=c;m++)o.push(m);return o},i0=(u,r)=>{const c=u.scrollElement;if(!c)return;const o=u.targetWindow;if(!o)return;const m=v=>{const{width:E,height:j}=v;r({width:Math.round(E),height:Math.round(j)})};if(m(Qm(c)),!o.ResizeObserver)return()=>{};const g=new o.ResizeObserver(v=>{const E=()=>{const j=v[0];if(j?.borderBoxSize){const M=j.borderBoxSize[0];if(M){m({width:M.inlineSize,height:M.blockSize});return}}m(Qm(c))};u.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(E):E()});return g.observe(c,{box:"border-box"}),()=>{g.unobserve(c)}},Zm={passive:!0},km=typeof window>"u"?!0:"onscrollend"in window,u0=(u,r)=>{const c=u.scrollElement;if(!c)return;const o=u.targetWindow;if(!o)return;let m=0;const g=u.options.useScrollendEvent&&km?()=>{}:l0(o,()=>{r(m,!1)},u.options.isScrollingResetDelay),v=R=>()=>{const{horizontal:C,isRtl:U}=u.options;m=C?c.scrollLeft*(U&&-1||1):c.scrollTop,g(),r(m,R)},E=v(!0),j=v(!1);c.addEventListener("scroll",E,Zm);const M=u.options.useScrollendEvent&&km;return M&&c.addEventListener("scrollend",j,Zm),()=>{c.removeEventListener("scroll",E),M&&c.removeEventListener("scrollend",j)}},s0=(u,r,c)=>{if(r?.borderBoxSize){const o=r.borderBoxSize[0];if(o)return Math.round(o[c.options.horizontal?"inlineSize":"blockSize"])}return u[c.options.horizontal?"offsetWidth":"offsetHeight"]},c0=(u,{adjustments:r=0,behavior:c},o)=>{var m,g;const v=u+r;(g=(m=o.scrollElement)==null?void 0:m.scrollTo)==null||g.call(m,{[o.options.horizontal?"left":"top"]:v,behavior:c})};class o0{constructor(r){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.currentScrollToIndex=null,this.measurementsCache=[],this.itemSizeCache=new Map,this.laneAssignments=new Map,this.pendingMeasuredCacheIndexes=[],this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.observer=(()=>{let c=null;const o=()=>c||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:c=new this.targetWindow.ResizeObserver(m=>{m.forEach(g=>{const v=()=>{this._measureElement(g.target,g)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(v):v()})}));return{disconnect:()=>{var m;(m=o())==null||m.disconnect(),c=null},observe:m=>{var g;return(g=o())==null?void 0:g.observe(m,{box:"border-box"})},unobserve:m=>{var g;return(g=o())==null?void 0:g.unobserve(m)}}})(),this.range=null,this.setOptions=c=>{Object.entries(c).forEach(([o,m])=>{typeof m>"u"&&delete c[o]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:a0,rangeExtractor:n0,onChange:()=>{},measureElement:s0,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,...c}},this.notify=c=>{var o,m;(m=(o=this.options).onChange)==null||m.call(o,this,c)},this.maybeNotify=Ka(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),c=>{this.notify(c)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(c=>c()),this.unsubs=[],this.observer.disconnect(),this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var c;const o=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==o){if(this.cleanup(),!o){this.maybeNotify();return}this.scrollElement=o,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((c=this.scrollElement)==null?void 0:c.window)??null,this.elementsCache.forEach(m=>{this.observer.observe(m)}),this.unsubs.push(this.options.observeElementRect(this,m=>{this.scrollRect=m,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(m,g)=>{this.scrollAdjustments=0,this.scrollDirection=g?this.getScrollOffset()<m?"forward":"backward":null,this.scrollOffset=m,this.isScrolling=g,this.maybeNotify()})),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}},this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(c,o)=>{const m=new Map,g=new Map;for(let v=o-1;v>=0;v--){const E=c[v];if(m.has(E.lane))continue;const j=g.get(E.lane);if(j==null||E.end>j.end?g.set(E.lane,E):E.end<j.end&&m.set(E.lane,!0),m.size===this.options.lanes)break}return g.size===this.options.lanes?Array.from(g.values()).sort((v,E)=>v.end===E.end?v.index-E.index:v.end-E.end)[0]:void 0},this.getMeasurementOptions=Ka(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes],(c,o,m,g,v,E)=>(this.prevLanes!==void 0&&this.prevLanes!==E&&(this.lanesChangedFlag=!0),this.prevLanes=E,this.pendingMeasuredCacheIndexes=[],{count:c,paddingStart:o,scrollMargin:m,getItemKey:g,enabled:v,lanes:E}),{key:!1}),this.getMeasurements=Ka(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:c,paddingStart:o,scrollMargin:m,getItemKey:g,enabled:v,lanes:E},j)=>{if(!v)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>c)for(const U of this.laneAssignments.keys())U>=c&&this.laneAssignments.delete(U);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMeasuredCacheIndexes=[]),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(U=>{this.itemSizeCache.set(U.key,U.size)}));const M=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===c&&(this.lanesSettling=!1);const R=this.measurementsCache.slice(0,M),C=new Array(E).fill(void 0);for(let U=0;U<M;U++){const k=R[U];k&&(C[k.lane]=U)}for(let U=M;U<c;U++){const k=g(U),Z=this.laneAssignments.get(U);let G,J;if(Z!==void 0&&this.options.lanes>1){G=Z;const bt=C[G],qt=bt!==void 0?R[bt]:void 0;J=qt?qt.end+this.options.gap:o+m}else{const bt=this.options.lanes===1?R[U-1]:this.getFurthestMeasurement(R,U);J=bt?bt.end+this.options.gap:o+m,G=bt?bt.lane:U%this.options.lanes,this.options.lanes>1&&this.laneAssignments.set(U,G)}const gt=j.get(k),St=typeof gt=="number"?gt:this.options.estimateSize(U),Et=J+St;R[U]={index:U,start:J,size:St,end:Et,key:k,lane:G},C[G]=U}return this.measurementsCache=R,R},{key:!1,debug:()=>this.options.debug}),this.calculateRange=Ka(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(c,o,m,g)=>this.range=c.length>0&&o>0?r0({measurements:c,outerSize:o,scrollOffset:m,lanes:g}):null,{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=Ka(()=>{let c=null,o=null;const m=this.calculateRange();return m&&(c=m.startIndex,o=m.endIndex),this.maybeNotify.updateDeps([this.isScrolling,c,o]),[this.options.rangeExtractor,this.options.overscan,this.options.count,c,o]},(c,o,m,g,v)=>g===null||v===null?[]:c({startIndex:g,endIndex:v,overscan:o,count:m}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=c=>{const o=this.options.indexAttribute,m=c.getAttribute(o);return m?parseInt(m,10):(console.warn(`Missing attribute name '${o}={index}' on measured element.`),-1)},this._measureElement=(c,o)=>{const m=this.indexFromElement(c),g=this.measurementsCache[m];if(!g)return;const v=g.key,E=this.elementsCache.get(v);E!==c&&(E&&this.observer.unobserve(E),this.observer.observe(c),this.elementsCache.set(v,c)),c.isConnected&&this.resizeItem(m,this.options.measureElement(c,o,this))},this.resizeItem=(c,o)=>{const m=this.measurementsCache[c];if(!m)return;const g=this.itemSizeCache.get(m.key)??m.size,v=o-g;v!==0&&((this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(m,v,this):m.start<this.getScrollOffset()+this.scrollAdjustments)&&this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=v,behavior:void 0}),this.pendingMeasuredCacheIndexes.push(m.index),this.itemSizeCache=new Map(this.itemSizeCache.set(m.key,o)),this.notify(!1))},this.measureElement=c=>{if(!c){this.elementsCache.forEach((o,m)=>{o.isConnected||(this.observer.unobserve(o),this.elementsCache.delete(m))});return}this._measureElement(c,void 0)},this.getVirtualItems=Ka(()=>[this.getVirtualIndexes(),this.getMeasurements()],(c,o)=>{const m=[];for(let g=0,v=c.length;g<v;g++){const E=c[g],j=o[E];m.push(j)}return m},{key:!1,debug:()=>this.options.debug}),this.getVirtualItemForOffset=c=>{const o=this.getMeasurements();if(o.length!==0)return Vm(o[Nh(0,o.length-1,m=>Vm(o[m]).start,c)])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const c=this.scrollElement.document.documentElement;return this.options.horizontal?c.scrollWidth-this.scrollElement.innerWidth:c.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(c,o,m=0)=>{if(!this.scrollElement)return 0;const g=this.getSize(),v=this.getScrollOffset();o==="auto"&&(o=c>=v+g?"end":"start"),o==="center"?c+=(m-g)/2:o==="end"&&(c-=g);const E=this.getMaxScrollOffset();return Math.max(Math.min(E,c),0)},this.getOffsetForIndex=(c,o="auto")=>{c=Math.max(0,Math.min(c,this.options.count-1));const m=this.measurementsCache[c];if(!m)return;const g=this.getSize(),v=this.getScrollOffset();if(o==="auto")if(m.end>=v+g-this.options.scrollPaddingEnd)o="end";else if(m.start<=v+this.options.scrollPaddingStart)o="start";else return[v,o];if(o==="end"&&c===this.options.count-1)return[this.getMaxScrollOffset(),o];const E=o==="end"?m.end+this.options.scrollPaddingEnd:m.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(E,o,m.size),o]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(c,{align:o="start",behavior:m}={})=>{m==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(c,o),{adjustments:void 0,behavior:m})},this.scrollToIndex=(c,{align:o="auto",behavior:m}={})=>{m==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),c=Math.max(0,Math.min(c,this.options.count-1)),this.currentScrollToIndex=c;let g=0;const v=10,E=M=>{if(!this.targetWindow)return;const R=this.getOffsetForIndex(c,M);if(!R){console.warn("Failed to get offset for index:",c);return}const[C,U]=R;this._scrollToOffset(C,{adjustments:void 0,behavior:m}),this.targetWindow.requestAnimationFrame(()=>{const k=()=>{if(this.currentScrollToIndex!==c)return;const Z=this.getScrollOffset(),G=this.getOffsetForIndex(c,U);if(!G){console.warn("Failed to get offset for index:",c);return}e0(G[0],Z)||j(U)};this.isDynamicMode()?this.targetWindow.requestAnimationFrame(k):k()})},j=M=>{this.targetWindow&&this.currentScrollToIndex===c&&(g++,g<v?this.targetWindow.requestAnimationFrame(()=>E(M)):console.warn(`Failed to scroll to index ${c} after ${v} attempts.`))};E(o)},this.scrollBy=(c,{behavior:o}={})=>{o==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getScrollOffset()+c,{adjustments:void 0,behavior:o})},this.getTotalSize=()=>{var c;const o=this.getMeasurements();let m;if(o.length===0)m=this.options.paddingStart;else if(this.options.lanes===1)m=((c=o[o.length-1])==null?void 0:c.end)??0;else{const g=Array(this.options.lanes).fill(null);let v=o.length-1;for(;v>=0&&g.some(E=>E===null);){const E=o[v];g[E.lane]===null&&(g[E.lane]=E.end),v--}m=Math.max(...g.filter(E=>E!==null))}return Math.max(m-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(c,{adjustments:o,behavior:m})=>{this.options.scrollToFn(c,{behavior:m,adjustments:o},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(r)}}const Nh=(u,r,c,o)=>{for(;u<=r;){const m=(u+r)/2|0,g=c(m);if(g<o)u=m+1;else if(g>o)r=m-1;else return m}return u>0?u-1:0};function r0({measurements:u,outerSize:r,scrollOffset:c,lanes:o}){const m=u.length-1,g=j=>u[j].start;if(u.length<=o)return{startIndex:0,endIndex:m};let v=Nh(0,m,g,c),E=v;if(o===1)for(;E<m&&u[E].end<c+r;)E++;else if(o>1){const j=Array(o).fill(0);for(;E<m&&j.some(R=>R<c+r);){const R=u[E];j[R.lane]=R.end,E++}const M=Array(o).fill(c+r);for(;v>=0&&M.some(R=>R>=c);){const R=u[v];M[R.lane]=R.start,v--}v=Math.max(0,v-v%o),E=Math.min(m,E+(o-1-E%o))}return{startIndex:v,endIndex:E}}const Km=typeof document<"u"?_.useLayoutEffect:_.useEffect;function f0({useFlushSync:u=!0,...r}){const c=_.useReducer(()=>({}),{})[1],o={...r,onChange:(g,v)=>{var E;u&&v?dp.flushSync(c):c(),(E=r.onChange)==null||E.call(r,g,v)}},[m]=_.useState(()=>new o0(o));return m.setOptions(o),Km(()=>m._didMount(),[]),Km(()=>m._willUpdate()),m}function d0(u){return f0({observeElementRect:i0,observeElementOffset:u0,scrollToFn:c0,...u})}const zh=24,m0=5,h0=50;function g0({status:u}){return u==="running"?f.jsxs("div",{"data-testid":"status-indicator-streaming",className:"flex items-center gap-1.5 text-primary text-sm",children:[f.jsx(rv,{className:"h-3.5 w-3.5 animate-spin","data-testid":"status-icon-loader"}),f.jsx("span",{children:"Streaming"})]}):f.jsxs("div",{"data-testid":"status-indicator-complete",className:"flex items-center gap-1.5 text-success text-sm",children:[f.jsx(bu,{className:"h-3.5 w-3.5","data-testid":"status-icon-complete"}),f.jsx("span",{children:"Complete"})]})}function y0(){return f.jsxs("div",{"data-testid":"log-viewer-skeleton",className:"p-4 space-y-2",children:[f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-3/4"}),f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-1/2"}),f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-5/6"}),f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-2/3"})]})}function p0({status:u,autoScroll:r,onToggleAutoScroll:c}){return f.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-b border-bg-light",children:[f.jsx(g0,{status:u}),f.jsxs("button",{type:"button","data-testid":"auto-scroll-toggle",onClick:c,"aria-pressed":r,title:r?"Autoscroll locked to bottom":"Autoscroll unlocked",className:`flex items-center gap-1.5 px-2 py-1 text-xs rounded-md transition-colors ${r?"bg-success/20 text-success hover:bg-success/30":"bg-bg-light text-text-muted hover:bg-bg-lighter"}`,children:[r?f.jsx(hv,{className:"h-3.5 w-3.5","data-testid":"autoscroll-icon-enabled"}):f.jsx(dv,{className:"h-3.5 w-3.5","data-testid":"autoscroll-icon-disabled"}),f.jsx("span",{children:"Autoscroll"})]})]})}function v0({virtualizer:u,virtualItems:r,lines:c}){return f.jsx("div",{className:"relative w-full",style:{height:`${u.getTotalSize()}px`},"data-testid":"log-height-container",children:f.jsx("div",{className:"absolute top-0 left-0 w-full px-4",style:{transform:`translateY(${r[0]?.start??0}px)`},children:r.map(o=>f.jsx("div",{"data-testid":"log-line","data-index":o.index,className:"text-text leading-relaxed",style:{height:`${zh}px`},children:c[o.index]||" "},o.key))})})}function b0(){return f.jsx("div",{"data-testid":"log-viewer",className:"h-full bg-bg-dark rounded-md font-mono flex items-center justify-center",children:f.jsx("span",{className:"text-text-muted",children:"Output unavailable"})})}function x0({error:u}){return f.jsxs("div",{"data-testid":"log-viewer-error",className:"h-full bg-bg-dark rounded-md font-mono flex flex-col items-center justify-center gap-2",children:[f.jsx(vu,{className:"h-6 w-6 text-danger"}),f.jsx("span",{className:"text-danger text-sm",children:"Failed to load logs"}),f.jsx("span",{className:"text-text-muted text-xs max-w-xs text-center",children:u})]})}function S0(u,r){const[c,o]=_.useState(""),[m,g]=_.useState(!0),[v,E]=_.useState(!1),[j,M]=_.useState(null);return _.useEffect(()=>{if(!r){g(!1);return}const R=jm();if(!R){g(!1);return}return wp(u,(C,U,k)=>{U?(o(C),g(!1)):o(Z=>Z+C),k&&E(!0)},C=>{M(C),g(!1)}),R({event:"subscribe:logs",data:{sessionName:u}}),()=>{Bp(u);const C=jm();C&&C({event:"unsubscribe:logs",data:{sessionName:u}})}},[u,r]),{content:c,isLoading:m,streamComplete:v,error:j}}function E0(u,r,c,o){const[m,g]=_.useState(c==="running"),v=_.useRef(0);_.useEffect(()=>{m&&o>v.current&&requestAnimationFrame(()=>{if(r.current&&u.current){const M=r.current.getTotalSize();u.current.scrollTop=M}}),v.current=o},[o,m,r,u]);const E=_.useCallback(()=>{const M=u.current;if(!M)return;!(M.scrollHeight-M.scrollTop-M.clientHeight<h0)&&m&&g(!1)},[m,u]),j=_.useCallback(()=>{g(M=>(M||requestAnimationFrame(()=>{if(r.current&&u.current){const R=r.current.getTotalSize();u.current.scrollTop=R}}),!M))},[r,u]);return{autoScroll:m,handleScroll:E,toggleAutoScroll:j}}function N0(u){return _.useMemo(()=>u?u.split(`
|
|
15
|
-
`):[],[u])}function z0({sessionName:u,status:r,outputAvailable:c,initialContent:o=""}){const m=_.useRef(null),g=_.useRef(null),{content:v,isLoading:E,streamComplete:j,error:M}=S0(u,c),C=N0(o||v),U=j?"completed":r,k=d0({count:C.length,getScrollElement:()=>m.current,estimateSize:()=>zh,overscan:m0});g.current=k;const{autoScroll:Z,handleScroll:G,toggleAutoScroll:J}=E0(m,g,U,C.length);if(!c)return f.jsx(b0,{});if(M)return f.jsx(x0,{error:M});const gt=E&&!o,St=k.getVirtualItems();return f.jsxs("div",{"data-testid":"log-viewer",className:"flex flex-col h-full bg-bg-dark rounded-md",children:[f.jsx(p0,{status:U,autoScroll:Z,onToggleAutoScroll:J}),f.jsx("div",{"data-testid":"log-content",ref:m,onScroll:G,className:"flex-1 min-h-0 font-mono overflow-auto",children:gt?f.jsx(y0,{}):f.jsx(v0,{virtualizer:k,virtualItems:St,lines:C})})]})}const T0=1e3,j0=1e3;function Jc(){return f.jsx(ne,{className:"animate-pulse","data-testid":"session-card-skeleton",children:f.jsxs(ye,{className:"pb-2",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[f.jsx("div",{className:"h-4 w-4 bg-bg-light rounded"}),f.jsx("div",{className:"h-5 w-48 bg-bg-light rounded"}),f.jsx("div",{className:"h-5 w-16 bg-bg-light rounded-full ml-auto"})]}),f.jsxs("div",{className:"flex items-center gap-4 mt-2",children:[f.jsx("div",{className:"h-4 w-32 bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-20 bg-bg-light rounded"})]})]})})}function A0(){return f.jsxs("div",{"data-testid":"sessions-panel-skeleton",className:"space-y-4",children:[f.jsx(Jc,{}),f.jsx(Jc,{}),f.jsx(Jc,{})]})}function Jm({status:u}){return u==="running"?f.jsxs(wl,{className:"bg-primary/20 text-primary flex items-center gap-1",children:[f.jsx(yv,{className:"w-3 h-3"}),"Running"]}):f.jsxs(wl,{className:"bg-success/20 text-success flex items-center gap-1",children:[f.jsx(bu,{className:"w-3 h-3"}),"Completed"]})}function Wm(u){return new Date(u).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function Wc(u,r){const c=new Date(u).getTime(),o=r?new Date(r).getTime():Date.now();return Math.floor((o-c)/T0)}function O0(u,r,c){const[o,m]=_.useState(()=>Wc(u,r));return _.useEffect(()=>{if(!c){m(Wc(u,r));return}const g=setInterval(()=>{m(Wc(u,r))},j0);return()=>clearInterval(g)},[u,r,c]),o}function M0({session:u,defaultExpanded:r=!1}){const[c,o]=_.useState(r),m=u.status==="running",g=O0(u.startTime,u.endTime,m);return u.outputAvailable?f.jsx(ho,{open:c,onOpenChange:o,children:f.jsxs(ne,{"data-testid":"session-detail-card",children:[f.jsx(mo,{asChild:!0,children:f.jsxs(ye,{className:"cursor-pointer hover:bg-bg-light/50 transition-colors py-3",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[c?f.jsx(so,{className:"w-4 h-4 text-text-muted"}):f.jsx(co,{className:"w-4 h-4 text-text-muted"}),f.jsx(Pc,{className:"w-4 h-4 text-text-muted"}),f.jsx("span",{className:"font-medium text-text truncate",children:u.name}),f.jsx(Jm,{status:u.status})]}),f.jsxs("div",{className:"flex items-center gap-4 mt-2 text-sm text-text-muted pl-8",children:[f.jsxs("span",{children:["Started at ",Wm(u.startTime)]}),f.jsx("span",{children:eo(g)})]})]})}),f.jsx(fo,{children:f.jsx(Ae,{className:"pt-0 pb-4",children:f.jsx("div",{className:"h-64",children:f.jsx(z0,{sessionName:u.name,status:u.status,outputAvailable:u.outputAvailable})})})})]})}):f.jsx(ne,{"data-testid":"session-detail-card",className:"opacity-60",children:f.jsxs(ye,{className:"py-3",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[f.jsx(Pc,{className:"w-4 h-4 text-text-muted"}),f.jsx("span",{className:"font-medium text-text truncate",children:u.name}),f.jsx(Jm,{status:u.status})]}),f.jsxs("div",{className:"flex items-center gap-4 mt-2 text-sm text-text-muted",children:[f.jsxs("span",{children:["Started at ",Wm(u.startTime)]}),f.jsx("span",{children:eo(g)})]}),f.jsx("div",{className:"mt-2 text-sm text-text-muted italic",children:"Output unavailable"})]})})}function C0(){return f.jsxs("div",{"data-testid":"sessions-panel-empty",className:"text-center py-8",children:[f.jsx(Pc,{className:"w-8 h-8 text-text-muted mx-auto mb-2"}),f.jsx("p",{className:"text-text-muted",children:"No sessions found for this story"})]})}function D0({onRetry:u}){return f.jsxs("div",{"data-testid":"sessions-panel-error",className:"text-center py-8",children:[f.jsx(vu,{className:"w-8 h-8 text-danger mx-auto mb-2"}),f.jsx("p",{className:"text-danger font-medium mb-1",children:"Failed to load sessions"}),f.jsx("p",{className:"text-text-muted text-sm mb-4",children:"Something went wrong while fetching sessions."}),f.jsxs(Eh,{variant:"outline",size:"sm",onClick:u,children:[f.jsx(vv,{className:"w-4 h-4 mr-2"}),"Retry"]})]})}function _0(u){if(u.length===0)return null;const r=u.filter(c=>c.status==="running");return r.length>0?r[0].name:u[0].name}function U0({epicSlug:u,storySlug:r}){const{sessions:c}=ua(),[o,m]=_.useState([]),[g,v]=_.useState(!0),[E,j]=_.useState(!1),M=_.useRef(void 0),R=_.useMemo(()=>c.filter(G=>G.epicSlug===u&&G.storySlug===r),[c,u,r]),C=R.length>0?R:o,U=_.useMemo(()=>[...C].sort((G,J)=>new Date(J.startTime).getTime()-new Date(G.startTime).getTime()),[C]);M.current===void 0&&U.length>0&&(M.current=_0(U));const k=M.current??null,Z=_.useCallback(async()=>{v(!0),j(!1);try{const G=await fetch(`/api/sessions?epicSlug=${u}&storySlug=${r}`);if(G.ok){const J=await G.json();m(J)}else j(!0),m([])}catch{j(!0),m([])}finally{v(!1)}},[u,r]);return _.useEffect(()=>{Z()},[Z]),g?f.jsx(A0,{}):E?f.jsx("div",{"data-testid":"sessions-panel",children:f.jsx(D0,{onRetry:Z})}):U.length===0?f.jsx("div",{"data-testid":"sessions-panel",children:f.jsx(C0,{})}):f.jsx("div",{"data-testid":"sessions-panel",className:"space-y-4",children:U.map(G=>f.jsx(M0,{session:G,defaultExpanded:G.name===k},G.name))})}const Th=_.forwardRef(({...u},r)=>f.jsx(mp,{ref:r,...u}));Th.displayName="Tabs";const jh=_.forwardRef(({className:u,...r},c)=>f.jsx(hp,{ref:c,className:Ht("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",u),...r}));jh.displayName="TabsList";const Zn=_.forwardRef(({className:u,...r},c)=>f.jsx(gp,{ref:c,className:Ht("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs",u),...r}));Zn.displayName="TabsTrigger";const kn=_.forwardRef(({className:u,...r},c)=>f.jsx(yp,{ref:c,className:Ht("mt-2 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",u),...r}));kn.displayName="TabsContent";const R0=404,w0=["tasks","content","journal","sessions"];function B0(u){const r=u.get("tab");return r&&w0.includes(r)?r:"tasks"}function H0(){return f.jsxs("div",{className:"animate-pulse space-y-4","data-testid":"story-header-skeleton",children:[f.jsx("div",{className:"h-8 w-64 bg-bg-light rounded"}),f.jsxs("div",{className:"flex items-center gap-4",children:[f.jsx("div",{className:"h-6 w-24 bg-bg-light rounded-full"}),f.jsx("div",{className:"h-4 w-32 bg-bg-light rounded"})]})]})}function q0(){return f.jsxs("div",{className:"animate-pulse space-y-4","data-testid":"story-content-skeleton",children:[f.jsx("div",{className:"h-6 w-48 bg-bg-light rounded"}),f.jsxs("div",{className:"space-y-2",children:[f.jsx("div",{className:"h-4 w-full bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-3/4 bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-5/6 bg-bg-light rounded"})]})]})}function Y0({status:u}){const r={ready:"bg-text-muted/20 text-text-muted",inProgress:"bg-primary/20 text-primary",blocked:"bg-danger/20 text-danger",completed:"bg-success/20 text-success"},c={ready:"Ready",inProgress:"In Progress",blocked:"Blocked",completed:"Completed"};return f.jsx(wl,{className:r[u],children:c[u]})}function G0({status:u}){const r={className:"w-5 h-5 pointer-events-none cursor-default"};switch(u){case"completed":return f.jsx(bu,{...r,className:`${r.className} text-success`,"data-testid":"icon-check-circle"});case"inProgress":return f.jsx(Ic,{...r,className:`${r.className} text-primary fill-primary/20`,"data-testid":"icon-circle-in-progress"});default:return f.jsx(Ic,{...r,className:`${r.className} text-text-muted`,"data-testid":"icon-circle-pending"})}}const $m={pending:"bg-text-muted/20 text-text-muted",inProgress:"bg-primary/20 text-primary",completed:"bg-success/20 text-success"},L0={pending:"pending",inProgress:"in progress",completed:"completed"};function X0(u){return $m[u]||$m.pending}function V0({task:u}){const r=X0(u.status);return f.jsxs("div",{className:"flex items-center gap-3 py-2 px-3 rounded-md hover:bg-bg-light/50",children:[f.jsx(G0,{status:u.status}),f.jsx("span",{className:u.status==="completed"?"text-text-muted line-through":"text-text",children:u.title}),f.jsx(wl,{className:`ml-auto text-xs ${r}`,children:L0[u.status]})]})}function Q0(u){switch(u){case"blocker":return{bg:"bg-danger/10",text:"text-danger",border:"border-danger/30"};case"resolution":return{bg:"bg-success/10",text:"text-success",border:"border-success/30"};default:return{bg:"bg-bg-light",text:"text-text",border:"border-border-muted"}}}function Z0({entry:u,defaultOpen:r=!1}){const[c,o]=_.useState(r),m=Q0(u.type);return f.jsx(ho,{open:c,onOpenChange:o,children:f.jsxs(ne,{className:`${m.bg} border ${m.border}`,children:[f.jsx(mo,{asChild:!0,children:f.jsx(ye,{className:"cursor-pointer hover:bg-bg-light/50 transition-colors py-3",children:f.jsxs("div",{className:"flex items-center gap-3",children:[c?f.jsx(so,{className:"w-4 h-4 text-text-muted","data-testid":"icon-chevron-down"}):f.jsx(co,{className:"w-4 h-4 text-text-muted","data-testid":"icon-chevron-right"}),f.jsx(wl,{className:`${m.bg} ${m.text} border ${m.border}`,children:u.type}),f.jsx(sa,{className:`text-sm font-medium ${m.text}`,children:u.title}),u.type==="blocker"&&f.jsx(vu,{className:"w-4 h-4 text-danger ml-auto","data-testid":"icon-alert-circle"}),u.timestamp&&f.jsx("span",{className:"text-xs text-text-muted ml-auto",children:u.timestamp})]})})}),f.jsx(fo,{children:f.jsx(Ae,{className:"pt-0 pb-4",children:f.jsx("div",{className:"prose prose-sm prose-invert max-w-none",children:f.jsx("pre",{className:"whitespace-pre-wrap text-sm text-text-muted font-mono bg-bg-dark p-3 rounded-md overflow-x-auto",children:u.content})})})})]})})}function k0(u){return u?{completed:u.tasks.filter(r=>r.status==="completed").length,total:u.tasks.length}:{completed:0,total:0}}function Ah(u){return{blockers:u.filter(r=>r.type==="blocker"),sessions:u.filter(r=>r.type==="session"),resolutions:u.filter(r=>r.type==="resolution")}}function K0({epicSlug:u,storySlug:r}){return f.jsxs("div",{className:"text-center py-12",children:[f.jsx("h1",{className:"text-2xl font-bold text-text mb-2",children:"Story not found"}),f.jsxs("p",{className:"text-text-muted mb-4",children:['The story "',r,'" does not exist in epic "',u,'".']}),f.jsx(il,{to:`/epic/${u}`,className:"text-primary hover:underline",children:"← Back to epic"})]})}function J0({epicSlug:u,error:r}){return f.jsxs("div",{className:"text-center py-12",children:[f.jsx("h1",{className:"text-2xl font-bold text-danger mb-2",children:"Error"}),f.jsx("p",{className:"text-text-muted mb-4",children:r}),f.jsx(il,{to:`/epic/${u}`,className:"text-primary hover:underline",children:"← Back to epic"})]})}function W0(){return f.jsxs("div",{className:"space-y-6",children:[f.jsx(H0,{}),f.jsx(q0,{})]})}function $0({story:u,epicSlug:r,storySlug:c}){const o=k0(u);return f.jsxs("div",{className:"space-y-4",children:[f.jsxs("div",{className:"flex items-center gap-2 text-sm text-text-muted",children:[f.jsx(il,{to:`/epic/${r}`,className:"hover:text-primary",children:r}),f.jsx("span",{children:"/"}),f.jsx("span",{className:"text-text",children:c})]}),f.jsx("h1",{className:"text-2xl font-bold text-text",children:u.title}),f.jsxs("div",{className:"flex items-center gap-4",children:[f.jsx(Y0,{status:u.status}),f.jsxs("span",{className:"text-sm text-text-muted",children:[o.completed,"/",o.total," tasks completed"]})]})]})}function F0({tasks:u}){return f.jsxs(ne,{children:[f.jsx(ye,{children:f.jsx(sa,{className:"text-lg",children:"Tasks"})}),f.jsx(Ae,{children:u.length===0?f.jsx("p",{className:"text-text-muted text-center py-4",children:"No tasks defined for this story."}):f.jsx("div",{className:"divide-y divide-border-muted",children:u.map(r=>f.jsx(V0,{task:r},r.id))})})]})}function I0({content:u}){return f.jsxs(ne,{children:[f.jsx(ye,{children:f.jsx(sa,{className:"text-lg",children:"Story Content"})}),f.jsx(Ae,{children:u?f.jsx("div",{className:"prose prose-sm prose-invert max-w-none prose-headings:text-text prose-p:text-text-muted prose-strong:text-text prose-code:text-primary prose-code:bg-bg-dark prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:before:content-none prose-code:after:content-none prose-pre:bg-bg-dark prose-pre:border prose-pre:border-border-muted prose-a:text-primary prose-a:no-underline prose-a:hover:underline prose-li:text-text-muted prose-table:border prose-table:border-border-muted prose-th:bg-bg-dark prose-th:px-3 prose-th:py-2 prose-th:text-text prose-td:px-3 prose-td:py-2 prose-td:border-t prose-td:border-border-muted",children:f.jsx(Fm,{remarkPlugins:[Im],children:u})}):f.jsx("p",{className:"text-text-muted text-center py-4",children:"No story content available."})})]})}function P0(u){return u==="Blockers"?"text-danger":u==="Resolutions"?"text-success":"text-text"}function $c({entries:u,type:r,icon:c}){if(u.length===0)return null;const o=P0(r);return f.jsxs("div",{className:"space-y-3",children:[f.jsxs("h3",{className:`text-sm font-semibold ${o} flex items-center gap-2`,children:[f.jsx(c,{className:"w-4 h-4"}),r," (",u.length,")"]}),u.map(m=>f.jsx(Z0,{entry:m,defaultOpen:r==="Blockers"},`${r.toLowerCase()}-${m.title}-${m.timestamp??""}`))]})}function tx({journal:u}){if(u.length===0)return f.jsx(ne,{children:f.jsx(Ae,{className:"py-8",children:f.jsx("p",{className:"text-text-muted text-center",children:"No journal entries yet."})})});const{blockers:r,sessions:c,resolutions:o}=Ah(u);return f.jsxs("div",{className:"space-y-4",children:[f.jsx($c,{entries:r,type:"Blockers",icon:vu}),f.jsx($c,{entries:o,type:"Resolutions",icon:bu}),f.jsx($c,{entries:c,type:"Sessions",icon:Ic})]})}async function ex(u){return u.status===R0?{type:"notFound"}:u.ok?{type:"success",data:await u.json()}:{type:"error"}}function lx(u,r,c){c("Failed to load story"),ro(u,r instanceof Error?r.message:"Unknown error")}function ax(u,r){const{currentStory:c,setCurrentStory:o,clearCurrentStory:m,subscribeToStory:g,unsubscribeFromStory:v,isConnected:E}=ua(),[j,M]=_.useState(!0),[R,C]=_.useState(!1),[U,k]=_.useState(null),Z=!!(u&&r);return _.useEffect(()=>(Z&&(async()=>{M(!0),C(!1),k(null);try{const J=await fetch(`/api/stories/${u}/${r}`),gt=await ex(J);gt.type==="notFound"?C(!0):gt.type==="error"?k("Failed to load story"):o(gt.data)}catch(J){lx(`/api/stories/${u}/${r}`,J,k)}finally{M(!1)}})(),m),[u,r,Z,o,m]),_.useEffect(()=>{if(Z&&E)return g(u,r),()=>{v(u,r)}},[u,r,Z,E,g,v]),{currentStory:c,loading:j,notFound:R,error:U}}function nx(){const{epicSlug:u,storySlug:r}=lo(),[c]=Np(),{currentStory:o,loading:m,notFound:g,error:v}=ax(u,r),E=B0(c);if(g)return f.jsx(K0,{epicSlug:u??"",storySlug:r??""});if(v&&!m)return f.jsx(J0,{epicSlug:u??"",error:v});if(m||!o)return f.jsx(W0,{});const{blockers:j}=Ah(o.journal);return f.jsxs("div",{className:"space-y-6",children:[f.jsx($0,{story:o,epicSlug:u??"",storySlug:r??""}),f.jsxs(Th,{defaultValue:E,className:"w-full",children:[f.jsxs(jh,{className:"mb-4",children:[f.jsx(Zn,{value:"tasks",children:"Tasks"}),f.jsx(Zn,{value:"content",children:"Story Content"}),f.jsxs(Zn,{value:"journal",children:["Journal",j.length>0&&f.jsx(wl,{className:"ml-2 bg-danger/20 text-danger text-xs",children:j.length})]}),f.jsx(Zn,{value:"sessions",children:"Sessions"})]}),f.jsx(kn,{value:"tasks",className:"space-y-4",children:f.jsx(F0,{tasks:o.tasks})}),f.jsx(kn,{value:"content",className:"space-y-4",children:f.jsx(I0,{content:o.content})}),f.jsx(kn,{value:"journal",className:"space-y-4",children:f.jsx(tx,{journal:o.journal})}),f.jsx(kn,{value:"sessions",className:"space-y-4",children:f.jsx(U0,{epicSlug:u??"",storySlug:r??""})})]})]})}const ix=[{path:"/",element:f.jsx(Nb,{}),children:[{path:"/",element:f.jsx(Pb,{})},{path:"epic/:slug",element:f.jsx(Qb,{})},{path:"epic/:epicSlug/story/:storySlug",element:f.jsx(nx,{})}]}];function ux(){return f.jsx(zp,{children:f.jsx(Tp,{children:ix.map(u=>f.jsx(bm,{path:u.path,element:u.element,children:u.children?.map(r=>f.jsx(bm,{path:r.path,element:r.element},r.path))},u.path))})})}const Oh=document.getElementById("root");if(!Oh)throw new Error("Root element not found");Cp.createRoot(Oh).render(f.jsx(_.StrictMode,{children:f.jsx(Zp,{children:f.jsx(ux,{})})}));
|
|
14
|
+
color: hsl(${Math.max(0,Math.min(120-120*J,120))}deg 100% 31%);`,c?.key)}return c?.onChange&&!(g&&c.skipInitialOnChange)&&c.onChange(m),g=!1,m}return v.updateDeps=E=>{o=E},v}function Vm(u,r){if(u===void 0)throw new Error("Unexpected undefined");return u}const e0=(u,r)=>Math.abs(u-r)<1.01,l0=(u,r,c)=>{let o;return function(...m){u.clearTimeout(o),o=u.setTimeout(()=>r.apply(this,m),c)}},Qm=u=>{const{offsetWidth:r,offsetHeight:c}=u;return{width:r,height:c}},a0=u=>u,n0=u=>{const r=Math.max(u.startIndex-u.overscan,0),c=Math.min(u.endIndex+u.overscan,u.count-1),o=[];for(let m=r;m<=c;m++)o.push(m);return o},i0=(u,r)=>{const c=u.scrollElement;if(!c)return;const o=u.targetWindow;if(!o)return;const m=v=>{const{width:E,height:j}=v;r({width:Math.round(E),height:Math.round(j)})};if(m(Qm(c)),!o.ResizeObserver)return()=>{};const g=new o.ResizeObserver(v=>{const E=()=>{const j=v[0];if(j?.borderBoxSize){const M=j.borderBoxSize[0];if(M){m({width:M.inlineSize,height:M.blockSize});return}}m(Qm(c))};u.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(E):E()});return g.observe(c,{box:"border-box"}),()=>{g.unobserve(c)}},Zm={passive:!0},km=typeof window>"u"?!0:"onscrollend"in window,u0=(u,r)=>{const c=u.scrollElement;if(!c)return;const o=u.targetWindow;if(!o)return;let m=0;const g=u.options.useScrollendEvent&&km?()=>{}:l0(o,()=>{r(m,!1)},u.options.isScrollingResetDelay),v=R=>()=>{const{horizontal:C,isRtl:U}=u.options;m=C?c.scrollLeft*(U&&-1||1):c.scrollTop,g(),r(m,R)},E=v(!0),j=v(!1);c.addEventListener("scroll",E,Zm);const M=u.options.useScrollendEvent&&km;return M&&c.addEventListener("scrollend",j,Zm),()=>{c.removeEventListener("scroll",E),M&&c.removeEventListener("scrollend",j)}},s0=(u,r,c)=>{if(r?.borderBoxSize){const o=r.borderBoxSize[0];if(o)return Math.round(o[c.options.horizontal?"inlineSize":"blockSize"])}return u[c.options.horizontal?"offsetWidth":"offsetHeight"]},c0=(u,{adjustments:r=0,behavior:c},o)=>{var m,g;const v=u+r;(g=(m=o.scrollElement)==null?void 0:m.scrollTo)==null||g.call(m,{[o.options.horizontal?"left":"top"]:v,behavior:c})};class o0{constructor(r){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.currentScrollToIndex=null,this.measurementsCache=[],this.itemSizeCache=new Map,this.laneAssignments=new Map,this.pendingMeasuredCacheIndexes=[],this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.observer=(()=>{let c=null;const o=()=>c||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:c=new this.targetWindow.ResizeObserver(m=>{m.forEach(g=>{const v=()=>{this._measureElement(g.target,g)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(v):v()})}));return{disconnect:()=>{var m;(m=o())==null||m.disconnect(),c=null},observe:m=>{var g;return(g=o())==null?void 0:g.observe(m,{box:"border-box"})},unobserve:m=>{var g;return(g=o())==null?void 0:g.unobserve(m)}}})(),this.range=null,this.setOptions=c=>{Object.entries(c).forEach(([o,m])=>{typeof m>"u"&&delete c[o]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:a0,rangeExtractor:n0,onChange:()=>{},measureElement:s0,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,...c}},this.notify=c=>{var o,m;(m=(o=this.options).onChange)==null||m.call(o,this,c)},this.maybeNotify=Ka(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),c=>{this.notify(c)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(c=>c()),this.unsubs=[],this.observer.disconnect(),this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var c;const o=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==o){if(this.cleanup(),!o){this.maybeNotify();return}this.scrollElement=o,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((c=this.scrollElement)==null?void 0:c.window)??null,this.elementsCache.forEach(m=>{this.observer.observe(m)}),this.unsubs.push(this.options.observeElementRect(this,m=>{this.scrollRect=m,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(m,g)=>{this.scrollAdjustments=0,this.scrollDirection=g?this.getScrollOffset()<m?"forward":"backward":null,this.scrollOffset=m,this.isScrolling=g,this.maybeNotify()})),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}},this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(c,o)=>{const m=new Map,g=new Map;for(let v=o-1;v>=0;v--){const E=c[v];if(m.has(E.lane))continue;const j=g.get(E.lane);if(j==null||E.end>j.end?g.set(E.lane,E):E.end<j.end&&m.set(E.lane,!0),m.size===this.options.lanes)break}return g.size===this.options.lanes?Array.from(g.values()).sort((v,E)=>v.end===E.end?v.index-E.index:v.end-E.end)[0]:void 0},this.getMeasurementOptions=Ka(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes],(c,o,m,g,v,E)=>(this.prevLanes!==void 0&&this.prevLanes!==E&&(this.lanesChangedFlag=!0),this.prevLanes=E,this.pendingMeasuredCacheIndexes=[],{count:c,paddingStart:o,scrollMargin:m,getItemKey:g,enabled:v,lanes:E}),{key:!1}),this.getMeasurements=Ka(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:c,paddingStart:o,scrollMargin:m,getItemKey:g,enabled:v,lanes:E},j)=>{if(!v)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>c)for(const U of this.laneAssignments.keys())U>=c&&this.laneAssignments.delete(U);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMeasuredCacheIndexes=[]),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(U=>{this.itemSizeCache.set(U.key,U.size)}));const M=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===c&&(this.lanesSettling=!1);const R=this.measurementsCache.slice(0,M),C=new Array(E).fill(void 0);for(let U=0;U<M;U++){const k=R[U];k&&(C[k.lane]=U)}for(let U=M;U<c;U++){const k=g(U),Z=this.laneAssignments.get(U);let G,J;if(Z!==void 0&&this.options.lanes>1){G=Z;const bt=C[G],qt=bt!==void 0?R[bt]:void 0;J=qt?qt.end+this.options.gap:o+m}else{const bt=this.options.lanes===1?R[U-1]:this.getFurthestMeasurement(R,U);J=bt?bt.end+this.options.gap:o+m,G=bt?bt.lane:U%this.options.lanes,this.options.lanes>1&&this.laneAssignments.set(U,G)}const gt=j.get(k),St=typeof gt=="number"?gt:this.options.estimateSize(U),Et=J+St;R[U]={index:U,start:J,size:St,end:Et,key:k,lane:G},C[G]=U}return this.measurementsCache=R,R},{key:!1,debug:()=>this.options.debug}),this.calculateRange=Ka(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(c,o,m,g)=>this.range=c.length>0&&o>0?r0({measurements:c,outerSize:o,scrollOffset:m,lanes:g}):null,{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=Ka(()=>{let c=null,o=null;const m=this.calculateRange();return m&&(c=m.startIndex,o=m.endIndex),this.maybeNotify.updateDeps([this.isScrolling,c,o]),[this.options.rangeExtractor,this.options.overscan,this.options.count,c,o]},(c,o,m,g,v)=>g===null||v===null?[]:c({startIndex:g,endIndex:v,overscan:o,count:m}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=c=>{const o=this.options.indexAttribute,m=c.getAttribute(o);return m?parseInt(m,10):(console.warn(`Missing attribute name '${o}={index}' on measured element.`),-1)},this._measureElement=(c,o)=>{const m=this.indexFromElement(c),g=this.measurementsCache[m];if(!g)return;const v=g.key,E=this.elementsCache.get(v);E!==c&&(E&&this.observer.unobserve(E),this.observer.observe(c),this.elementsCache.set(v,c)),c.isConnected&&this.resizeItem(m,this.options.measureElement(c,o,this))},this.resizeItem=(c,o)=>{const m=this.measurementsCache[c];if(!m)return;const g=this.itemSizeCache.get(m.key)??m.size,v=o-g;v!==0&&((this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(m,v,this):m.start<this.getScrollOffset()+this.scrollAdjustments)&&this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=v,behavior:void 0}),this.pendingMeasuredCacheIndexes.push(m.index),this.itemSizeCache=new Map(this.itemSizeCache.set(m.key,o)),this.notify(!1))},this.measureElement=c=>{if(!c){this.elementsCache.forEach((o,m)=>{o.isConnected||(this.observer.unobserve(o),this.elementsCache.delete(m))});return}this._measureElement(c,void 0)},this.getVirtualItems=Ka(()=>[this.getVirtualIndexes(),this.getMeasurements()],(c,o)=>{const m=[];for(let g=0,v=c.length;g<v;g++){const E=c[g],j=o[E];m.push(j)}return m},{key:!1,debug:()=>this.options.debug}),this.getVirtualItemForOffset=c=>{const o=this.getMeasurements();if(o.length!==0)return Vm(o[Nh(0,o.length-1,m=>Vm(o[m]).start,c)])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const c=this.scrollElement.document.documentElement;return this.options.horizontal?c.scrollWidth-this.scrollElement.innerWidth:c.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(c,o,m=0)=>{if(!this.scrollElement)return 0;const g=this.getSize(),v=this.getScrollOffset();o==="auto"&&(o=c>=v+g?"end":"start"),o==="center"?c+=(m-g)/2:o==="end"&&(c-=g);const E=this.getMaxScrollOffset();return Math.max(Math.min(E,c),0)},this.getOffsetForIndex=(c,o="auto")=>{c=Math.max(0,Math.min(c,this.options.count-1));const m=this.measurementsCache[c];if(!m)return;const g=this.getSize(),v=this.getScrollOffset();if(o==="auto")if(m.end>=v+g-this.options.scrollPaddingEnd)o="end";else if(m.start<=v+this.options.scrollPaddingStart)o="start";else return[v,o];if(o==="end"&&c===this.options.count-1)return[this.getMaxScrollOffset(),o];const E=o==="end"?m.end+this.options.scrollPaddingEnd:m.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(E,o,m.size),o]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(c,{align:o="start",behavior:m}={})=>{m==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(c,o),{adjustments:void 0,behavior:m})},this.scrollToIndex=(c,{align:o="auto",behavior:m}={})=>{m==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),c=Math.max(0,Math.min(c,this.options.count-1)),this.currentScrollToIndex=c;let g=0;const v=10,E=M=>{if(!this.targetWindow)return;const R=this.getOffsetForIndex(c,M);if(!R){console.warn("Failed to get offset for index:",c);return}const[C,U]=R;this._scrollToOffset(C,{adjustments:void 0,behavior:m}),this.targetWindow.requestAnimationFrame(()=>{const k=()=>{if(this.currentScrollToIndex!==c)return;const Z=this.getScrollOffset(),G=this.getOffsetForIndex(c,U);if(!G){console.warn("Failed to get offset for index:",c);return}e0(G[0],Z)||j(U)};this.isDynamicMode()?this.targetWindow.requestAnimationFrame(k):k()})},j=M=>{this.targetWindow&&this.currentScrollToIndex===c&&(g++,g<v?this.targetWindow.requestAnimationFrame(()=>E(M)):console.warn(`Failed to scroll to index ${c} after ${v} attempts.`))};E(o)},this.scrollBy=(c,{behavior:o}={})=>{o==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getScrollOffset()+c,{adjustments:void 0,behavior:o})},this.getTotalSize=()=>{var c;const o=this.getMeasurements();let m;if(o.length===0)m=this.options.paddingStart;else if(this.options.lanes===1)m=((c=o[o.length-1])==null?void 0:c.end)??0;else{const g=Array(this.options.lanes).fill(null);let v=o.length-1;for(;v>=0&&g.some(E=>E===null);){const E=o[v];g[E.lane]===null&&(g[E.lane]=E.end),v--}m=Math.max(...g.filter(E=>E!==null))}return Math.max(m-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(c,{adjustments:o,behavior:m})=>{this.options.scrollToFn(c,{behavior:m,adjustments:o},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(r)}}const Nh=(u,r,c,o)=>{for(;u<=r;){const m=(u+r)/2|0,g=c(m);if(g<o)u=m+1;else if(g>o)r=m-1;else return m}return u>0?u-1:0};function r0({measurements:u,outerSize:r,scrollOffset:c,lanes:o}){const m=u.length-1,g=j=>u[j].start;if(u.length<=o)return{startIndex:0,endIndex:m};let v=Nh(0,m,g,c),E=v;if(o===1)for(;E<m&&u[E].end<c+r;)E++;else if(o>1){const j=Array(o).fill(0);for(;E<m&&j.some(R=>R<c+r);){const R=u[E];j[R.lane]=R.end,E++}const M=Array(o).fill(c+r);for(;v>=0&&M.some(R=>R>=c);){const R=u[v];M[R.lane]=R.start,v--}v=Math.max(0,v-v%o),E=Math.min(m,E+(o-1-E%o))}return{startIndex:v,endIndex:E}}const Km=typeof document<"u"?_.useLayoutEffect:_.useEffect;function f0({useFlushSync:u=!0,...r}){const c=_.useReducer(()=>({}),{})[1],o={...r,onChange:(g,v)=>{var E;u&&v?dp.flushSync(c):c(),(E=r.onChange)==null||E.call(r,g,v)}},[m]=_.useState(()=>new o0(o));return m.setOptions(o),Km(()=>m._didMount(),[]),Km(()=>m._willUpdate()),m}function d0(u){return f0({observeElementRect:i0,observeElementOffset:u0,scrollToFn:c0,...u})}const zh=24,m0=5,h0=50;function g0({status:u}){return u==="running"?f.jsxs("div",{"data-testid":"status-indicator-streaming",className:"flex items-center gap-1.5 text-primary text-sm",children:[f.jsx(rv,{className:"h-3.5 w-3.5 animate-spin","data-testid":"status-icon-loader"}),f.jsx("span",{children:"Streaming"})]}):f.jsxs("div",{"data-testid":"status-indicator-complete",className:"flex items-center gap-1.5 text-success text-sm",children:[f.jsx(bu,{className:"h-3.5 w-3.5","data-testid":"status-icon-complete"}),f.jsx("span",{children:"Complete"})]})}function y0(){return f.jsxs("div",{"data-testid":"log-viewer-skeleton",className:"p-4 space-y-2",children:[f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-3/4"}),f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-1/2"}),f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-5/6"}),f.jsx("div",{className:"h-4 bg-bg-light rounded animate-pulse w-2/3"})]})}function p0({status:u,autoScroll:r,onToggleAutoScroll:c}){return f.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-b border-bg-light",children:[f.jsx(g0,{status:u}),f.jsxs("button",{type:"button","data-testid":"auto-scroll-toggle",onClick:c,"aria-pressed":r,title:r?"Autoscroll locked to bottom":"Autoscroll unlocked",className:`flex items-center gap-1.5 px-2 py-1 text-xs rounded-md transition-colors ${r?"bg-success/20 text-success hover:bg-success/30":"bg-bg-light text-text-muted hover:bg-bg-lighter"}`,children:[r?f.jsx(hv,{className:"h-3.5 w-3.5","data-testid":"autoscroll-icon-enabled"}):f.jsx(dv,{className:"h-3.5 w-3.5","data-testid":"autoscroll-icon-disabled"}),f.jsx("span",{children:"Autoscroll"})]})]})}function v0({virtualizer:u,virtualItems:r,lines:c}){return f.jsx("div",{className:"relative w-full",style:{height:`${u.getTotalSize()}px`},"data-testid":"log-height-container",children:f.jsx("div",{className:"absolute top-0 left-0 w-full px-4",style:{transform:`translateY(${r[0]?.start??0}px)`},children:r.map(o=>f.jsx("div",{"data-testid":"log-line","data-index":o.index,className:"text-text leading-relaxed",style:{height:`${zh}px`},children:c[o.index]||" "},o.key))})})}function b0(){return f.jsx("div",{"data-testid":"log-viewer",className:"h-full bg-bg-dark rounded-md font-mono flex items-center justify-center",children:f.jsx("span",{className:"text-text-muted",children:"Output unavailable"})})}function x0({error:u}){return f.jsxs("div",{"data-testid":"log-viewer",className:"h-full bg-bg-dark rounded-md font-mono flex flex-col items-center justify-center gap-2",children:[f.jsx(vu,{className:"h-6 w-6 text-danger"}),f.jsx("span",{className:"text-danger text-sm",children:"Failed to load logs"}),f.jsx("span",{className:"text-text-muted text-xs max-w-xs text-center",children:u})]})}function S0(u,r){const[c,o]=_.useState(""),[m,g]=_.useState(!0),[v,E]=_.useState(!1),[j,M]=_.useState(null);return _.useEffect(()=>{if(!r){g(!1);return}const R=jm();if(!R){g(!1);return}return wp(u,(C,U,k)=>{U?(o(C),g(!1)):o(Z=>Z+C),k&&E(!0)},C=>{M(C),g(!1)}),R({event:"subscribe:logs",data:{sessionName:u}}),()=>{Bp(u);const C=jm();C&&C({event:"unsubscribe:logs",data:{sessionName:u}})}},[u,r]),{content:c,isLoading:m,streamComplete:v,error:j}}function E0(u,r,c,o){const[m,g]=_.useState(c==="running"),v=_.useRef(0);_.useEffect(()=>{m&&o>v.current&&requestAnimationFrame(()=>{if(r.current&&u.current){const M=r.current.getTotalSize();u.current.scrollTop=M}}),v.current=o},[o,m,r,u]);const E=_.useCallback(()=>{const M=u.current;if(!M)return;!(M.scrollHeight-M.scrollTop-M.clientHeight<h0)&&m&&g(!1)},[m,u]),j=_.useCallback(()=>{g(M=>(M||requestAnimationFrame(()=>{if(r.current&&u.current){const R=r.current.getTotalSize();u.current.scrollTop=R}}),!M))},[r,u]);return{autoScroll:m,handleScroll:E,toggleAutoScroll:j}}function N0(u){return _.useMemo(()=>u?u.split(`
|
|
15
|
+
`):[],[u])}function z0({sessionName:u,status:r,outputAvailable:c,initialContent:o=""}){const m=_.useRef(null),g=_.useRef(null),{content:v,isLoading:E,streamComplete:j,error:M}=S0(u,c),C=N0(o||v),U=j?"completed":r,k=d0({count:C.length,getScrollElement:()=>m.current,estimateSize:()=>zh,overscan:m0});g.current=k;const{autoScroll:Z,handleScroll:G,toggleAutoScroll:J}=E0(m,g,U,C.length);if(!c)return f.jsx(b0,{});if(M)return f.jsx(x0,{error:M});const gt=E&&!o,St=k.getVirtualItems();return f.jsxs("div",{"data-testid":"log-viewer",className:"flex flex-col h-full bg-bg-dark rounded-md",children:[f.jsx(p0,{status:U,autoScroll:Z,onToggleAutoScroll:J}),f.jsx("div",{"data-testid":"log-content",ref:m,onScroll:G,className:"flex-1 min-h-0 font-mono overflow-auto",children:gt?f.jsx(y0,{}):f.jsx(v0,{virtualizer:k,virtualItems:St,lines:C})})]})}const T0=1e3,j0=1e3;function Jc(){return f.jsx(ne,{className:"animate-pulse","data-testid":"session-card-skeleton",children:f.jsxs(ye,{className:"pb-2",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[f.jsx("div",{className:"h-4 w-4 bg-bg-light rounded"}),f.jsx("div",{className:"h-5 w-48 bg-bg-light rounded"}),f.jsx("div",{className:"h-5 w-16 bg-bg-light rounded-full ml-auto"})]}),f.jsxs("div",{className:"flex items-center gap-4 mt-2",children:[f.jsx("div",{className:"h-4 w-32 bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-20 bg-bg-light rounded"})]})]})})}function A0(){return f.jsxs("div",{"data-testid":"sessions-panel-skeleton",className:"space-y-4",children:[f.jsx(Jc,{}),f.jsx(Jc,{}),f.jsx(Jc,{})]})}function Jm({status:u}){return u==="running"?f.jsxs(wl,{className:"bg-primary/20 text-primary flex items-center gap-1",children:[f.jsx(yv,{className:"w-3 h-3"}),"Running"]}):f.jsxs(wl,{className:"bg-success/20 text-success flex items-center gap-1",children:[f.jsx(bu,{className:"w-3 h-3"}),"Completed"]})}function Wm(u){return new Date(u).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function Wc(u,r){const c=new Date(u).getTime(),o=r?new Date(r).getTime():Date.now();return Math.floor((o-c)/T0)}function O0(u,r,c){const[o,m]=_.useState(()=>Wc(u,r));return _.useEffect(()=>{if(!c){m(Wc(u,r));return}const g=setInterval(()=>{m(Wc(u,r))},j0);return()=>clearInterval(g)},[u,r,c]),o}function M0({session:u,defaultExpanded:r=!1}){const[c,o]=_.useState(r),m=u.status==="running",g=O0(u.startTime,u.endTime,m);return u.outputAvailable?f.jsx(ho,{open:c,onOpenChange:o,children:f.jsxs(ne,{"data-testid":"session-detail-card",children:[f.jsx(mo,{asChild:!0,children:f.jsxs(ye,{"data-testid":"session-card-trigger",className:"cursor-pointer hover:bg-bg-light/50 transition-colors py-3",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[c?f.jsx(so,{className:"w-4 h-4 text-text-muted"}):f.jsx(co,{className:"w-4 h-4 text-text-muted"}),f.jsx(Pc,{className:"w-4 h-4 text-text-muted"}),f.jsx("span",{className:"font-medium text-text truncate",children:u.name}),f.jsx(Jm,{status:u.status})]}),f.jsxs("div",{className:"flex items-center gap-4 mt-2 text-sm text-text-muted pl-8",children:[f.jsxs("span",{children:["Started at ",Wm(u.startTime)]}),f.jsx("span",{children:eo(g)})]})]})}),f.jsx(fo,{children:f.jsx(Ae,{className:"pt-0 pb-4",children:f.jsx("div",{className:"h-64",children:f.jsx(z0,{sessionName:u.name,status:u.status,outputAvailable:u.outputAvailable})})})})]})}):f.jsx(ne,{"data-testid":"session-detail-card",className:"opacity-60",children:f.jsxs(ye,{className:"py-3",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[f.jsx(Pc,{className:"w-4 h-4 text-text-muted"}),f.jsx("span",{className:"font-medium text-text truncate",children:u.name}),f.jsx(Jm,{status:u.status})]}),f.jsxs("div",{className:"flex items-center gap-4 mt-2 text-sm text-text-muted",children:[f.jsxs("span",{children:["Started at ",Wm(u.startTime)]}),f.jsx("span",{children:eo(g)})]}),f.jsx("div",{className:"mt-2 text-sm text-text-muted italic",children:"Output unavailable"})]})})}function C0(){return f.jsxs("div",{"data-testid":"sessions-panel-empty",className:"text-center py-8",children:[f.jsx(Pc,{className:"w-8 h-8 text-text-muted mx-auto mb-2"}),f.jsx("p",{className:"text-text-muted",children:"No sessions found for this story"})]})}function D0({onRetry:u}){return f.jsxs("div",{"data-testid":"sessions-panel-error",className:"text-center py-8",children:[f.jsx(vu,{className:"w-8 h-8 text-danger mx-auto mb-2"}),f.jsx("p",{className:"text-danger font-medium mb-1",children:"Failed to load sessions"}),f.jsx("p",{className:"text-text-muted text-sm mb-4",children:"Something went wrong while fetching sessions."}),f.jsxs(Eh,{variant:"outline",size:"sm",onClick:u,children:[f.jsx(vv,{className:"w-4 h-4 mr-2"}),"Retry"]})]})}function _0(u){if(u.length===0)return null;const r=u.filter(c=>c.status==="running");return r.length>0?r[0].name:u[0].name}function U0({epicSlug:u,storySlug:r}){const{sessions:c}=ua(),[o,m]=_.useState([]),[g,v]=_.useState(!0),[E,j]=_.useState(!1),M=_.useRef(void 0),R=_.useMemo(()=>c.filter(G=>G.epicSlug===u&&G.storySlug===r),[c,u,r]),C=R.length>0?R:o,U=_.useMemo(()=>[...C].sort((G,J)=>new Date(J.startTime).getTime()-new Date(G.startTime).getTime()),[C]);M.current===void 0&&U.length>0&&(M.current=_0(U));const k=M.current??null,Z=_.useCallback(async()=>{v(!0),j(!1);try{const G=await fetch(`/api/sessions?epicSlug=${u}&storySlug=${r}`);if(G.ok){const J=await G.json();m(J)}else j(!0),m([])}catch{j(!0),m([])}finally{v(!1)}},[u,r]);return _.useEffect(()=>{Z()},[Z]),g?f.jsx(A0,{}):E?f.jsx("div",{"data-testid":"sessions-panel",children:f.jsx(D0,{onRetry:Z})}):U.length===0?f.jsx("div",{"data-testid":"sessions-panel",children:f.jsx(C0,{})}):f.jsx("div",{"data-testid":"sessions-panel",className:"space-y-4",children:U.map(G=>f.jsx(M0,{session:G,defaultExpanded:G.name===k},G.name))})}const Th=_.forwardRef(({...u},r)=>f.jsx(mp,{ref:r,...u}));Th.displayName="Tabs";const jh=_.forwardRef(({className:u,...r},c)=>f.jsx(hp,{ref:c,className:Ht("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",u),...r}));jh.displayName="TabsList";const Zn=_.forwardRef(({className:u,...r},c)=>f.jsx(gp,{ref:c,className:Ht("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs",u),...r}));Zn.displayName="TabsTrigger";const kn=_.forwardRef(({className:u,...r},c)=>f.jsx(yp,{ref:c,className:Ht("mt-2 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",u),...r}));kn.displayName="TabsContent";const R0=404,w0=["tasks","content","journal","sessions"];function B0(u){const r=u.get("tab");return r&&w0.includes(r)?r:"tasks"}function H0(){return f.jsxs("div",{className:"animate-pulse space-y-4","data-testid":"story-header-skeleton",children:[f.jsx("div",{className:"h-8 w-64 bg-bg-light rounded"}),f.jsxs("div",{className:"flex items-center gap-4",children:[f.jsx("div",{className:"h-6 w-24 bg-bg-light rounded-full"}),f.jsx("div",{className:"h-4 w-32 bg-bg-light rounded"})]})]})}function q0(){return f.jsxs("div",{className:"animate-pulse space-y-4","data-testid":"story-content-skeleton",children:[f.jsx("div",{className:"h-6 w-48 bg-bg-light rounded"}),f.jsxs("div",{className:"space-y-2",children:[f.jsx("div",{className:"h-4 w-full bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-3/4 bg-bg-light rounded"}),f.jsx("div",{className:"h-4 w-5/6 bg-bg-light rounded"})]})]})}function Y0({status:u}){const r={ready:"bg-text-muted/20 text-text-muted",inProgress:"bg-primary/20 text-primary",blocked:"bg-danger/20 text-danger",completed:"bg-success/20 text-success"},c={ready:"Ready",inProgress:"In Progress",blocked:"Blocked",completed:"Completed"};return f.jsx(wl,{className:r[u],children:c[u]})}function G0({status:u}){const r={className:"w-5 h-5 pointer-events-none cursor-default"};switch(u){case"completed":return f.jsx(bu,{...r,className:`${r.className} text-success`,"data-testid":"icon-check-circle"});case"inProgress":return f.jsx(Ic,{...r,className:`${r.className} text-primary fill-primary/20`,"data-testid":"icon-circle-in-progress"});default:return f.jsx(Ic,{...r,className:`${r.className} text-text-muted`,"data-testid":"icon-circle-pending"})}}const $m={pending:"bg-text-muted/20 text-text-muted",inProgress:"bg-primary/20 text-primary",completed:"bg-success/20 text-success"},L0={pending:"pending",inProgress:"in progress",completed:"completed"};function X0(u){return $m[u]||$m.pending}function V0({task:u}){const r=X0(u.status);return f.jsxs("div",{className:"flex items-center gap-3 py-2 px-3 rounded-md hover:bg-bg-light/50",children:[f.jsx(G0,{status:u.status}),f.jsx("span",{className:u.status==="completed"?"text-text-muted line-through":"text-text",children:u.title}),f.jsx(wl,{className:`ml-auto text-xs ${r}`,children:L0[u.status]})]})}function Q0(u){switch(u){case"blocker":return{bg:"bg-danger/10",text:"text-danger",border:"border-danger/30"};case"resolution":return{bg:"bg-success/10",text:"text-success",border:"border-success/30"};default:return{bg:"bg-bg-light",text:"text-text",border:"border-border-muted"}}}function Z0({entry:u,defaultOpen:r=!1}){const[c,o]=_.useState(r),m=Q0(u.type);return f.jsx(ho,{open:c,onOpenChange:o,children:f.jsxs(ne,{className:`${m.bg} border ${m.border}`,children:[f.jsx(mo,{asChild:!0,children:f.jsx(ye,{className:"cursor-pointer hover:bg-bg-light/50 transition-colors py-3",children:f.jsxs("div",{className:"flex items-center gap-3",children:[c?f.jsx(so,{className:"w-4 h-4 text-text-muted","data-testid":"icon-chevron-down"}):f.jsx(co,{className:"w-4 h-4 text-text-muted","data-testid":"icon-chevron-right"}),f.jsx(wl,{className:`${m.bg} ${m.text} border ${m.border}`,children:u.type}),f.jsx(sa,{className:`text-sm font-medium ${m.text}`,children:u.title}),u.type==="blocker"&&f.jsx(vu,{className:"w-4 h-4 text-danger ml-auto","data-testid":"icon-alert-circle"}),u.timestamp&&f.jsx("span",{className:"text-xs text-text-muted ml-auto",children:u.timestamp})]})})}),f.jsx(fo,{children:f.jsx(Ae,{className:"pt-0 pb-4",children:f.jsx("div",{className:"prose prose-sm prose-invert max-w-none",children:f.jsx("pre",{className:"whitespace-pre-wrap text-sm text-text-muted font-mono bg-bg-dark p-3 rounded-md overflow-x-auto",children:u.content})})})})]})})}function k0(u){return u?{completed:u.tasks.filter(r=>r.status==="completed").length,total:u.tasks.length}:{completed:0,total:0}}function Ah(u){return{blockers:u.filter(r=>r.type==="blocker"),sessions:u.filter(r=>r.type==="session"),resolutions:u.filter(r=>r.type==="resolution")}}function K0({epicSlug:u,storySlug:r}){return f.jsxs("div",{className:"text-center py-12",children:[f.jsx("h1",{className:"text-2xl font-bold text-text mb-2",children:"Story not found"}),f.jsxs("p",{className:"text-text-muted mb-4",children:['The story "',r,'" does not exist in epic "',u,'".']}),f.jsx(il,{to:`/epic/${u}`,className:"text-primary hover:underline",children:"← Back to epic"})]})}function J0({epicSlug:u,error:r}){return f.jsxs("div",{className:"text-center py-12",children:[f.jsx("h1",{className:"text-2xl font-bold text-danger mb-2",children:"Error"}),f.jsx("p",{className:"text-text-muted mb-4",children:r}),f.jsx(il,{to:`/epic/${u}`,className:"text-primary hover:underline",children:"← Back to epic"})]})}function W0(){return f.jsxs("div",{className:"space-y-6",children:[f.jsx(H0,{}),f.jsx(q0,{})]})}function $0({story:u,epicSlug:r,storySlug:c}){const o=k0(u);return f.jsxs("div",{className:"space-y-4",children:[f.jsxs("div",{className:"flex items-center gap-2 text-sm text-text-muted",children:[f.jsx(il,{to:`/epic/${r}`,className:"hover:text-primary",children:r}),f.jsx("span",{children:"/"}),f.jsx("span",{className:"text-text",children:c})]}),f.jsx("h1",{className:"text-2xl font-bold text-text",children:u.title}),f.jsxs("div",{className:"flex items-center gap-4",children:[f.jsx(Y0,{status:u.status}),f.jsxs("span",{className:"text-sm text-text-muted",children:[o.completed,"/",o.total," tasks completed"]})]})]})}function F0({tasks:u}){return f.jsxs(ne,{children:[f.jsx(ye,{children:f.jsx(sa,{className:"text-lg",children:"Tasks"})}),f.jsx(Ae,{children:u.length===0?f.jsx("p",{className:"text-text-muted text-center py-4",children:"No tasks defined for this story."}):f.jsx("div",{className:"divide-y divide-border-muted",children:u.map(r=>f.jsx(V0,{task:r},r.id))})})]})}function I0({content:u}){return f.jsxs(ne,{children:[f.jsx(ye,{children:f.jsx(sa,{className:"text-lg",children:"Story Content"})}),f.jsx(Ae,{children:u?f.jsx("div",{className:"prose prose-sm prose-invert max-w-none prose-headings:text-text prose-p:text-text-muted prose-strong:text-text prose-code:text-primary prose-code:bg-bg-dark prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:before:content-none prose-code:after:content-none prose-pre:bg-bg-dark prose-pre:border prose-pre:border-border-muted prose-a:text-primary prose-a:no-underline prose-a:hover:underline prose-li:text-text-muted prose-table:border prose-table:border-border-muted prose-th:bg-bg-dark prose-th:px-3 prose-th:py-2 prose-th:text-text prose-td:px-3 prose-td:py-2 prose-td:border-t prose-td:border-border-muted",children:f.jsx(Fm,{remarkPlugins:[Im],children:u})}):f.jsx("p",{className:"text-text-muted text-center py-4",children:"No story content available."})})]})}function P0(u){return u==="Blockers"?"text-danger":u==="Resolutions"?"text-success":"text-text"}function $c({entries:u,type:r,icon:c}){if(u.length===0)return null;const o=P0(r);return f.jsxs("div",{className:"space-y-3",children:[f.jsxs("h3",{className:`text-sm font-semibold ${o} flex items-center gap-2`,children:[f.jsx(c,{className:"w-4 h-4"}),r," (",u.length,")"]}),u.map(m=>f.jsx(Z0,{entry:m,defaultOpen:r==="Blockers"},`${r.toLowerCase()}-${m.title}-${m.timestamp??""}`))]})}function tx({journal:u}){if(u.length===0)return f.jsx(ne,{children:f.jsx(Ae,{className:"py-8",children:f.jsx("p",{className:"text-text-muted text-center",children:"No journal entries yet."})})});const{blockers:r,sessions:c,resolutions:o}=Ah(u);return f.jsxs("div",{className:"space-y-4",children:[f.jsx($c,{entries:r,type:"Blockers",icon:vu}),f.jsx($c,{entries:o,type:"Resolutions",icon:bu}),f.jsx($c,{entries:c,type:"Sessions",icon:Ic})]})}async function ex(u){return u.status===R0?{type:"notFound"}:u.ok?{type:"success",data:await u.json()}:{type:"error"}}function lx(u,r,c){c("Failed to load story"),ro(u,r instanceof Error?r.message:"Unknown error")}function ax(u,r){const{currentStory:c,setCurrentStory:o,clearCurrentStory:m,subscribeToStory:g,unsubscribeFromStory:v,isConnected:E}=ua(),[j,M]=_.useState(!0),[R,C]=_.useState(!1),[U,k]=_.useState(null),Z=!!(u&&r);return _.useEffect(()=>(Z&&(async()=>{M(!0),C(!1),k(null);try{const J=await fetch(`/api/stories/${u}/${r}`),gt=await ex(J);gt.type==="notFound"?C(!0):gt.type==="error"?k("Failed to load story"):o(gt.data)}catch(J){lx(`/api/stories/${u}/${r}`,J,k)}finally{M(!1)}})(),m),[u,r,Z,o,m]),_.useEffect(()=>{if(Z&&E)return g(u,r),()=>{v(u,r)}},[u,r,Z,E,g,v]),{currentStory:c,loading:j,notFound:R,error:U}}function nx(){const{epicSlug:u,storySlug:r}=lo(),[c]=Np(),{currentStory:o,loading:m,notFound:g,error:v}=ax(u,r),E=B0(c);if(g)return f.jsx(K0,{epicSlug:u??"",storySlug:r??""});if(v&&!m)return f.jsx(J0,{epicSlug:u??"",error:v});if(m||!o)return f.jsx(W0,{});const{blockers:j}=Ah(o.journal??[]);return f.jsxs("div",{className:"space-y-6",children:[f.jsx($0,{story:o,epicSlug:u??"",storySlug:r??""}),f.jsxs(Th,{defaultValue:E,className:"w-full",children:[f.jsxs(jh,{className:"mb-4",children:[f.jsx(Zn,{value:"tasks",children:"Tasks"}),f.jsx(Zn,{value:"content",children:"Story Content"}),f.jsxs(Zn,{value:"journal",children:["Journal",j.length>0&&f.jsx(wl,{className:"ml-2 bg-danger/20 text-danger text-xs",children:j.length})]}),f.jsx(Zn,{value:"sessions",children:"Sessions"})]}),f.jsx(kn,{value:"tasks",className:"space-y-4",children:f.jsx(F0,{tasks:o.tasks})}),f.jsx(kn,{value:"content",className:"space-y-4",children:f.jsx(I0,{content:o.content})}),f.jsx(kn,{value:"journal",className:"space-y-4",children:f.jsx(tx,{journal:o.journal??[]})}),f.jsx(kn,{value:"sessions",className:"space-y-4",children:f.jsx(U0,{epicSlug:u??"",storySlug:r??""})})]})]})}const ix=[{path:"/",element:f.jsx(Nb,{}),children:[{path:"/",element:f.jsx(Pb,{})},{path:"epic/:slug",element:f.jsx(Qb,{})},{path:"epic/:epicSlug/story/:storySlug",element:f.jsx(nx,{})}]}];function ux(){return f.jsx(zp,{children:f.jsx(Tp,{children:ix.map(u=>f.jsx(bm,{path:u.path,element:u.element,children:u.children?.map(r=>f.jsx(bm,{path:r.path,element:r.element},r.path))},u.path))})})}const Oh=document.getElementById("root");if(!Oh)throw new Error("Root element not found");Cp.createRoot(Oh).render(f.jsx(_.StrictMode,{children:f.jsx(Zp,{children:f.jsx(ux,{})})}));
|
package/dist/client/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>SAGA Dashboard</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-D3_tHSXd.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vendor-xstate-Dogcz2PC.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-radix-BuqlnHDi.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BQ8AP4vp.js">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saga-ai/cli",
|
|
3
|
-
"version": "2.17.
|
|
3
|
+
"version": "2.17.1",
|
|
4
4
|
"description": "CLI for SAGA - Structured Autonomous Goal Achievement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"build:cli": "esbuild src/cli.ts --bundle --platform=node --outfile=dist/cli.cjs --format=cjs --banner:js='#!/usr/bin/env node' --external:express --external:ws --external:chokidar --external:gray-matter --external:fuse.js --external:commander",
|
|
94
94
|
"build:client": "vite build --config src/client/vite.config.ts",
|
|
95
95
|
"build": "pnpm lint && concurrently -g \"pnpm build:cli\" \"pnpm build:client\"",
|
|
96
|
-
"test": "pnpm build && vitest run && pnpm
|
|
96
|
+
"test": "pnpm build && vitest run && pnpm test:integration && pnpm test:e2e",
|
|
97
97
|
"test:watch": "vitest",
|
|
98
98
|
"test:integration": "playwright test --config src/client/playwright.config.ts",
|
|
99
99
|
"test:integration:ui": "playwright test --config src/client/playwright.config.ts --ui",
|