coding-agent-adapters 0.6.0 → 0.7.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/README.md +31 -2
- package/dist/index.cjs +92 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -4
- package/dist/index.d.ts +50 -4
- package/dist/index.js +92 -5
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -53,7 +53,9 @@ session.send('Help me refactor this function to use async/await');
|
|
|
53
53
|
|
|
54
54
|
## Session Lifecycle Detection
|
|
55
55
|
|
|
56
|
-
Each adapter implements detection for every stage of a CLI session
|
|
56
|
+
Each adapter implements detection for every stage of a CLI session.
|
|
57
|
+
|
|
58
|
+
All detection methods use `stripAnsi()` which strips ANSI escape sequences, cursor positioning codes, bare control characters, TUI spinner/box-drawing characters, and collapses whitespace — ensuring regex patterns match through raw terminal output. Prompt indicators (`❯`, `›`, `◇`) are preserved.
|
|
57
59
|
|
|
58
60
|
### Login / Auth Detection
|
|
59
61
|
|
|
@@ -105,9 +107,31 @@ Adapters detect prompts that block the session and require user action:
|
|
|
105
107
|
| Codex | Directory trust, tool approval, update available, model migration, CWD selection |
|
|
106
108
|
| Aider | File operations, shell commands, git init, pip install, destructive operations |
|
|
107
109
|
|
|
110
|
+
### Loading / Active-Work Detection
|
|
111
|
+
|
|
112
|
+
Each adapter implements `detectLoading(output)` to detect when the CLI is actively processing — thinking spinners, file reading, model streaming. When loading is detected, pty-manager suppresses stall detection entirely, avoiding unnecessary LLM classifier calls during normal operation.
|
|
113
|
+
|
|
114
|
+
| Adapter | Loading Indicators | Source Patterns |
|
|
115
|
+
|---------|-------------------|----------------|
|
|
116
|
+
| Claude | `esc to interrupt`, `Reading N files` | `claude_active_reading_files` |
|
|
117
|
+
| Gemini | `esc to cancel`, `Waiting for user confirmation` | `gemini_active_loading_line` |
|
|
118
|
+
| Codex | `esc to interrupt`, `Booting MCP server`, `Searching the web` | `codex_active_status_row`, `codex_active_booting_mcp` |
|
|
119
|
+
| Aider | `Waiting for LLM/<model>`, `Generating commit message with` | `aider_active_waiting_model`, `aider_active_waiting_llm_default` |
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const claude = new ClaudeAdapter();
|
|
123
|
+
claude.detectLoading('• Working (5s • esc to interrupt)'); // true
|
|
124
|
+
claude.detectLoading('Reading 42 files…'); // true
|
|
125
|
+
claude.detectLoading('❯ '); // false
|
|
126
|
+
|
|
127
|
+
const aider = new AiderAdapter();
|
|
128
|
+
aider.detectLoading('Waiting for claude-sonnet-4-20250514'); // true
|
|
129
|
+
aider.detectLoading('code> '); // false
|
|
130
|
+
```
|
|
131
|
+
|
|
108
132
|
### Task Completion Detection
|
|
109
133
|
|
|
110
|
-
Each adapter implements `detectTaskComplete(output)` to recognize when the CLI has finished a task and returned to its idle prompt. This is more specific than `detectReady()` — it matches high-confidence completion indicators (duration summaries, explicit done messages) that short-circuit the LLM stall classifier in pty-manager.
|
|
134
|
+
Each adapter implements `detectTaskComplete(output)` to recognize when the CLI has finished a task and returned to its idle prompt. This is more specific than `detectReady()` — it matches high-confidence completion indicators (duration summaries, explicit done messages) that short-circuit the LLM stall classifier in pty-manager. Patterns match through raw ANSI-laden TUI output including spinner characters and cursor positioning codes.
|
|
111
135
|
|
|
112
136
|
| Adapter | Completion Indicators | Source Patterns |
|
|
113
137
|
|---------|----------------------|----------------|
|
|
@@ -425,6 +449,11 @@ export class CursorAdapter extends BaseCodingAdapter {
|
|
|
425
449
|
return /cursor>\s*$/m.test(output);
|
|
426
450
|
}
|
|
427
451
|
|
|
452
|
+
detectLoading(output: string): boolean {
|
|
453
|
+
// Active loading indicator — suppresses stall detection
|
|
454
|
+
return /processing|thinking/i.test(output);
|
|
455
|
+
}
|
|
456
|
+
|
|
428
457
|
detectTaskComplete(output: string): boolean {
|
|
429
458
|
// High-confidence: task summary + idle prompt
|
|
430
459
|
return /completed in \d+s/.test(output) && /cursor>\s*$/m.test(output);
|
package/dist/index.cjs
CHANGED
|
@@ -401,17 +401,27 @@ var BaseCodingAdapter = class extends ptyManager.BaseCLIAdapter {
|
|
|
401
401
|
return adapterConfig?.interactive === true;
|
|
402
402
|
}
|
|
403
403
|
/**
|
|
404
|
-
* Override stripAnsi to handle TUI cursor movement codes
|
|
404
|
+
* Override stripAnsi to handle TUI cursor movement codes, spinner/box-drawing
|
|
405
|
+
* characters, bare control characters, and extra whitespace.
|
|
406
|
+
*
|
|
405
407
|
* TUI CLIs (Claude Code, Gemini CLI, Codex) use cursor positioning
|
|
406
|
-
* sequences instead of literal spaces
|
|
407
|
-
*
|
|
408
|
-
*
|
|
408
|
+
* sequences instead of literal spaces, and render decorative Unicode
|
|
409
|
+
* characters (spinners, box-drawing). All of these must be stripped so
|
|
410
|
+
* adapter detection methods (detectReady, detectTaskComplete, etc.) can
|
|
411
|
+
* match visible text with their regex patterns.
|
|
412
|
+
*
|
|
413
|
+
* Note: ❯ and › are preserved — they are prompt indicators used by
|
|
414
|
+
* detectReady / detectTaskComplete.
|
|
409
415
|
*/
|
|
410
416
|
stripAnsi(str) {
|
|
411
417
|
let result = str.replace(/\x1b\[\d*[CDABGdEF]/g, " ");
|
|
412
418
|
result = result.replace(/\x1b\[\d*(?:;\d+)?[Hf]/g, " ");
|
|
413
419
|
result = result.replace(/\x1b\[\d*[JK]/g, " ");
|
|
414
|
-
|
|
420
|
+
result = super.stripAnsi(result);
|
|
421
|
+
result = result.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
422
|
+
result = result.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⣾⣽⣻⢿⡿⣟⣯⣷✻✶✳✢⏺←→↑↓⬆⬇◆▪▫■□▲△▼▽◈⟨⟩⌘⏎⏏⌫⌦⇧⇪⌥]/g, " ");
|
|
423
|
+
result = result.replace(/ {2,}/g, " ");
|
|
424
|
+
return result;
|
|
415
425
|
}
|
|
416
426
|
/**
|
|
417
427
|
* Override detectExit to include installation instructions
|
|
@@ -760,6 +770,24 @@ var ClaudeAdapter = class extends BaseCodingAdapter {
|
|
|
760
770
|
}
|
|
761
771
|
return super.detectBlockingPrompt(output);
|
|
762
772
|
}
|
|
773
|
+
/**
|
|
774
|
+
* Detect if Claude Code is actively loading/processing.
|
|
775
|
+
*
|
|
776
|
+
* Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
|
|
777
|
+
* - claude_active_reading_files: "Reading N files…"
|
|
778
|
+
* - General: "esc to interrupt" spinner status line
|
|
779
|
+
*/
|
|
780
|
+
detectLoading(output) {
|
|
781
|
+
const stripped = this.stripAnsi(output);
|
|
782
|
+
const tail = stripped.slice(-500);
|
|
783
|
+
if (/esc\s+to\s+interrupt/i.test(tail)) {
|
|
784
|
+
return true;
|
|
785
|
+
}
|
|
786
|
+
if (/Reading\s+\d+\s+files/i.test(tail)) {
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
789
|
+
return false;
|
|
790
|
+
}
|
|
763
791
|
/**
|
|
764
792
|
* Detect task completion for Claude Code.
|
|
765
793
|
*
|
|
@@ -1051,6 +1079,24 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
1051
1079
|
}
|
|
1052
1080
|
return super.detectBlockingPrompt(output);
|
|
1053
1081
|
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Detect if Gemini CLI is actively loading/processing.
|
|
1084
|
+
*
|
|
1085
|
+
* Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
|
|
1086
|
+
* - gemini_active_loading_line: "(esc to cancel, Xs)"
|
|
1087
|
+
* - gemini_active_waiting_user_confirmation: "Waiting for user confirmation..."
|
|
1088
|
+
*/
|
|
1089
|
+
detectLoading(output) {
|
|
1090
|
+
const stripped = this.stripAnsi(output);
|
|
1091
|
+
const tail = stripped.slice(-500);
|
|
1092
|
+
if (/esc\s+to\s+cancel/i.test(tail)) {
|
|
1093
|
+
return true;
|
|
1094
|
+
}
|
|
1095
|
+
if (/Waiting\s+for\s+user\s+confirmation/i.test(tail)) {
|
|
1096
|
+
return true;
|
|
1097
|
+
}
|
|
1098
|
+
return false;
|
|
1099
|
+
}
|
|
1054
1100
|
/**
|
|
1055
1101
|
* Detect task completion for Gemini CLI.
|
|
1056
1102
|
*
|
|
@@ -1387,6 +1433,28 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
1387
1433
|
}
|
|
1388
1434
|
return super.detectBlockingPrompt(output);
|
|
1389
1435
|
}
|
|
1436
|
+
/**
|
|
1437
|
+
* Detect if Codex CLI is actively loading/processing.
|
|
1438
|
+
*
|
|
1439
|
+
* Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
|
|
1440
|
+
* - codex_active_status_row: "• Working (0s • esc to interrupt)"
|
|
1441
|
+
* - codex_active_booting_mcp: "Booting MCP server: ..."
|
|
1442
|
+
* - codex_active_web_search: "Searching the web"
|
|
1443
|
+
*/
|
|
1444
|
+
detectLoading(output) {
|
|
1445
|
+
const stripped = this.stripAnsi(output);
|
|
1446
|
+
const tail = stripped.slice(-500);
|
|
1447
|
+
if (/esc\s+to\s+interrupt/i.test(tail)) {
|
|
1448
|
+
return true;
|
|
1449
|
+
}
|
|
1450
|
+
if (/Booting\s+MCP\s+server/i.test(tail)) {
|
|
1451
|
+
return true;
|
|
1452
|
+
}
|
|
1453
|
+
if (/Searching\s+the\s+web/i.test(tail)) {
|
|
1454
|
+
return true;
|
|
1455
|
+
}
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1390
1458
|
/**
|
|
1391
1459
|
* Detect task completion for Codex CLI.
|
|
1392
1460
|
*
|
|
@@ -1819,6 +1887,25 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
1819
1887
|
}
|
|
1820
1888
|
return super.detectBlockingPrompt(output);
|
|
1821
1889
|
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Detect if Aider is actively loading/processing.
|
|
1892
|
+
*
|
|
1893
|
+
* Patterns from: AGENT_LOADING_STATUS_PATTERNS.json
|
|
1894
|
+
* - aider_active_waiting_model: "Waiting for <model>"
|
|
1895
|
+
* - aider_active_waiting_llm_default: "Waiting for LLM"
|
|
1896
|
+
* - aider_active_generating_commit_message: "Generating commit message with ..."
|
|
1897
|
+
*/
|
|
1898
|
+
detectLoading(output) {
|
|
1899
|
+
const stripped = this.stripAnsi(output);
|
|
1900
|
+
const tail = stripped.slice(-500);
|
|
1901
|
+
if (/Waiting\s+for\s+(?:LLM|[A-Za-z0-9_./:@-]+)/i.test(tail)) {
|
|
1902
|
+
return true;
|
|
1903
|
+
}
|
|
1904
|
+
if (/Generating\s+commit\s+message\s+with\s+/i.test(tail)) {
|
|
1905
|
+
return true;
|
|
1906
|
+
}
|
|
1907
|
+
return false;
|
|
1908
|
+
}
|
|
1822
1909
|
/**
|
|
1823
1910
|
* Detect task completion for Aider.
|
|
1824
1911
|
*
|