coding-agent-adapters 0.2.12 → 0.2.15

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