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