coding-agent-adapters 0.2.13 → 0.2.16
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 +409 -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 +409 -23
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -230,6 +230,9 @@ var ClaudeAdapter = class extends BaseCodingAdapter {
|
|
|
230
230
|
* Detect blocking prompts specific to Claude Code CLI
|
|
231
231
|
*/
|
|
232
232
|
detectBlockingPrompt(output) {
|
|
233
|
+
if (this.detectReady(output)) {
|
|
234
|
+
return { detected: false };
|
|
235
|
+
}
|
|
233
236
|
const stripped = this.stripAnsi(output);
|
|
234
237
|
const loginDetection = this.detectLogin(output);
|
|
235
238
|
if (loginDetection.required) {
|
|
@@ -339,6 +342,43 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
339
342
|
],
|
|
340
343
|
docsUrl: "https://github.com/anthropics/gemini-cli#installation"
|
|
341
344
|
};
|
|
345
|
+
/**
|
|
346
|
+
* Auto-response rules for Gemini CLI.
|
|
347
|
+
* Gemini uses Ink/React TUI with arrow-key radio menus.
|
|
348
|
+
* Source: FolderTrustDialog.tsx, MultiFolderTrustDialog.tsx, CloudFreePrivacyNotice.tsx
|
|
349
|
+
*/
|
|
350
|
+
autoResponseRules = [
|
|
351
|
+
{
|
|
352
|
+
pattern: /do.?you.?trust.?this.?folder|trust.?folder|trust.?parent.?folder/i,
|
|
353
|
+
type: "permission",
|
|
354
|
+
response: "",
|
|
355
|
+
responseType: "keys",
|
|
356
|
+
keys: ["enter"],
|
|
357
|
+
description: "Trust current folder (default selection in radio menu)",
|
|
358
|
+
safe: true,
|
|
359
|
+
once: true
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
pattern: /trust.?the.?following.?folders.*(added|workspace)/i,
|
|
363
|
+
type: "permission",
|
|
364
|
+
response: "",
|
|
365
|
+
responseType: "keys",
|
|
366
|
+
keys: ["enter"],
|
|
367
|
+
description: "Trust multiple folders being added to workspace",
|
|
368
|
+
safe: true,
|
|
369
|
+
once: true
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
pattern: /allow.?google.?to.?use.?this.?data/i,
|
|
373
|
+
type: "config",
|
|
374
|
+
response: "",
|
|
375
|
+
responseType: "keys",
|
|
376
|
+
keys: ["down", "enter"],
|
|
377
|
+
description: 'Decline Google data collection (select "No")',
|
|
378
|
+
safe: true,
|
|
379
|
+
once: true
|
|
380
|
+
}
|
|
381
|
+
];
|
|
342
382
|
getRecommendedModels(_credentials) {
|
|
343
383
|
return {
|
|
344
384
|
powerful: "gemini-3-pro",
|
|
@@ -383,6 +423,27 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
383
423
|
instructions: "Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable"
|
|
384
424
|
};
|
|
385
425
|
}
|
|
426
|
+
if (/enter.?gemini.?api.?key/i.test(stripped)) {
|
|
427
|
+
return {
|
|
428
|
+
required: true,
|
|
429
|
+
type: "api_key",
|
|
430
|
+
instructions: "Enter a Gemini API key or set GEMINI_API_KEY environment variable"
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
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)) {
|
|
434
|
+
return {
|
|
435
|
+
required: true,
|
|
436
|
+
type: "oauth",
|
|
437
|
+
instructions: "Gemini CLI authentication required \u2014 select an auth method"
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
if (/waiting.?for.?auth/i.test(stripped)) {
|
|
441
|
+
return {
|
|
442
|
+
required: true,
|
|
443
|
+
type: "oauth",
|
|
444
|
+
instructions: "Waiting for browser authentication to complete"
|
|
445
|
+
};
|
|
446
|
+
}
|
|
386
447
|
if (stripped.includes("Sign in with Google") || stripped.includes("OAuth") || stripped.includes("accounts.google.com")) {
|
|
387
448
|
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
388
449
|
return {
|
|
@@ -403,7 +464,7 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
403
464
|
}
|
|
404
465
|
detectBlockingPrompt(output) {
|
|
405
466
|
const stripped = this.stripAnsi(output);
|
|
406
|
-
if (/
|
|
467
|
+
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)) {
|
|
407
468
|
return {
|
|
408
469
|
detected: true,
|
|
409
470
|
type: "permission",
|
|
@@ -424,6 +485,15 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
424
485
|
instructions: loginDetection.instructions
|
|
425
486
|
};
|
|
426
487
|
}
|
|
488
|
+
if (/further.?action.?is.?required/i.test(stripped) || /verify.?your.?account/i.test(stripped) || /waiting.?for.?verification/i.test(stripped)) {
|
|
489
|
+
return {
|
|
490
|
+
detected: true,
|
|
491
|
+
type: "config",
|
|
492
|
+
prompt: "Account verification required",
|
|
493
|
+
canAutoRespond: false,
|
|
494
|
+
instructions: "Your Gemini account requires verification before continuing"
|
|
495
|
+
};
|
|
496
|
+
}
|
|
427
497
|
if (/select.*model|choose.*model|gemini-/i.test(stripped) && /\d+\)/i.test(stripped)) {
|
|
428
498
|
return {
|
|
429
499
|
detected: true,
|
|
@@ -455,7 +525,16 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
455
525
|
}
|
|
456
526
|
detectReady(output) {
|
|
457
527
|
const stripped = this.stripAnsi(output);
|
|
458
|
-
|
|
528
|
+
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)) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
if (/type.?your.?message/i.test(stripped)) {
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
if (/^\s*[>!*]\s+/m.test(stripped) || /\(r:\)/.test(stripped)) {
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
return stripped.includes("How can I help") || stripped.includes("What would you like") || // Match "gemini> " prompt specifically, not bare ">"
|
|
459
538
|
/gemini>\s*$/i.test(stripped);
|
|
460
539
|
}
|
|
461
540
|
parseOutput(output) {
|
|
@@ -477,6 +556,27 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
477
556
|
}
|
|
478
557
|
};
|
|
479
558
|
}
|
|
559
|
+
/**
|
|
560
|
+
* Detect exit conditions specific to Gemini CLI.
|
|
561
|
+
* Source: FolderTrustDialog.tsx:127, LogoutConfirmationDialog.tsx:64
|
|
562
|
+
*/
|
|
563
|
+
detectExit(output) {
|
|
564
|
+
const stripped = this.stripAnsi(output);
|
|
565
|
+
if (/folder.?trust.?level.?must.?be.?selected.*exiting/i.test(stripped)) {
|
|
566
|
+
return {
|
|
567
|
+
exited: true,
|
|
568
|
+
code: 1,
|
|
569
|
+
error: "Gemini CLI exited because no folder trust level was selected"
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
if (/you are now logged out/i.test(stripped)) {
|
|
573
|
+
return {
|
|
574
|
+
exited: true,
|
|
575
|
+
code: 0
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
return super.detectExit(output);
|
|
579
|
+
}
|
|
480
580
|
getPromptPattern() {
|
|
481
581
|
return /gemini>\s*$/i;
|
|
482
582
|
}
|
|
@@ -498,11 +598,12 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
498
598
|
};
|
|
499
599
|
/**
|
|
500
600
|
* Auto-response rules for OpenAI Codex CLI.
|
|
501
|
-
* Codex uses
|
|
601
|
+
* Codex uses ratatui/crossterm full-screen TUI with arrow-key menus.
|
|
602
|
+
* Source: trust_directory.rs, update_prompt.rs, model_migration.rs, cwd_prompt.rs, chatwidget.rs, main.rs
|
|
502
603
|
*/
|
|
503
604
|
autoResponseRules = [
|
|
504
605
|
{
|
|
505
|
-
pattern: /
|
|
606
|
+
pattern: /update.?available.*->|update.?now|skip.?until.?next.?version/i,
|
|
506
607
|
type: "config",
|
|
507
608
|
response: "",
|
|
508
609
|
responseType: "keys",
|
|
@@ -511,14 +612,51 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
511
612
|
safe: true
|
|
512
613
|
},
|
|
513
614
|
{
|
|
514
|
-
pattern: /trust
|
|
615
|
+
pattern: /do.?you.?trust.?the.?contents|trust.?this.?directory|yes,?.?continue|prompt.?injection/i,
|
|
616
|
+
type: "permission",
|
|
617
|
+
response: "",
|
|
618
|
+
responseType: "keys",
|
|
619
|
+
keys: ["enter"],
|
|
620
|
+
description: 'Trust directory contents (default: "Yes, continue")',
|
|
621
|
+
safe: true,
|
|
622
|
+
once: true
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
pattern: /choose.?how.?you.?d.?like.?codex.?to.?proceed|try.?new.?model|use.?existing.?model/i,
|
|
626
|
+
type: "config",
|
|
627
|
+
response: "",
|
|
628
|
+
responseType: "keys",
|
|
629
|
+
keys: ["enter"],
|
|
630
|
+
description: 'Accept model migration (default: "Try new model")',
|
|
631
|
+
safe: true,
|
|
632
|
+
once: true
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
pattern: /choose.?working.?directory.?to.?(resume|fork)/i,
|
|
636
|
+
type: "config",
|
|
637
|
+
response: "",
|
|
638
|
+
responseType: "keys",
|
|
639
|
+
keys: ["enter"],
|
|
640
|
+
description: "Accept default working directory for session resume",
|
|
641
|
+
safe: true
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
pattern: /enable.?full.?access\??/i,
|
|
515
645
|
type: "permission",
|
|
516
646
|
response: "",
|
|
517
647
|
responseType: "keys",
|
|
518
648
|
keys: ["enter"],
|
|
519
|
-
description:
|
|
649
|
+
description: 'Confirm full access mode (default: "Yes, continue anyway")',
|
|
520
650
|
safe: true,
|
|
521
651
|
once: true
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
pattern: /continue.?anyway\?\s*\[y\/N\]/i,
|
|
655
|
+
type: "config",
|
|
656
|
+
response: "y",
|
|
657
|
+
responseType: "text",
|
|
658
|
+
description: "Confirm dumb terminal continuation",
|
|
659
|
+
safe: true
|
|
522
660
|
}
|
|
523
661
|
];
|
|
524
662
|
getRecommendedModels(_credentials) {
|
|
@@ -563,6 +701,23 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
563
701
|
instructions: "Set OPENAI_API_KEY environment variable or provide credentials in adapterConfig"
|
|
564
702
|
};
|
|
565
703
|
}
|
|
704
|
+
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)) {
|
|
705
|
+
return {
|
|
706
|
+
required: true,
|
|
707
|
+
type: "oauth",
|
|
708
|
+
instructions: "Codex authentication required \u2014 select a sign-in method or provide an API key"
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
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)) {
|
|
712
|
+
const codeMatch = stripped.match(/code[:\s]+([A-Z0-9-]+)/i);
|
|
713
|
+
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
714
|
+
return {
|
|
715
|
+
required: true,
|
|
716
|
+
type: "device_code",
|
|
717
|
+
url: urlMatch ? urlMatch[0] : void 0,
|
|
718
|
+
instructions: codeMatch ? `Enter code ${codeMatch[1]} at the URL` : "Device code authentication in progress \u2014 complete in browser"
|
|
719
|
+
};
|
|
720
|
+
}
|
|
566
721
|
if (stripped.includes("device code") || stripped.includes("Enter the code")) {
|
|
567
722
|
const codeMatch = stripped.match(/code[:\s]+([A-Z0-9-]+)/i);
|
|
568
723
|
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
@@ -576,10 +731,21 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
576
731
|
return { required: false };
|
|
577
732
|
}
|
|
578
733
|
/**
|
|
579
|
-
* Detect blocking prompts specific to OpenAI Codex CLI
|
|
734
|
+
* Detect blocking prompts specific to OpenAI Codex CLI.
|
|
735
|
+
* Source: approval_overlay.rs, chatwidget.rs, request_user_input/mod.rs
|
|
580
736
|
*/
|
|
581
737
|
detectBlockingPrompt(output) {
|
|
582
738
|
const stripped = this.stripAnsi(output);
|
|
739
|
+
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)) {
|
|
740
|
+
return {
|
|
741
|
+
detected: true,
|
|
742
|
+
type: "permission",
|
|
743
|
+
prompt: "Codex tool approval",
|
|
744
|
+
suggestedResponse: "keys:enter",
|
|
745
|
+
canAutoRespond: true,
|
|
746
|
+
instructions: "Codex is asking permission to execute a command, approve access, or apply edits"
|
|
747
|
+
};
|
|
748
|
+
}
|
|
583
749
|
const loginDetection = this.detectLogin(output);
|
|
584
750
|
if (loginDetection.required) {
|
|
585
751
|
return {
|
|
@@ -591,6 +757,24 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
591
757
|
instructions: loginDetection.instructions
|
|
592
758
|
};
|
|
593
759
|
}
|
|
760
|
+
if (/set.?up.?default.?sandbox/i.test(stripped) || /use.?non-admin.?sandbox/i.test(stripped)) {
|
|
761
|
+
return {
|
|
762
|
+
detected: true,
|
|
763
|
+
type: "config",
|
|
764
|
+
prompt: "Windows sandbox setup",
|
|
765
|
+
canAutoRespond: false,
|
|
766
|
+
instructions: "Codex needs a sandbox configuration on Windows"
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
if (/type.?your.?answer/i.test(stripped) && /select.?an.?option/i.test(stripped)) {
|
|
770
|
+
return {
|
|
771
|
+
detected: true,
|
|
772
|
+
type: "unknown",
|
|
773
|
+
prompt: "Codex requesting structured user input",
|
|
774
|
+
canAutoRespond: false,
|
|
775
|
+
instructions: "Codex model is asking multi-step questions that require user input"
|
|
776
|
+
};
|
|
777
|
+
}
|
|
594
778
|
if (/select.*model|choose.*model|gpt-4|gpt-3\.5/i.test(stripped) && /\d+\)/i.test(stripped)) {
|
|
595
779
|
return {
|
|
596
780
|
detected: true,
|
|
@@ -622,7 +806,16 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
622
806
|
}
|
|
623
807
|
detectReady(output) {
|
|
624
808
|
const stripped = this.stripAnsi(output);
|
|
625
|
-
|
|
809
|
+
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)) {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
if (/›\s+/m.test(stripped)) {
|
|
813
|
+
return true;
|
|
814
|
+
}
|
|
815
|
+
if (/explain this codebase|summarize recent commits|find and fix a bug/i.test(stripped)) {
|
|
816
|
+
return true;
|
|
817
|
+
}
|
|
818
|
+
return stripped.includes("How can I help") || /(?:codex|>)\s*$/i.test(stripped);
|
|
626
819
|
}
|
|
627
820
|
parseOutput(output) {
|
|
628
821
|
const stripped = this.stripAnsi(output);
|
|
@@ -642,6 +835,24 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
642
835
|
}
|
|
643
836
|
};
|
|
644
837
|
}
|
|
838
|
+
/**
|
|
839
|
+
* Detect exit conditions specific to Codex CLI.
|
|
840
|
+
* Source: main.rs:404, main.rs:414, main.rs:461
|
|
841
|
+
*/
|
|
842
|
+
detectExit(output) {
|
|
843
|
+
const stripped = this.stripAnsi(output);
|
|
844
|
+
if (/to.?continue.?this.?session,?.?run/i.test(stripped)) {
|
|
845
|
+
return { exited: true, code: 0 };
|
|
846
|
+
}
|
|
847
|
+
if (/update.?ran.?successfully.*restart.?codex/i.test(stripped)) {
|
|
848
|
+
return {
|
|
849
|
+
exited: true,
|
|
850
|
+
code: 0,
|
|
851
|
+
error: "Codex updated successfully \u2014 restart required"
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
return super.detectExit(output);
|
|
855
|
+
}
|
|
645
856
|
getPromptPattern() {
|
|
646
857
|
return /(?:codex|>)\s*$/i;
|
|
647
858
|
}
|
|
@@ -669,12 +880,42 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
669
880
|
};
|
|
670
881
|
/**
|
|
671
882
|
* Auto-response rules for Aider CLI.
|
|
672
|
-
* Aider uses plain text
|
|
673
|
-
*
|
|
883
|
+
* Aider uses plain text prompts via io.py:832 with (Y)es/(N)o format.
|
|
884
|
+
* All rules are responseType: 'text' — Aider never uses TUI menus.
|
|
885
|
+
*
|
|
886
|
+
* Decline rules come first to override the generic accept patterns.
|
|
674
887
|
*/
|
|
675
888
|
autoResponseRules = [
|
|
889
|
+
// ── Decline rules (specific, checked first) ────────────────────────
|
|
890
|
+
{
|
|
891
|
+
pattern: /allow collection of anonymous analytics/i,
|
|
892
|
+
type: "config",
|
|
893
|
+
response: "n",
|
|
894
|
+
responseType: "text",
|
|
895
|
+
description: "Decline Aider telemetry opt-in",
|
|
896
|
+
safe: true,
|
|
897
|
+
once: true
|
|
898
|
+
},
|
|
676
899
|
{
|
|
677
|
-
pattern: /
|
|
900
|
+
pattern: /would you like to see what.?s new in this version/i,
|
|
901
|
+
type: "config",
|
|
902
|
+
response: "n",
|
|
903
|
+
responseType: "text",
|
|
904
|
+
description: "Decline release notes offer",
|
|
905
|
+
safe: true,
|
|
906
|
+
once: true
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
pattern: /open a github issue pre-filled/i,
|
|
910
|
+
type: "config",
|
|
911
|
+
response: "n",
|
|
912
|
+
responseType: "text",
|
|
913
|
+
description: "Decline automatic bug report",
|
|
914
|
+
safe: true
|
|
915
|
+
},
|
|
916
|
+
// ── File / edit operations ──────────────────────────────────────────
|
|
917
|
+
{
|
|
918
|
+
pattern: /add .+ to the chat\?/i,
|
|
678
919
|
type: "permission",
|
|
679
920
|
response: "y",
|
|
680
921
|
responseType: "text",
|
|
@@ -682,7 +923,15 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
682
923
|
safe: true
|
|
683
924
|
},
|
|
684
925
|
{
|
|
685
|
-
pattern: /
|
|
926
|
+
pattern: /add url to the chat\?/i,
|
|
927
|
+
type: "permission",
|
|
928
|
+
response: "y",
|
|
929
|
+
responseType: "text",
|
|
930
|
+
description: "Allow Aider to add URL content to chat",
|
|
931
|
+
safe: true
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
pattern: /create new file\?/i,
|
|
686
935
|
type: "permission",
|
|
687
936
|
response: "y",
|
|
688
937
|
responseType: "text",
|
|
@@ -690,11 +939,96 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
690
939
|
safe: true
|
|
691
940
|
},
|
|
692
941
|
{
|
|
693
|
-
pattern: /
|
|
942
|
+
pattern: /allow edits to file/i,
|
|
943
|
+
type: "permission",
|
|
944
|
+
response: "y",
|
|
945
|
+
responseType: "text",
|
|
946
|
+
description: "Allow edits to file not yet in chat",
|
|
947
|
+
safe: true
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
pattern: /edit the files\?/i,
|
|
694
951
|
type: "permission",
|
|
695
952
|
response: "y",
|
|
696
953
|
responseType: "text",
|
|
697
|
-
description: "
|
|
954
|
+
description: "Accept architect mode edits",
|
|
955
|
+
safe: true
|
|
956
|
+
},
|
|
957
|
+
// ── Shell operations ────────────────────────────────────────────────
|
|
958
|
+
{
|
|
959
|
+
pattern: /run shell commands?\?/i,
|
|
960
|
+
type: "permission",
|
|
961
|
+
response: "y",
|
|
962
|
+
responseType: "text",
|
|
963
|
+
description: "Allow Aider to run shell commands",
|
|
964
|
+
safe: true
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
pattern: /add command output to the chat\?/i,
|
|
968
|
+
type: "permission",
|
|
969
|
+
response: "y",
|
|
970
|
+
responseType: "text",
|
|
971
|
+
description: "Add shell command output to chat context",
|
|
972
|
+
safe: true
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
pattern: /add \d+.*tokens of command output to the chat\?/i,
|
|
976
|
+
type: "permission",
|
|
977
|
+
response: "y",
|
|
978
|
+
responseType: "text",
|
|
979
|
+
description: "Add /run command output to chat context",
|
|
980
|
+
safe: true
|
|
981
|
+
},
|
|
982
|
+
// ── Setup / maintenance ─────────────────────────────────────────────
|
|
983
|
+
{
|
|
984
|
+
pattern: /no git repo found.*create one/i,
|
|
985
|
+
type: "config",
|
|
986
|
+
response: "y",
|
|
987
|
+
responseType: "text",
|
|
988
|
+
description: "Create git repo for change tracking",
|
|
989
|
+
safe: true,
|
|
990
|
+
once: true
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
pattern: /add .+ to \.gitignore/i,
|
|
994
|
+
type: "config",
|
|
995
|
+
response: "y",
|
|
996
|
+
responseType: "text",
|
|
997
|
+
description: "Update .gitignore with Aider patterns",
|
|
998
|
+
safe: true,
|
|
999
|
+
once: true
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
pattern: /run pip install\?/i,
|
|
1003
|
+
type: "config",
|
|
1004
|
+
response: "y",
|
|
1005
|
+
responseType: "text",
|
|
1006
|
+
description: "Install missing Python dependencies",
|
|
1007
|
+
safe: true
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
pattern: /install playwright\?/i,
|
|
1011
|
+
type: "config",
|
|
1012
|
+
response: "y",
|
|
1013
|
+
responseType: "text",
|
|
1014
|
+
description: "Install Playwright for web scraping",
|
|
1015
|
+
safe: true
|
|
1016
|
+
},
|
|
1017
|
+
// ── Other safe confirmations ────────────────────────────────────────
|
|
1018
|
+
{
|
|
1019
|
+
pattern: /fix lint errors in/i,
|
|
1020
|
+
type: "permission",
|
|
1021
|
+
response: "y",
|
|
1022
|
+
responseType: "text",
|
|
1023
|
+
description: "Accept lint error fix suggestion",
|
|
1024
|
+
safe: true
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
pattern: /try to proceed anyway\?/i,
|
|
1028
|
+
type: "config",
|
|
1029
|
+
response: "y",
|
|
1030
|
+
responseType: "text",
|
|
1031
|
+
description: "Continue despite context limit warning",
|
|
698
1032
|
safe: true
|
|
699
1033
|
}
|
|
700
1034
|
];
|
|
@@ -774,8 +1108,28 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
774
1108
|
instructions: "API key is invalid - please check your credentials"
|
|
775
1109
|
};
|
|
776
1110
|
}
|
|
1111
|
+
if (/login to openrouter or create a free account/i.test(stripped)) {
|
|
1112
|
+
return {
|
|
1113
|
+
required: true,
|
|
1114
|
+
type: "oauth",
|
|
1115
|
+
instructions: "Aider offering OpenRouter OAuth login \u2014 provide API keys to skip"
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
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)) {
|
|
1119
|
+
const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
|
|
1120
|
+
return {
|
|
1121
|
+
required: true,
|
|
1122
|
+
type: "browser",
|
|
1123
|
+
url: urlMatch ? urlMatch[0] : void 0,
|
|
1124
|
+
instructions: "Complete OpenRouter authentication in browser"
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
777
1127
|
return { required: false };
|
|
778
1128
|
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Detect blocking prompts specific to Aider CLI.
|
|
1131
|
+
* Source: io.py, onboarding.py, base_coder.py, report.py
|
|
1132
|
+
*/
|
|
779
1133
|
detectBlockingPrompt(output) {
|
|
780
1134
|
const stripped = this.stripAnsi(output);
|
|
781
1135
|
const loginDetection = this.detectLogin(output);
|
|
@@ -784,6 +1138,7 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
784
1138
|
detected: true,
|
|
785
1139
|
type: "login",
|
|
786
1140
|
prompt: loginDetection.instructions,
|
|
1141
|
+
url: loginDetection.url,
|
|
787
1142
|
canAutoRespond: false,
|
|
788
1143
|
instructions: loginDetection.instructions
|
|
789
1144
|
};
|
|
@@ -797,16 +1152,16 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
797
1152
|
instructions: "Please select a model or set AIDER_MODEL env var"
|
|
798
1153
|
};
|
|
799
1154
|
}
|
|
800
|
-
if (/
|
|
1155
|
+
if (/please answer with one of:/i.test(stripped)) {
|
|
801
1156
|
return {
|
|
802
1157
|
detected: true,
|
|
803
|
-
type: "
|
|
804
|
-
prompt: "
|
|
1158
|
+
type: "unknown",
|
|
1159
|
+
prompt: "Invalid confirmation input",
|
|
805
1160
|
canAutoRespond: false,
|
|
806
|
-
instructions: "Aider
|
|
1161
|
+
instructions: "Aider received an invalid response to a confirmation prompt"
|
|
807
1162
|
};
|
|
808
1163
|
}
|
|
809
|
-
if (/delete|remove|overwrite/i.test(stripped) && /\[y\/n\]/i.test(stripped)) {
|
|
1164
|
+
if (/delete|remove|overwrite/i.test(stripped) && (/\[y\/n\]/i.test(stripped) || /\(Y\)es\/\(N\)o/i.test(stripped))) {
|
|
810
1165
|
return {
|
|
811
1166
|
detected: true,
|
|
812
1167
|
type: "permission",
|
|
@@ -820,9 +1175,22 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
820
1175
|
}
|
|
821
1176
|
detectReady(output) {
|
|
822
1177
|
const stripped = this.stripAnsi(output);
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1178
|
+
if (/login to openrouter/i.test(stripped) || /open this url in your browser/i.test(stripped) || /waiting up to 5 minutes/i.test(stripped)) {
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
if (/(?:ask|code|architect|help)(?:\s+multi)?>\s*$/m.test(stripped) || /^multi>\s*$/m.test(stripped)) {
|
|
1182
|
+
return true;
|
|
1183
|
+
}
|
|
1184
|
+
if (/^Aider v\d+/m.test(stripped)) {
|
|
1185
|
+
return true;
|
|
1186
|
+
}
|
|
1187
|
+
if (/^(?:Readonly|Editable):/m.test(stripped)) {
|
|
1188
|
+
return true;
|
|
1189
|
+
}
|
|
1190
|
+
return (
|
|
1191
|
+
// Legacy prompt patterns
|
|
1192
|
+
stripped.includes("aider>") || /Added.*to the chat/i.test(stripped) || />\s*$/.test(stripped)
|
|
1193
|
+
);
|
|
826
1194
|
}
|
|
827
1195
|
parseOutput(output) {
|
|
828
1196
|
const stripped = this.stripAnsi(output);
|
|
@@ -843,8 +1211,26 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
843
1211
|
}
|
|
844
1212
|
};
|
|
845
1213
|
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Detect exit conditions specific to Aider.
|
|
1216
|
+
* Source: base_coder.py:994, base_coder.py:998, report.py:77, versioncheck.py:58
|
|
1217
|
+
*/
|
|
1218
|
+
detectExit(output) {
|
|
1219
|
+
const stripped = this.stripAnsi(output);
|
|
1220
|
+
if (/\^C again to exit/i.test(stripped) || /\^C KeyboardInterrupt/i.test(stripped)) {
|
|
1221
|
+
return { exited: true, code: 130 };
|
|
1222
|
+
}
|
|
1223
|
+
if (/re-run aider to use new version/i.test(stripped)) {
|
|
1224
|
+
return {
|
|
1225
|
+
exited: true,
|
|
1226
|
+
code: 0,
|
|
1227
|
+
error: "Aider updated \u2014 restart required"
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
return super.detectExit(output);
|
|
1231
|
+
}
|
|
846
1232
|
getPromptPattern() {
|
|
847
|
-
return /(?:aider
|
|
1233
|
+
return /(?:ask|code|architect|help|aider|multi)(?:\s+multi)?>\s*$/i;
|
|
848
1234
|
}
|
|
849
1235
|
getHealthCheckCommand() {
|
|
850
1236
|
return "aider --version";
|