@adhdev/daemon-core 0.6.53 → 0.6.55

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.
Files changed (164) hide show
  1. package/dist/index.d.ts +76 -34
  2. package/dist/index.js +714 -271
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/providers/_builtin/_helpers/index.js +26 -26
  6. package/providers/_builtin/cli/aider-cli/provider.json +37 -0
  7. package/providers/_builtin/cli/aider-cli/scripts/1.0/detect_status.js +20 -0
  8. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_approval.js +10 -0
  9. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_output.js +49 -0
  10. package/providers/_builtin/cli/aider-cli/scripts/1.0/scripts.js +7 -0
  11. package/providers/_builtin/cli/claude-cli/provider.json +9 -2
  12. package/providers/_builtin/cli/claude-cli/scripts/1.0/detect_status.js +31 -0
  13. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_approval.js +38 -0
  14. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_output.js +164 -0
  15. package/providers/_builtin/cli/claude-cli/scripts/1.0/scripts.js +42 -0
  16. package/providers/_builtin/cli/codex-cli/provider.json +9 -2
  17. package/providers/_builtin/cli/codex-cli/scripts/1.0/detect_status.js +20 -0
  18. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_approval.js +15 -0
  19. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_output.js +68 -0
  20. package/providers/_builtin/cli/codex-cli/scripts/1.0/scripts.js +11 -0
  21. package/providers/_builtin/cli/cursor-cli/provider.json +37 -0
  22. package/providers/_builtin/cli/cursor-cli/scripts/1.0/detect_status.js +19 -0
  23. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_approval.js +10 -0
  24. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_output.js +48 -0
  25. package/providers/_builtin/cli/cursor-cli/scripts/1.0/scripts.js +7 -0
  26. package/providers/_builtin/cli/gemini-cli/provider.json +9 -2
  27. package/providers/_builtin/cli/gemini-cli/scripts/1.0/detect_status.js +26 -0
  28. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_approval.js +22 -0
  29. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_output.js +71 -0
  30. package/providers/_builtin/cli/gemini-cli/scripts/1.0/scripts.js +12 -0
  31. package/providers/_builtin/cli/github-copilot-cli/provider.json +37 -0
  32. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/detect_status.js +19 -0
  33. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_approval.js +9 -0
  34. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_output.js +48 -0
  35. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/scripts.js +7 -0
  36. package/providers/_builtin/cli/goose-cli/provider.json +37 -0
  37. package/providers/_builtin/cli/goose-cli/scripts/1.0/detect_status.js +20 -0
  38. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_approval.js +10 -0
  39. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_output.js +48 -0
  40. package/providers/_builtin/cli/goose-cli/scripts/1.0/scripts.js +7 -0
  41. package/providers/_builtin/cli/opencode-cli/provider.json +37 -0
  42. package/providers/_builtin/cli/opencode-cli/scripts/1.0/detect_status.js +15 -0
  43. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_approval.js +9 -0
  44. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_output.js +48 -0
  45. package/providers/_builtin/cli/opencode-cli/scripts/1.0/scripts.js +7 -0
  46. package/providers/_builtin/extension/cline/scripts/1.0/focus_editor.js +5 -5
  47. package/providers/_builtin/extension/cline/scripts/1.0/list_chats.js +11 -11
  48. package/providers/_builtin/extension/cline/scripts/1.0/list_models.js +6 -6
  49. package/providers/_builtin/extension/cline/scripts/1.0/list_modes.js +5 -5
  50. package/providers/_builtin/extension/cline/scripts/1.0/new_session.js +12 -12
  51. package/providers/_builtin/extension/cline/scripts/1.0/open_panel.js +7 -7
  52. package/providers/_builtin/extension/cline/scripts/1.0/read_chat.js +29 -29
  53. package/providers/_builtin/extension/cline/scripts/1.0/resolve_action.js +19 -19
  54. package/providers/_builtin/extension/cline/scripts/1.0/send_message.js +15 -15
  55. package/providers/_builtin/extension/cline/scripts/1.0/set_mode.js +4 -4
  56. package/providers/_builtin/extension/cline/scripts/1.0/set_model.js +4 -4
  57. package/providers/_builtin/extension/cline/scripts/1.0/switch_session.js +21 -21
  58. package/providers/_builtin/extension/codex/scripts/1.0/explore_controls_webview.js +2 -2
  59. package/providers/_builtin/extension/codex/scripts/1.0/list_models.js +1 -1
  60. package/providers/_builtin/extension/codex/scripts/1.0/list_modes.js +1 -1
  61. package/providers/_builtin/extension/codex/scripts/1.0/new_session.js +2 -2
  62. package/providers/_builtin/extension/codex/scripts/1.0/read_chat.js +6 -6
  63. package/providers/_builtin/extension/codex/scripts/1.0/resolve_action.js +3 -3
  64. package/providers/_builtin/extension/codex/scripts/1.0/set_model.js +1 -1
  65. package/providers/_builtin/ide/antigravity/scripts/1.0/focus_editor.js +2 -2
  66. package/providers/_builtin/ide/antigravity/scripts/1.0/list_chats.js +19 -19
  67. package/providers/_builtin/ide/antigravity/scripts/1.0/list_models.js +1 -1
  68. package/providers/_builtin/ide/antigravity/scripts/1.0/list_modes.js +1 -1
  69. package/providers/_builtin/ide/antigravity/scripts/1.0/new_session.js +17 -17
  70. package/providers/_builtin/ide/antigravity/scripts/1.0/read_chat.js +41 -41
  71. package/providers/_builtin/ide/antigravity/scripts/1.0/resolve_action.js +6 -6
  72. package/providers/_builtin/ide/antigravity/scripts/1.0/send_message.js +13 -13
  73. package/providers/_builtin/ide/antigravity/scripts/1.0/set_model.js +1 -1
  74. package/providers/_builtin/ide/antigravity/scripts/1.0/switch_session.js +13 -13
  75. package/providers/_builtin/ide/cursor/scripts/1.0/dismiss_notification.js +3 -3
  76. package/providers/_builtin/ide/cursor/scripts/1.0/focus_editor.js +1 -1
  77. package/providers/_builtin/ide/cursor/scripts/1.0/list_models.js +12 -12
  78. package/providers/_builtin/ide/cursor/scripts/1.0/list_modes.js +5 -5
  79. package/providers/_builtin/ide/cursor/scripts/1.0/list_notifications.js +2 -2
  80. package/providers/_builtin/ide/cursor/scripts/1.0/list_sessions.js +5 -5
  81. package/providers/_builtin/ide/cursor/scripts/1.0/new_session.js +1 -1
  82. package/providers/_builtin/ide/cursor/scripts/1.0/open_panel.js +3 -3
  83. package/providers/_builtin/ide/cursor/scripts/1.0/read_chat.js +9 -9
  84. package/providers/_builtin/ide/cursor/scripts/1.0/resolve_action.js +4 -4
  85. package/providers/_builtin/ide/cursor/scripts/1.0/send_message.js +5 -5
  86. package/providers/_builtin/ide/cursor/scripts/1.0/set_mode.js +4 -4
  87. package/providers/_builtin/ide/cursor/scripts/1.0/set_model.js +12 -12
  88. package/providers/_builtin/ide/cursor/scripts/1.0/switch_session.js +2 -2
  89. package/providers/_builtin/ide/kiro/scripts/1.0/focus_editor.js +2 -2
  90. package/providers/_builtin/ide/kiro/scripts/1.0/open_panel.js +7 -7
  91. package/providers/_builtin/ide/kiro/scripts/1.0/resolve_action.js +3 -3
  92. package/providers/_builtin/ide/kiro/scripts/1.0/send_message.js +4 -4
  93. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_sessions.js +2 -2
  94. package/providers/_builtin/ide/kiro/scripts/1.0/webview_new_session.js +5 -5
  95. package/providers/_builtin/ide/kiro/scripts/1.0/webview_read_chat.js +13 -13
  96. package/providers/_builtin/ide/kiro/scripts/1.0/webview_resolve_action.js +1 -1
  97. package/providers/_builtin/ide/kiro/scripts/1.0/webview_send_message.js +8 -8
  98. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_mode.js +1 -1
  99. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_model.js +1 -1
  100. package/providers/_builtin/ide/kiro/scripts/1.0/webview_switch_session.js +3 -3
  101. package/providers/_builtin/ide/pearai/.tmp/after_rich.json +157 -0
  102. package/providers/_builtin/ide/pearai/.tmp/after_rich_raw.json +161 -0
  103. package/providers/_builtin/ide/pearai/.tmp/after_switch.json +592 -0
  104. package/providers/_builtin/ide/pearai/.tmp/after_switch_raw.json +596 -0
  105. package/providers/_builtin/ide/pearai/.tmp/home_dump_raw.json +176 -0
  106. package/providers/_builtin/ide/pearai/.tmp/items_raw.json +778 -0
  107. package/providers/_builtin/ide/pearai/.tmp/webview_dump.json +157 -0
  108. package/providers/_builtin/ide/pearai/.tmp/webview_dump_raw.json +161 -0
  109. package/providers/_builtin/ide/pearai/provider.json +1 -3
  110. package/providers/_builtin/ide/pearai/scripts/1.0/focus_editor.js +12 -16
  111. package/providers/_builtin/ide/pearai/scripts/1.0/list_models.js +45 -0
  112. package/providers/_builtin/ide/pearai/scripts/1.0/list_modes.js +44 -0
  113. package/providers/_builtin/ide/pearai/scripts/1.0/list_sessions.js +82 -27
  114. package/providers/_builtin/ide/pearai/scripts/1.0/new_session.js +26 -43
  115. package/providers/_builtin/ide/pearai/scripts/1.0/open_panel.js +10 -33
  116. package/providers/_builtin/ide/pearai/scripts/1.0/read_chat.js +169 -0
  117. package/providers/_builtin/ide/pearai/scripts/1.0/resolve_action.js +47 -41
  118. package/providers/_builtin/ide/pearai/scripts/1.0/scripts.js +36 -7
  119. package/providers/_builtin/ide/pearai/scripts/1.0/send_message.js +97 -22
  120. package/providers/_builtin/ide/pearai/scripts/1.0/set_mode.js +51 -0
  121. package/providers/_builtin/ide/pearai/scripts/1.0/set_model.js +54 -0
  122. package/providers/_builtin/ide/pearai/scripts/1.0/switch_session.js +81 -0
  123. package/providers/_builtin/ide/trae/scripts/1.0/focus_editor.js +2 -2
  124. package/providers/_builtin/ide/trae/scripts/1.0/list_chats.js +2 -2
  125. package/providers/_builtin/ide/trae/scripts/1.0/new_session.js +4 -4
  126. package/providers/_builtin/ide/trae/scripts/1.0/open_panel.js +6 -6
  127. package/providers/_builtin/ide/trae/scripts/1.0/read_chat.js +13 -13
  128. package/providers/_builtin/ide/trae/scripts/1.0/resolve_action.js +3 -3
  129. package/providers/_builtin/ide/trae/scripts/1.0/send_message.js +11 -11
  130. package/providers/_builtin/ide/trae/scripts/1.0/switch_session.js +2 -2
  131. package/providers/_builtin/ide/windsurf/scripts/1.0/focus_editor.js +6 -6
  132. package/providers/_builtin/ide/windsurf/scripts/1.0/list_chats.js +4 -4
  133. package/providers/_builtin/ide/windsurf/scripts/1.0/list_sessions.js +6 -6
  134. package/providers/_builtin/ide/windsurf/scripts/1.0/new_session.js +9 -9
  135. package/providers/_builtin/ide/windsurf/scripts/1.0/open_panel.js +6 -6
  136. package/providers/_builtin/ide/windsurf/scripts/1.0/resolve_action.js +8 -8
  137. package/providers/_builtin/ide/windsurf/scripts/1.0/switch_session.js +8 -8
  138. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/focus_editor.js +6 -6
  139. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_chats.js +12 -12
  140. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/new_session.js +15 -15
  141. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/open_panel.js +10 -10
  142. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/read_chat.js +33 -33
  143. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/resolve_action.js +6 -6
  144. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/send_message.js +16 -16
  145. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/switch_session.js +7 -7
  146. package/providers/_builtin/registry.json +76 -3
  147. package/src/cli-adapters/provider-cli-adapter.ts +267 -251
  148. package/src/cli-adapters/terminal-screen.ts +268 -0
  149. package/src/commands/chat-commands.ts +41 -15
  150. package/src/commands/cli-manager.ts +4 -2
  151. package/src/daemon/dev-server.ts +245 -35
  152. package/src/providers/acp-provider-instance.ts +1 -1
  153. package/src/providers/cli-provider-instance.ts +21 -8
  154. package/src/providers/provider-loader.ts +3 -2
  155. package/providers/_builtin/ide/pearai/scripts/1.0/webview_list_models.js +0 -43
  156. package/providers/_builtin/ide/pearai/scripts/1.0/webview_list_modes.js +0 -35
  157. package/providers/_builtin/ide/pearai/scripts/1.0/webview_list_sessions.js +0 -62
  158. package/providers/_builtin/ide/pearai/scripts/1.0/webview_new_session.js +0 -49
  159. package/providers/_builtin/ide/pearai/scripts/1.0/webview_read_chat.js +0 -92
  160. package/providers/_builtin/ide/pearai/scripts/1.0/webview_resolve_action.js +0 -59
  161. package/providers/_builtin/ide/pearai/scripts/1.0/webview_send_message.js +0 -72
  162. package/providers/_builtin/ide/pearai/scripts/1.0/webview_set_mode.js +0 -36
  163. package/providers/_builtin/ide/pearai/scripts/1.0/webview_set_model.js +0 -36
  164. package/providers/_builtin/ide/pearai/scripts/1.0/webview_switch_session.js +0 -34
package/dist/index.js CHANGED
@@ -591,6 +591,246 @@ var init_logger = __esm({
591
591
  }
592
592
  });
593
593
 
594
+ // src/cli-adapters/terminal-screen.ts
595
+ function clamp(value, min, max) {
596
+ return Math.max(min, Math.min(max, value));
597
+ }
598
+ var TerminalScreen;
599
+ var init_terminal_screen = __esm({
600
+ "src/cli-adapters/terminal-screen.ts"() {
601
+ "use strict";
602
+ TerminalScreen = class {
603
+ rows;
604
+ cols;
605
+ cursorRow = 0;
606
+ cursorCol = 0;
607
+ savedRow = 0;
608
+ savedCol = 0;
609
+ lines;
610
+ constructor(rows = 40, cols = 120) {
611
+ this.rows = rows;
612
+ this.cols = cols;
613
+ this.lines = this.makeLines(rows, cols);
614
+ }
615
+ reset(rows = this.rows, cols = this.cols) {
616
+ this.rows = rows;
617
+ this.cols = cols;
618
+ this.cursorRow = 0;
619
+ this.cursorCol = 0;
620
+ this.savedRow = 0;
621
+ this.savedCol = 0;
622
+ this.lines = this.makeLines(rows, cols);
623
+ }
624
+ resize(rows, cols) {
625
+ const nextRows = Math.max(1, rows | 0);
626
+ const nextCols = Math.max(1, cols | 0);
627
+ const next = this.makeLines(nextRows, nextCols);
628
+ const copyRows = Math.min(this.rows, nextRows);
629
+ const copyCols = Math.min(this.cols, nextCols);
630
+ for (let r = 0; r < copyRows; r++) {
631
+ for (let c = 0; c < copyCols; c++) {
632
+ next[r][c] = this.lines[r][c];
633
+ }
634
+ }
635
+ this.rows = nextRows;
636
+ this.cols = nextCols;
637
+ this.lines = next;
638
+ this.cursorRow = clamp(this.cursorRow, 0, this.rows - 1);
639
+ this.cursorCol = clamp(this.cursorCol, 0, this.cols - 1);
640
+ this.savedRow = clamp(this.savedRow, 0, this.rows - 1);
641
+ this.savedCol = clamp(this.savedCol, 0, this.cols - 1);
642
+ }
643
+ write(data) {
644
+ let i = 0;
645
+ while (i < data.length) {
646
+ const ch = data[i];
647
+ if (ch === "\x1B") {
648
+ const consumed = this.consumeEscape(data, i);
649
+ i = consumed > i ? consumed : i + 1;
650
+ continue;
651
+ }
652
+ if (ch === "\r") {
653
+ this.cursorCol = 0;
654
+ i++;
655
+ continue;
656
+ }
657
+ if (ch === "\n") {
658
+ this.newLine();
659
+ i++;
660
+ continue;
661
+ }
662
+ if (ch === "\b") {
663
+ this.cursorCol = Math.max(0, this.cursorCol - 1);
664
+ i++;
665
+ continue;
666
+ }
667
+ if (ch === " ") {
668
+ const nextStop = Math.min(this.cols - 1, this.cursorCol + (8 - (this.cursorCol % 8 || 8)));
669
+ while (this.cursorCol < nextStop) this.putChar(" ");
670
+ i++;
671
+ continue;
672
+ }
673
+ if (ch >= " " && ch !== "\x7F") {
674
+ this.putChar(ch);
675
+ }
676
+ i++;
677
+ }
678
+ }
679
+ getText() {
680
+ const raw = this.lines.map((line) => line.join("").replace(/\s+$/, ""));
681
+ let start = 0;
682
+ let end = raw.length;
683
+ while (start < end && raw[start] === "") start++;
684
+ while (end > start && raw[end - 1] === "") end--;
685
+ return raw.slice(start, end).join("\n");
686
+ }
687
+ consumeEscape(data, start) {
688
+ const next = data[start + 1];
689
+ if (!next) return start + 1;
690
+ if (next === "[") {
691
+ let end = start + 2;
692
+ while (end < data.length && !/[@-~]/.test(data[end])) end++;
693
+ if (end >= data.length) return data.length;
694
+ this.applyCsi(data.slice(start + 2, end), data[end]);
695
+ return end + 1;
696
+ }
697
+ if (next === "]") {
698
+ let end = start + 2;
699
+ while (end < data.length) {
700
+ if (data[end] === "\x07") return end + 1;
701
+ if (data[end] === "\x1B" && data[end + 1] === "\\") return end + 2;
702
+ end++;
703
+ }
704
+ return data.length;
705
+ }
706
+ if (next === "7") {
707
+ this.savedRow = this.cursorRow;
708
+ this.savedCol = this.cursorCol;
709
+ return start + 2;
710
+ }
711
+ if (next === "8") {
712
+ this.cursorRow = this.savedRow;
713
+ this.cursorCol = this.savedCol;
714
+ return start + 2;
715
+ }
716
+ return start + 2;
717
+ }
718
+ applyCsi(paramText, finalChar) {
719
+ const privateMode = paramText.startsWith("?");
720
+ const normalized = privateMode ? paramText.slice(1) : paramText;
721
+ const params = normalized.length > 0 ? normalized.split(";").map((p) => parseInt(p || "0", 10) || 0) : [0];
722
+ switch (finalChar) {
723
+ case "A":
724
+ this.cursorRow = clamp(this.cursorRow - (params[0] || 1), 0, this.rows - 1);
725
+ return;
726
+ case "B":
727
+ this.cursorRow = clamp(this.cursorRow + (params[0] || 1), 0, this.rows - 1);
728
+ return;
729
+ case "C":
730
+ this.cursorCol = clamp(this.cursorCol + (params[0] || 1), 0, this.cols - 1);
731
+ return;
732
+ case "D":
733
+ this.cursorCol = clamp(this.cursorCol - (params[0] || 1), 0, this.cols - 1);
734
+ return;
735
+ case "E":
736
+ this.cursorRow = clamp(this.cursorRow + (params[0] || 1), 0, this.rows - 1);
737
+ this.cursorCol = 0;
738
+ return;
739
+ case "F":
740
+ this.cursorRow = clamp(this.cursorRow - (params[0] || 1), 0, this.rows - 1);
741
+ this.cursorCol = 0;
742
+ return;
743
+ case "G":
744
+ this.cursorCol = clamp((params[0] || 1) - 1, 0, this.cols - 1);
745
+ return;
746
+ case "H":
747
+ case "f": {
748
+ const row = (params[0] || 1) - 1;
749
+ const col = (params[1] || 1) - 1;
750
+ this.cursorRow = clamp(row, 0, this.rows - 1);
751
+ this.cursorCol = clamp(col, 0, this.cols - 1);
752
+ return;
753
+ }
754
+ case "J": {
755
+ const mode = params[0] || 0;
756
+ if (mode === 2 || mode === 3) {
757
+ this.reset(this.rows, this.cols);
758
+ } else if (mode === 0) {
759
+ this.clearToEndOfScreen();
760
+ } else if (mode === 1) {
761
+ this.clearToStartOfScreen();
762
+ }
763
+ return;
764
+ }
765
+ case "K": {
766
+ const mode = params[0] || 0;
767
+ if (mode === 2) this.clearLine(this.cursorRow, 0, this.cols - 1);
768
+ else if (mode === 1) this.clearLine(this.cursorRow, 0, this.cursorCol);
769
+ else this.clearLine(this.cursorRow, this.cursorCol, this.cols - 1);
770
+ return;
771
+ }
772
+ case "m":
773
+ return;
774
+ case "s":
775
+ this.savedRow = this.cursorRow;
776
+ this.savedCol = this.cursorCol;
777
+ return;
778
+ case "u":
779
+ this.cursorRow = this.savedRow;
780
+ this.cursorCol = this.savedCol;
781
+ return;
782
+ case "h":
783
+ case "l":
784
+ if (privateMode && (normalized === "1049" || normalized === "47")) {
785
+ this.reset(this.rows, this.cols);
786
+ }
787
+ return;
788
+ default:
789
+ return;
790
+ }
791
+ }
792
+ putChar(ch) {
793
+ if (this.cursorRow < 0 || this.cursorRow >= this.rows) return;
794
+ if (this.cursorCol < 0) this.cursorCol = 0;
795
+ if (this.cursorCol >= this.cols) this.newLine();
796
+ this.lines[this.cursorRow][this.cursorCol] = ch;
797
+ this.cursorCol++;
798
+ if (this.cursorCol >= this.cols) this.newLine();
799
+ }
800
+ newLine() {
801
+ this.cursorCol = 0;
802
+ if (this.cursorRow >= this.rows - 1) {
803
+ this.lines.shift();
804
+ this.lines.push(Array.from({ length: this.cols }, () => " "));
805
+ } else {
806
+ this.cursorRow++;
807
+ }
808
+ }
809
+ clearLine(row, start, end) {
810
+ if (row < 0 || row >= this.rows) return;
811
+ for (let c = clamp(start, 0, this.cols - 1); c <= clamp(end, 0, this.cols - 1); c++) {
812
+ this.lines[row][c] = " ";
813
+ }
814
+ }
815
+ clearToEndOfScreen() {
816
+ this.clearLine(this.cursorRow, this.cursorCol, this.cols - 1);
817
+ for (let r = this.cursorRow + 1; r < this.rows; r++) {
818
+ this.clearLine(r, 0, this.cols - 1);
819
+ }
820
+ }
821
+ clearToStartOfScreen() {
822
+ for (let r = 0; r < this.cursorRow; r++) {
823
+ this.clearLine(r, 0, this.cols - 1);
824
+ }
825
+ this.clearLine(this.cursorRow, 0, this.cursorCol);
826
+ }
827
+ makeLines(rows, cols) {
828
+ return Array.from({ length: rows }, () => Array.from({ length: cols }, () => " "));
829
+ }
830
+ };
831
+ }
832
+ });
833
+
594
834
  // src/cli-adapters/provider-cli-adapter.ts
595
835
  var provider_cli_adapter_exports = {};
596
836
  __export(provider_cli_adapter_exports, {
@@ -663,28 +903,19 @@ function parsePatternEntry(x) {
663
903
  }
664
904
  return null;
665
905
  }
666
- function coercePatternArray(raw, fallbacks) {
667
- if (!Array.isArray(raw)) return [...fallbacks];
668
- const parsed = raw.map(parsePatternEntry).filter((r) => r != null);
669
- return parsed.length > 0 ? parsed : [...fallbacks];
670
- }
671
- function defaultCleanOutput(raw, _lastUserInput) {
672
- return stripAnsi(raw).trim();
906
+ function coercePatternArray(raw) {
907
+ if (!Array.isArray(raw)) return [];
908
+ return raw.map(parsePatternEntry).filter((r) => r != null);
673
909
  }
674
910
  function normalizeCliProviderForRuntime(raw) {
675
911
  const patterns = raw?.patterns || {};
676
912
  return {
677
- ...raw,
678
913
  patterns: {
679
- prompt: coercePatternArray(patterns.prompt, FALLBACK_PROMPT),
680
- generating: coercePatternArray(patterns.generating, FALLBACK_GENERATING),
681
- approval: coercePatternArray(patterns.approval, FALLBACK_APPROVAL),
682
- ready: coercePatternArray(patterns.ready, [])
683
- },
684
- cleanOutput: typeof raw?.cleanOutput === "function" ? raw.cleanOutput : defaultCleanOutput
914
+ approval: coercePatternArray(patterns.approval)
915
+ }
685
916
  };
686
917
  }
687
- var os11, path9, import_child_process5, pty, FALLBACK_PROMPT, FALLBACK_GENERATING, FALLBACK_APPROVAL, ProviderCliAdapter;
918
+ var os11, path9, import_child_process5, pty, ProviderCliAdapter;
688
919
  var init_provider_cli_adapter = __esm({
689
920
  "src/cli-adapters/provider-cli-adapter.ts"() {
690
921
  "use strict";
@@ -692,6 +923,7 @@ var init_provider_cli_adapter = __esm({
692
923
  path9 = __toESM(require("path"));
693
924
  import_child_process5 = require("child_process");
694
925
  init_logger();
926
+ init_terminal_screen();
695
927
  try {
696
928
  pty = require("node-pty");
697
929
  if (os11.platform() !== "win32") {
@@ -713,40 +945,10 @@ var init_provider_cli_adapter = __esm({
713
945
  } catch {
714
946
  LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
715
947
  }
716
- FALLBACK_PROMPT = [
717
- /Type your message/i,
718
- /for\s*shortcuts/i,
719
- // Claude Code prompt
720
- /\?\s*for\s*help/i,
721
- // Claude Code help prompt
722
- /Press enter/i,
723
- /^[>›❯]\s*$/i,
724
- // Prompt char as the complete evaluated string
725
- /[>›❯]\s*$/
726
- // Prompt char at the very end of evaluated string
727
- ];
728
- FALLBACK_GENERATING = [
729
- /[\u2800-\u28ff]/,
730
- // Braille spinner blocks (universal TUI)
731
- /esc to (cancel|interrupt|stop)/i,
732
- // Common TUI generation status line
733
- /generating\.\.\./i,
734
- /Claude is (?:thinking|processing|working)/i
735
- // Specific Claude Code status
736
- ];
737
- FALLBACK_APPROVAL = [
738
- /Allow\s*once/i,
739
- // ANSI strip may remove spaces
740
- /Always\s*allow/i,
741
- /\(y\/n\)/i,
742
- /\[Y\/n\]/i,
743
- /Yes,?\s*don'?t\s*ask/i
744
- // "Yes, don't ask again" (Claude Code)
745
- ];
746
- ProviderCliAdapter = class {
948
+ ProviderCliAdapter = class _ProviderCliAdapter {
747
949
  constructor(provider, workingDir, extraArgs = []) {
748
950
  this.extraArgs = extraArgs;
749
- this.provider = normalizeCliProviderForRuntime(provider);
951
+ this.provider = provider;
750
952
  this.cliType = provider.type;
751
953
  this.cliName = provider.name;
752
954
  this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os11.homedir()) : workingDir;
@@ -763,6 +965,13 @@ var init_provider_cli_adapter = __esm({
763
965
  };
764
966
  const rawKeys = provider.approvalKeys;
765
967
  this.approvalKeys = rawKeys && typeof rawKeys === "object" ? rawKeys : {};
968
+ this.cliScripts = provider.scripts || {};
969
+ const scriptNames = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
970
+ if (scriptNames.length > 0) {
971
+ LOG.info("CLI", `[${this.cliType}] CLI scripts: [${scriptNames.join(", ")}]`);
972
+ } else {
973
+ LOG.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js`);
974
+ }
766
975
  }
767
976
  cliType;
768
977
  cliName;
@@ -770,6 +979,7 @@ var init_provider_cli_adapter = __esm({
770
979
  provider;
771
980
  ptyProcess = null;
772
981
  messages = [];
982
+ structuredMessages = [];
773
983
  currentStatus = "starting";
774
984
  onStatusChange = null;
775
985
  responseBuffer = "";
@@ -780,7 +990,6 @@ var init_provider_cli_adapter = __esm({
780
990
  idleTimeout = null;
781
991
  ready = false;
782
992
  startupBuffer = "";
783
- /** After spawn: briefly skip generating/settle so splash/redraw does not flip status; not used to gate sendMessage */
784
993
  startupParseGate = false;
785
994
  spawnAt = 0;
786
995
  // PTY I/O
@@ -798,11 +1007,20 @@ var init_provider_cli_adapter = __esm({
798
1007
  // Output settle debounce — fires after PTY output goes quiet
799
1008
  settleTimer = null;
800
1009
  settledBuffer = "";
801
- // snapshot of recentOutputBuffer at settle time
802
1010
  // Resize redraw suppression
803
1011
  resizeSuppressUntil = 0;
804
1012
  // Debug: status transition history
805
1013
  statusHistory = [];
1014
+ // ─── CLI Scripts (script-based parsing) ───
1015
+ cliScripts;
1016
+ /** Full accumulated ANSI-stripped PTY output */
1017
+ accumulatedBuffer = "";
1018
+ /** Full accumulated raw PTY output (with ANSI) */
1019
+ accumulatedRawBuffer = "";
1020
+ /** Current visible terminal screen snapshot */
1021
+ terminalScreen = new TerminalScreen(40, 120);
1022
+ /** Max accumulated buffer size (last 50KB) */
1023
+ static MAX_ACCUMULATED_BUFFER = 5e4;
806
1024
  setStatus(status, trigger) {
807
1025
  const prev = this.currentStatus;
808
1026
  if (prev === status) return;
@@ -811,10 +1029,16 @@ var init_provider_cli_adapter = __esm({
811
1029
  if (this.statusHistory.length > 50) this.statusHistory.shift();
812
1030
  LOG.info("CLI", `[${this.cliType}] status: ${prev} \u2192 ${status}${trigger ? ` (${trigger})` : ""}`);
813
1031
  }
814
- // Resolved timeouts (provider defaults + overrides)
1032
+ // Resolved timeouts
815
1033
  timeouts;
816
- // Provider approval key mapping (e.g. { 0: '1', 1: '2', 2: '3' }) — loaded from provider.json
1034
+ // Provider approval key mapping
817
1035
  approvalKeys;
1036
+ /** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
1037
+ setCliScripts(scripts) {
1038
+ this.cliScripts = scripts;
1039
+ const scriptNames = Object.keys(scripts).filter((k) => typeof scripts[k] === "function");
1040
+ LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
1041
+ }
818
1042
  // ─── Lifecycle ─────────────────────────────────
819
1043
  setServerConn(serverConn) {
820
1044
  this.serverConn = serverConn;
@@ -903,15 +1127,19 @@ var init_provider_cli_adapter = __esm({
903
1127
  this.spawnAt = Date.now();
904
1128
  this.startupParseGate = true;
905
1129
  this.startupBuffer = "";
1130
+ this.terminalScreen.reset(40, 120);
906
1131
  this.ready = true;
907
1132
  this.setStatus("idle", "pty_ready");
908
1133
  this.onStatusChange?.();
909
1134
  }
910
- // ─── Output state machine ────────────────────────────
1135
+ // ─── Output Handling ────────────────────────────
911
1136
  handleOutput(rawData) {
912
1137
  if (Date.now() < this.resizeSuppressUntil) return;
1138
+ this.terminalScreen.write(rawData);
913
1139
  const cleanData = stripAnsi(rawData);
914
- const { patterns } = this.provider;
1140
+ if (this.isWaitingForResponse && cleanData) {
1141
+ this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
1142
+ }
915
1143
  if (cleanData.trim()) {
916
1144
  if (this.serverConn) {
917
1145
  this.serverConn.sendMessage("log", { message: cleanData.trim(), level: "info" });
@@ -920,9 +1148,10 @@ var init_provider_cli_adapter = __esm({
920
1148
  }
921
1149
  }
922
1150
  this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
1151
+ this.accumulatedBuffer = (this.accumulatedBuffer + cleanData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
1152
+ this.accumulatedRawBuffer = (this.accumulatedRawBuffer + rawData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
923
1153
  if (this.startupParseGate) {
924
1154
  this.startupBuffer += cleanData;
925
- LOG.info("CLI", `[${this.cliType}] startup chunk (${cleanData.length} chars): ${cleanData.slice(0, 200).replace(/\n/g, "\\n")}`);
926
1155
  const dialogPatterns = [
927
1156
  /Do you want to connect/i,
928
1157
  /Do you trust the files/i,
@@ -937,60 +1166,17 @@ var init_provider_cli_adapter = __esm({
937
1166
  }
938
1167
  const elapsed = Date.now() - this.spawnAt;
939
1168
  const bufCap = this.startupBuffer.length > 12e3;
940
- const promptMatched = patterns.prompt.some((p) => p.test(this.startupBuffer));
941
- if (promptMatched || elapsed > 8e3 || bufCap) {
1169
+ const scriptStatus = this.runDetectStatus(this.startupBuffer);
1170
+ const isReady = scriptStatus === "idle" || elapsed > 8e3 || bufCap;
1171
+ if (isReady) {
942
1172
  this.startupParseGate = false;
943
- if (promptMatched) {
944
- LOG.info("CLI", `[${this.cliType}] \u2713 Startup gate end (prompt matched)`);
945
- } else {
946
- LOG.info("CLI", `[${this.cliType}] startup gate end (${elapsed}ms, cap=${bufCap}, prompt=${promptMatched})`);
947
- }
1173
+ LOG.info("CLI", `[${this.cliType}] Startup gate end (${elapsed}ms, scriptStatus=${scriptStatus})`);
948
1174
  } else {
949
1175
  return;
950
1176
  }
951
1177
  }
952
- if (cleanData.trim().length > 5) {
953
- LOG.debug("CLI", `[${this.cliType}] output chunk (${cleanData.length}): ${cleanData.slice(0, 300).replace(/\n/g, "\\n")}`);
954
- }
955
- if (!this.isWaitingForResponse) {
956
- if (patterns.generating.some((p) => p.test(cleanData))) {
957
- if (this.settleTimer) {
958
- clearTimeout(this.settleTimer);
959
- this.settleTimer = null;
960
- }
961
- this.isWaitingForResponse = true;
962
- this.responseBuffer = "";
963
- this.setStatus("generating", "autonomous_gen");
964
- this.onStatusChange?.();
965
- }
966
- }
967
- if (this.isWaitingForResponse) {
968
- this.responseBuffer += cleanData;
969
- if (this.idleTimeout) clearTimeout(this.idleTimeout);
970
- if (patterns.generating.some((p) => p.test(cleanData))) {
971
- this.setStatus("generating", "still_generating");
972
- this.idleTimeout = setTimeout(() => {
973
- if (this.isWaitingForResponse) this.finishResponse();
974
- }, this.timeouts.generatingIdle);
975
- this.onStatusChange?.();
976
- if (this.settleTimer) {
977
- clearTimeout(this.settleTimer);
978
- this.settleTimer = null;
979
- }
980
- return;
981
- }
982
- }
983
- if (this.currentStatus === "waiting_approval") {
984
- this.approvalTransitionBuffer = (this.approvalTransitionBuffer + cleanData).slice(-500);
985
- this.scheduleSettle();
986
- return;
987
- }
988
1178
  this.scheduleSettle();
989
1179
  }
990
- /**
991
- * Fired after output goes quiet for outputSettle ms.
992
- * Evaluates the stabilised buffer for approval, prompt (idle), or timeout.
993
- */
994
1180
  scheduleSettle() {
995
1181
  if (this.settleTimer) clearTimeout(this.settleTimer);
996
1182
  this.settleTimer = setTimeout(() => {
@@ -1000,59 +1186,25 @@ var init_provider_cli_adapter = __esm({
1000
1186
  }, this.timeouts.outputSettle);
1001
1187
  }
1002
1188
  evaluateSettled() {
1003
- const { patterns } = this.provider;
1004
- const buf = this.settledBuffer;
1005
- if (this.currentStatus === "waiting_approval") {
1006
- const genResume = patterns.generating.some((p) => p.test(this.approvalTransitionBuffer));
1007
- const promptResume = patterns.prompt.some((p) => p.test(this.approvalTransitionBuffer));
1008
- if (genResume) {
1009
- if (this.approvalExitTimeout) {
1010
- clearTimeout(this.approvalExitTimeout);
1011
- this.approvalExitTimeout = null;
1012
- }
1013
- this.setStatus("generating", "approval_gen_resume");
1014
- this.activeModal = null;
1015
- this.recentOutputBuffer = "";
1016
- this.approvalTransitionBuffer = "";
1017
- this.lastApprovalResolvedAt = Date.now();
1018
- this.onStatusChange?.();
1019
- } else if (promptResume) {
1020
- if (this.approvalExitTimeout) {
1021
- clearTimeout(this.approvalExitTimeout);
1022
- this.approvalExitTimeout = null;
1023
- }
1024
- this.activeModal = null;
1025
- this.recentOutputBuffer = "";
1026
- this.approvalTransitionBuffer = "";
1027
- this.lastApprovalResolvedAt = Date.now();
1028
- this.finishResponse();
1029
- }
1030
- return;
1031
- }
1032
- const hasApproval = patterns.approval.some((p) => p.test(buf));
1033
- if (hasApproval) {
1189
+ const tail = this.settledBuffer;
1190
+ const scriptStatus = this.runDetectStatus(tail);
1191
+ if (!scriptStatus) return;
1192
+ const prevStatus = this.currentStatus;
1193
+ if (scriptStatus === "waiting_approval") {
1034
1194
  const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
1035
1195
  if (!inCooldown) {
1036
- const ctxLines = buf.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
1037
1196
  this.isWaitingForResponse = true;
1038
- this.setStatus("waiting_approval", "approval_pattern");
1039
- this.recentOutputBuffer = "";
1040
- this.approvalTransitionBuffer = "";
1041
- this.activeModal = {
1042
- message: ctxLines.slice(-5).join(" ").slice(0, 200) || "Approval required",
1043
- buttons: this.cliType === "claude-cli" ? ["Yes (y)", "Always allow (a)", "Deny (Esc)"] : ["Allow once", "Always allow", "Deny"]
1044
- };
1197
+ this.setStatus("waiting_approval", "script_detect");
1198
+ const modal = this.runParseApproval(tail);
1199
+ this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
1045
1200
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
1046
1201
  if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
1047
1202
  this.approvalExitTimeout = setTimeout(() => {
1048
1203
  if (this.currentStatus === "waiting_approval") {
1049
- LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-exiting waiting_approval`);
1204
+ LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-clearing`);
1050
1205
  this.activeModal = null;
1051
1206
  this.lastApprovalResolvedAt = Date.now();
1052
- this.recentOutputBuffer = "";
1053
- this.approvalTransitionBuffer = "";
1054
- this.approvalExitTimeout = null;
1055
- this.setStatus(this.isWaitingForResponse ? "generating" : "idle", "approval_cleared");
1207
+ this.setStatus("idle", "approval_timeout");
1056
1208
  this.onStatusChange?.();
1057
1209
  }
1058
1210
  }, 6e4);
@@ -1060,19 +1212,42 @@ var init_provider_cli_adapter = __esm({
1060
1212
  return;
1061
1213
  }
1062
1214
  }
1063
- if (this.isWaitingForResponse) {
1064
- const trailingLines = buf.split("\n").slice(-3).join("\n");
1065
- if (patterns.prompt.some((p) => p.test(trailingLines)) && !hasApproval) {
1066
- this.finishResponse();
1067
- } else if (!patterns.generating.some((p) => p.test(buf))) {
1068
- if (this.idleTimeout) clearTimeout(this.idleTimeout);
1069
- this.idleTimeout = setTimeout(() => {
1070
- if (this.isWaitingForResponse && this.responseBuffer.trim()) {
1071
- this.finishResponse();
1072
- }
1073
- }, this.timeouts.idleFinish);
1215
+ if (scriptStatus === "generating") {
1216
+ if (prevStatus === "waiting_approval") {
1217
+ if (this.approvalExitTimeout) {
1218
+ clearTimeout(this.approvalExitTimeout);
1219
+ this.approvalExitTimeout = null;
1220
+ }
1221
+ this.activeModal = null;
1222
+ this.lastApprovalResolvedAt = Date.now();
1223
+ }
1224
+ if (!this.isWaitingForResponse) {
1225
+ this.isWaitingForResponse = true;
1226
+ this.responseBuffer = "";
1074
1227
  }
1228
+ this.setStatus("generating", "script_detect");
1229
+ if (this.idleTimeout) clearTimeout(this.idleTimeout);
1230
+ this.idleTimeout = setTimeout(() => {
1231
+ if (this.isWaitingForResponse) this.finishResponse();
1232
+ }, this.timeouts.generatingIdle);
1075
1233
  this.onStatusChange?.();
1234
+ return;
1235
+ }
1236
+ if (scriptStatus === "idle") {
1237
+ if (prevStatus === "waiting_approval") {
1238
+ if (this.approvalExitTimeout) {
1239
+ clearTimeout(this.approvalExitTimeout);
1240
+ this.approvalExitTimeout = null;
1241
+ }
1242
+ this.activeModal = null;
1243
+ this.lastApprovalResolvedAt = Date.now();
1244
+ }
1245
+ if (this.isWaitingForResponse) {
1246
+ this.finishResponse();
1247
+ } else if (prevStatus !== "idle") {
1248
+ this.setStatus("idle", "script_detect");
1249
+ this.onStatusChange?.();
1250
+ }
1076
1251
  }
1077
1252
  }
1078
1253
  finishResponse() {
@@ -1088,25 +1263,50 @@ var init_provider_cli_adapter = __esm({
1088
1263
  clearTimeout(this.approvalExitTimeout);
1089
1264
  this.approvalExitTimeout = null;
1090
1265
  }
1091
- const lastUserText = this.messages.filter((m) => m.role === "user").pop()?.content;
1092
- let response = this.provider.cleanOutput(this.responseBuffer, lastUserText);
1093
- if (lastUserText && response) {
1094
- const userTrimmed = lastUserText.trim();
1095
- response = response.split("\n").filter((l) => l.trim() !== userTrimmed).join("\n").trim();
1096
- }
1097
- if (response) {
1098
- this.messages.push({ role: "assistant", content: response, timestamp: Date.now() });
1099
- if (this.messages.length > 200) this.messages = this.messages.slice(-200);
1100
- LOG.info("CLI", `[${this.cliType}] Response (${response.length} chars)`);
1101
- }
1102
1266
  this.responseBuffer = "";
1103
1267
  this.isWaitingForResponse = false;
1104
1268
  this.activeModal = null;
1105
1269
  this.setStatus("idle", "response_finished");
1106
1270
  this.onStatusChange?.();
1107
1271
  }
1108
- // ─── Public API (CliAdapter interface) ──────────
1272
+ // ─── Script Execution ──────────────────────────
1273
+ runDetectStatus(text) {
1274
+ if (!this.cliScripts?.detectStatus) return null;
1275
+ try {
1276
+ return this.cliScripts.detectStatus({ tail: text.slice(-500) });
1277
+ } catch (e) {
1278
+ LOG.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
1279
+ return null;
1280
+ }
1281
+ }
1282
+ runParseApproval(tail) {
1283
+ if (!this.cliScripts?.parseApproval) return null;
1284
+ try {
1285
+ return this.cliScripts.parseApproval({
1286
+ buffer: this.terminalScreen.getText() || this.accumulatedBuffer,
1287
+ rawBuffer: this.accumulatedRawBuffer,
1288
+ tail
1289
+ });
1290
+ } catch (e) {
1291
+ LOG.warn("CLI", `[${this.cliType}] parseApproval error: ${e.message}`);
1292
+ return null;
1293
+ }
1294
+ }
1295
+ // ─── Public API (CliAdapter) ───────────────────
1109
1296
  getStatus() {
1297
+ const scriptResult = this.getScriptParsedStatus();
1298
+ if (scriptResult) {
1299
+ return {
1300
+ status: this.currentStatus,
1301
+ messages: (scriptResult.messages || []).map((m) => ({
1302
+ role: m.role,
1303
+ content: m.content,
1304
+ timestamp: m.timestamp
1305
+ })),
1306
+ workingDir: this.workingDir,
1307
+ activeModal: this.activeModal
1308
+ };
1309
+ }
1110
1310
  return {
1111
1311
  status: this.currentStatus,
1112
1312
  messages: [...this.messages],
@@ -1114,11 +1314,71 @@ var init_provider_cli_adapter = __esm({
1114
1314
  activeModal: this.activeModal
1115
1315
  };
1116
1316
  }
1317
+ /**
1318
+ * Script-based full parse — returns ReadChatResult.
1319
+ * Called by command handler / dashboard for rich content rendering.
1320
+ */
1321
+ getScriptParsedStatus() {
1322
+ if (!this.cliScripts?.parseOutput) return null;
1323
+ try {
1324
+ const input = {
1325
+ buffer: this.accumulatedBuffer,
1326
+ rawBuffer: this.accumulatedRawBuffer,
1327
+ recentBuffer: this.recentOutputBuffer,
1328
+ screenText: this.terminalScreen.getText(),
1329
+ messages: [...this.structuredMessages.length > 0 ? this.structuredMessages : this.messages],
1330
+ partialResponse: this.responseBuffer
1331
+ };
1332
+ const result = this.cliScripts.parseOutput(input);
1333
+ if (result && typeof result === "object") {
1334
+ if (Array.isArray(result.messages)) {
1335
+ this.structuredMessages = result.messages.map((m) => ({
1336
+ role: m.role,
1337
+ content: m.content,
1338
+ timestamp: m.timestamp
1339
+ }));
1340
+ }
1341
+ return result;
1342
+ }
1343
+ } catch (e) {
1344
+ LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${e.message}`);
1345
+ }
1346
+ return null;
1347
+ }
1348
+ /** Whether this adapter has CLI scripts loaded */
1349
+ hasCliScripts() {
1350
+ return typeof this.cliScripts?.detectStatus === "function";
1351
+ }
1352
+ /**
1353
+ * Resolves an action (like 'fix' lint error) from the dashboard.
1354
+ * Uses resolveAction script if available, otherwise falls back to standard text.
1355
+ */
1356
+ async resolveAction(data) {
1357
+ let promptText = "";
1358
+ if (this.cliScripts && typeof this.cliScripts.resolveAction === "function") {
1359
+ try {
1360
+ promptText = this.cliScripts.resolveAction(data);
1361
+ } catch (e) {
1362
+ LOG.warn("CLI", `[${this.cliType}] resolveAction error: ${e.message}`);
1363
+ }
1364
+ }
1365
+ if (!promptText && data) {
1366
+ promptText = `Please fix the following issue:
1367
+ ${data.title || ""}
1368
+ ${data.explanation || ""}
1369
+
1370
+ ${data.message || ""}`.trim();
1371
+ }
1372
+ if (promptText) {
1373
+ await this.sendMessage(promptText);
1374
+ }
1375
+ }
1117
1376
  async sendMessage(text) {
1118
1377
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
1119
1378
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
1120
1379
  if (this.isWaitingForResponse) return;
1121
1380
  this.messages.push({ role: "user", content: text, timestamp: Date.now() });
1381
+ this.structuredMessages.push({ role: "user", content: text, timestamp: Date.now() });
1122
1382
  this.isWaitingForResponse = true;
1123
1383
  this.responseBuffer = "";
1124
1384
  this.setStatus("generating", "sendMessage");
@@ -1130,8 +1390,7 @@ var init_provider_cli_adapter = __esm({
1130
1390
  }
1131
1391
  getPartialResponse() {
1132
1392
  if (!this.isWaitingForResponse) return "";
1133
- const partial = this.provider.cleanOutput(this.responseBuffer);
1134
- return partial || (this.isWaitingForResponse ? "(generating...)" : "");
1393
+ return this.responseBuffer;
1135
1394
  }
1136
1395
  cancel() {
1137
1396
  this.shutdown();
@@ -1163,6 +1422,10 @@ var init_provider_cli_adapter = __esm({
1163
1422
  }
1164
1423
  clearHistory() {
1165
1424
  this.messages = [];
1425
+ this.structuredMessages = [];
1426
+ this.accumulatedBuffer = "";
1427
+ this.accumulatedRawBuffer = "";
1428
+ this.terminalScreen.reset();
1166
1429
  this.onStatusChange?.();
1167
1430
  }
1168
1431
  isProcessing() {
@@ -1174,11 +1437,6 @@ var init_provider_cli_adapter = __esm({
1174
1437
  writeRaw(data) {
1175
1438
  this.ptyProcess?.write(data);
1176
1439
  }
1177
- /**
1178
- * Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
1179
- * Index 0 = first option (already selected by default — just Enter).
1180
- * Index N = press Arrow Down N times, then Enter.
1181
- */
1182
1440
  resolveModal(buttonIndex) {
1183
1441
  if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
1184
1442
  if (buttonIndex in this.approvalKeys) {
@@ -1193,25 +1451,13 @@ var init_provider_cli_adapter = __esm({
1193
1451
  if (this.ptyProcess) {
1194
1452
  try {
1195
1453
  this.ptyProcess.resize(cols, rows);
1454
+ this.terminalScreen.resize(rows, cols);
1196
1455
  this.resizeSuppressUntil = Date.now() + 300;
1197
1456
  } catch {
1198
1457
  }
1199
1458
  }
1200
1459
  }
1201
- /**
1202
- * Full debug state — exposes all internal buffers, status, and patterns for debugging.
1203
- * Used by DevServer /api/cli/debug endpoint.
1204
- */
1205
1460
  getDebugState() {
1206
- const sb = this.startupBuffer;
1207
- const testOnStartup = (p) => {
1208
- const flags = p.flags.includes("g") ? p.flags.replace(/g/g, "") : p.flags;
1209
- return new RegExp(p.source, flags).test(sb);
1210
- };
1211
- const promptDiagnostics = this.provider.patterns.prompt.map((p) => ({
1212
- pattern: p.toString(),
1213
- matchedAgainstStartupBuffer: testOnStartup(p)
1214
- }));
1215
1461
  return {
1216
1462
  type: this.cliType,
1217
1463
  name: this.cliName,
@@ -1221,32 +1467,20 @@ var init_provider_cli_adapter = __esm({
1221
1467
  spawnAt: this.spawnAt,
1222
1468
  workingDir: this.workingDir,
1223
1469
  messages: this.messages.slice(-20),
1470
+ structuredMessages: this.structuredMessages.slice(-20),
1224
1471
  messageCount: this.messages.length,
1225
- // Buffers (longer tails here than in periodic logs — for matching provider.json patterns)
1226
- startupBuffer: sb.slice(-4e3),
1227
- startupBufferLength: sb.length,
1228
- promptDiagnostics,
1472
+ startupBuffer: this.startupBuffer.slice(-4e3),
1229
1473
  recentOutputBuffer: this.recentOutputBuffer.slice(-500),
1230
1474
  settledBuffer: this.settledBuffer.slice(-500),
1231
- responseBuffer: this.responseBuffer.slice(-500),
1232
- approvalTransitionBuffer: this.approvalTransitionBuffer.slice(-500),
1233
- // State
1475
+ accumulatedBufferLength: this.accumulatedBuffer.length,
1234
1476
  isWaitingForResponse: this.isWaitingForResponse,
1235
1477
  activeModal: this.activeModal,
1236
1478
  lastApprovalResolvedAt: this.lastApprovalResolvedAt,
1237
1479
  resizeSuppressUntil: this.resizeSuppressUntil,
1238
- // Provider patterns (serialized)
1239
- patterns: {
1240
- prompt: this.provider.patterns.prompt.map((p) => p.toString()),
1241
- generating: this.provider.patterns.generating.map((p) => p.toString()),
1242
- approval: this.provider.patterns.approval.map((p) => p.toString()),
1243
- ready: this.provider.patterns.ready.map((p) => p.toString())
1244
- },
1245
- // Status history
1480
+ hasCliScripts: this.hasCliScripts(),
1481
+ scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
1246
1482
  statusHistory: this.statusHistory.slice(-30),
1247
- // Timeouts config
1248
1483
  timeouts: this.timeouts,
1249
- // PTY alive
1250
1484
  ptyAlive: !!this.ptyProcess
1251
1485
  };
1252
1486
  }
@@ -3987,6 +4221,9 @@ init_logger();
3987
4221
 
3988
4222
  // src/commands/chat-commands.ts
3989
4223
  init_logger();
4224
+ function getTargetedCliAdapter(h, args, providerType) {
4225
+ return h.getCliAdapter(args?._targetInstance || h.currentIdeType || providerType);
4226
+ }
3990
4227
  async function handleChatHistory(h, args) {
3991
4228
  const { agentType, offset, limit, instanceId } = args;
3992
4229
  try {
@@ -3999,10 +4236,10 @@ async function handleChatHistory(h, args) {
3999
4236
  }
4000
4237
  }
4001
4238
  async function handleReadChat(h, args) {
4002
- const provider = h.getProvider();
4239
+ const provider = h.getProvider(args?.agentType);
4003
4240
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
4004
4241
  if (provider?.category === "cli" || provider?.category === "acp") {
4005
- const adapter = h.getCliAdapter(provider.type);
4242
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4006
4243
  if (adapter) {
4007
4244
  _log(`${provider.category} adapter: ${adapter.cliType}`);
4008
4245
  const status = adapter.getStatus?.();
@@ -4118,7 +4355,7 @@ async function handleSendChat(h, args) {
4118
4355
  const text = args?.text || args?.message;
4119
4356
  if (!text) return { success: false, error: "text required" };
4120
4357
  const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
4121
- const provider = h.getProvider();
4358
+ const provider = h.getProvider(args?.agentType);
4122
4359
  const _logSendSuccess = (method, targetAgent) => {
4123
4360
  h.historyWriter.appendNewMessages(
4124
4361
  targetAgent || provider?.type || h.currentIdeType || "unknown_agent",
@@ -4130,7 +4367,7 @@ async function handleSendChat(h, args) {
4130
4367
  return { success: true, sent: true, method, targetAgent };
4131
4368
  };
4132
4369
  if (provider?.category === "cli" || provider?.category === "acp") {
4133
- const adapter = h.getCliAdapter(provider.type);
4370
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4134
4371
  if (adapter) {
4135
4372
  _log(`${provider.category} adapter: ${adapter.cliType}`);
4136
4373
  try {
@@ -4283,7 +4520,7 @@ async function handleSendChat(h, args) {
4283
4520
  return { success: false, error: "No provider method could send the message" };
4284
4521
  }
4285
4522
  async function handleListChats(h, args) {
4286
- const provider = h.getProvider();
4523
+ const provider = h.getProvider(args?.agentType);
4287
4524
  if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
4288
4525
  try {
4289
4526
  const chats = await h.agentStream.listAgentChats(h.getCdp(), provider.type);
@@ -4335,7 +4572,16 @@ async function handleListChats(h, args) {
4335
4572
  return { success: false, error: "listSessions script not available for this provider" };
4336
4573
  }
4337
4574
  async function handleNewChat(h, args) {
4338
- const provider = h.getProvider();
4575
+ const provider = h.getProvider(args?.agentType);
4576
+ if (provider?.category === "cli") {
4577
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4578
+ if (!adapter) return { success: false, error: "CLI adapter not running" };
4579
+ if (typeof adapter.clearHistory === "function") {
4580
+ adapter.clearHistory();
4581
+ return { success: true, cleared: true };
4582
+ }
4583
+ return { success: false, error: "new_chat not supported by this CLI provider" };
4584
+ }
4339
4585
  if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
4340
4586
  const ok = await h.agentStream.newAgentSession(h.getCdp(), provider.type, h.currentIdeType);
4341
4587
  return { success: ok };
@@ -4360,7 +4606,7 @@ async function handleNewChat(h, args) {
4360
4606
  return { success: false, error: "newSession script not available for this provider" };
4361
4607
  }
4362
4608
  async function handleSwitchChat(h, args) {
4363
- const provider = h.getProvider();
4609
+ const provider = h.getProvider(args?.agentType);
4364
4610
  const ideType = h.currentIdeType;
4365
4611
  const sessionId = args?.sessionId || args?.id || args?.chatId;
4366
4612
  if (!sessionId) return { success: false, error: "sessionId required" };
@@ -4454,10 +4700,10 @@ async function handleSwitchChat(h, args) {
4454
4700
  }
4455
4701
  }
4456
4702
  async function handleSetMode(h, args) {
4457
- const provider = h.getProvider();
4703
+ const provider = h.getProvider(args?.agentType);
4458
4704
  const mode = args?.mode || "agent";
4459
4705
  if (provider?.category === "acp") {
4460
- const adapter = h.getCliAdapter(provider.type);
4706
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4461
4707
  if (adapter) {
4462
4708
  const acpInstance = adapter._acpInstance;
4463
4709
  if (acpInstance && typeof acpInstance.onEvent === "function") {
@@ -4509,11 +4755,11 @@ async function handleSetMode(h, args) {
4509
4755
  return { success: false, error: `setMode '${mode}' not supported by this provider` };
4510
4756
  }
4511
4757
  async function handleChangeModel(h, args) {
4512
- const provider = h.getProvider();
4758
+ const provider = h.getProvider(args?.agentType);
4513
4759
  const model = args?.model;
4514
4760
  LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} ideType=${h.currentIdeType} providerType=${h.currentProviderType}`);
4515
4761
  if (provider?.category === "acp") {
4516
- const adapter = h.getCliAdapter(provider.type);
4762
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4517
4763
  LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
4518
4764
  if (adapter) {
4519
4765
  const acpInstance = adapter._acpInstance;
@@ -4570,11 +4816,11 @@ async function handleSetThoughtLevel(h, args) {
4570
4816
  const configId = args?.configId;
4571
4817
  const value = args?.value;
4572
4818
  if (!configId || !value) return { success: false, error: "configId and value required" };
4573
- const provider = h.getProvider();
4819
+ const provider = h.getProvider(args?.agentType);
4574
4820
  if (!provider || provider.category !== "acp") {
4575
4821
  return { success: false, error: "set_thought_level only for ACP providers" };
4576
4822
  }
4577
- const adapter = h.getCliAdapter(provider.type);
4823
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4578
4824
  const acpInstance = adapter?._acpInstance;
4579
4825
  if (!acpInstance) return { success: false, error: "ACP instance not found" };
4580
4826
  try {
@@ -4586,13 +4832,22 @@ async function handleSetThoughtLevel(h, args) {
4586
4832
  }
4587
4833
  }
4588
4834
  async function handleResolveAction(h, args) {
4589
- const provider = h.getProvider();
4835
+ const provider = h.getProvider(args?.agentType);
4590
4836
  const action = args?.action || "approve";
4591
4837
  const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
4592
4838
  LOG.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
4593
4839
  if (provider?.category === "cli") {
4594
- const adapter = h.getCliAdapter(provider.type);
4840
+ const adapter = getTargetedCliAdapter(h, args, provider.type);
4595
4841
  if (!adapter) return { success: false, error: "CLI adapter not running" };
4842
+ if (args?.data && typeof adapter.resolveAction === "function") {
4843
+ try {
4844
+ await adapter.resolveAction(args.data);
4845
+ LOG.info("Command", `[resolveAction] CLI PTY \u2192 resolveAction triggered with data payload`);
4846
+ return { success: true, method: "cli-resolve-action" };
4847
+ } catch (e) {
4848
+ return { success: false, error: `CLI resolveAction failed: ${e.message}` };
4849
+ }
4850
+ }
4596
4851
  const status = adapter.getStatus?.();
4597
4852
  if (status?.status !== "waiting_approval") {
4598
4853
  return { success: false, error: "Not in approval state" };
@@ -6790,8 +7045,9 @@ var ProviderLoader = class _ProviderLoader {
6790
7045
  }
6791
7046
  }
6792
7047
  compareVersions(a, b) {
6793
- const pa = a.split(".").map(Number);
6794
- const pb = b.split(".").map(Number);
7048
+ const normalize2 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
7049
+ const pa = normalize2(a);
7050
+ const pb = normalize2(b);
6795
7051
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
6796
7052
  const va = pa[i] || 0;
6797
7053
  const vb = pb[i] || 0;
@@ -7868,21 +8124,27 @@ var CliProviderInstance = class {
7868
8124
  async onTick() {
7869
8125
  }
7870
8126
  getState() {
7871
- const adapterStatus = this.adapter.getStatus();
8127
+ const rawStatus = this.adapter.getStatus();
8128
+ const parsedStatus = this.adapter.getScriptParsedStatus();
8129
+ const adapterStatus = parsedStatus ? {
8130
+ ...rawStatus,
8131
+ messages: parsedStatus.messages || rawStatus.messages,
8132
+ activeModal: parsedStatus.activeModal || rawStatus.activeModal
8133
+ } : rawStatus;
7872
8134
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
7873
- const recentMessages = adapterStatus.messages.slice(-50).map((m) => ({
7874
- role: m.role,
7875
- content: m.content.length > 2e3 ? m.content.slice(0, 2e3) + "\n... (truncated)" : m.content,
7876
- timestamp: m.timestamp
7877
- }));
8135
+ const recentMessages = adapterStatus.messages.slice(-50).map((m) => {
8136
+ const content = typeof m.content === "string" && m.content.length > 8e3 ? m.content.slice(0, 8e3) + "\n... (truncated)" : m.content;
8137
+ return { ...m, content };
8138
+ });
7878
8139
  const partial = this.adapter.getPartialResponse();
7879
8140
  if (adapterStatus.status === "generating" && partial) {
7880
8141
  const cleaned = partial.trim();
7881
8142
  if (cleaned && cleaned !== "(generating...)") {
7882
8143
  recentMessages.push({
7883
8144
  role: "assistant",
7884
- content: (cleaned.length > 2e3 ? cleaned.slice(0, 2e3) + "..." : cleaned) + "...",
7885
- timestamp: Date.now()
8145
+ content: (cleaned.length > 8e3 ? cleaned.slice(0, 8e3) + "..." : cleaned) + "...",
8146
+ timestamp: Date.now(),
8147
+ meta: { streaming: true }
7886
8148
  });
7887
8149
  }
7888
8150
  }
@@ -7921,6 +8183,8 @@ var CliProviderInstance = class {
7921
8183
  this.adapter.sendMessage(data.text);
7922
8184
  } else if (event === "server_connected" && data?.serverConn) {
7923
8185
  this.adapter.setServerConn(data.serverConn);
8186
+ } else if (event === "resolve_action" && data) {
8187
+ this.adapter.resolveAction(data);
7924
8188
  }
7925
8189
  }
7926
8190
  dispose() {
@@ -8978,7 +9242,8 @@ var DaemonCliManager = class {
8978
9242
  const provider = this.providerLoader.getMeta(normalizedType);
8979
9243
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
8980
9244
  console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
8981
- return new ProviderCliAdapter(provider, workingDir, cliArgs);
9245
+ const resolvedProvider = this.providerLoader.resolve(normalizedType) || provider;
9246
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs);
8982
9247
  }
8983
9248
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
8984
9249
  }
@@ -9063,7 +9328,8 @@ ${installInfo}`
9063
9328
  }
9064
9329
  const instanceManager = this.deps.getInstanceManager();
9065
9330
  if (provider && instanceManager) {
9066
- const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key);
9331
+ const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
9332
+ const cliInstance = new CliProviderInstance(resolvedProvider, resolvedDir, cliArgs, key);
9067
9333
  try {
9068
9334
  await instanceManager.addInstance(key, cliInstance, {
9069
9335
  serverConn: this.deps.getServerConn(),
@@ -12261,6 +12527,46 @@ var DevServer = class _DevServer {
12261
12527
  }
12262
12528
  }
12263
12529
  // ─── Phase 2: Auto-Implement Backend ───
12530
+ getDefaultAutoImplReference(category, type) {
12531
+ if (category === "cli") {
12532
+ return type === "codex-cli" ? "claude-cli" : "codex-cli";
12533
+ }
12534
+ return "antigravity";
12535
+ }
12536
+ resolveAutoImplReference(category, requestedReference, targetType) {
12537
+ const desired = requestedReference || this.getDefaultAutoImplReference(category, targetType);
12538
+ const ref = this.providerLoader.resolve(desired) || this.providerLoader.getMeta(desired);
12539
+ if (ref?.category === category) return desired;
12540
+ const all = this.providerLoader.getAll();
12541
+ const fallback = all.find((p) => p.category === category && p.type !== targetType);
12542
+ return fallback?.type || null;
12543
+ }
12544
+ loadAutoImplReferenceScripts(category, referenceType) {
12545
+ if (!referenceType) return {};
12546
+ const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
12547
+ const refDir = path12.join(builtinDir, category, referenceType);
12548
+ if (!fs9.existsSync(refDir)) return {};
12549
+ const referenceScripts = {};
12550
+ const scriptsDir = path12.join(refDir, "scripts");
12551
+ if (!fs9.existsSync(scriptsDir)) return referenceScripts;
12552
+ const versions = fs9.readdirSync(scriptsDir).filter((d) => {
12553
+ try {
12554
+ return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
12555
+ } catch {
12556
+ return false;
12557
+ }
12558
+ }).sort().reverse();
12559
+ if (versions.length === 0) return referenceScripts;
12560
+ const latestDir = path12.join(scriptsDir, versions[0]);
12561
+ for (const file of fs9.readdirSync(latestDir)) {
12562
+ if (!file.endsWith(".js")) continue;
12563
+ try {
12564
+ referenceScripts[file] = fs9.readFileSync(path12.join(latestDir, file), "utf-8");
12565
+ } catch {
12566
+ }
12567
+ }
12568
+ return referenceScripts;
12569
+ }
12264
12570
  async handleAutoImplement(type, req, res) {
12265
12571
  const body = await this.readBody(req);
12266
12572
  const { agent = "claude-cli", functions, reference = "antigravity", model, comment } = body;
@@ -12283,36 +12589,26 @@ var DevServer = class _DevServer {
12283
12589
  return;
12284
12590
  }
12285
12591
  try {
12286
- this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "analyzing", message: "\uC5D0\uC774\uC804\uD2B8 \uCD08\uAE30\uD654 (DOM \uD0D0\uC0C9 \uAD8C\uD55C \uBD80\uC5EC)..." } });
12592
+ const resolvedReference = this.resolveAutoImplReference(provider.category, reference, type);
12593
+ this.sendAutoImplSSE({
12594
+ event: "progress",
12595
+ data: {
12596
+ function: "_init",
12597
+ status: "analyzing",
12598
+ message: provider.category === "cli" ? "Initializing agent (granting CLI PTY debug access)..." : "Initializing agent (granting DOM access)..."
12599
+ }
12600
+ });
12287
12601
  const domContext = null;
12288
- this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "loading_reference", message: `\uB808\uD37C\uB7F0\uC2A4 \uC2A4\uD06C\uB9BD\uD2B8 \uB85C\uB4DC \uC911 (${reference})...` } });
12289
- let referenceScripts = {};
12290
- const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
12291
- const refDir = path12.join(builtinDir, "ide", reference);
12292
- if (fs9.existsSync(refDir)) {
12293
- const scriptsDir = path12.join(refDir, "scripts");
12294
- if (fs9.existsSync(scriptsDir)) {
12295
- const versions = fs9.readdirSync(scriptsDir).filter((d) => {
12296
- try {
12297
- return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
12298
- } catch {
12299
- return false;
12300
- }
12301
- }).sort().reverse();
12302
- if (versions.length > 0) {
12303
- const latestDir = path12.join(scriptsDir, versions[0]);
12304
- for (const file of fs9.readdirSync(latestDir)) {
12305
- if (file.endsWith(".js")) {
12306
- try {
12307
- referenceScripts[file] = fs9.readFileSync(path12.join(latestDir, file), "utf-8");
12308
- } catch {
12309
- }
12310
- }
12311
- }
12312
- }
12602
+ this.sendAutoImplSSE({
12603
+ event: "progress",
12604
+ data: {
12605
+ function: "_init",
12606
+ status: "loading_reference",
12607
+ message: `Loading reference script (${resolvedReference || "none"})...`
12313
12608
  }
12314
- }
12315
- const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment);
12609
+ });
12610
+ const referenceScripts = this.loadAutoImplReferenceScripts(provider.category, resolvedReference);
12611
+ const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
12316
12612
  const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
12317
12613
  if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
12318
12614
  const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
@@ -12330,7 +12626,7 @@ var DevServer = class _DevServer {
12330
12626
  }
12331
12627
  const agentCategory = agentProvider?.category;
12332
12628
  if (agentCategory === "acp") {
12333
- this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `ACP \uC5D0\uC774\uC804\uD2B8 \uC2E4\uD589 \uC911: ${spawn3.command} ${(spawn3.args || []).join(" ")}` } });
12629
+ this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn3.command} ${(spawn3.args || []).join(" ")}` } });
12334
12630
  this.autoImplStatus = { running: true, type, progress: [] };
12335
12631
  const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await import("@agentclientprotocol/sdk");
12336
12632
  const { Readable: Readable2, Writable: Writable2 } = await import("stream");
@@ -12417,7 +12713,7 @@ var DevServer = class _DevServer {
12417
12713
  this.autoImplProcess = null;
12418
12714
  this.autoImplStatus.running = false;
12419
12715
  const success = code === 0;
12420
- this.sendAutoImplSSE({ event: "complete", data: { success, exitCode: code, functions, message: success ? "\u2705 ACP Auto-implement \uC644\uB8CC" : `\u274C ACP \uC5D0\uC774\uC804\uD2B8 \uC885\uB8CC (code: ${code})` } });
12716
+ this.sendAutoImplSSE({ event: "complete", data: { success, exitCode: code, functions, message: success ? "\u2705 ACP Auto-implement complete" : `\u274C ACP agent exited (code: ${code})` } });
12421
12717
  try {
12422
12718
  this.providerLoader.reload();
12423
12719
  } catch {
@@ -12432,16 +12728,16 @@ var DevServer = class _DevServer {
12432
12728
  try {
12433
12729
  this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "initializing", message: "ACP initialize..." } });
12434
12730
  await connection.initialize({ protocolVersion: PROTOCOL_VERSION2, clientCapabilities: {} });
12435
- this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "session", message: "ACP session \uC0DD\uC131 \uC911..." } });
12731
+ this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "session", message: "Creating ACP session..." } });
12436
12732
  const session = await connection.newSession({ cwd: providerDir, mcpServers: [] });
12437
12733
  const sessionId = session?.sessionId;
12438
12734
  if (!sessionId) throw new Error("No sessionId returned from session/new");
12439
- this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "prompting", message: `\uD504\uB86C\uD504\uD2B8 \uC804\uC1A1 \uC911 (${prompt.length} chars)...` } });
12735
+ this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "prompting", message: `Sending prompt (${prompt.length} chars)...` } });
12440
12736
  await connection.prompt({
12441
12737
  sessionId,
12442
12738
  prompt: [{ type: "text", text: prompt }]
12443
12739
  });
12444
- this.sendAutoImplSSE({ event: "progress", data: { function: "_done", status: "complete", message: "\u2705 ACP \uD504\uB86C\uD504\uD2B8 \uCC98\uB9AC \uC644\uB8CC" } });
12740
+ this.sendAutoImplSSE({ event: "progress", data: { function: "_done", status: "complete", message: "\u2705 ACP prompt processing complete" } });
12445
12741
  } catch (e) {
12446
12742
  this.sendAutoImplSSE({ event: "output", data: { chunk: `[ACP Error] ${e.message}
12447
12743
  `, stream: "stderr" } });
@@ -12493,7 +12789,7 @@ var DevServer = class _DevServer {
12493
12789
  const escapedArgs = baseArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
12494
12790
  shellCmd = `cat '${promptFile}' | ${command} ${escapedArgs}`;
12495
12791
  }
12496
- this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `\uC5D0\uC774\uC804\uD2B8 \uC2E4\uD589 \uC911: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
12792
+ this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
12497
12793
  this.autoImplStatus = { running: true, type, progress: [] };
12498
12794
  const spawnedAt = Date.now();
12499
12795
  let child;
@@ -12589,7 +12885,7 @@ var DevServer = class _DevServer {
12589
12885
  const success = code === 0;
12590
12886
  this.sendAutoImplSSE({
12591
12887
  event: "complete",
12592
- data: { success, exitCode: code, functions, message: success ? "\u2705 Auto-implement \uC644\uB8CC" : `\u274C \uC5D0\uC774\uC804\uD2B8 \uC885\uB8CC (code: ${code})` }
12888
+ data: { success, exitCode: code, functions, message: success ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})` }
12593
12889
  });
12594
12890
  try {
12595
12891
  this.providerLoader.reload();
@@ -12624,7 +12920,7 @@ var DevServer = class _DevServer {
12624
12920
  success,
12625
12921
  exitCode: code,
12626
12922
  functions,
12627
- message: success ? "\u2705 Auto-implement \uC644\uB8CC" : `\u274C \uC5D0\uC774\uC804\uD2B8 \uC885\uB8CC (code: ${code})`
12923
+ message: success ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`
12628
12924
  }
12629
12925
  });
12630
12926
  try {
@@ -12652,7 +12948,10 @@ var DevServer = class _DevServer {
12652
12948
  this.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
12653
12949
  }
12654
12950
  }
12655
- buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, userComment) {
12951
+ buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType) {
12952
+ if (provider.category === "cli") {
12953
+ return this.buildCliAutoImplPrompt(type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
12954
+ }
12656
12955
  const lines = [];
12657
12956
  lines.push("You are implementing browser automation scripts for an IDE provider.");
12658
12957
  lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
@@ -12715,7 +13014,7 @@ var DevServer = class _DevServer {
12715
13014
  setMode: "set_mode.js"
12716
13015
  };
12717
13016
  if (Object.keys(referenceScripts).length > 0) {
12718
- lines.push("## Reference Implementation (from Antigravity provider)");
13017
+ lines.push(`## Reference Implementation (from ${referenceType || "antigravity"} provider)`);
12719
13018
  lines.push("These are WORKING scripts from another IDE. Adapt the PATTERNS (not selectors) for the target IDE.");
12720
13019
  lines.push("");
12721
13020
  for (const fn of functions) {
@@ -12864,6 +13163,150 @@ var DevServer = class _DevServer {
12864
13163
  lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
12865
13164
  return lines.join("\n");
12866
13165
  }
13166
+ buildCliAutoImplPrompt(type, provider, providerDir, functions, referenceScripts, userComment, referenceType) {
13167
+ const lines = [];
13168
+ lines.push("You are implementing PTY parsing scripts for a CLI provider.");
13169
+ lines.push("Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.");
13170
+ lines.push("");
13171
+ lines.push(`# Target: ${provider.name || type} (${type})`);
13172
+ lines.push(`Provider directory: \`${providerDir}\``);
13173
+ lines.push("Provider category: `cli`");
13174
+ lines.push("");
13175
+ lines.push("## Current Target Files");
13176
+ lines.push("These are the files you need to edit. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
13177
+ lines.push("");
13178
+ const scriptsDir = path12.join(providerDir, "scripts");
13179
+ if (fs9.existsSync(scriptsDir)) {
13180
+ const versions = fs9.readdirSync(scriptsDir).filter((d) => {
13181
+ try {
13182
+ return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
13183
+ } catch {
13184
+ return false;
13185
+ }
13186
+ }).sort().reverse();
13187
+ if (versions.length > 0) {
13188
+ const vDir = path12.join(scriptsDir, versions[0]);
13189
+ lines.push(`Scripts version directory: \`${vDir}\``);
13190
+ lines.push("");
13191
+ for (const file of fs9.readdirSync(vDir)) {
13192
+ if (!file.endsWith(".js")) continue;
13193
+ try {
13194
+ const content = fs9.readFileSync(path12.join(vDir, file), "utf-8");
13195
+ lines.push(`### \`${file}\``);
13196
+ lines.push("```javascript");
13197
+ lines.push(content);
13198
+ lines.push("```");
13199
+ lines.push("");
13200
+ } catch {
13201
+ }
13202
+ }
13203
+ }
13204
+ }
13205
+ const funcToFile = {
13206
+ parseOutput: "parse_output.js",
13207
+ detectStatus: "detect_status.js",
13208
+ parseApproval: "parse_approval.js"
13209
+ };
13210
+ if (Object.keys(referenceScripts).length > 0) {
13211
+ lines.push(`## Reference Implementation (from ${referenceType || "another CLI"} provider)`);
13212
+ lines.push("These are working CLI PTY parser scripts. Reuse the parsing shape and runtime contract, but adapt to the target CLI screen.");
13213
+ lines.push("");
13214
+ for (const fn of functions) {
13215
+ const fileName = funcToFile[fn];
13216
+ if (fileName && referenceScripts[fileName]) {
13217
+ lines.push(`### ${fn} \u2192 \`${fileName}\``);
13218
+ lines.push("```javascript");
13219
+ lines.push(referenceScripts[fileName]);
13220
+ lines.push("```");
13221
+ lines.push("");
13222
+ }
13223
+ }
13224
+ if (referenceScripts["scripts.js"]) {
13225
+ lines.push("### Router \u2192 `scripts.js`");
13226
+ lines.push("```javascript");
13227
+ lines.push(referenceScripts["scripts.js"]);
13228
+ lines.push("```");
13229
+ lines.push("");
13230
+ }
13231
+ }
13232
+ lines.push("## Runtime Contract");
13233
+ lines.push("The daemon runtime is already implemented in `packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts`.");
13234
+ lines.push("Your scripts receive PTY-derived input and must return plain JS objects.");
13235
+ lines.push("");
13236
+ lines.push("| Function | Input | Return |");
13237
+ lines.push("|---|---|---|");
13238
+ lines.push("| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
13239
+ lines.push("| `detectStatus` | `{ tail }` | `idle`, `generating`, `waiting_approval`, or `error` |");
13240
+ lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
13241
+ lines.push("");
13242
+ lines.push("## Rules");
13243
+ lines.push("1. These scripts run in Node.js CommonJS, not in the browser. Do NOT use DOM APIs.");
13244
+ lines.push("2. Prefer `screenText` for current visible UI state. That is the PTY equivalent of parsing the current IDE DOM.");
13245
+ lines.push("3. Use `messages` as prior transcript state so redraws do not duplicate old turns on every parse.");
13246
+ lines.push("4. Use `partialResponse` for the actively streaming assistant text when status is `generating`.");
13247
+ lines.push("5. `detectStatus` must stay lightweight and tail-based. Do not scan the entire history there.");
13248
+ lines.push("6. `parseApproval` should understand the live approval area and return clean button labels.");
13249
+ lines.push("7. Use `rawBuffer` only when ANSI/control-sequence artifacts matter. Do not depend on raw escape noise unless necessary.");
13250
+ lines.push("8. Keep exports compatible with the existing `scripts.js` router (`module.exports = function ...`).");
13251
+ lines.push("9. Do not rewrite unrelated provider config. Only touch the scripts needed for this task unless a tiny supporting change is required.");
13252
+ lines.push("");
13253
+ lines.push("## Task");
13254
+ lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
13255
+ lines.push("");
13256
+ lines.push("## Verification API");
13257
+ lines.push("Use the DevServer CLI debug endpoints, not DOM/CDP routes.");
13258
+ lines.push("");
13259
+ lines.push("### 1. Launch the target CLI");
13260
+ lines.push("```bash");
13261
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
13262
+ lines.push(' -H "Content-Type: application/json" \\');
13263
+ lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, "\\\\")}"}'`);
13264
+ lines.push("```");
13265
+ lines.push("");
13266
+ lines.push("### 2. Inspect parsed + raw adapter state");
13267
+ lines.push("```bash");
13268
+ lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
13269
+ lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
13270
+ lines.push("```");
13271
+ lines.push("");
13272
+ lines.push("### 3. Send a rich test prompt");
13273
+ lines.push("```bash");
13274
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
13275
+ lines.push(' -H "Content-Type: application/json" \\');
13276
+ lines.push(` -d '{"type":"${type}","text":"Write a short python snippet, include a markdown table, and briefly explain what you did."}'`);
13277
+ lines.push("```");
13278
+ lines.push("");
13279
+ lines.push("### 4. If approval appears, resolve it");
13280
+ lines.push("```bash");
13281
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
13282
+ lines.push(' -H "Content-Type: application/json" \\');
13283
+ lines.push(` -d '{"type":"${type}","buttonIndex":0}'`);
13284
+ lines.push("```");
13285
+ lines.push("");
13286
+ lines.push("### 5. Stop the CLI when finished");
13287
+ lines.push("```bash");
13288
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/stop \\`);
13289
+ lines.push(' -H "Content-Type: application/json" \\');
13290
+ lines.push(` -d '{"type":"${type}"}'`);
13291
+ lines.push("```");
13292
+ lines.push("");
13293
+ lines.push("## Required Validation");
13294
+ lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
13295
+ lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
13296
+ lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
13297
+ lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
13298
+ lines.push("5. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
13299
+ lines.push("");
13300
+ if (userComment) {
13301
+ lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
13302
+ lines.push("The user has provided the following additional instructions. Follow them strictly:");
13303
+ lines.push("");
13304
+ lines.push(userComment);
13305
+ lines.push("");
13306
+ }
13307
+ lines.push("Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.");
13308
+ return lines.join("\n");
13309
+ }
12867
13310
  handleAutoImplSSE(type, req, res) {
12868
13311
  res.writeHead(200, {
12869
13312
  "Content-Type": "text/event-stream",
@@ -12891,7 +13334,7 @@ data: ${JSON.stringify(p.data)}
12891
13334
  setTimeout(() => {
12892
13335
  if (this.autoImplProcess) this.autoImplProcess.kill("SIGKILL");
12893
13336
  }, 3e3);
12894
- this.sendAutoImplSSE({ event: "complete", data: { success: false, exitCode: -1, message: "\u26D4 \uC0AC\uC6A9\uC790\uC5D0 \uC758\uD574 \uC911\uB2E8\uB428" } });
13337
+ this.sendAutoImplSSE({ event: "complete", data: { success: false, exitCode: -1, message: "\u26D4 Aborted by user" } });
12895
13338
  this.autoImplProcess = null;
12896
13339
  this.autoImplStatus.running = false;
12897
13340
  this.json(res, 200, { cancelled: true });