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