coding-agent-adapters 0.2.13 → 0.2.15
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 +137 -85
- package/dist/index.cjs +406 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -4
- package/dist/index.d.ts +45 -4
- package/dist/index.js +406 -23
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -153,6 +153,12 @@ declare class GeminiAdapter extends BaseCodingAdapter {
|
|
|
153
153
|
readonly adapterType = "gemini";
|
|
154
154
|
readonly displayName = "Google Gemini";
|
|
155
155
|
readonly installation: InstallationInfo;
|
|
156
|
+
/**
|
|
157
|
+
* Auto-response rules for Gemini CLI.
|
|
158
|
+
* Gemini uses Ink/React TUI with arrow-key radio menus.
|
|
159
|
+
* Source: FolderTrustDialog.tsx, MultiFolderTrustDialog.tsx, CloudFreePrivacyNotice.tsx
|
|
160
|
+
*/
|
|
161
|
+
readonly autoResponseRules: AutoResponseRule[];
|
|
156
162
|
getRecommendedModels(_credentials?: AgentCredentials): ModelRecommendations;
|
|
157
163
|
getCommand(): string;
|
|
158
164
|
getArgs(config: SpawnConfig): string[];
|
|
@@ -161,6 +167,15 @@ declare class GeminiAdapter extends BaseCodingAdapter {
|
|
|
161
167
|
detectBlockingPrompt(output: string): BlockingPromptDetection;
|
|
162
168
|
detectReady(output: string): boolean;
|
|
163
169
|
parseOutput(output: string): ParsedOutput | null;
|
|
170
|
+
/**
|
|
171
|
+
* Detect exit conditions specific to Gemini CLI.
|
|
172
|
+
* Source: FolderTrustDialog.tsx:127, LogoutConfirmationDialog.tsx:64
|
|
173
|
+
*/
|
|
174
|
+
detectExit(output: string): {
|
|
175
|
+
exited: boolean;
|
|
176
|
+
code?: number;
|
|
177
|
+
error?: string;
|
|
178
|
+
};
|
|
164
179
|
getPromptPattern(): RegExp;
|
|
165
180
|
getHealthCheckCommand(): string;
|
|
166
181
|
}
|
|
@@ -177,7 +192,8 @@ declare class CodexAdapter extends BaseCodingAdapter {
|
|
|
177
192
|
readonly installation: InstallationInfo;
|
|
178
193
|
/**
|
|
179
194
|
* Auto-response rules for OpenAI Codex CLI.
|
|
180
|
-
* Codex uses
|
|
195
|
+
* Codex uses ratatui/crossterm full-screen TUI with arrow-key menus.
|
|
196
|
+
* Source: trust_directory.rs, update_prompt.rs, model_migration.rs, cwd_prompt.rs, chatwidget.rs, main.rs
|
|
181
197
|
*/
|
|
182
198
|
readonly autoResponseRules: AutoResponseRule[];
|
|
183
199
|
getRecommendedModels(_credentials?: AgentCredentials): ModelRecommendations;
|
|
@@ -186,11 +202,21 @@ declare class CodexAdapter extends BaseCodingAdapter {
|
|
|
186
202
|
getEnv(config: SpawnConfig): Record<string, string>;
|
|
187
203
|
detectLogin(output: string): LoginDetection;
|
|
188
204
|
/**
|
|
189
|
-
* Detect blocking prompts specific to OpenAI Codex CLI
|
|
205
|
+
* Detect blocking prompts specific to OpenAI Codex CLI.
|
|
206
|
+
* Source: approval_overlay.rs, chatwidget.rs, request_user_input/mod.rs
|
|
190
207
|
*/
|
|
191
208
|
detectBlockingPrompt(output: string): BlockingPromptDetection;
|
|
192
209
|
detectReady(output: string): boolean;
|
|
193
210
|
parseOutput(output: string): ParsedOutput | null;
|
|
211
|
+
/**
|
|
212
|
+
* Detect exit conditions specific to Codex CLI.
|
|
213
|
+
* Source: main.rs:404, main.rs:414, main.rs:461
|
|
214
|
+
*/
|
|
215
|
+
detectExit(output: string): {
|
|
216
|
+
exited: boolean;
|
|
217
|
+
code?: number;
|
|
218
|
+
error?: string;
|
|
219
|
+
};
|
|
194
220
|
getPromptPattern(): RegExp;
|
|
195
221
|
getHealthCheckCommand(): string;
|
|
196
222
|
}
|
|
@@ -212,8 +238,10 @@ declare class AiderAdapter extends BaseCodingAdapter {
|
|
|
212
238
|
readonly installation: InstallationInfo;
|
|
213
239
|
/**
|
|
214
240
|
* Auto-response rules for Aider CLI.
|
|
215
|
-
* Aider uses plain text
|
|
216
|
-
*
|
|
241
|
+
* Aider uses plain text prompts via io.py:832 with (Y)es/(N)o format.
|
|
242
|
+
* All rules are responseType: 'text' — Aider never uses TUI menus.
|
|
243
|
+
*
|
|
244
|
+
* Decline rules come first to override the generic accept patterns.
|
|
217
245
|
*/
|
|
218
246
|
readonly autoResponseRules: AutoResponseRule[];
|
|
219
247
|
getRecommendedModels(credentials?: AgentCredentials): ModelRecommendations;
|
|
@@ -221,9 +249,22 @@ declare class AiderAdapter extends BaseCodingAdapter {
|
|
|
221
249
|
getArgs(config: SpawnConfig): string[];
|
|
222
250
|
getEnv(config: SpawnConfig): Record<string, string>;
|
|
223
251
|
detectLogin(output: string): LoginDetection;
|
|
252
|
+
/**
|
|
253
|
+
* Detect blocking prompts specific to Aider CLI.
|
|
254
|
+
* Source: io.py, onboarding.py, base_coder.py, report.py
|
|
255
|
+
*/
|
|
224
256
|
detectBlockingPrompt(output: string): BlockingPromptDetection;
|
|
225
257
|
detectReady(output: string): boolean;
|
|
226
258
|
parseOutput(output: string): ParsedOutput | null;
|
|
259
|
+
/**
|
|
260
|
+
* Detect exit conditions specific to Aider.
|
|
261
|
+
* Source: base_coder.py:994, base_coder.py:998, report.py:77, versioncheck.py:58
|
|
262
|
+
*/
|
|
263
|
+
detectExit(output: string): {
|
|
264
|
+
exited: boolean;
|
|
265
|
+
code?: number;
|
|
266
|
+
error?: string;
|
|
267
|
+
};
|
|
227
268
|
getPromptPattern(): RegExp;
|
|
228
269
|
getHealthCheckCommand(): string;
|
|
229
270
|
}
|
package/dist/index.js
CHANGED
|
@@ -337,6 +337,43 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
337
337
|
],
|
|
338
338
|
docsUrl: "https://github.com/anthropics/gemini-cli#installation"
|
|
339
339
|
};
|
|
340
|
+
/**
|
|
341
|
+
* Auto-response rules for Gemini CLI.
|
|
342
|
+
* Gemini uses Ink/React TUI with arrow-key radio menus.
|
|
343
|
+
* Source: FolderTrustDialog.tsx, MultiFolderTrustDialog.tsx, CloudFreePrivacyNotice.tsx
|
|
344
|
+
*/
|
|
345
|
+
autoResponseRules = [
|
|
346
|
+
{
|
|
347
|
+
pattern: /do.?you.?trust.?this.?folder|trust.?folder|trust.?parent.?folder/i,
|
|
348
|
+
type: "permission",
|
|
349
|
+
response: "",
|
|
350
|
+
responseType: "keys",
|
|
351
|
+
keys: ["enter"],
|
|
352
|
+
description: "Trust current folder (default selection in radio menu)",
|
|
353
|
+
safe: true,
|
|
354
|
+
once: true
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
pattern: /trust.?the.?following.?folders.*(added|workspace)/i,
|
|
358
|
+
type: "permission",
|
|
359
|
+
response: "",
|
|
360
|
+
responseType: "keys",
|
|
361
|
+
keys: ["enter"],
|
|
362
|
+
description: "Trust multiple folders being added to workspace",
|
|
363
|
+
safe: true,
|
|
364
|
+
once: true
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
pattern: /allow.?google.?to.?use.?this.?data/i,
|
|
368
|
+
type: "config",
|
|
369
|
+
response: "",
|
|
370
|
+
responseType: "keys",
|
|
371
|
+
keys: ["down", "enter"],
|
|
372
|
+
description: 'Decline Google data collection (select "No")',
|
|
373
|
+
safe: true,
|
|
374
|
+
once: true
|
|
375
|
+
}
|
|
376
|
+
];
|
|
340
377
|
getRecommendedModels(_credentials) {
|
|
341
378
|
return {
|
|
342
379
|
powerful: "gemini-3-pro",
|
|
@@ -381,6 +418,27 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
381
418
|
instructions: "Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable"
|
|
382
419
|
};
|
|
383
420
|
}
|
|
421
|
+
if (/enter.?gemini.?api.?key/i.test(stripped)) {
|
|
422
|
+
return {
|
|
423
|
+
required: true,
|
|
424
|
+
type: "api_key",
|
|
425
|
+
instructions: "Enter a Gemini API key or set GEMINI_API_KEY environment variable"
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (/how.?would.?you.?like.?to.?authenticate/i.test(stripped) || /get.?started/i.test(stripped) && /login.?with.?google|use.?gemini.?api.?key|vertex/i.test(stripped)) {
|
|
429
|
+
return {
|
|
430
|
+
required: true,
|
|
431
|
+
type: "oauth",
|
|
432
|
+
instructions: "Gemini CLI authentication required \u2014 select an auth method"
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
if (/waiting.?for.?auth/i.test(stripped)) {
|
|
436
|
+
return {
|
|
437
|
+
required: true,
|
|
438
|
+
type: "oauth",
|
|
439
|
+
instructions: "Waiting for browser authentication to complete"
|
|
440
|
+
};
|
|
441
|
+
}
|
|
384
442
|
if (stripped.includes("Sign in with Google") || stripped.includes("OAuth") || stripped.includes("accounts.google.com")) {
|
|
385
443
|
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
386
444
|
return {
|
|
@@ -401,7 +459,7 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
401
459
|
}
|
|
402
460
|
detectBlockingPrompt(output) {
|
|
403
461
|
const stripped = this.stripAnsi(output);
|
|
404
|
-
if (/
|
|
462
|
+
if (/apply.?this.?change\??/i.test(stripped) || /allow.?execution.?of/i.test(stripped) || /do.?you.?want.?to.?proceed\??/i.test(stripped) || /waiting.?for.?user.?confirmation/i.test(stripped)) {
|
|
405
463
|
return {
|
|
406
464
|
detected: true,
|
|
407
465
|
type: "permission",
|
|
@@ -422,6 +480,15 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
422
480
|
instructions: loginDetection.instructions
|
|
423
481
|
};
|
|
424
482
|
}
|
|
483
|
+
if (/further.?action.?is.?required/i.test(stripped) || /verify.?your.?account/i.test(stripped) || /waiting.?for.?verification/i.test(stripped)) {
|
|
484
|
+
return {
|
|
485
|
+
detected: true,
|
|
486
|
+
type: "config",
|
|
487
|
+
prompt: "Account verification required",
|
|
488
|
+
canAutoRespond: false,
|
|
489
|
+
instructions: "Your Gemini account requires verification before continuing"
|
|
490
|
+
};
|
|
491
|
+
}
|
|
425
492
|
if (/select.*model|choose.*model|gemini-/i.test(stripped) && /\d+\)/i.test(stripped)) {
|
|
426
493
|
return {
|
|
427
494
|
detected: true,
|
|
@@ -453,7 +520,16 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
453
520
|
}
|
|
454
521
|
detectReady(output) {
|
|
455
522
|
const stripped = this.stripAnsi(output);
|
|
456
|
-
|
|
523
|
+
if (/do.?you.?trust.?this.?folder/i.test(stripped) || /how.?would.?you.?like.?to.?authenticate/i.test(stripped) || /waiting.?for.?auth/i.test(stripped) || /allow.?google.?to.?use.?this.?data/i.test(stripped)) {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
if (/type.?your.?message/i.test(stripped)) {
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
if (/^\s*[>!*]\s+/m.test(stripped) || /\(r:\)/.test(stripped)) {
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
return stripped.includes("How can I help") || stripped.includes("What would you like") || // Match "gemini> " prompt specifically, not bare ">"
|
|
457
533
|
/gemini>\s*$/i.test(stripped);
|
|
458
534
|
}
|
|
459
535
|
parseOutput(output) {
|
|
@@ -475,6 +551,27 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
475
551
|
}
|
|
476
552
|
};
|
|
477
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* Detect exit conditions specific to Gemini CLI.
|
|
556
|
+
* Source: FolderTrustDialog.tsx:127, LogoutConfirmationDialog.tsx:64
|
|
557
|
+
*/
|
|
558
|
+
detectExit(output) {
|
|
559
|
+
const stripped = this.stripAnsi(output);
|
|
560
|
+
if (/folder.?trust.?level.?must.?be.?selected.*exiting/i.test(stripped)) {
|
|
561
|
+
return {
|
|
562
|
+
exited: true,
|
|
563
|
+
code: 1,
|
|
564
|
+
error: "Gemini CLI exited because no folder trust level was selected"
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
if (/you are now logged out/i.test(stripped)) {
|
|
568
|
+
return {
|
|
569
|
+
exited: true,
|
|
570
|
+
code: 0
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
return super.detectExit(output);
|
|
574
|
+
}
|
|
478
575
|
getPromptPattern() {
|
|
479
576
|
return /gemini>\s*$/i;
|
|
480
577
|
}
|
|
@@ -496,11 +593,12 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
496
593
|
};
|
|
497
594
|
/**
|
|
498
595
|
* Auto-response rules for OpenAI Codex CLI.
|
|
499
|
-
* Codex uses
|
|
596
|
+
* Codex uses ratatui/crossterm full-screen TUI with arrow-key menus.
|
|
597
|
+
* Source: trust_directory.rs, update_prompt.rs, model_migration.rs, cwd_prompt.rs, chatwidget.rs, main.rs
|
|
500
598
|
*/
|
|
501
599
|
autoResponseRules = [
|
|
502
600
|
{
|
|
503
|
-
pattern: /
|
|
601
|
+
pattern: /update.?available.*->|update.?now|skip.?until.?next.?version/i,
|
|
504
602
|
type: "config",
|
|
505
603
|
response: "",
|
|
506
604
|
responseType: "keys",
|
|
@@ -509,14 +607,51 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
509
607
|
safe: true
|
|
510
608
|
},
|
|
511
609
|
{
|
|
512
|
-
pattern: /trust
|
|
610
|
+
pattern: /do.?you.?trust.?the.?contents|trust.?this.?directory|yes,?.?continue|prompt.?injection/i,
|
|
513
611
|
type: "permission",
|
|
514
612
|
response: "",
|
|
515
613
|
responseType: "keys",
|
|
516
614
|
keys: ["enter"],
|
|
517
|
-
description:
|
|
615
|
+
description: 'Trust directory contents (default: "Yes, continue")',
|
|
518
616
|
safe: true,
|
|
519
617
|
once: true
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
pattern: /choose.?how.?you.?d.?like.?codex.?to.?proceed|try.?new.?model|use.?existing.?model/i,
|
|
621
|
+
type: "config",
|
|
622
|
+
response: "",
|
|
623
|
+
responseType: "keys",
|
|
624
|
+
keys: ["enter"],
|
|
625
|
+
description: 'Accept model migration (default: "Try new model")',
|
|
626
|
+
safe: true,
|
|
627
|
+
once: true
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
pattern: /choose.?working.?directory.?to.?(resume|fork)/i,
|
|
631
|
+
type: "config",
|
|
632
|
+
response: "",
|
|
633
|
+
responseType: "keys",
|
|
634
|
+
keys: ["enter"],
|
|
635
|
+
description: "Accept default working directory for session resume",
|
|
636
|
+
safe: true
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
pattern: /enable.?full.?access\??/i,
|
|
640
|
+
type: "permission",
|
|
641
|
+
response: "",
|
|
642
|
+
responseType: "keys",
|
|
643
|
+
keys: ["enter"],
|
|
644
|
+
description: 'Confirm full access mode (default: "Yes, continue anyway")',
|
|
645
|
+
safe: true,
|
|
646
|
+
once: true
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
pattern: /continue.?anyway\?\s*\[y\/N\]/i,
|
|
650
|
+
type: "config",
|
|
651
|
+
response: "y",
|
|
652
|
+
responseType: "text",
|
|
653
|
+
description: "Confirm dumb terminal continuation",
|
|
654
|
+
safe: true
|
|
520
655
|
}
|
|
521
656
|
];
|
|
522
657
|
getRecommendedModels(_credentials) {
|
|
@@ -561,6 +696,23 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
561
696
|
instructions: "Set OPENAI_API_KEY environment variable or provide credentials in adapterConfig"
|
|
562
697
|
};
|
|
563
698
|
}
|
|
699
|
+
if (/sign.?in.?with.?chatgpt/i.test(stripped) || /sign.?in.?with.?device.?code/i.test(stripped) && !/open.?this.?link/i.test(stripped) || /provide.?your.?own.?api.?key/i.test(stripped)) {
|
|
700
|
+
return {
|
|
701
|
+
required: true,
|
|
702
|
+
type: "oauth",
|
|
703
|
+
instructions: "Codex authentication required \u2014 select a sign-in method or provide an API key"
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
if (/preparing.?device.?code.?login/i.test(stripped) || /open.?this.?link.?in.?your.?browser/i.test(stripped) || /enter.?this.?one-time.?code/i.test(stripped)) {
|
|
707
|
+
const codeMatch = stripped.match(/code[:\s]+([A-Z0-9-]+)/i);
|
|
708
|
+
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
709
|
+
return {
|
|
710
|
+
required: true,
|
|
711
|
+
type: "device_code",
|
|
712
|
+
url: urlMatch ? urlMatch[0] : void 0,
|
|
713
|
+
instructions: codeMatch ? `Enter code ${codeMatch[1]} at the URL` : "Device code authentication in progress \u2014 complete in browser"
|
|
714
|
+
};
|
|
715
|
+
}
|
|
564
716
|
if (stripped.includes("device code") || stripped.includes("Enter the code")) {
|
|
565
717
|
const codeMatch = stripped.match(/code[:\s]+([A-Z0-9-]+)/i);
|
|
566
718
|
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
@@ -574,10 +726,21 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
574
726
|
return { required: false };
|
|
575
727
|
}
|
|
576
728
|
/**
|
|
577
|
-
* Detect blocking prompts specific to OpenAI Codex CLI
|
|
729
|
+
* Detect blocking prompts specific to OpenAI Codex CLI.
|
|
730
|
+
* Source: approval_overlay.rs, chatwidget.rs, request_user_input/mod.rs
|
|
578
731
|
*/
|
|
579
732
|
detectBlockingPrompt(output) {
|
|
580
733
|
const stripped = this.stripAnsi(output);
|
|
734
|
+
if (/would.?you.?like.?to.?run.?the.?following.?command/i.test(stripped) || /do.?you.?want.?to.?approve.?access/i.test(stripped) || /would.?you.?like.?to.?make.?the.?following.?edits/i.test(stripped) || /press.?enter.?to.?confirm/i.test(stripped) && /esc.?to.?cancel/i.test(stripped)) {
|
|
735
|
+
return {
|
|
736
|
+
detected: true,
|
|
737
|
+
type: "permission",
|
|
738
|
+
prompt: "Codex tool approval",
|
|
739
|
+
suggestedResponse: "keys:enter",
|
|
740
|
+
canAutoRespond: true,
|
|
741
|
+
instructions: "Codex is asking permission to execute a command, approve access, or apply edits"
|
|
742
|
+
};
|
|
743
|
+
}
|
|
581
744
|
const loginDetection = this.detectLogin(output);
|
|
582
745
|
if (loginDetection.required) {
|
|
583
746
|
return {
|
|
@@ -589,6 +752,24 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
589
752
|
instructions: loginDetection.instructions
|
|
590
753
|
};
|
|
591
754
|
}
|
|
755
|
+
if (/set.?up.?default.?sandbox/i.test(stripped) || /use.?non-admin.?sandbox/i.test(stripped)) {
|
|
756
|
+
return {
|
|
757
|
+
detected: true,
|
|
758
|
+
type: "config",
|
|
759
|
+
prompt: "Windows sandbox setup",
|
|
760
|
+
canAutoRespond: false,
|
|
761
|
+
instructions: "Codex needs a sandbox configuration on Windows"
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
if (/type.?your.?answer/i.test(stripped) && /select.?an.?option/i.test(stripped)) {
|
|
765
|
+
return {
|
|
766
|
+
detected: true,
|
|
767
|
+
type: "unknown",
|
|
768
|
+
prompt: "Codex requesting structured user input",
|
|
769
|
+
canAutoRespond: false,
|
|
770
|
+
instructions: "Codex model is asking multi-step questions that require user input"
|
|
771
|
+
};
|
|
772
|
+
}
|
|
592
773
|
if (/select.*model|choose.*model|gpt-4|gpt-3\.5/i.test(stripped) && /\d+\)/i.test(stripped)) {
|
|
593
774
|
return {
|
|
594
775
|
detected: true,
|
|
@@ -620,7 +801,16 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
620
801
|
}
|
|
621
802
|
detectReady(output) {
|
|
622
803
|
const stripped = this.stripAnsi(output);
|
|
623
|
-
|
|
804
|
+
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)) {
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
if (/›\s+/m.test(stripped)) {
|
|
808
|
+
return true;
|
|
809
|
+
}
|
|
810
|
+
if (/explain this codebase|summarize recent commits|find and fix a bug/i.test(stripped)) {
|
|
811
|
+
return true;
|
|
812
|
+
}
|
|
813
|
+
return stripped.includes("How can I help") || /(?:codex|>)\s*$/i.test(stripped);
|
|
624
814
|
}
|
|
625
815
|
parseOutput(output) {
|
|
626
816
|
const stripped = this.stripAnsi(output);
|
|
@@ -640,6 +830,24 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
640
830
|
}
|
|
641
831
|
};
|
|
642
832
|
}
|
|
833
|
+
/**
|
|
834
|
+
* Detect exit conditions specific to Codex CLI.
|
|
835
|
+
* Source: main.rs:404, main.rs:414, main.rs:461
|
|
836
|
+
*/
|
|
837
|
+
detectExit(output) {
|
|
838
|
+
const stripped = this.stripAnsi(output);
|
|
839
|
+
if (/to.?continue.?this.?session,?.?run/i.test(stripped)) {
|
|
840
|
+
return { exited: true, code: 0 };
|
|
841
|
+
}
|
|
842
|
+
if (/update.?ran.?successfully.*restart.?codex/i.test(stripped)) {
|
|
843
|
+
return {
|
|
844
|
+
exited: true,
|
|
845
|
+
code: 0,
|
|
846
|
+
error: "Codex updated successfully \u2014 restart required"
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
return super.detectExit(output);
|
|
850
|
+
}
|
|
643
851
|
getPromptPattern() {
|
|
644
852
|
return /(?:codex|>)\s*$/i;
|
|
645
853
|
}
|
|
@@ -667,12 +875,42 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
667
875
|
};
|
|
668
876
|
/**
|
|
669
877
|
* Auto-response rules for Aider CLI.
|
|
670
|
-
* Aider uses plain text
|
|
671
|
-
*
|
|
878
|
+
* Aider uses plain text prompts via io.py:832 with (Y)es/(N)o format.
|
|
879
|
+
* All rules are responseType: 'text' — Aider never uses TUI menus.
|
|
880
|
+
*
|
|
881
|
+
* Decline rules come first to override the generic accept patterns.
|
|
672
882
|
*/
|
|
673
883
|
autoResponseRules = [
|
|
884
|
+
// ── Decline rules (specific, checked first) ────────────────────────
|
|
885
|
+
{
|
|
886
|
+
pattern: /allow collection of anonymous analytics/i,
|
|
887
|
+
type: "config",
|
|
888
|
+
response: "n",
|
|
889
|
+
responseType: "text",
|
|
890
|
+
description: "Decline Aider telemetry opt-in",
|
|
891
|
+
safe: true,
|
|
892
|
+
once: true
|
|
893
|
+
},
|
|
674
894
|
{
|
|
675
|
-
pattern: /
|
|
895
|
+
pattern: /would you like to see what.?s new in this version/i,
|
|
896
|
+
type: "config",
|
|
897
|
+
response: "n",
|
|
898
|
+
responseType: "text",
|
|
899
|
+
description: "Decline release notes offer",
|
|
900
|
+
safe: true,
|
|
901
|
+
once: true
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
pattern: /open a github issue pre-filled/i,
|
|
905
|
+
type: "config",
|
|
906
|
+
response: "n",
|
|
907
|
+
responseType: "text",
|
|
908
|
+
description: "Decline automatic bug report",
|
|
909
|
+
safe: true
|
|
910
|
+
},
|
|
911
|
+
// ── File / edit operations ──────────────────────────────────────────
|
|
912
|
+
{
|
|
913
|
+
pattern: /add .+ to the chat\?/i,
|
|
676
914
|
type: "permission",
|
|
677
915
|
response: "y",
|
|
678
916
|
responseType: "text",
|
|
@@ -680,7 +918,15 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
680
918
|
safe: true
|
|
681
919
|
},
|
|
682
920
|
{
|
|
683
|
-
pattern: /
|
|
921
|
+
pattern: /add url to the chat\?/i,
|
|
922
|
+
type: "permission",
|
|
923
|
+
response: "y",
|
|
924
|
+
responseType: "text",
|
|
925
|
+
description: "Allow Aider to add URL content to chat",
|
|
926
|
+
safe: true
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
pattern: /create new file\?/i,
|
|
684
930
|
type: "permission",
|
|
685
931
|
response: "y",
|
|
686
932
|
responseType: "text",
|
|
@@ -688,11 +934,96 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
688
934
|
safe: true
|
|
689
935
|
},
|
|
690
936
|
{
|
|
691
|
-
pattern: /
|
|
937
|
+
pattern: /allow edits to file/i,
|
|
938
|
+
type: "permission",
|
|
939
|
+
response: "y",
|
|
940
|
+
responseType: "text",
|
|
941
|
+
description: "Allow edits to file not yet in chat",
|
|
942
|
+
safe: true
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
pattern: /edit the files\?/i,
|
|
692
946
|
type: "permission",
|
|
693
947
|
response: "y",
|
|
694
948
|
responseType: "text",
|
|
695
|
-
description: "
|
|
949
|
+
description: "Accept architect mode edits",
|
|
950
|
+
safe: true
|
|
951
|
+
},
|
|
952
|
+
// ── Shell operations ────────────────────────────────────────────────
|
|
953
|
+
{
|
|
954
|
+
pattern: /run shell commands?\?/i,
|
|
955
|
+
type: "permission",
|
|
956
|
+
response: "y",
|
|
957
|
+
responseType: "text",
|
|
958
|
+
description: "Allow Aider to run shell commands",
|
|
959
|
+
safe: true
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
pattern: /add command output to the chat\?/i,
|
|
963
|
+
type: "permission",
|
|
964
|
+
response: "y",
|
|
965
|
+
responseType: "text",
|
|
966
|
+
description: "Add shell command output to chat context",
|
|
967
|
+
safe: true
|
|
968
|
+
},
|
|
969
|
+
{
|
|
970
|
+
pattern: /add \d+.*tokens of command output to the chat\?/i,
|
|
971
|
+
type: "permission",
|
|
972
|
+
response: "y",
|
|
973
|
+
responseType: "text",
|
|
974
|
+
description: "Add /run command output to chat context",
|
|
975
|
+
safe: true
|
|
976
|
+
},
|
|
977
|
+
// ── Setup / maintenance ─────────────────────────────────────────────
|
|
978
|
+
{
|
|
979
|
+
pattern: /no git repo found.*create one/i,
|
|
980
|
+
type: "config",
|
|
981
|
+
response: "y",
|
|
982
|
+
responseType: "text",
|
|
983
|
+
description: "Create git repo for change tracking",
|
|
984
|
+
safe: true,
|
|
985
|
+
once: true
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
pattern: /add .+ to \.gitignore/i,
|
|
989
|
+
type: "config",
|
|
990
|
+
response: "y",
|
|
991
|
+
responseType: "text",
|
|
992
|
+
description: "Update .gitignore with Aider patterns",
|
|
993
|
+
safe: true,
|
|
994
|
+
once: true
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
pattern: /run pip install\?/i,
|
|
998
|
+
type: "config",
|
|
999
|
+
response: "y",
|
|
1000
|
+
responseType: "text",
|
|
1001
|
+
description: "Install missing Python dependencies",
|
|
1002
|
+
safe: true
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
pattern: /install playwright\?/i,
|
|
1006
|
+
type: "config",
|
|
1007
|
+
response: "y",
|
|
1008
|
+
responseType: "text",
|
|
1009
|
+
description: "Install Playwright for web scraping",
|
|
1010
|
+
safe: true
|
|
1011
|
+
},
|
|
1012
|
+
// ── Other safe confirmations ────────────────────────────────────────
|
|
1013
|
+
{
|
|
1014
|
+
pattern: /fix lint errors in/i,
|
|
1015
|
+
type: "permission",
|
|
1016
|
+
response: "y",
|
|
1017
|
+
responseType: "text",
|
|
1018
|
+
description: "Accept lint error fix suggestion",
|
|
1019
|
+
safe: true
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
pattern: /try to proceed anyway\?/i,
|
|
1023
|
+
type: "config",
|
|
1024
|
+
response: "y",
|
|
1025
|
+
responseType: "text",
|
|
1026
|
+
description: "Continue despite context limit warning",
|
|
696
1027
|
safe: true
|
|
697
1028
|
}
|
|
698
1029
|
];
|
|
@@ -772,8 +1103,28 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
772
1103
|
instructions: "API key is invalid - please check your credentials"
|
|
773
1104
|
};
|
|
774
1105
|
}
|
|
1106
|
+
if (/login to openrouter or create a free account/i.test(stripped)) {
|
|
1107
|
+
return {
|
|
1108
|
+
required: true,
|
|
1109
|
+
type: "oauth",
|
|
1110
|
+
instructions: "Aider offering OpenRouter OAuth login \u2014 provide API keys to skip"
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
if (/please open this url in your browser to connect aider with openrouter/i.test(stripped) || /waiting up to 5 minutes for you to finish in the browser/i.test(stripped)) {
|
|
1114
|
+
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
1115
|
+
return {
|
|
1116
|
+
required: true,
|
|
1117
|
+
type: "browser",
|
|
1118
|
+
url: urlMatch ? urlMatch[0] : void 0,
|
|
1119
|
+
instructions: "Complete OpenRouter authentication in browser"
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
775
1122
|
return { required: false };
|
|
776
1123
|
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Detect blocking prompts specific to Aider CLI.
|
|
1126
|
+
* Source: io.py, onboarding.py, base_coder.py, report.py
|
|
1127
|
+
*/
|
|
777
1128
|
detectBlockingPrompt(output) {
|
|
778
1129
|
const stripped = this.stripAnsi(output);
|
|
779
1130
|
const loginDetection = this.detectLogin(output);
|
|
@@ -782,6 +1133,7 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
782
1133
|
detected: true,
|
|
783
1134
|
type: "login",
|
|
784
1135
|
prompt: loginDetection.instructions,
|
|
1136
|
+
url: loginDetection.url,
|
|
785
1137
|
canAutoRespond: false,
|
|
786
1138
|
instructions: loginDetection.instructions
|
|
787
1139
|
};
|
|
@@ -795,16 +1147,16 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
795
1147
|
instructions: "Please select a model or set AIDER_MODEL env var"
|
|
796
1148
|
};
|
|
797
1149
|
}
|
|
798
|
-
if (/
|
|
1150
|
+
if (/please answer with one of:/i.test(stripped)) {
|
|
799
1151
|
return {
|
|
800
1152
|
detected: true,
|
|
801
|
-
type: "
|
|
802
|
-
prompt: "
|
|
1153
|
+
type: "unknown",
|
|
1154
|
+
prompt: "Invalid confirmation input",
|
|
803
1155
|
canAutoRespond: false,
|
|
804
|
-
instructions: "Aider
|
|
1156
|
+
instructions: "Aider received an invalid response to a confirmation prompt"
|
|
805
1157
|
};
|
|
806
1158
|
}
|
|
807
|
-
if (/delete|remove|overwrite/i.test(stripped) && /\[y\/n\]/i.test(stripped)) {
|
|
1159
|
+
if (/delete|remove|overwrite/i.test(stripped) && (/\[y\/n\]/i.test(stripped) || /\(Y\)es\/\(N\)o/i.test(stripped))) {
|
|
808
1160
|
return {
|
|
809
1161
|
detected: true,
|
|
810
1162
|
type: "permission",
|
|
@@ -818,9 +1170,22 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
818
1170
|
}
|
|
819
1171
|
detectReady(output) {
|
|
820
1172
|
const stripped = this.stripAnsi(output);
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
1173
|
+
if (/login to openrouter/i.test(stripped) || /open this url in your browser/i.test(stripped) || /waiting up to 5 minutes/i.test(stripped)) {
|
|
1174
|
+
return false;
|
|
1175
|
+
}
|
|
1176
|
+
if (/(?:ask|code|architect|help)(?:\s+multi)?>\s*$/m.test(stripped) || /^multi>\s*$/m.test(stripped)) {
|
|
1177
|
+
return true;
|
|
1178
|
+
}
|
|
1179
|
+
if (/^Aider v\d+/m.test(stripped)) {
|
|
1180
|
+
return true;
|
|
1181
|
+
}
|
|
1182
|
+
if (/^(?:Readonly|Editable):/m.test(stripped)) {
|
|
1183
|
+
return true;
|
|
1184
|
+
}
|
|
1185
|
+
return (
|
|
1186
|
+
// Legacy prompt patterns
|
|
1187
|
+
stripped.includes("aider>") || /Added.*to the chat/i.test(stripped) || />\s*$/.test(stripped)
|
|
1188
|
+
);
|
|
824
1189
|
}
|
|
825
1190
|
parseOutput(output) {
|
|
826
1191
|
const stripped = this.stripAnsi(output);
|
|
@@ -841,8 +1206,26 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
841
1206
|
}
|
|
842
1207
|
};
|
|
843
1208
|
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Detect exit conditions specific to Aider.
|
|
1211
|
+
* Source: base_coder.py:994, base_coder.py:998, report.py:77, versioncheck.py:58
|
|
1212
|
+
*/
|
|
1213
|
+
detectExit(output) {
|
|
1214
|
+
const stripped = this.stripAnsi(output);
|
|
1215
|
+
if (/\^C again to exit/i.test(stripped) || /\^C KeyboardInterrupt/i.test(stripped)) {
|
|
1216
|
+
return { exited: true, code: 130 };
|
|
1217
|
+
}
|
|
1218
|
+
if (/re-run aider to use new version/i.test(stripped)) {
|
|
1219
|
+
return {
|
|
1220
|
+
exited: true,
|
|
1221
|
+
code: 0,
|
|
1222
|
+
error: "Aider updated \u2014 restart required"
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
return super.detectExit(output);
|
|
1226
|
+
}
|
|
844
1227
|
getPromptPattern() {
|
|
845
|
-
return /(?:aider
|
|
1228
|
+
return /(?:ask|code|architect|help|aider|multi)(?:\s+multi)?>\s*$/i;
|
|
846
1229
|
}
|
|
847
1230
|
getHealthCheckCommand() {
|
|
848
1231
|
return "aider --version";
|