coding-agent-adapters 0.2.13 → 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
@@ -339,6 +339,43 @@ var GeminiAdapter = class extends BaseCodingAdapter {
339
339
  ],
340
340
  docsUrl: "https://github.com/anthropics/gemini-cli#installation"
341
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
+ ];
342
379
  getRecommendedModels(_credentials) {
343
380
  return {
344
381
  powerful: "gemini-3-pro",
@@ -383,6 +420,27 @@ var GeminiAdapter = class extends BaseCodingAdapter {
383
420
  instructions: "Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable"
384
421
  };
385
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
+ }
386
444
  if (stripped.includes("Sign in with Google") || stripped.includes("OAuth") || stripped.includes("accounts.google.com")) {
387
445
  const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
388
446
  return {
@@ -403,7 +461,7 @@ var GeminiAdapter = class extends BaseCodingAdapter {
403
461
  }
404
462
  detectBlockingPrompt(output) {
405
463
  const stripped = this.stripAnsi(output);
406
- 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)) {
407
465
  return {
408
466
  detected: true,
409
467
  type: "permission",
@@ -424,6 +482,15 @@ var GeminiAdapter = class extends BaseCodingAdapter {
424
482
  instructions: loginDetection.instructions
425
483
  };
426
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
+ }
427
494
  if (/select.*model|choose.*model|gemini-/i.test(stripped) && /\d+\)/i.test(stripped)) {
428
495
  return {
429
496
  detected: true,
@@ -455,7 +522,16 @@ var GeminiAdapter = class extends BaseCodingAdapter {
455
522
  }
456
523
  detectReady(output) {
457
524
  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 ">"
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 ">"
459
535
  /gemini>\s*$/i.test(stripped);
460
536
  }
461
537
  parseOutput(output) {
@@ -477,6 +553,27 @@ var GeminiAdapter = class extends BaseCodingAdapter {
477
553
  }
478
554
  };
479
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
+ }
480
577
  getPromptPattern() {
481
578
  return /gemini>\s*$/i;
482
579
  }
@@ -498,11 +595,12 @@ var CodexAdapter = class extends BaseCodingAdapter {
498
595
  };
499
596
  /**
500
597
  * Auto-response rules for OpenAI Codex CLI.
501
- * 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
502
600
  */
503
601
  autoResponseRules = [
504
602
  {
505
- pattern: /Update (available|now)|Skip until next version/i,
603
+ pattern: /update.?available.*->|update.?now|skip.?until.?next.?version/i,
506
604
  type: "config",
507
605
  response: "",
508
606
  responseType: "keys",
@@ -511,14 +609,51 @@ var CodexAdapter = class extends BaseCodingAdapter {
511
609
  safe: true
512
610
  },
513
611
  {
514
- pattern: /trust.the.contents|trust.this.directory|do.you.trust/i,
612
+ pattern: /do.?you.?trust.?the.?contents|trust.?this.?directory|yes,?.?continue|prompt.?injection/i,
515
613
  type: "permission",
516
614
  response: "",
517
615
  responseType: "keys",
518
616
  keys: ["enter"],
519
- description: "Trust directory contents to allow Codex to operate",
617
+ description: 'Trust directory contents (default: "Yes, continue")',
520
618
  safe: true,
521
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",
656
+ safe: true
522
657
  }
523
658
  ];
524
659
  getRecommendedModels(_credentials) {
@@ -563,6 +698,23 @@ var CodexAdapter = class extends BaseCodingAdapter {
563
698
  instructions: "Set OPENAI_API_KEY environment variable or provide credentials in adapterConfig"
564
699
  };
565
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
+ }
566
718
  if (stripped.includes("device code") || stripped.includes("Enter the code")) {
567
719
  const codeMatch = stripped.match(/code[:\s]+([A-Z0-9-]+)/i);
568
720
  const urlMatch = stripped.match(/https?:\/\/[^\s]+/);
@@ -576,10 +728,21 @@ var CodexAdapter = class extends BaseCodingAdapter {
576
728
  return { required: false };
577
729
  }
578
730
  /**
579
- * 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
580
733
  */
581
734
  detectBlockingPrompt(output) {
582
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
+ }
583
746
  const loginDetection = this.detectLogin(output);
584
747
  if (loginDetection.required) {
585
748
  return {
@@ -591,6 +754,24 @@ var CodexAdapter = class extends BaseCodingAdapter {
591
754
  instructions: loginDetection.instructions
592
755
  };
593
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
+ }
594
775
  if (/select.*model|choose.*model|gpt-4|gpt-3\.5/i.test(stripped) && /\d+\)/i.test(stripped)) {
595
776
  return {
596
777
  detected: true,
@@ -622,7 +803,16 @@ var CodexAdapter = class extends BaseCodingAdapter {
622
803
  }
623
804
  detectReady(output) {
624
805
  const stripped = this.stripAnsi(output);
625
- 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);
626
816
  }
627
817
  parseOutput(output) {
628
818
  const stripped = this.stripAnsi(output);
@@ -642,6 +832,24 @@ var CodexAdapter = class extends BaseCodingAdapter {
642
832
  }
643
833
  };
644
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
+ }
645
853
  getPromptPattern() {
646
854
  return /(?:codex|>)\s*$/i;
647
855
  }
@@ -669,12 +877,42 @@ var AiderAdapter = class extends BaseCodingAdapter {
669
877
  };
670
878
  /**
671
879
  * 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.
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.
674
884
  */
675
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
+ },
676
896
  {
677
- pattern: /Add .+ to the chat\?.*(\[y\/n\]|\[Yes\]|\(Y\)es)/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,
678
916
  type: "permission",
679
917
  response: "y",
680
918
  responseType: "text",
@@ -682,7 +920,15 @@ var AiderAdapter = class extends BaseCodingAdapter {
682
920
  safe: true
683
921
  },
684
922
  {
685
- pattern: /Create new file.*(\[y\/n\]|\[Yes\]|\(Y\)es)/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,
686
932
  type: "permission",
687
933
  response: "y",
688
934
  responseType: "text",
@@ -690,11 +936,96 @@ var AiderAdapter = class extends BaseCodingAdapter {
690
936
  safe: true
691
937
  },
692
938
  {
693
- pattern: /Apply.*changes.*(\[y\/n\]|\[Yes\]|\(Y\)es)/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,
694
948
  type: "permission",
695
949
  response: "y",
696
950
  responseType: "text",
697
- description: "Apply proposed changes",
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,
1017
+ type: "permission",
1018
+ response: "y",
1019
+ responseType: "text",
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",
698
1029
  safe: true
699
1030
  }
700
1031
  ];
@@ -774,8 +1105,28 @@ var AiderAdapter = class extends BaseCodingAdapter {
774
1105
  instructions: "API key is invalid - please check your credentials"
775
1106
  };
776
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
+ }
777
1124
  return { required: false };
778
1125
  }
1126
+ /**
1127
+ * Detect blocking prompts specific to Aider CLI.
1128
+ * Source: io.py, onboarding.py, base_coder.py, report.py
1129
+ */
779
1130
  detectBlockingPrompt(output) {
780
1131
  const stripped = this.stripAnsi(output);
781
1132
  const loginDetection = this.detectLogin(output);
@@ -784,6 +1135,7 @@ var AiderAdapter = class extends BaseCodingAdapter {
784
1135
  detected: true,
785
1136
  type: "login",
786
1137
  prompt: loginDetection.instructions,
1138
+ url: loginDetection.url,
787
1139
  canAutoRespond: false,
788
1140
  instructions: loginDetection.instructions
789
1141
  };
@@ -797,16 +1149,16 @@ var AiderAdapter = class extends BaseCodingAdapter {
797
1149
  instructions: "Please select a model or set AIDER_MODEL env var"
798
1150
  };
799
1151
  }
800
- if (/not.*git.*repo|git.*not.*found|initialize.*git/i.test(stripped)) {
1152
+ if (/please answer with one of:/i.test(stripped)) {
801
1153
  return {
802
1154
  detected: true,
803
- type: "config",
804
- prompt: "Git repository required",
1155
+ type: "unknown",
1156
+ prompt: "Invalid confirmation input",
805
1157
  canAutoRespond: false,
806
- instructions: "Aider requires a git repository. Run git init or use --no-git"
1158
+ instructions: "Aider received an invalid response to a confirmation prompt"
807
1159
  };
808
1160
  }
809
- 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))) {
810
1162
  return {
811
1163
  detected: true,
812
1164
  type: "permission",
@@ -820,9 +1172,22 @@ var AiderAdapter = class extends BaseCodingAdapter {
820
1172
  }
821
1173
  detectReady(output) {
822
1174
  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);
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
+ );
826
1191
  }
827
1192
  parseOutput(output) {
828
1193
  const stripped = this.stripAnsi(output);
@@ -843,8 +1208,26 @@ var AiderAdapter = class extends BaseCodingAdapter {
843
1208
  }
844
1209
  };
845
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
+ }
846
1229
  getPromptPattern() {
847
- return /(?:aider>|>)\s*$/i;
1230
+ return /(?:ask|code|architect|help|aider|multi)(?:\s+multi)?>\s*$/i;
848
1231
  }
849
1232
  getHealthCheckCommand() {
850
1233
  return "aider --version";