coding-agent-adapters 0.3.0 → 0.4.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/index.d.cts CHANGED
@@ -207,6 +207,14 @@ declare abstract class BaseCodingAdapter extends BaseCLIAdapter {
207
207
  * Extract the main content from CLI output, removing common artifacts
208
208
  */
209
209
  protected extractContent(output: string, promptPattern: RegExp): string;
210
+ /**
211
+ * Detect if the CLI has completed a task and returned to its idle prompt.
212
+ * More specific than detectReady() — matches high-confidence completion indicators
213
+ * (e.g. duration summaries, explicit "done" messages) alongside the idle prompt.
214
+ *
215
+ * Used as a fast-path in stall detection to avoid expensive LLM classifier calls.
216
+ */
217
+ abstract detectTaskComplete(output: string): boolean;
210
218
  /**
211
219
  * Extract the approval preset from a spawn config, if set.
212
220
  */
@@ -258,6 +266,18 @@ declare class ClaudeAdapter extends BaseCodingAdapter {
258
266
  * Detect blocking prompts specific to Claude Code CLI
259
267
  */
260
268
  detectBlockingPrompt(output: string): BlockingPromptDetection;
269
+ /**
270
+ * Detect task completion for Claude Code.
271
+ *
272
+ * High-confidence pattern: turn duration summary + idle prompt.
273
+ * Claude Code shows "<Verb> for Xm Ys" (e.g. "Cooked for 3m 12s")
274
+ * when a turn completes, followed by the ❯ input prompt.
275
+ *
276
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
277
+ * - claude_completed_turn_duration
278
+ * - claude_completed_turn_duration_custom_verb
279
+ */
280
+ detectTaskComplete(output: string): boolean;
261
281
  detectReady(output: string): boolean;
262
282
  parseOutput(output: string): ParsedOutput | null;
263
283
  getPromptPattern(): RegExp;
@@ -287,6 +307,17 @@ declare class GeminiAdapter extends BaseCodingAdapter {
287
307
  getEnv(config: SpawnConfig): Record<string, string>;
288
308
  detectLogin(output: string): LoginDetection;
289
309
  detectBlockingPrompt(output: string): BlockingPromptDetection;
310
+ /**
311
+ * Detect task completion for Gemini CLI.
312
+ *
313
+ * High-confidence patterns:
314
+ * - "◇ Ready" window title signal (OSC sequence, may survive ANSI stripping)
315
+ * - "Type your message" composer placeholder after agent output
316
+ *
317
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
318
+ * - gemini_ready_title
319
+ */
320
+ detectTaskComplete(output: string): boolean;
290
321
  detectReady(output: string): boolean;
291
322
  parseOutput(output: string): ParsedOutput | null;
292
323
  /**
@@ -329,6 +360,18 @@ declare class CodexAdapter extends BaseCodingAdapter {
329
360
  * Source: approval_overlay.rs, chatwidget.rs, request_user_input/mod.rs
330
361
  */
331
362
  detectBlockingPrompt(output: string): BlockingPromptDetection;
363
+ /**
364
+ * Detect task completion for Codex CLI.
365
+ *
366
+ * High-confidence patterns:
367
+ * - "Worked for Xm Ys" separator after work-heavy turns
368
+ * - "› Ask Codex to do anything" ready prompt
369
+ *
370
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
371
+ * - codex_completed_worked_for_separator
372
+ * - codex_ready_prompt
373
+ */
374
+ detectTaskComplete(output: string): boolean;
332
375
  detectReady(output: string): boolean;
333
376
  parseOutput(output: string): ParsedOutput | null;
334
377
  /**
@@ -378,6 +421,17 @@ declare class AiderAdapter extends BaseCodingAdapter {
378
421
  * Source: io.py, onboarding.py, base_coder.py, report.py
379
422
  */
380
423
  detectBlockingPrompt(output: string): BlockingPromptDetection;
424
+ /**
425
+ * Detect task completion for Aider.
426
+ *
427
+ * High-confidence patterns:
428
+ * - "Aider is waiting for your input" notification (bell message)
429
+ * - Edit-format mode prompts (ask>, code>, architect>) after output
430
+ *
431
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
432
+ * - aider_completed_llm_response_ready
433
+ */
434
+ detectTaskComplete(output: string): boolean;
381
435
  detectReady(output: string): boolean;
382
436
  parseOutput(output: string): ParsedOutput | null;
383
437
  /**
package/dist/index.d.ts CHANGED
@@ -207,6 +207,14 @@ declare abstract class BaseCodingAdapter extends BaseCLIAdapter {
207
207
  * Extract the main content from CLI output, removing common artifacts
208
208
  */
209
209
  protected extractContent(output: string, promptPattern: RegExp): string;
210
+ /**
211
+ * Detect if the CLI has completed a task and returned to its idle prompt.
212
+ * More specific than detectReady() — matches high-confidence completion indicators
213
+ * (e.g. duration summaries, explicit "done" messages) alongside the idle prompt.
214
+ *
215
+ * Used as a fast-path in stall detection to avoid expensive LLM classifier calls.
216
+ */
217
+ abstract detectTaskComplete(output: string): boolean;
210
218
  /**
211
219
  * Extract the approval preset from a spawn config, if set.
212
220
  */
@@ -258,6 +266,18 @@ declare class ClaudeAdapter extends BaseCodingAdapter {
258
266
  * Detect blocking prompts specific to Claude Code CLI
259
267
  */
260
268
  detectBlockingPrompt(output: string): BlockingPromptDetection;
269
+ /**
270
+ * Detect task completion for Claude Code.
271
+ *
272
+ * High-confidence pattern: turn duration summary + idle prompt.
273
+ * Claude Code shows "<Verb> for Xm Ys" (e.g. "Cooked for 3m 12s")
274
+ * when a turn completes, followed by the ❯ input prompt.
275
+ *
276
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
277
+ * - claude_completed_turn_duration
278
+ * - claude_completed_turn_duration_custom_verb
279
+ */
280
+ detectTaskComplete(output: string): boolean;
261
281
  detectReady(output: string): boolean;
262
282
  parseOutput(output: string): ParsedOutput | null;
263
283
  getPromptPattern(): RegExp;
@@ -287,6 +307,17 @@ declare class GeminiAdapter extends BaseCodingAdapter {
287
307
  getEnv(config: SpawnConfig): Record<string, string>;
288
308
  detectLogin(output: string): LoginDetection;
289
309
  detectBlockingPrompt(output: string): BlockingPromptDetection;
310
+ /**
311
+ * Detect task completion for Gemini CLI.
312
+ *
313
+ * High-confidence patterns:
314
+ * - "◇ Ready" window title signal (OSC sequence, may survive ANSI stripping)
315
+ * - "Type your message" composer placeholder after agent output
316
+ *
317
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
318
+ * - gemini_ready_title
319
+ */
320
+ detectTaskComplete(output: string): boolean;
290
321
  detectReady(output: string): boolean;
291
322
  parseOutput(output: string): ParsedOutput | null;
292
323
  /**
@@ -329,6 +360,18 @@ declare class CodexAdapter extends BaseCodingAdapter {
329
360
  * Source: approval_overlay.rs, chatwidget.rs, request_user_input/mod.rs
330
361
  */
331
362
  detectBlockingPrompt(output: string): BlockingPromptDetection;
363
+ /**
364
+ * Detect task completion for Codex CLI.
365
+ *
366
+ * High-confidence patterns:
367
+ * - "Worked for Xm Ys" separator after work-heavy turns
368
+ * - "› Ask Codex to do anything" ready prompt
369
+ *
370
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
371
+ * - codex_completed_worked_for_separator
372
+ * - codex_ready_prompt
373
+ */
374
+ detectTaskComplete(output: string): boolean;
332
375
  detectReady(output: string): boolean;
333
376
  parseOutput(output: string): ParsedOutput | null;
334
377
  /**
@@ -378,6 +421,17 @@ declare class AiderAdapter extends BaseCodingAdapter {
378
421
  * Source: io.py, onboarding.py, base_coder.py, report.py
379
422
  */
380
423
  detectBlockingPrompt(output: string): BlockingPromptDetection;
424
+ /**
425
+ * Detect task completion for Aider.
426
+ *
427
+ * High-confidence patterns:
428
+ * - "Aider is waiting for your input" notification (bell message)
429
+ * - Edit-format mode prompts (ask>, code>, architect>) after output
430
+ *
431
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
432
+ * - aider_completed_llm_response_ready
433
+ */
434
+ detectTaskComplete(output: string): boolean;
381
435
  detectReady(output: string): boolean;
382
436
  parseOutput(output: string): ParsedOutput | null;
383
437
  /**
package/dist/index.js CHANGED
@@ -54,6 +54,8 @@ var CLAUDE_TOOL_CATEGORIES = {
54
54
  // file_write
55
55
  Write: "file_write",
56
56
  Edit: "file_write",
57
+ MultiEdit: "file_write",
58
+ NotebookEdit: "file_write",
57
59
  // shell
58
60
  Bash: "shell",
59
61
  BashOutput: "shell",
@@ -745,15 +747,40 @@ var ClaudeAdapter = class extends BaseCodingAdapter {
745
747
  }
746
748
  return super.detectBlockingPrompt(output);
747
749
  }
750
+ /**
751
+ * Detect task completion for Claude Code.
752
+ *
753
+ * High-confidence pattern: turn duration summary + idle prompt.
754
+ * Claude Code shows "<Verb> for Xm Ys" (e.g. "Cooked for 3m 12s")
755
+ * when a turn completes, followed by the ❯ input prompt.
756
+ *
757
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
758
+ * - claude_completed_turn_duration
759
+ * - claude_completed_turn_duration_custom_verb
760
+ */
761
+ detectTaskComplete(output) {
762
+ const stripped = this.stripAnsi(output);
763
+ const hasDuration = /[A-Z][A-Za-z' -]{2,40}\s+for\s+\d+(?:h\s+\d{1,2}m\s+\d{1,2}s|m\s+\d{1,2}s|s)/.test(stripped);
764
+ const tail = stripped.slice(-300);
765
+ const hasIdlePrompt = /❯/.test(tail);
766
+ if (hasDuration && hasIdlePrompt) {
767
+ return true;
768
+ }
769
+ if (hasIdlePrompt && stripped.includes("for shortcuts")) {
770
+ return true;
771
+ }
772
+ return false;
773
+ }
748
774
  detectReady(output) {
749
775
  const stripped = this.stripAnsi(output);
750
776
  if (/trust.*directory|do you want to|needs? your permission/i.test(stripped)) {
751
777
  return false;
752
778
  }
779
+ const tail = stripped.slice(-300);
753
780
  return stripped.includes("How can I help") || stripped.includes("What would you like") || // v2.1+ shows "for shortcuts" hint when ready
754
781
  stripped.includes("for shortcuts") || // Match "claude> " or similar specific prompts, not bare ">"
755
- /claude>\s*$/i.test(stripped) || // v2.1+ uses ❯ as the input prompt
756
- /❯\s*$/.test(stripped);
782
+ /claude>/i.test(tail) || // v2.1+ uses ❯ as the input prompt
783
+ /❯/.test(tail);
757
784
  }
758
785
  parseOutput(output) {
759
786
  const stripped = this.stripAnsi(output);
@@ -1002,6 +1029,26 @@ var GeminiAdapter = class extends BaseCodingAdapter {
1002
1029
  }
1003
1030
  return super.detectBlockingPrompt(output);
1004
1031
  }
1032
+ /**
1033
+ * Detect task completion for Gemini CLI.
1034
+ *
1035
+ * High-confidence patterns:
1036
+ * - "◇ Ready" window title signal (OSC sequence, may survive ANSI stripping)
1037
+ * - "Type your message" composer placeholder after agent output
1038
+ *
1039
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
1040
+ * - gemini_ready_title
1041
+ */
1042
+ detectTaskComplete(output) {
1043
+ const stripped = this.stripAnsi(output);
1044
+ if (/◇\s+Ready/.test(stripped)) {
1045
+ return true;
1046
+ }
1047
+ if (/type.?your.?message/i.test(stripped)) {
1048
+ return true;
1049
+ }
1050
+ return false;
1051
+ }
1005
1052
  detectReady(output) {
1006
1053
  const stripped = this.stripAnsi(output);
1007
1054
  if (/type.?your.?message/i.test(stripped)) {
@@ -1312,6 +1359,32 @@ var CodexAdapter = class extends BaseCodingAdapter {
1312
1359
  }
1313
1360
  return super.detectBlockingPrompt(output);
1314
1361
  }
1362
+ /**
1363
+ * Detect task completion for Codex CLI.
1364
+ *
1365
+ * High-confidence patterns:
1366
+ * - "Worked for Xm Ys" separator after work-heavy turns
1367
+ * - "› Ask Codex to do anything" ready prompt
1368
+ *
1369
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
1370
+ * - codex_completed_worked_for_separator
1371
+ * - codex_ready_prompt
1372
+ */
1373
+ detectTaskComplete(output) {
1374
+ const stripped = this.stripAnsi(output);
1375
+ const hasWorkedFor = /Worked\s+for\s+\d+(?:h\s+\d{2}m\s+\d{2}s|m\s+\d{2}s|s)/.test(stripped);
1376
+ const hasReadyPrompt = /›\s+Ask\s+Codex\s+to\s+do\s+anything/.test(stripped);
1377
+ if (hasWorkedFor && hasReadyPrompt) {
1378
+ return true;
1379
+ }
1380
+ if (hasReadyPrompt) {
1381
+ return true;
1382
+ }
1383
+ if (hasWorkedFor && /›\s+/m.test(stripped)) {
1384
+ return true;
1385
+ }
1386
+ return false;
1387
+ }
1315
1388
  detectReady(output) {
1316
1389
  const stripped = this.stripAnsi(output);
1317
1390
  if (/do.?you.?trust.?the.?contents/i.test(stripped) || /sign.?in.?with.?chatgpt/i.test(stripped) || /update.?available/i.test(stripped) || /enable.?full.?access/i.test(stripped) || /choose.?working.?directory/i.test(stripped)) {
@@ -1716,6 +1789,31 @@ var AiderAdapter = class extends BaseCodingAdapter {
1716
1789
  }
1717
1790
  return super.detectBlockingPrompt(output);
1718
1791
  }
1792
+ /**
1793
+ * Detect task completion for Aider.
1794
+ *
1795
+ * High-confidence patterns:
1796
+ * - "Aider is waiting for your input" notification (bell message)
1797
+ * - Edit-format mode prompts (ask>, code>, architect>) after output
1798
+ *
1799
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
1800
+ * - aider_completed_llm_response_ready
1801
+ */
1802
+ detectTaskComplete(output) {
1803
+ const stripped = this.stripAnsi(output);
1804
+ if (/Aider\s+is\s+waiting\s+for\s+your\s+input/.test(stripped)) {
1805
+ return true;
1806
+ }
1807
+ const hasPrompt = /(?:ask|code|architect)(?:\s+multi)?>\s*$/m.test(stripped);
1808
+ if (hasPrompt) {
1809
+ const hasEditMarkers = /Applied edit to|Commit [a-f0-9]+|wrote to|Updated/i.test(stripped);
1810
+ const hasTokenUsage = /Tokens:|Cost:/i.test(stripped);
1811
+ if (hasEditMarkers || hasTokenUsage) {
1812
+ return true;
1813
+ }
1814
+ }
1815
+ return false;
1816
+ }
1719
1817
  detectReady(output) {
1720
1818
  const stripped = this.stripAnsi(output);
1721
1819
  if (/login to openrouter/i.test(stripped) || /open this url in your browser/i.test(stripped) || /waiting up to 5 minutes/i.test(stripped)) {