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/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 (/Apply this change\?/i.test(stripped) || /Waiting for user confirmation/i.test(stripped)) {
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
- return stripped.includes("Ready") || stripped.includes("Type your message") || stripped.includes("How can I help") || stripped.includes("What would you like") || // Match "gemini> " prompt specifically, not bare ">"
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 TUI menus (Ink/React) rules use key sequences.
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: /Update (available|now)|Skip until next version/i,
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.the.contents|trust.this.directory|do.you.trust/i,
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: "Trust directory contents to allow Codex to operate",
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
- return stripped.includes("Codex") || stripped.includes("Ready") || stripped.includes("How can I help") || /(?:codex|>)\s*$/i.test(stripped);
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 [y/n] prompts, NOT TUI menus.
673
- * Explicit responseType: 'text' prevents the usesTuiMenus default from kicking in.
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: /Add .+ to the chat\?.*(\[y\/n\]|\[Yes\]|\(Y\)es)/i,
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: /Create new file.*(\[y\/n\]|\[Yes\]|\(Y\)es)/i,
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: /Apply.*changes.*(\[y\/n\]|\[Yes\]|\(Y\)es)/i,
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: "Apply proposed changes",
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 (/not.*git.*repo|git.*not.*found|initialize.*git/i.test(stripped)) {
1155
+ if (/please answer with one of:/i.test(stripped)) {
801
1156
  return {
802
1157
  detected: true,
803
- type: "config",
804
- prompt: "Git repository required",
1158
+ type: "unknown",
1159
+ prompt: "Invalid confirmation input",
805
1160
  canAutoRespond: false,
806
- instructions: "Aider requires a git repository. Run git init or use --no-git"
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
- return stripped.includes("aider>") || stripped.includes("Aider") || /aider.*ready/i.test(stripped) || // Aider shows file list when ready
824
- /Added.*to the chat/i.test(stripped) || // Or the prompt
825
- />\s*$/.test(stripped);
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>|>)\s*$/i;
1233
+ return /(?:ask|code|architect|help|aider|multi)(?:\s+multi)?>\s*$/i;
848
1234
  }
849
1235
  getHealthCheckCommand() {
850
1236
  return "aider --version";