@saga-ai/cli 2.16.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 +196 -65
- package/dist/client/assets/index-BBUWGVOv.css +1 -0
- package/dist/client/assets/index-D3_tHSXd.js +15 -0
- package/dist/client/assets/{vendor-markdown-DYPIbB23.js → vendor-markdown-Cy8XX9Jb.js} +1 -1
- package/dist/client/assets/{vendor-radix-Cn9lyvpX.js → vendor-radix-BuqlnHDi.js} +2 -2
- package/dist/client/assets/vendor-react-BQ8AP4vp.js +3 -0
- package/dist/client/index.html +5 -5
- package/package.json +2 -2
- package/dist/client/assets/index-B1WKLIKQ.css +0 -1
- package/dist/client/assets/index-BalaFQNj.js +0 -11
- package/dist/client/assets/vendor-react-Ca05HUaC.js +0 -3
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";
|
|
@@ -2194,17 +2198,144 @@ function buildScopeSettings() {
|
|
|
2194
2198
|
}
|
|
2195
2199
|
};
|
|
2196
2200
|
}
|
|
2201
|
+
function truncateString(str, maxLength) {
|
|
2202
|
+
if (str.length <= maxLength) {
|
|
2203
|
+
return str;
|
|
2204
|
+
}
|
|
2205
|
+
return `${str.slice(0, maxLength)}...`;
|
|
2206
|
+
}
|
|
2207
|
+
function formatInputValue(value, maxLength) {
|
|
2208
|
+
if (value === null || value === void 0) {
|
|
2209
|
+
return "null";
|
|
2210
|
+
}
|
|
2211
|
+
if (typeof value === "string") {
|
|
2212
|
+
const singleLine = value.replace(/\n/g, " ").replace(/\s+/g, " ");
|
|
2213
|
+
return truncateString(singleLine, maxLength);
|
|
2214
|
+
}
|
|
2215
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
2216
|
+
return String(value);
|
|
2217
|
+
}
|
|
2218
|
+
if (Array.isArray(value)) {
|
|
2219
|
+
return truncateString(JSON.stringify(value), maxLength);
|
|
2220
|
+
}
|
|
2221
|
+
if (typeof value === "object") {
|
|
2222
|
+
return truncateString(JSON.stringify(value), maxLength);
|
|
2223
|
+
}
|
|
2224
|
+
return String(value);
|
|
2225
|
+
}
|
|
2226
|
+
function formatAllInputFields(input) {
|
|
2227
|
+
const maxValueLength = 100;
|
|
2228
|
+
const entries = Object.entries(input);
|
|
2229
|
+
if (entries.length === 0) {
|
|
2230
|
+
return "";
|
|
2231
|
+
}
|
|
2232
|
+
return entries.map(([key, value]) => `${key}=${formatInputValue(value, maxValueLength)}`).join(", ");
|
|
2233
|
+
}
|
|
2234
|
+
function formatToolUsage(name, input) {
|
|
2235
|
+
try {
|
|
2236
|
+
const safeInput = input || {};
|
|
2237
|
+
const maxLength = 100;
|
|
2238
|
+
switch (name) {
|
|
2239
|
+
// File operations - show path
|
|
2240
|
+
case "Read": {
|
|
2241
|
+
const path = safeInput.file_path || "unknown";
|
|
2242
|
+
const extras = [];
|
|
2243
|
+
if (safeInput.offset) {
|
|
2244
|
+
extras.push(`offset=${safeInput.offset}`);
|
|
2245
|
+
}
|
|
2246
|
+
if (safeInput.limit) {
|
|
2247
|
+
extras.push(`limit=${safeInput.limit}`);
|
|
2248
|
+
}
|
|
2249
|
+
const suffix = extras.length > 0 ? ` (${extras.join(", ")})` : "";
|
|
2250
|
+
return `[Tool Used: Read] ${path}${suffix}`;
|
|
2251
|
+
}
|
|
2252
|
+
case "Write":
|
|
2253
|
+
return `[Tool Used: Write] ${safeInput.file_path || "unknown"}`;
|
|
2254
|
+
case "Edit": {
|
|
2255
|
+
const file = safeInput.file_path || "unknown";
|
|
2256
|
+
const replaceAll = safeInput.replace_all ? " (replace_all)" : "";
|
|
2257
|
+
return `[Tool Used: Edit] ${file}${replaceAll}`;
|
|
2258
|
+
}
|
|
2259
|
+
// Shell command - show command and description
|
|
2260
|
+
case "Bash": {
|
|
2261
|
+
const cmd = truncateString(String(safeInput.command || ""), maxLength);
|
|
2262
|
+
const desc = safeInput.description ? ` - ${truncateString(String(safeInput.description), 60)}` : "";
|
|
2263
|
+
return `[Tool Used: Bash] ${cmd}${desc}`;
|
|
2264
|
+
}
|
|
2265
|
+
// Search operations - show pattern and path
|
|
2266
|
+
case "Glob": {
|
|
2267
|
+
const pattern = safeInput.pattern || "unknown";
|
|
2268
|
+
const path = safeInput.path ? ` in ${safeInput.path}` : "";
|
|
2269
|
+
return `[Tool Used: Glob] ${pattern}${path}`;
|
|
2270
|
+
}
|
|
2271
|
+
case "Grep": {
|
|
2272
|
+
const pattern = truncateString(String(safeInput.pattern || ""), 60);
|
|
2273
|
+
const path = safeInput.path ? ` in ${safeInput.path}` : "";
|
|
2274
|
+
const mode = safeInput.output_mode ? ` (${safeInput.output_mode})` : "";
|
|
2275
|
+
return `[Tool Used: Grep] "${pattern}"${path}${mode}`;
|
|
2276
|
+
}
|
|
2277
|
+
// Agent task - show description and type
|
|
2278
|
+
case "Task": {
|
|
2279
|
+
const desc = truncateString(
|
|
2280
|
+
String(safeInput.description || safeInput.prompt || ""),
|
|
2281
|
+
maxLength
|
|
2282
|
+
);
|
|
2283
|
+
const agentType = safeInput.subagent_type ? ` [${safeInput.subagent_type}]` : "";
|
|
2284
|
+
return `[Tool Used: Task]${agentType} ${desc}`;
|
|
2285
|
+
}
|
|
2286
|
+
// Todo operations
|
|
2287
|
+
case "TodoWrite": {
|
|
2288
|
+
const todos = safeInput.todos;
|
|
2289
|
+
if (todos && Array.isArray(todos)) {
|
|
2290
|
+
const subjects = todos.map((t) => {
|
|
2291
|
+
if (t && typeof t === "object" && "subject" in t) {
|
|
2292
|
+
return String(t.subject || "untitled");
|
|
2293
|
+
}
|
|
2294
|
+
return "untitled";
|
|
2295
|
+
}).join(", ");
|
|
2296
|
+
return `[Tool Used: TodoWrite] ${truncateString(subjects, maxLength)}`;
|
|
2297
|
+
}
|
|
2298
|
+
return "[Tool Used: TodoWrite]";
|
|
2299
|
+
}
|
|
2300
|
+
// Structured output - show status
|
|
2301
|
+
case "StructuredOutput": {
|
|
2302
|
+
const status = safeInput.status || "unknown";
|
|
2303
|
+
const summary = safeInput.summary ? ` - ${truncateString(String(safeInput.summary), maxLength)}` : "";
|
|
2304
|
+
return `[Tool Used: StructuredOutput] ${status}${summary}`;
|
|
2305
|
+
}
|
|
2306
|
+
// Unknown tools - show all fields
|
|
2307
|
+
default: {
|
|
2308
|
+
const fields = formatAllInputFields(safeInput);
|
|
2309
|
+
return fields ? `[Tool Used: ${name}] ${fields}` : `[Tool Used: ${name}]`;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
} catch {
|
|
2313
|
+
return `[Tool Used: ${name}]`;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2197
2316
|
function formatAssistantContent(content) {
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
return blockData.text;
|
|
2317
|
+
try {
|
|
2318
|
+
if (!(content && Array.isArray(content))) {
|
|
2319
|
+
return null;
|
|
2202
2320
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2321
|
+
for (const block of content) {
|
|
2322
|
+
if (!block || typeof block !== "object") {
|
|
2323
|
+
continue;
|
|
2324
|
+
}
|
|
2325
|
+
const blockData = block;
|
|
2326
|
+
if (blockData.type === "text" && blockData.text) {
|
|
2327
|
+
return `${blockData.text}
|
|
2328
|
+
`;
|
|
2329
|
+
}
|
|
2330
|
+
if (blockData.type === "tool_use" && blockData.name) {
|
|
2331
|
+
return `${formatToolUsage(blockData.name, blockData.input || {})}
|
|
2332
|
+
`;
|
|
2333
|
+
}
|
|
2205
2334
|
}
|
|
2335
|
+
return null;
|
|
2336
|
+
} catch {
|
|
2337
|
+
return null;
|
|
2206
2338
|
}
|
|
2207
|
-
return null;
|
|
2208
2339
|
}
|
|
2209
2340
|
function formatStreamLine(line) {
|
|
2210
2341
|
try {
|
|
@@ -2309,19 +2440,19 @@ function spawnWorkerAsync(prompt, model, settings, workingDir) {
|
|
|
2309
2440
|
if (line.trim()) {
|
|
2310
2441
|
const formatted = formatStreamLine(line);
|
|
2311
2442
|
if (formatted) {
|
|
2312
|
-
|
|
2443
|
+
import_node_process6.default.stdout.write(formatted);
|
|
2313
2444
|
}
|
|
2314
2445
|
}
|
|
2315
2446
|
}
|
|
2316
2447
|
});
|
|
2317
2448
|
child.stderr.on("data", (chunk) => {
|
|
2318
|
-
|
|
2449
|
+
import_node_process6.default.stderr.write(chunk);
|
|
2319
2450
|
});
|
|
2320
2451
|
child.on("error", (err) => {
|
|
2321
2452
|
reject(new Error(`Failed to spawn worker: ${err.message}`));
|
|
2322
2453
|
});
|
|
2323
2454
|
child.on("close", (_code) => {
|
|
2324
|
-
|
|
2455
|
+
import_node_process6.default.stdout.write("\n");
|
|
2325
2456
|
try {
|
|
2326
2457
|
const result = parseStreamingResult(buffer);
|
|
2327
2458
|
resolve2(result);
|
|
@@ -2485,7 +2616,7 @@ function buildDetachedCommand(storySlug, projectPath, options) {
|
|
|
2485
2616
|
function handleDryRun(storyInfo, projectPath, pluginRoot) {
|
|
2486
2617
|
const dryRunResult = runDryRun(storyInfo, projectPath, pluginRoot);
|
|
2487
2618
|
printDryRunResults(dryRunResult);
|
|
2488
|
-
|
|
2619
|
+
import_node_process6.default.exit(dryRunResult.success ? 0 : 1);
|
|
2489
2620
|
}
|
|
2490
2621
|
async function handleDetachedMode(storySlug, storyInfo, projectPath, options) {
|
|
2491
2622
|
const detachedCommand = buildDetachedCommand(storySlug, projectPath, {
|
|
@@ -2504,7 +2635,7 @@ async function handleDetachedMode(storySlug, storyInfo, projectPath, options) {
|
|
|
2504
2635
|
console.error(
|
|
2505
2636
|
`Error creating session: ${error instanceof Error ? error.message : String(error)}`
|
|
2506
2637
|
);
|
|
2507
|
-
|
|
2638
|
+
import_node_process6.default.exit(1);
|
|
2508
2639
|
}
|
|
2509
2640
|
}
|
|
2510
2641
|
async function handleInternalSession(storyInfo, projectPath, pluginRoot, options) {
|
|
@@ -2526,7 +2657,7 @@ async function handleInternalSession(storyInfo, projectPath, pluginRoot, options
|
|
|
2526
2657
|
);
|
|
2527
2658
|
if (result.status === "ERROR") {
|
|
2528
2659
|
console.error(`Error: ${result.summary}`);
|
|
2529
|
-
|
|
2660
|
+
import_node_process6.default.exit(1);
|
|
2530
2661
|
}
|
|
2531
2662
|
console.log(`
|
|
2532
2663
|
Implementation ${result.status}: ${result.summary}`);
|
|
@@ -2537,28 +2668,28 @@ async function implementCommand(storySlug, options) {
|
|
|
2537
2668
|
projectPath = resolveProjectPath(options.path);
|
|
2538
2669
|
} catch (_error) {
|
|
2539
2670
|
console.error("Error: SAGA project not found. Run saga init first or use --path option.");
|
|
2540
|
-
|
|
2671
|
+
import_node_process6.default.exit(1);
|
|
2541
2672
|
}
|
|
2542
2673
|
const storyInfo = await findStory2(projectPath, storySlug);
|
|
2543
2674
|
if (!storyInfo) {
|
|
2544
2675
|
console.error(`Error: Story '${storySlug}' not found in project.`);
|
|
2545
2676
|
console.error("Use /generate-stories to create stories for an epic first.");
|
|
2546
|
-
|
|
2677
|
+
import_node_process6.default.exit(1);
|
|
2547
2678
|
}
|
|
2548
|
-
const pluginRoot =
|
|
2679
|
+
const pluginRoot = import_node_process6.default.env.SAGA_PLUGIN_ROOT;
|
|
2549
2680
|
if (options.dryRun) {
|
|
2550
2681
|
handleDryRun(storyInfo, projectPath, pluginRoot);
|
|
2551
2682
|
}
|
|
2552
2683
|
if (!pluginRoot) {
|
|
2553
2684
|
console.error("Error: SAGA_PLUGIN_ROOT environment variable is not set.");
|
|
2554
2685
|
console.error("This is required to find the worker prompt template.");
|
|
2555
|
-
|
|
2686
|
+
import_node_process6.default.exit(1);
|
|
2556
2687
|
}
|
|
2557
2688
|
if (!(0, import_node_fs6.existsSync)(storyInfo.worktreePath)) {
|
|
2558
2689
|
console.error(`Error: Worktree not found at ${storyInfo.worktreePath}`);
|
|
2559
|
-
|
|
2690
|
+
import_node_process6.default.exit(1);
|
|
2560
2691
|
}
|
|
2561
|
-
const isInternalSession =
|
|
2692
|
+
const isInternalSession = import_node_process6.default.env.SAGA_INTERNAL_SESSION === "1";
|
|
2562
2693
|
if (isInternalSession) {
|
|
2563
2694
|
await handleInternalSession(storyInfo, projectPath, pluginRoot, options);
|
|
2564
2695
|
} else {
|
|
@@ -2569,7 +2700,7 @@ async function implementCommand(storySlug, options) {
|
|
|
2569
2700
|
// src/commands/init.ts
|
|
2570
2701
|
var import_node_fs7 = require("node:fs");
|
|
2571
2702
|
var import_node_path12 = require("node:path");
|
|
2572
|
-
var
|
|
2703
|
+
var import_node_process7 = __toESM(require("node:process"), 1);
|
|
2573
2704
|
var WORKTREES_PATTERN = ".saga/worktrees/";
|
|
2574
2705
|
function runInitDryRun(targetPath) {
|
|
2575
2706
|
const sagaDir = (0, import_node_path12.join)(targetPath, ".saga");
|
|
@@ -2633,7 +2764,7 @@ function resolveTargetPath(explicitPath) {
|
|
|
2633
2764
|
if (existingRoot) {
|
|
2634
2765
|
return existingRoot;
|
|
2635
2766
|
}
|
|
2636
|
-
return
|
|
2767
|
+
return import_node_process7.default.cwd();
|
|
2637
2768
|
}
|
|
2638
2769
|
function createDirectoryStructure(projectRoot) {
|
|
2639
2770
|
const sagaDir = (0, import_node_path12.join)(projectRoot, ".saga");
|
|
@@ -2668,11 +2799,11 @@ function initCommand(options) {
|
|
|
2668
2799
|
if (options.path) {
|
|
2669
2800
|
if (!(0, import_node_fs7.existsSync)(options.path)) {
|
|
2670
2801
|
console.error(`Error: Path does not exist: ${options.path}`);
|
|
2671
|
-
|
|
2802
|
+
import_node_process7.default.exit(1);
|
|
2672
2803
|
}
|
|
2673
2804
|
if (!(0, import_node_fs7.statSync)(options.path).isDirectory()) {
|
|
2674
2805
|
console.error(`Error: Path is not a directory: ${options.path}`);
|
|
2675
|
-
|
|
2806
|
+
import_node_process7.default.exit(1);
|
|
2676
2807
|
}
|
|
2677
2808
|
}
|
|
2678
2809
|
const targetPath = resolveTargetPath(options.path);
|
|
@@ -2688,7 +2819,7 @@ function initCommand(options) {
|
|
|
2688
2819
|
|
|
2689
2820
|
// src/commands/scope-validator.ts
|
|
2690
2821
|
var import_node_path13 = require("node:path");
|
|
2691
|
-
var
|
|
2822
|
+
var import_node_process8 = __toESM(require("node:process"), 1);
|
|
2692
2823
|
var FILE_PATH_WIDTH = 50;
|
|
2693
2824
|
var EPIC_STORY_WIDTH = 43;
|
|
2694
2825
|
var REASON_WIDTH = 56;
|
|
@@ -2757,19 +2888,19 @@ function printScopeViolation(filePath, epicSlug, storySlug, worktreePath, reason
|
|
|
2757
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",
|
|
2758
2889
|
""
|
|
2759
2890
|
].join("\n");
|
|
2760
|
-
|
|
2891
|
+
import_node_process8.default.stderr.write(message);
|
|
2761
2892
|
}
|
|
2762
2893
|
async function readStdinInput() {
|
|
2763
2894
|
const chunks = [];
|
|
2764
|
-
for await (const chunk of
|
|
2895
|
+
for await (const chunk of import_node_process8.default.stdin) {
|
|
2765
2896
|
chunks.push(chunk);
|
|
2766
2897
|
}
|
|
2767
2898
|
return Buffer.concat(chunks).toString("utf-8");
|
|
2768
2899
|
}
|
|
2769
2900
|
function getScopeEnvironment() {
|
|
2770
|
-
const worktreePath =
|
|
2771
|
-
const epicSlug =
|
|
2772
|
-
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 || "";
|
|
2773
2904
|
if (!(worktreePath && epicSlug && storySlug)) {
|
|
2774
2905
|
return null;
|
|
2775
2906
|
}
|
|
@@ -2791,23 +2922,23 @@ function validatePath(filePath, worktreePath, epicSlug, storySlug) {
|
|
|
2791
2922
|
async function scopeValidatorCommand() {
|
|
2792
2923
|
const env = getScopeEnvironment();
|
|
2793
2924
|
if (!env) {
|
|
2794
|
-
|
|
2925
|
+
import_node_process8.default.exit(2);
|
|
2795
2926
|
}
|
|
2796
2927
|
const toolInput = await readStdinInput();
|
|
2797
2928
|
const filePath = getFilePathFromInput(toolInput);
|
|
2798
2929
|
if (!filePath) {
|
|
2799
|
-
|
|
2930
|
+
import_node_process8.default.exit(0);
|
|
2800
2931
|
}
|
|
2801
2932
|
const violation = validatePath(filePath, env.worktreePath, env.epicSlug, env.storySlug);
|
|
2802
2933
|
if (violation) {
|
|
2803
2934
|
printScopeViolation(filePath, env.epicSlug, env.storySlug, env.worktreePath, violation);
|
|
2804
|
-
|
|
2935
|
+
import_node_process8.default.exit(2);
|
|
2805
2936
|
}
|
|
2806
|
-
|
|
2937
|
+
import_node_process8.default.exit(0);
|
|
2807
2938
|
}
|
|
2808
2939
|
|
|
2809
2940
|
// src/commands/sessions/index.ts
|
|
2810
|
-
var
|
|
2941
|
+
var import_node_process9 = __toESM(require("node:process"), 1);
|
|
2811
2942
|
async function sessionsListCommand() {
|
|
2812
2943
|
const sessions = await listSessions();
|
|
2813
2944
|
console.log(JSON.stringify(sessions, null, 2));
|
|
@@ -2821,7 +2952,7 @@ async function sessionsLogsCommand(sessionName) {
|
|
|
2821
2952
|
await streamLogs(sessionName);
|
|
2822
2953
|
} catch (error) {
|
|
2823
2954
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
2824
|
-
|
|
2955
|
+
import_node_process9.default.exit(1);
|
|
2825
2956
|
}
|
|
2826
2957
|
}
|
|
2827
2958
|
async function sessionsKillCommand(sessionName) {
|
|
@@ -2833,7 +2964,7 @@ async function sessionsKillCommand(sessionName) {
|
|
|
2833
2964
|
var import_node_child_process3 = require("node:child_process");
|
|
2834
2965
|
var import_node_fs8 = require("node:fs");
|
|
2835
2966
|
var import_node_path14 = require("node:path");
|
|
2836
|
-
var
|
|
2967
|
+
var import_node_process10 = __toESM(require("node:process"), 1);
|
|
2837
2968
|
function runGitCommand(args, cwd) {
|
|
2838
2969
|
try {
|
|
2839
2970
|
const output = (0, import_node_child_process3.execSync)(`git ${args.join(" ")}`, {
|
|
@@ -2914,12 +3045,12 @@ function worktreeCommand(epicSlug, storySlug, options) {
|
|
|
2914
3045
|
error: error instanceof Error ? error.message : String(error)
|
|
2915
3046
|
};
|
|
2916
3047
|
console.log(JSON.stringify(result2, null, 2));
|
|
2917
|
-
|
|
3048
|
+
import_node_process10.default.exit(1);
|
|
2918
3049
|
}
|
|
2919
3050
|
const result = createWorktree(projectPath, epicSlug, storySlug);
|
|
2920
3051
|
console.log(JSON.stringify(result, null, 2));
|
|
2921
3052
|
if (!result.success) {
|
|
2922
|
-
|
|
3053
|
+
import_node_process10.default.exit(1);
|
|
2923
3054
|
}
|
|
2924
3055
|
}
|
|
2925
3056
|
|
|
@@ -2982,6 +3113,6 @@ sessionsCommand.command("kill <name>").description("Terminate a session").action
|
|
|
2982
3113
|
});
|
|
2983
3114
|
program.on("command:*", (operands) => {
|
|
2984
3115
|
console.error(`error: unknown command '${operands[0]}'`);
|
|
2985
|
-
|
|
3116
|
+
import_node_process11.default.exit(1);
|
|
2986
3117
|
});
|
|
2987
3118
|
program.parse();
|