@adhdev/daemon-core 0.6.55 → 0.6.56
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.d.ts +8 -0
- package/dist/index.js +144 -261
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/cli-adapters/provider-cli-adapter.ts +46 -8
- package/src/cli-adapters/terminal-screen.ts +66 -239
- package/src/daemon/dev-server.ts +69 -35
- package/src/providers/cli-provider-instance.ts +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -2575,6 +2575,8 @@ interface CliScripts {
|
|
|
2575
2575
|
/** Lightweight status detection (high-frequency polling) → AgentStatus string */
|
|
2576
2576
|
detectStatus?: (input: {
|
|
2577
2577
|
tail: string;
|
|
2578
|
+
screenText?: string;
|
|
2579
|
+
rawBuffer?: string;
|
|
2578
2580
|
}) => string | null;
|
|
2579
2581
|
/** Parse approval modal from PTY output → ModalInfo | null */
|
|
2580
2582
|
parseApproval?: (input: {
|
|
@@ -2603,6 +2605,8 @@ interface CliProviderModule {
|
|
|
2603
2605
|
name: string;
|
|
2604
2606
|
category: 'cli';
|
|
2605
2607
|
binary: string;
|
|
2608
|
+
sendDelayMs?: number;
|
|
2609
|
+
sendKey?: string;
|
|
2606
2610
|
spawn: {
|
|
2607
2611
|
command: string;
|
|
2608
2612
|
args: string[];
|
|
@@ -2659,6 +2663,7 @@ declare class ProviderCliAdapter implements CliAdapter {
|
|
|
2659
2663
|
private approvalExitTimeout;
|
|
2660
2664
|
private settleTimer;
|
|
2661
2665
|
private settledBuffer;
|
|
2666
|
+
private submitPendingUntil;
|
|
2662
2667
|
private resizeSuppressUntil;
|
|
2663
2668
|
private statusHistory;
|
|
2664
2669
|
private cliScripts;
|
|
@@ -2673,6 +2678,8 @@ declare class ProviderCliAdapter implements CliAdapter {
|
|
|
2673
2678
|
private setStatus;
|
|
2674
2679
|
private readonly timeouts;
|
|
2675
2680
|
private readonly approvalKeys;
|
|
2681
|
+
private readonly sendDelayMs;
|
|
2682
|
+
private readonly sendKey;
|
|
2676
2683
|
constructor(provider: CliProviderModule, workingDir: string, extraArgs?: string[]);
|
|
2677
2684
|
/** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
|
|
2678
2685
|
setCliScripts(scripts: CliScripts): void;
|
|
@@ -2957,6 +2964,7 @@ declare class DevServer {
|
|
|
2957
2964
|
private readBody;
|
|
2958
2965
|
/** GET /api/cli/status — list all running CLI/ACP instances with state */
|
|
2959
2966
|
private handleCliStatus;
|
|
2967
|
+
private findCliTarget;
|
|
2960
2968
|
/** POST /api/cli/launch — launch a CLI agent { type, workingDir?, args? } */
|
|
2961
2969
|
private handleCliLaunch;
|
|
2962
2970
|
/** POST /api/cli/send — send message to a running CLI { type, text } */
|
package/dist/index.js
CHANGED
|
@@ -592,240 +592,67 @@ var init_logger = __esm({
|
|
|
592
592
|
});
|
|
593
593
|
|
|
594
594
|
// src/cli-adapters/terminal-screen.ts
|
|
595
|
-
function
|
|
596
|
-
|
|
595
|
+
function loadTerminalCtor() {
|
|
596
|
+
if (!TerminalCtor) {
|
|
597
|
+
const mod = require("@xterm/xterm");
|
|
598
|
+
TerminalCtor = mod.Terminal || mod.default?.Terminal || mod.default;
|
|
599
|
+
if (!TerminalCtor) {
|
|
600
|
+
throw new Error("@xterm/xterm Terminal export not found");
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return TerminalCtor;
|
|
597
604
|
}
|
|
598
|
-
var TerminalScreen;
|
|
605
|
+
var TerminalCtor, TerminalScreen;
|
|
599
606
|
var init_terminal_screen = __esm({
|
|
600
607
|
"src/cli-adapters/terminal-screen.ts"() {
|
|
601
608
|
"use strict";
|
|
609
|
+
TerminalCtor = null;
|
|
602
610
|
TerminalScreen = class {
|
|
603
611
|
rows;
|
|
604
612
|
cols;
|
|
605
|
-
|
|
606
|
-
cursorCol = 0;
|
|
607
|
-
savedRow = 0;
|
|
608
|
-
savedCol = 0;
|
|
609
|
-
lines;
|
|
613
|
+
terminal;
|
|
610
614
|
constructor(rows = 40, cols = 120) {
|
|
611
|
-
this.rows = rows;
|
|
612
|
-
this.cols = cols;
|
|
613
|
-
this.
|
|
615
|
+
this.rows = Math.max(1, rows | 0);
|
|
616
|
+
this.cols = Math.max(1, cols | 0);
|
|
617
|
+
this.terminal = this.createTerminal();
|
|
614
618
|
}
|
|
615
619
|
reset(rows = this.rows, cols = this.cols) {
|
|
616
|
-
this.rows = rows;
|
|
617
|
-
this.cols = cols;
|
|
618
|
-
this.
|
|
619
|
-
this.
|
|
620
|
-
this.savedRow = 0;
|
|
621
|
-
this.savedCol = 0;
|
|
622
|
-
this.lines = this.makeLines(rows, cols);
|
|
620
|
+
this.rows = Math.max(1, rows | 0);
|
|
621
|
+
this.cols = Math.max(1, cols | 0);
|
|
622
|
+
this.terminal.dispose();
|
|
623
|
+
this.terminal = this.createTerminal();
|
|
623
624
|
}
|
|
624
625
|
resize(rows, cols) {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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);
|
|
626
|
+
this.rows = Math.max(1, rows | 0);
|
|
627
|
+
this.cols = Math.max(1, cols | 0);
|
|
628
|
+
this.terminal.resize(this.cols, this.rows);
|
|
642
629
|
}
|
|
643
630
|
write(data) {
|
|
644
|
-
|
|
645
|
-
|
|
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
|
-
}
|
|
631
|
+
if (!data) return;
|
|
632
|
+
this.terminal.write(data);
|
|
678
633
|
}
|
|
679
634
|
getText() {
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
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 }, () => " "));
|
|
635
|
+
const buffer = this.terminal.buffer.active;
|
|
636
|
+
const start = Math.max(0, buffer.viewportY || 0);
|
|
637
|
+
const end = Math.max(start, Math.min(buffer.length || 0, start + this.rows));
|
|
638
|
+
const lines = [];
|
|
639
|
+
for (let i = start; i < end; i++) {
|
|
640
|
+
const line = buffer.getLine(i);
|
|
641
|
+
lines.push(line ? line.translateToString(true) : "");
|
|
642
|
+
}
|
|
643
|
+
let first = 0;
|
|
644
|
+
let last = lines.length;
|
|
645
|
+
while (first < last && !lines[first]?.trim()) first++;
|
|
646
|
+
while (last > first && !lines[last - 1]?.trim()) last--;
|
|
647
|
+
return lines.slice(first, last).join("\n");
|
|
648
|
+
}
|
|
649
|
+
createTerminal() {
|
|
650
|
+
const Terminal = loadTerminalCtor();
|
|
651
|
+
return new Terminal({
|
|
652
|
+
cols: this.cols,
|
|
653
|
+
rows: this.rows,
|
|
654
|
+
scrollback: 2e3
|
|
655
|
+
});
|
|
829
656
|
}
|
|
830
657
|
};
|
|
831
658
|
}
|
|
@@ -965,6 +792,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
965
792
|
};
|
|
966
793
|
const rawKeys = provider.approvalKeys;
|
|
967
794
|
this.approvalKeys = rawKeys && typeof rawKeys === "object" ? rawKeys : {};
|
|
795
|
+
this.sendDelayMs = typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0;
|
|
796
|
+
this.sendKey = typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r";
|
|
968
797
|
this.cliScripts = provider.scripts || {};
|
|
969
798
|
const scriptNames = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
|
|
970
799
|
if (scriptNames.length > 0) {
|
|
@@ -1007,6 +836,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1007
836
|
// Output settle debounce — fires after PTY output goes quiet
|
|
1008
837
|
settleTimer = null;
|
|
1009
838
|
settledBuffer = "";
|
|
839
|
+
submitPendingUntil = 0;
|
|
1010
840
|
// Resize redraw suppression
|
|
1011
841
|
resizeSuppressUntil = 0;
|
|
1012
842
|
// Debug: status transition history
|
|
@@ -1033,6 +863,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
1033
863
|
timeouts;
|
|
1034
864
|
// Provider approval key mapping
|
|
1035
865
|
approvalKeys;
|
|
866
|
+
sendDelayMs;
|
|
867
|
+
sendKey;
|
|
1036
868
|
/** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
|
|
1037
869
|
setCliScripts(scripts) {
|
|
1038
870
|
this.cliScripts = scripts;
|
|
@@ -1135,6 +967,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1135
967
|
// ─── Output Handling ────────────────────────────
|
|
1136
968
|
handleOutput(rawData) {
|
|
1137
969
|
if (Date.now() < this.resizeSuppressUntil) return;
|
|
970
|
+
if (rawData.includes("\x1B[6n") || rawData.includes("\x1B[?6n")) {
|
|
971
|
+
this.ptyProcess?.write("\x1B[1;1R");
|
|
972
|
+
}
|
|
1138
973
|
this.terminalScreen.write(rawData);
|
|
1139
974
|
const cleanData = stripAnsi(rawData);
|
|
1140
975
|
if (this.isWaitingForResponse && cleanData) {
|
|
@@ -1179,11 +1014,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
1179
1014
|
}
|
|
1180
1015
|
scheduleSettle() {
|
|
1181
1016
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
1017
|
+
const delay = Math.max(
|
|
1018
|
+
this.timeouts.outputSettle,
|
|
1019
|
+
this.submitPendingUntil > Date.now() ? this.submitPendingUntil - Date.now() + this.timeouts.outputSettle : 0
|
|
1020
|
+
);
|
|
1182
1021
|
this.settleTimer = setTimeout(() => {
|
|
1183
1022
|
this.settleTimer = null;
|
|
1184
1023
|
this.settledBuffer = this.recentOutputBuffer;
|
|
1185
1024
|
this.evaluateSettled();
|
|
1186
|
-
},
|
|
1025
|
+
}, delay);
|
|
1187
1026
|
}
|
|
1188
1027
|
evaluateSettled() {
|
|
1189
1028
|
const tail = this.settledBuffer;
|
|
@@ -1273,7 +1112,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
1273
1112
|
runDetectStatus(text) {
|
|
1274
1113
|
if (!this.cliScripts?.detectStatus) return null;
|
|
1275
1114
|
try {
|
|
1276
|
-
return this.cliScripts.detectStatus({
|
|
1115
|
+
return this.cliScripts.detectStatus({
|
|
1116
|
+
tail: text.slice(-500),
|
|
1117
|
+
screenText: this.terminalScreen.getText(),
|
|
1118
|
+
rawBuffer: this.accumulatedRawBuffer
|
|
1119
|
+
});
|
|
1277
1120
|
} catch (e) {
|
|
1278
1121
|
LOG.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
1279
1122
|
return null;
|
|
@@ -1383,10 +1226,21 @@ ${data.message || ""}`.trim();
|
|
|
1383
1226
|
this.responseBuffer = "";
|
|
1384
1227
|
this.setStatus("generating", "sendMessage");
|
|
1385
1228
|
this.onStatusChange?.();
|
|
1386
|
-
this.ptyProcess.write(text
|
|
1387
|
-
|
|
1388
|
-
if (this.
|
|
1389
|
-
|
|
1229
|
+
this.ptyProcess.write(text);
|
|
1230
|
+
const submit = () => {
|
|
1231
|
+
if (!this.ptyProcess) return;
|
|
1232
|
+
this.submitPendingUntil = 0;
|
|
1233
|
+
this.ptyProcess.write(this.sendKey);
|
|
1234
|
+
this.responseTimeout = setTimeout(() => {
|
|
1235
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
1236
|
+
}, this.timeouts.maxResponse);
|
|
1237
|
+
};
|
|
1238
|
+
if (this.sendDelayMs > 0) {
|
|
1239
|
+
this.submitPendingUntil = Date.now() + this.sendDelayMs;
|
|
1240
|
+
setTimeout(submit, this.sendDelayMs);
|
|
1241
|
+
} else {
|
|
1242
|
+
submit();
|
|
1243
|
+
}
|
|
1390
1244
|
}
|
|
1391
1245
|
getPartialResponse() {
|
|
1392
1246
|
if (!this.isWaitingForResponse) return "";
|
|
@@ -1469,10 +1323,14 @@ ${data.message || ""}`.trim();
|
|
|
1469
1323
|
messages: this.messages.slice(-20),
|
|
1470
1324
|
structuredMessages: this.structuredMessages.slice(-20),
|
|
1471
1325
|
messageCount: this.messages.length,
|
|
1326
|
+
screenText: this.terminalScreen.getText().slice(-4e3),
|
|
1472
1327
|
startupBuffer: this.startupBuffer.slice(-4e3),
|
|
1473
1328
|
recentOutputBuffer: this.recentOutputBuffer.slice(-500),
|
|
1474
1329
|
settledBuffer: this.settledBuffer.slice(-500),
|
|
1475
1330
|
accumulatedBufferLength: this.accumulatedBuffer.length,
|
|
1331
|
+
accumulatedRawBufferLength: this.accumulatedRawBuffer.length,
|
|
1332
|
+
rawBufferPreview: this.accumulatedRawBuffer.slice(-1e3),
|
|
1333
|
+
responseBuffer: this.responseBuffer.slice(-1e3),
|
|
1476
1334
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
1477
1335
|
activeModal: this.activeModal,
|
|
1478
1336
|
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
@@ -8137,7 +7995,8 @@ var CliProviderInstance = class {
|
|
|
8137
7995
|
return { ...m, content };
|
|
8138
7996
|
});
|
|
8139
7997
|
const partial = this.adapter.getPartialResponse();
|
|
8140
|
-
|
|
7998
|
+
const shouldAppendRawPartial = !parsedStatus;
|
|
7999
|
+
if (shouldAppendRawPartial && adapterStatus.status === "generating" && partial) {
|
|
8141
8000
|
const cleaned = partial.trim();
|
|
8142
8001
|
if (cleaned && cleaned !== "(generating...)") {
|
|
8143
8002
|
recentMessages.push({
|
|
@@ -13236,7 +13095,7 @@ var DevServer = class _DevServer {
|
|
|
13236
13095
|
lines.push("| Function | Input | Return |");
|
|
13237
13096
|
lines.push("|---|---|---|");
|
|
13238
13097
|
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` |");
|
|
13098
|
+
lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
|
|
13240
13099
|
lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
|
|
13241
13100
|
lines.push("");
|
|
13242
13101
|
lines.push("## Rules");
|
|
@@ -13249,6 +13108,7 @@ var DevServer = class _DevServer {
|
|
|
13249
13108
|
lines.push("7. Use `rawBuffer` only when ANSI/control-sequence artifacts matter. Do not depend on raw escape noise unless necessary.");
|
|
13250
13109
|
lines.push("8. Keep exports compatible with the existing `scripts.js` router (`module.exports = function ...`).");
|
|
13251
13110
|
lines.push("9. Do not rewrite unrelated provider config. Only touch the scripts needed for this task unless a tiny supporting change is required.");
|
|
13111
|
+
lines.push("10. When the verification API returns `instanceId`, keep using that exact instance for follow-up `send`, `resolve`, `raw`, and `stop` calls. Do not assume type-only routing is safe if multiple sessions exist.");
|
|
13252
13112
|
lines.push("");
|
|
13253
13113
|
lines.push("## Task");
|
|
13254
13114
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
@@ -13269,25 +13129,38 @@ var DevServer = class _DevServer {
|
|
|
13269
13129
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
13270
13130
|
lines.push("```");
|
|
13271
13131
|
lines.push("");
|
|
13272
|
-
lines.push("
|
|
13132
|
+
lines.push("Extract the current `instanceId` from the launch or status response and keep using it below.");
|
|
13133
|
+
lines.push("");
|
|
13134
|
+
lines.push("### 3. Send a realistic approval-triggering prompt");
|
|
13273
13135
|
lines.push("```bash");
|
|
13274
13136
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
|
|
13275
13137
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
13276
|
-
lines.push(` -d '{"type":"${type}","text":"
|
|
13138
|
+
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","text":"Create a file at tmp/adhdev_provider_fix_test.py that prints the current working directory and the squares of 1 through 5, then run python3 tmp/adhdev_provider_fix_test.py and tell me the exact output."}'`);
|
|
13277
13139
|
lines.push("```");
|
|
13278
13140
|
lines.push("");
|
|
13279
|
-
lines.push("### 4. If approval appears, resolve it");
|
|
13141
|
+
lines.push("### 4. If approval appears, resolve it until the CLI reaches idle");
|
|
13280
13142
|
lines.push("```bash");
|
|
13281
13143
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
|
|
13282
13144
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
13283
|
-
lines.push(` -d '{"type":"${type}","buttonIndex":0}'`);
|
|
13145
|
+
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","buttonIndex":0}'`);
|
|
13146
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/raw \\`);
|
|
13147
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
13148
|
+
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","keys":"1"}'`);
|
|
13149
|
+
lines.push("```");
|
|
13150
|
+
lines.push("");
|
|
13151
|
+
lines.push("Use `resolve` when the parsed modal buttons are correct. Use `raw` when the CLI expects a literal keystroke like `1`, `y`, or Enter. Repeat until idle.");
|
|
13152
|
+
lines.push("");
|
|
13153
|
+
lines.push("### 5. Verify the side effects outside the CLI");
|
|
13154
|
+
lines.push("```bash");
|
|
13155
|
+
lines.push("test -f tmp/adhdev_provider_fix_test.py");
|
|
13156
|
+
lines.push("python3 tmp/adhdev_provider_fix_test.py");
|
|
13284
13157
|
lines.push("```");
|
|
13285
13158
|
lines.push("");
|
|
13286
|
-
lines.push("###
|
|
13159
|
+
lines.push("### 6. Stop the CLI when finished");
|
|
13287
13160
|
lines.push("```bash");
|
|
13288
13161
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/stop \\`);
|
|
13289
13162
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
13290
|
-
lines.push(` -d '{"type":"${type}"}'`);
|
|
13163
|
+
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>"}'`);
|
|
13291
13164
|
lines.push("```");
|
|
13292
13165
|
lines.push("");
|
|
13293
13166
|
lines.push("## Required Validation");
|
|
@@ -13295,7 +13168,9 @@ var DevServer = class _DevServer {
|
|
|
13295
13168
|
lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
|
|
13296
13169
|
lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
|
|
13297
13170
|
lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
|
|
13298
|
-
lines.push("5.
|
|
13171
|
+
lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
|
|
13172
|
+
lines.push("6. Confirm the final assistant transcript includes the exact Python output, including the working directory line and the five square numbers.");
|
|
13173
|
+
lines.push("7. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
|
|
13299
13174
|
lines.push("");
|
|
13300
13175
|
if (userComment) {
|
|
13301
13176
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
@@ -13417,6 +13292,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13417
13292
|
}));
|
|
13418
13293
|
this.json(res, 200, { instances: result, count: result.length });
|
|
13419
13294
|
}
|
|
13295
|
+
findCliTarget(type, instanceId) {
|
|
13296
|
+
if (!this.instanceManager) return null;
|
|
13297
|
+
const cliStates = this.instanceManager.collectAllStates().filter((s) => s.category === "cli" || s.category === "acp");
|
|
13298
|
+
if (instanceId) return cliStates.find((s) => s.instanceId === instanceId) || null;
|
|
13299
|
+
if (!type) return cliStates[cliStates.length - 1] || null;
|
|
13300
|
+
const matches = cliStates.filter((s) => s.type === type);
|
|
13301
|
+
return matches[matches.length - 1] || null;
|
|
13302
|
+
}
|
|
13420
13303
|
/** POST /api/cli/launch — launch a CLI agent { type, workingDir?, args? } */
|
|
13421
13304
|
async handleCliLaunch(req, res) {
|
|
13422
13305
|
if (!this.cliManager) {
|
|
@@ -13448,10 +13331,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13448
13331
|
this.json(res, 400, { error: "text required" });
|
|
13449
13332
|
return;
|
|
13450
13333
|
}
|
|
13451
|
-
const
|
|
13452
|
-
const target = allStates.find(
|
|
13453
|
-
(s) => (s.category === "cli" || s.category === "acp") && (instanceId ? s.instanceId === instanceId : s.type === type)
|
|
13454
|
-
);
|
|
13334
|
+
const target = this.findCliTarget(type, instanceId);
|
|
13455
13335
|
if (!target) {
|
|
13456
13336
|
this.json(res, 404, { error: `No running instance found for: ${type || instanceId}` });
|
|
13457
13337
|
return;
|
|
@@ -13471,10 +13351,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13471
13351
|
}
|
|
13472
13352
|
const body = await this.readBody(req);
|
|
13473
13353
|
const { type, instanceId } = body;
|
|
13474
|
-
const
|
|
13475
|
-
const target = allStates.find(
|
|
13476
|
-
(s) => (s.category === "cli" || s.category === "acp") && (instanceId ? s.instanceId === instanceId : s.type === type)
|
|
13477
|
-
);
|
|
13354
|
+
const target = this.findCliTarget(type, instanceId);
|
|
13478
13355
|
if (!target) {
|
|
13479
13356
|
this.json(res, 404, { error: `No running instance found for: ${type || instanceId}` });
|
|
13480
13357
|
return;
|
|
@@ -13529,11 +13406,9 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13529
13406
|
this.json(res, 503, { error: "InstanceManager not available" });
|
|
13530
13407
|
return;
|
|
13531
13408
|
}
|
|
13532
|
-
const
|
|
13533
|
-
const target = allStates.find(
|
|
13534
|
-
(s) => (s.category === "cli" || s.category === "acp") && s.type === type
|
|
13535
|
-
);
|
|
13409
|
+
const target = this.findCliTarget(type);
|
|
13536
13410
|
if (!target) {
|
|
13411
|
+
const allStates = this.instanceManager.collectAllStates();
|
|
13537
13412
|
this.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s) => s.category === "cli" || s.category === "acp").map((s) => s.type) });
|
|
13538
13413
|
return;
|
|
13539
13414
|
}
|
|
@@ -13580,21 +13455,25 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13580
13455
|
this.json(res, 503, { error: "CliManager not available" });
|
|
13581
13456
|
return;
|
|
13582
13457
|
}
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
adapter = a;
|
|
13587
|
-
break;
|
|
13588
|
-
}
|
|
13458
|
+
if (!this.instanceManager) {
|
|
13459
|
+
this.json(res, 503, { error: "InstanceManager not available" });
|
|
13460
|
+
return;
|
|
13589
13461
|
}
|
|
13590
|
-
|
|
13462
|
+
const target = this.findCliTarget(type, instanceId);
|
|
13463
|
+
if (!target) {
|
|
13591
13464
|
this.json(res, 404, { error: `No running adapter for: ${type || instanceId}` });
|
|
13592
13465
|
return;
|
|
13593
13466
|
}
|
|
13467
|
+
const instance = this.instanceManager.getInstance(target.instanceId);
|
|
13468
|
+
const adapter = instance?.getAdapter?.() || instance?.adapter;
|
|
13469
|
+
if (!adapter) {
|
|
13470
|
+
this.json(res, 404, { error: `Adapter not found for instance: ${target.instanceId}` });
|
|
13471
|
+
return;
|
|
13472
|
+
}
|
|
13594
13473
|
try {
|
|
13595
13474
|
if (typeof adapter.resolveModal === "function") {
|
|
13596
13475
|
adapter.resolveModal(buttonIndex);
|
|
13597
|
-
this.json(res, 200, { resolved: true, type, buttonIndex });
|
|
13476
|
+
this.json(res, 200, { resolved: true, type: target.type, instanceId: target.instanceId, buttonIndex });
|
|
13598
13477
|
} else {
|
|
13599
13478
|
this.json(res, 400, { error: "resolveModal not available on this adapter" });
|
|
13600
13479
|
}
|
|
@@ -13614,21 +13493,25 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13614
13493
|
this.json(res, 503, { error: "CliManager not available" });
|
|
13615
13494
|
return;
|
|
13616
13495
|
}
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
adapter = a;
|
|
13621
|
-
break;
|
|
13622
|
-
}
|
|
13496
|
+
if (!this.instanceManager) {
|
|
13497
|
+
this.json(res, 503, { error: "InstanceManager not available" });
|
|
13498
|
+
return;
|
|
13623
13499
|
}
|
|
13624
|
-
|
|
13500
|
+
const target = this.findCliTarget(type, instanceId);
|
|
13501
|
+
if (!target) {
|
|
13625
13502
|
this.json(res, 404, { error: `No running adapter for: ${type || instanceId}` });
|
|
13626
13503
|
return;
|
|
13627
13504
|
}
|
|
13505
|
+
const instance = this.instanceManager.getInstance(target.instanceId);
|
|
13506
|
+
const adapter = instance?.getAdapter?.() || instance?.adapter;
|
|
13507
|
+
if (!adapter) {
|
|
13508
|
+
this.json(res, 404, { error: `Adapter not found for instance: ${target.instanceId}` });
|
|
13509
|
+
return;
|
|
13510
|
+
}
|
|
13628
13511
|
try {
|
|
13629
13512
|
if (typeof adapter.writeRaw === "function") {
|
|
13630
13513
|
adapter.writeRaw(keys);
|
|
13631
|
-
this.json(res, 200, { sent: true, type, keysLength: keys.length });
|
|
13514
|
+
this.json(res, 200, { sent: true, type: target.type, instanceId: target.instanceId, keysLength: keys.length });
|
|
13632
13515
|
} else {
|
|
13633
13516
|
this.json(res, 400, { error: "writeRaw not available on this adapter" });
|
|
13634
13517
|
}
|