coding-agent-adapters 0.3.0 → 0.4.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/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,6 +747,29 @@ 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 hasIdlePrompt = /❯\s*$/.test(stripped);
765
+ if (hasDuration && hasIdlePrompt) {
766
+ return true;
767
+ }
768
+ if (hasIdlePrompt && stripped.includes("for shortcuts")) {
769
+ return true;
770
+ }
771
+ return false;
772
+ }
748
773
  detectReady(output) {
749
774
  const stripped = this.stripAnsi(output);
750
775
  if (/trust.*directory|do you want to|needs? your permission/i.test(stripped)) {
@@ -1002,6 +1027,26 @@ var GeminiAdapter = class extends BaseCodingAdapter {
1002
1027
  }
1003
1028
  return super.detectBlockingPrompt(output);
1004
1029
  }
1030
+ /**
1031
+ * Detect task completion for Gemini CLI.
1032
+ *
1033
+ * High-confidence patterns:
1034
+ * - "◇ Ready" window title signal (OSC sequence, may survive ANSI stripping)
1035
+ * - "Type your message" composer placeholder after agent output
1036
+ *
1037
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
1038
+ * - gemini_ready_title
1039
+ */
1040
+ detectTaskComplete(output) {
1041
+ const stripped = this.stripAnsi(output);
1042
+ if (/◇\s+Ready/.test(stripped)) {
1043
+ return true;
1044
+ }
1045
+ if (/type.?your.?message/i.test(stripped)) {
1046
+ return true;
1047
+ }
1048
+ return false;
1049
+ }
1005
1050
  detectReady(output) {
1006
1051
  const stripped = this.stripAnsi(output);
1007
1052
  if (/type.?your.?message/i.test(stripped)) {
@@ -1312,6 +1357,32 @@ var CodexAdapter = class extends BaseCodingAdapter {
1312
1357
  }
1313
1358
  return super.detectBlockingPrompt(output);
1314
1359
  }
1360
+ /**
1361
+ * Detect task completion for Codex CLI.
1362
+ *
1363
+ * High-confidence patterns:
1364
+ * - "Worked for Xm Ys" separator after work-heavy turns
1365
+ * - "› Ask Codex to do anything" ready prompt
1366
+ *
1367
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
1368
+ * - codex_completed_worked_for_separator
1369
+ * - codex_ready_prompt
1370
+ */
1371
+ detectTaskComplete(output) {
1372
+ const stripped = this.stripAnsi(output);
1373
+ const hasWorkedFor = /Worked\s+for\s+\d+(?:h\s+\d{2}m\s+\d{2}s|m\s+\d{2}s|s)/.test(stripped);
1374
+ const hasReadyPrompt = /›\s+Ask\s+Codex\s+to\s+do\s+anything/.test(stripped);
1375
+ if (hasWorkedFor && hasReadyPrompt) {
1376
+ return true;
1377
+ }
1378
+ if (hasReadyPrompt) {
1379
+ return true;
1380
+ }
1381
+ if (hasWorkedFor && /›\s+/m.test(stripped)) {
1382
+ return true;
1383
+ }
1384
+ return false;
1385
+ }
1315
1386
  detectReady(output) {
1316
1387
  const stripped = this.stripAnsi(output);
1317
1388
  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 +1787,31 @@ var AiderAdapter = class extends BaseCodingAdapter {
1716
1787
  }
1717
1788
  return super.detectBlockingPrompt(output);
1718
1789
  }
1790
+ /**
1791
+ * Detect task completion for Aider.
1792
+ *
1793
+ * High-confidence patterns:
1794
+ * - "Aider is waiting for your input" notification (bell message)
1795
+ * - Edit-format mode prompts (ask>, code>, architect>) after output
1796
+ *
1797
+ * Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
1798
+ * - aider_completed_llm_response_ready
1799
+ */
1800
+ detectTaskComplete(output) {
1801
+ const stripped = this.stripAnsi(output);
1802
+ if (/Aider\s+is\s+waiting\s+for\s+your\s+input/.test(stripped)) {
1803
+ return true;
1804
+ }
1805
+ const hasPrompt = /(?:ask|code|architect)(?:\s+multi)?>\s*$/m.test(stripped);
1806
+ if (hasPrompt) {
1807
+ const hasEditMarkers = /Applied edit to|Commit [a-f0-9]+|wrote to|Updated/i.test(stripped);
1808
+ const hasTokenUsage = /Tokens:|Cost:/i.test(stripped);
1809
+ if (hasEditMarkers || hasTokenUsage) {
1810
+ return true;
1811
+ }
1812
+ }
1813
+ return false;
1814
+ }
1719
1815
  detectReady(output) {
1720
1816
  const stripped = this.stripAnsi(output);
1721
1817
  if (/login to openrouter/i.test(stripped) || /open this url in your browser/i.test(stripped) || /waiting up to 5 minutes/i.test(stripped)) {