@saga-ai/cli 2.15.1 → 2.17.0

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
@@ -1331,7 +1331,13 @@ function createChokidarWatcher(sagaRoot) {
1331
1331
  persistent: true,
1332
1332
  ignoreInitial: true,
1333
1333
  usePolling: true,
1334
- interval: DEBOUNCE_DELAY_MS
1334
+ interval: DEBOUNCE_DELAY_MS,
1335
+ // Wait for writes to finish before emitting events - prevents missing
1336
+ // rapid file changes when polling
1337
+ awaitWriteFinish: {
1338
+ stabilityThreshold: 50,
1339
+ pollInterval: 50
1340
+ }
1335
1341
  });
1336
1342
  }
1337
1343
  async function createSagaWatcher(sagaRoot) {
@@ -2188,17 +2194,144 @@ function buildScopeSettings() {
2188
2194
  }
2189
2195
  };
2190
2196
  }
2197
+ function truncateString(str, maxLength) {
2198
+ if (str.length <= maxLength) {
2199
+ return str;
2200
+ }
2201
+ return `${str.slice(0, maxLength)}...`;
2202
+ }
2203
+ function formatInputValue(value, maxLength) {
2204
+ if (value === null || value === void 0) {
2205
+ return "null";
2206
+ }
2207
+ if (typeof value === "string") {
2208
+ const singleLine = value.replace(/\n/g, " ").replace(/\s+/g, " ");
2209
+ return truncateString(singleLine, maxLength);
2210
+ }
2211
+ if (typeof value === "boolean" || typeof value === "number") {
2212
+ return String(value);
2213
+ }
2214
+ if (Array.isArray(value)) {
2215
+ return truncateString(JSON.stringify(value), maxLength);
2216
+ }
2217
+ if (typeof value === "object") {
2218
+ return truncateString(JSON.stringify(value), maxLength);
2219
+ }
2220
+ return String(value);
2221
+ }
2222
+ function formatAllInputFields(input) {
2223
+ const maxValueLength = 100;
2224
+ const entries = Object.entries(input);
2225
+ if (entries.length === 0) {
2226
+ return "";
2227
+ }
2228
+ return entries.map(([key, value]) => `${key}=${formatInputValue(value, maxValueLength)}`).join(", ");
2229
+ }
2230
+ function formatToolUsage(name, input) {
2231
+ try {
2232
+ const safeInput = input || {};
2233
+ const maxLength = 100;
2234
+ switch (name) {
2235
+ // File operations - show path
2236
+ case "Read": {
2237
+ const path = safeInput.file_path || "unknown";
2238
+ const extras = [];
2239
+ if (safeInput.offset) {
2240
+ extras.push(`offset=${safeInput.offset}`);
2241
+ }
2242
+ if (safeInput.limit) {
2243
+ extras.push(`limit=${safeInput.limit}`);
2244
+ }
2245
+ const suffix = extras.length > 0 ? ` (${extras.join(", ")})` : "";
2246
+ return `[Tool Used: Read] ${path}${suffix}`;
2247
+ }
2248
+ case "Write":
2249
+ return `[Tool Used: Write] ${safeInput.file_path || "unknown"}`;
2250
+ case "Edit": {
2251
+ const file = safeInput.file_path || "unknown";
2252
+ const replaceAll = safeInput.replace_all ? " (replace_all)" : "";
2253
+ return `[Tool Used: Edit] ${file}${replaceAll}`;
2254
+ }
2255
+ // Shell command - show command and description
2256
+ case "Bash": {
2257
+ const cmd = truncateString(String(safeInput.command || ""), maxLength);
2258
+ const desc = safeInput.description ? ` - ${truncateString(String(safeInput.description), 60)}` : "";
2259
+ return `[Tool Used: Bash] ${cmd}${desc}`;
2260
+ }
2261
+ // Search operations - show pattern and path
2262
+ case "Glob": {
2263
+ const pattern = safeInput.pattern || "unknown";
2264
+ const path = safeInput.path ? ` in ${safeInput.path}` : "";
2265
+ return `[Tool Used: Glob] ${pattern}${path}`;
2266
+ }
2267
+ case "Grep": {
2268
+ const pattern = truncateString(String(safeInput.pattern || ""), 60);
2269
+ const path = safeInput.path ? ` in ${safeInput.path}` : "";
2270
+ const mode = safeInput.output_mode ? ` (${safeInput.output_mode})` : "";
2271
+ return `[Tool Used: Grep] "${pattern}"${path}${mode}`;
2272
+ }
2273
+ // Agent task - show description and type
2274
+ case "Task": {
2275
+ const desc = truncateString(
2276
+ String(safeInput.description || safeInput.prompt || ""),
2277
+ maxLength
2278
+ );
2279
+ const agentType = safeInput.subagent_type ? ` [${safeInput.subagent_type}]` : "";
2280
+ return `[Tool Used: Task]${agentType} ${desc}`;
2281
+ }
2282
+ // Todo operations
2283
+ case "TodoWrite": {
2284
+ const todos = safeInput.todos;
2285
+ if (todos && Array.isArray(todos)) {
2286
+ const subjects = todos.map((t) => {
2287
+ if (t && typeof t === "object" && "subject" in t) {
2288
+ return String(t.subject || "untitled");
2289
+ }
2290
+ return "untitled";
2291
+ }).join(", ");
2292
+ return `[Tool Used: TodoWrite] ${truncateString(subjects, maxLength)}`;
2293
+ }
2294
+ return "[Tool Used: TodoWrite]";
2295
+ }
2296
+ // Structured output - show status
2297
+ case "StructuredOutput": {
2298
+ const status = safeInput.status || "unknown";
2299
+ const summary = safeInput.summary ? ` - ${truncateString(String(safeInput.summary), maxLength)}` : "";
2300
+ return `[Tool Used: StructuredOutput] ${status}${summary}`;
2301
+ }
2302
+ // Unknown tools - show all fields
2303
+ default: {
2304
+ const fields = formatAllInputFields(safeInput);
2305
+ return fields ? `[Tool Used: ${name}] ${fields}` : `[Tool Used: ${name}]`;
2306
+ }
2307
+ }
2308
+ } catch {
2309
+ return `[Tool Used: ${name}]`;
2310
+ }
2311
+ }
2191
2312
  function formatAssistantContent(content) {
2192
- for (const block of content) {
2193
- const blockData = block;
2194
- if (blockData.type === "text" && blockData.text) {
2195
- return blockData.text;
2313
+ try {
2314
+ if (!(content && Array.isArray(content))) {
2315
+ return null;
2196
2316
  }
2197
- if (blockData.type === "tool_use") {
2198
- return `[Tool: ${blockData.name}]`;
2317
+ for (const block of content) {
2318
+ if (!block || typeof block !== "object") {
2319
+ continue;
2320
+ }
2321
+ const blockData = block;
2322
+ if (blockData.type === "text" && blockData.text) {
2323
+ return `${blockData.text}
2324
+ `;
2325
+ }
2326
+ if (blockData.type === "tool_use" && blockData.name) {
2327
+ return `${formatToolUsage(blockData.name, blockData.input || {})}
2328
+ `;
2329
+ }
2199
2330
  }
2331
+ return null;
2332
+ } catch {
2333
+ return null;
2200
2334
  }
2201
- return null;
2202
2335
  }
2203
2336
  function formatStreamLine(line) {
2204
2337
  try {