@adhdev/daemon-core 0.7.42 → 0.7.44
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/cli-adapters/provider-cli-adapter.d.ts +2 -4
- package/dist/cli-adapters/pty-transport.d.ts +1 -0
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +4 -0
- package/dist/cli-adapters/terminal-backends/types.d.ts +4 -0
- package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +4 -0
- package/dist/cli-adapters/terminal-screen.d.ts +4 -0
- package/dist/commands/upgrade-helper.d.ts +10 -0
- package/dist/config/chat-history.d.ts +0 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +509 -364
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +497 -353
- package/dist/index.mjs.map +1 -1
- package/dist/providers/provider-instance.d.ts +0 -1
- package/dist/status/normalize.js +0 -7
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +0 -7
- package/dist/status/normalize.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.js +2 -2
- package/node_modules/@adhdev/session-host-core/dist/index.js.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.mjs +2 -2
- package/node_modules/@adhdev/session-host-core/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +79 -70
- package/src/cli-adapters/pty-transport.ts +2 -0
- package/src/cli-adapters/session-host-transport.ts +1 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +5 -0
- package/src/cli-adapters/terminal-backends/types.ts +1 -0
- package/src/cli-adapters/terminal-backends/xterm-backend.ts +10 -0
- package/src/cli-adapters/terminal-screen.ts +4 -0
- package/src/commands/router.ts +29 -23
- package/src/commands/upgrade-helper.ts +214 -0
- package/src/config/chat-history.ts +3 -55
- package/src/index.ts +1 -0
- package/src/providers/cli-provider-instance.ts +1 -11
- package/src/providers/provider-instance.d.ts +0 -1
- package/src/providers/provider-instance.ts +0 -1
- package/src/status/normalize.ts +0 -4
package/dist/index.mjs
CHANGED
|
@@ -515,6 +515,9 @@ var init_ghostty_vt_backend = __esm({
|
|
|
515
515
|
getText() {
|
|
516
516
|
return this.terminal.formatPlainText({ trim: true }) || "";
|
|
517
517
|
}
|
|
518
|
+
getCursorPosition() {
|
|
519
|
+
return this.terminal.getCursorPosition();
|
|
520
|
+
}
|
|
518
521
|
dispose() {
|
|
519
522
|
this.terminal.dispose();
|
|
520
523
|
}
|
|
@@ -572,6 +575,13 @@ var init_xterm_backend = __esm({
|
|
|
572
575
|
while (last > first && !lines[last - 1]?.trim()) last--;
|
|
573
576
|
return lines.slice(first, last).join("\n");
|
|
574
577
|
}
|
|
578
|
+
getCursorPosition() {
|
|
579
|
+
const buffer = this.terminal.buffer.active;
|
|
580
|
+
return {
|
|
581
|
+
col: Math.max(0, buffer.cursorX || 0),
|
|
582
|
+
row: Math.max(0, buffer.cursorY || 0)
|
|
583
|
+
};
|
|
584
|
+
}
|
|
575
585
|
dispose() {
|
|
576
586
|
this.terminal.dispose();
|
|
577
587
|
}
|
|
@@ -658,6 +668,9 @@ var init_terminal_screen = __esm({
|
|
|
658
668
|
getText() {
|
|
659
669
|
return this.terminal.getText();
|
|
660
670
|
}
|
|
671
|
+
getCursorPosition() {
|
|
672
|
+
return this.terminal.getCursorPosition();
|
|
673
|
+
}
|
|
661
674
|
dispose() {
|
|
662
675
|
this.terminal.dispose();
|
|
663
676
|
}
|
|
@@ -673,7 +686,7 @@ var init_terminal_screen = __esm({
|
|
|
673
686
|
});
|
|
674
687
|
|
|
675
688
|
// src/cli-adapters/pty-transport.ts
|
|
676
|
-
import * as
|
|
689
|
+
import * as os12 from "os";
|
|
677
690
|
var pty, NodePtyRuntimeTransport, NodePtyTransportFactory;
|
|
678
691
|
var init_pty_transport = __esm({
|
|
679
692
|
"src/cli-adapters/pty-transport.ts"() {
|
|
@@ -688,6 +701,7 @@ var init_pty_transport = __esm({
|
|
|
688
701
|
this.handle = handle;
|
|
689
702
|
}
|
|
690
703
|
ready = Promise.resolve();
|
|
704
|
+
terminalQueriesHandled = false;
|
|
691
705
|
get pid() {
|
|
692
706
|
return this.handle.pid;
|
|
693
707
|
}
|
|
@@ -714,7 +728,7 @@ var init_pty_transport = __esm({
|
|
|
714
728
|
spawn(command, args, options) {
|
|
715
729
|
if (!pty) throw new Error("node-pty is not installed");
|
|
716
730
|
const handle = pty.spawn(command, args, {
|
|
717
|
-
name:
|
|
731
|
+
name: os12.platform() === "win32" ? "xterm-color" : "xterm-256color",
|
|
718
732
|
cols: options.cols,
|
|
719
733
|
rows: options.rows,
|
|
720
734
|
cwd: options.cwd,
|
|
@@ -732,8 +746,8 @@ __export(provider_cli_adapter_exports, {
|
|
|
732
746
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
733
747
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
734
748
|
});
|
|
735
|
-
import * as
|
|
736
|
-
import * as
|
|
749
|
+
import * as os13 from "os";
|
|
750
|
+
import * as path10 from "path";
|
|
737
751
|
import { execSync as execSync4 } from "child_process";
|
|
738
752
|
function stripAnsi(str) {
|
|
739
753
|
return str.replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "").replace(/ +/g, " ");
|
|
@@ -744,8 +758,34 @@ function stripTerminalNoise(str) {
|
|
|
744
758
|
function sanitizeTerminalText(str) {
|
|
745
759
|
return stripTerminalNoise(stripAnsi(str));
|
|
746
760
|
}
|
|
761
|
+
function buildCliSpawnEnv(baseEnv, overrides) {
|
|
762
|
+
const env = {};
|
|
763
|
+
const source = { ...baseEnv, ...overrides || {} };
|
|
764
|
+
for (const [key, value] of Object.entries(source)) {
|
|
765
|
+
if (typeof value !== "string") continue;
|
|
766
|
+
env[key] = value;
|
|
767
|
+
}
|
|
768
|
+
for (const key of Object.keys(env)) {
|
|
769
|
+
if (key === "INIT_CWD" || key === "NO_COLOR" || key === "FORCE_COLOR" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_")) {
|
|
770
|
+
delete env[key];
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return env;
|
|
774
|
+
}
|
|
775
|
+
function computeTerminalQueryTail(buffer) {
|
|
776
|
+
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
777
|
+
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
778
|
+
const start = Math.max(0, buffer.length - maxLength);
|
|
779
|
+
for (let i = start; i < buffer.length; i++) {
|
|
780
|
+
const suffix = buffer.slice(i);
|
|
781
|
+
if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {
|
|
782
|
+
return suffix;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return "";
|
|
786
|
+
}
|
|
747
787
|
function findBinary(name) {
|
|
748
|
-
const isWin =
|
|
788
|
+
const isWin = os13.platform() === "win32";
|
|
749
789
|
try {
|
|
750
790
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
751
791
|
return execSync4(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
@@ -754,14 +794,14 @@ function findBinary(name) {
|
|
|
754
794
|
}
|
|
755
795
|
}
|
|
756
796
|
function isScriptBinary(binaryPath) {
|
|
757
|
-
if (!
|
|
797
|
+
if (!path10.isAbsolute(binaryPath)) return false;
|
|
758
798
|
try {
|
|
759
|
-
const
|
|
760
|
-
const resolved =
|
|
799
|
+
const fs13 = __require("fs");
|
|
800
|
+
const resolved = fs13.realpathSync(binaryPath);
|
|
761
801
|
const head = Buffer.alloc(8);
|
|
762
|
-
const fd =
|
|
763
|
-
|
|
764
|
-
|
|
802
|
+
const fd = fs13.openSync(resolved, "r");
|
|
803
|
+
fs13.readSync(fd, head, 0, 8, 0);
|
|
804
|
+
fs13.closeSync(fd);
|
|
765
805
|
let i = 0;
|
|
766
806
|
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
767
807
|
return head[i] === 35 && head[i + 1] === 33;
|
|
@@ -770,14 +810,14 @@ function isScriptBinary(binaryPath) {
|
|
|
770
810
|
}
|
|
771
811
|
}
|
|
772
812
|
function looksLikeMachOOrElf(filePath) {
|
|
773
|
-
if (!
|
|
813
|
+
if (!path10.isAbsolute(filePath)) return false;
|
|
774
814
|
try {
|
|
775
|
-
const
|
|
776
|
-
const resolved =
|
|
815
|
+
const fs13 = __require("fs");
|
|
816
|
+
const resolved = fs13.realpathSync(filePath);
|
|
777
817
|
const buf = Buffer.alloc(8);
|
|
778
|
-
const fd =
|
|
779
|
-
|
|
780
|
-
|
|
818
|
+
const fd = fs13.openSync(resolved, "r");
|
|
819
|
+
fs13.readSync(fd, buf, 0, 8, 0);
|
|
820
|
+
fs13.closeSync(fd);
|
|
781
821
|
let i = 0;
|
|
782
822
|
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
783
823
|
const b = buf.subarray(i);
|
|
@@ -793,7 +833,7 @@ function looksLikeMachOOrElf(filePath) {
|
|
|
793
833
|
}
|
|
794
834
|
function shSingleQuote(arg) {
|
|
795
835
|
if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
|
|
796
|
-
if (
|
|
836
|
+
if (os13.platform() === "win32") {
|
|
797
837
|
return `"${arg.replace(/"/g, '""')}"`;
|
|
798
838
|
}
|
|
799
839
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
@@ -830,36 +870,6 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
830
870
|
).length;
|
|
831
871
|
return matched >= required;
|
|
832
872
|
}
|
|
833
|
-
function splitHistoryLines(text) {
|
|
834
|
-
return String(text || "").split("\n").map((line) => line.replace(/\s+$/, ""));
|
|
835
|
-
}
|
|
836
|
-
function normalizeHistoryLine(line) {
|
|
837
|
-
return String(line || "").replace(/\s+/g, " ").trim();
|
|
838
|
-
}
|
|
839
|
-
function mergeTerminalHistory(existing, snapshot) {
|
|
840
|
-
const next = String(snapshot || "").trim();
|
|
841
|
-
if (!next) return existing;
|
|
842
|
-
const prev = String(existing || "").trim();
|
|
843
|
-
if (!prev) return next;
|
|
844
|
-
if (prev === next || prev.endsWith(next)) return prev;
|
|
845
|
-
const prevLines = splitHistoryLines(prev);
|
|
846
|
-
const nextLines = splitHistoryLines(next);
|
|
847
|
-
const prevNorm = prevLines.map(normalizeHistoryLine);
|
|
848
|
-
const nextNorm = nextLines.map(normalizeHistoryLine);
|
|
849
|
-
const maxOverlap = Math.min(prevLines.length, nextLines.length);
|
|
850
|
-
for (let overlap = maxOverlap; overlap >= 1; overlap -= 1) {
|
|
851
|
-
const prevTail = prevNorm.slice(prevNorm.length - overlap);
|
|
852
|
-
const nextHead = nextNorm.slice(0, overlap);
|
|
853
|
-
if (prevTail.every((line, index) => line === nextHead[index])) {
|
|
854
|
-
return [...prevLines, ...nextLines.slice(overlap)].join("\n").trim();
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
const compactPrev = prevNorm.join("\n");
|
|
858
|
-
const compactNext = nextNorm.join("\n");
|
|
859
|
-
if (compactPrev.includes(compactNext)) return prev;
|
|
860
|
-
return `${prev}
|
|
861
|
-
${next}`.trim();
|
|
862
|
-
}
|
|
863
873
|
function parsePatternEntry(x) {
|
|
864
874
|
if (x instanceof RegExp) return x;
|
|
865
875
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -893,16 +903,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
893
903
|
init_pty_transport();
|
|
894
904
|
try {
|
|
895
905
|
pty2 = __require("node-pty");
|
|
896
|
-
if (
|
|
906
|
+
if (os13.platform() !== "win32") {
|
|
897
907
|
try {
|
|
898
|
-
const
|
|
899
|
-
const ptyDir =
|
|
900
|
-
const platformArch = `${
|
|
901
|
-
const helper =
|
|
902
|
-
if (
|
|
903
|
-
const stat =
|
|
908
|
+
const fs13 = __require("fs");
|
|
909
|
+
const ptyDir = path10.resolve(path10.dirname(__require.resolve("node-pty")), "..");
|
|
910
|
+
const platformArch = `${os13.platform()}-${os13.arch()}`;
|
|
911
|
+
const helper = path10.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
912
|
+
if (fs13.existsSync(helper)) {
|
|
913
|
+
const stat = fs13.statSync(helper);
|
|
904
914
|
if (!(stat.mode & 73)) {
|
|
905
|
-
|
|
915
|
+
fs13.chmodSync(helper, stat.mode | 493);
|
|
906
916
|
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
907
917
|
}
|
|
908
918
|
}
|
|
@@ -919,7 +929,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
919
929
|
this.transportFactory = transportFactory;
|
|
920
930
|
this.cliType = provider.type;
|
|
921
931
|
this.cliName = provider.name;
|
|
922
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
932
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os13.homedir()) : workingDir;
|
|
923
933
|
const t = provider.timeouts || {};
|
|
924
934
|
this.timeouts = {
|
|
925
935
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -971,6 +981,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
971
981
|
pendingOutputParseTimer = null;
|
|
972
982
|
ptyOutputBuffer = "";
|
|
973
983
|
ptyOutputFlushTimer = null;
|
|
984
|
+
pendingTerminalQueryTail = "";
|
|
974
985
|
// Server log forwarding
|
|
975
986
|
serverConn = null;
|
|
976
987
|
logBuffer = [];
|
|
@@ -1002,9 +1013,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1002
1013
|
/** Full accumulated raw PTY output (with ANSI) */
|
|
1003
1014
|
accumulatedRawBuffer = "";
|
|
1004
1015
|
/** Current visible terminal screen snapshot */
|
|
1005
|
-
terminalScreen = new TerminalScreen(
|
|
1006
|
-
/** Rolling append-only terminal transcript built from screen snapshots */
|
|
1007
|
-
terminalHistory = "";
|
|
1016
|
+
terminalScreen = new TerminalScreen(30, 100);
|
|
1008
1017
|
/** Max accumulated buffer size (last 50KB) */
|
|
1009
1018
|
static MAX_ACCUMULATED_BUFFER = 5e4;
|
|
1010
1019
|
currentTurnScope = null;
|
|
@@ -1026,15 +1035,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
1026
1035
|
return text.slice(start);
|
|
1027
1036
|
}
|
|
1028
1037
|
buildParseInput(baseMessages, partialResponse, scope) {
|
|
1029
|
-
const buffer = scope ? this.sliceFromOffset(this.
|
|
1038
|
+
const buffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
1030
1039
|
const rawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
1031
|
-
const terminalHistory = scope ? this.sliceFromOffset(this.terminalHistory, scope.terminalHistoryStart) || this.terminalHistory : this.terminalHistory;
|
|
1032
1040
|
return {
|
|
1033
1041
|
buffer,
|
|
1034
1042
|
rawBuffer,
|
|
1035
1043
|
recentBuffer: buffer.slice(-1e3) || this.recentOutputBuffer,
|
|
1036
1044
|
screenText: this.terminalScreen.getText(),
|
|
1037
|
-
terminalHistory,
|
|
1038
1045
|
messages: [...baseMessages],
|
|
1039
1046
|
partialResponse
|
|
1040
1047
|
};
|
|
@@ -1089,12 +1096,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
1089
1096
|
if (this.ptyProcess) return;
|
|
1090
1097
|
const { spawn: spawnConfig } = this.provider;
|
|
1091
1098
|
const binaryPath = findBinary(spawnConfig.command);
|
|
1092
|
-
const isWin =
|
|
1099
|
+
const isWin = os13.platform() === "win32";
|
|
1093
1100
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
1094
1101
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1095
1102
|
let shellCmd;
|
|
1096
1103
|
let shellArgs;
|
|
1097
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1104
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1098
1105
|
const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
|
|
1099
1106
|
if (useShell) {
|
|
1100
1107
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -1112,13 +1119,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
1112
1119
|
shellArgs = allArgs;
|
|
1113
1120
|
}
|
|
1114
1121
|
const ptyOpts = {
|
|
1115
|
-
cols:
|
|
1116
|
-
rows:
|
|
1122
|
+
cols: 100,
|
|
1123
|
+
rows: 30,
|
|
1117
1124
|
cwd: this.workingDir,
|
|
1118
|
-
env:
|
|
1119
|
-
...process.env,
|
|
1120
|
-
...spawnConfig.env
|
|
1121
|
-
}
|
|
1125
|
+
env: buildCliSpawnEnv(process.env, spawnConfig.env)
|
|
1122
1126
|
};
|
|
1123
1127
|
try {
|
|
1124
1128
|
this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
|
|
@@ -1136,8 +1140,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
1136
1140
|
}
|
|
1137
1141
|
this.ptyProcess.onData((data) => {
|
|
1138
1142
|
if (Date.now() < this.resizeSuppressUntil) return;
|
|
1139
|
-
if (
|
|
1140
|
-
this.
|
|
1143
|
+
if (!this.ptyProcess?.terminalQueriesHandled) {
|
|
1144
|
+
this.respondToTerminalQueries(data);
|
|
1141
1145
|
}
|
|
1142
1146
|
this.pendingOutputParseBuffer += data;
|
|
1143
1147
|
if (!this.pendingOutputParseTimer) {
|
|
@@ -1172,8 +1176,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
1172
1176
|
this.spawnAt = Date.now();
|
|
1173
1177
|
this.startupParseGate = true;
|
|
1174
1178
|
this.startupBuffer = "";
|
|
1175
|
-
this.terminalScreen.reset(
|
|
1176
|
-
this.
|
|
1179
|
+
this.terminalScreen.reset(30, 100);
|
|
1180
|
+
this.pendingTerminalQueryTail = "";
|
|
1177
1181
|
this.currentTurnScope = null;
|
|
1178
1182
|
this.ready = false;
|
|
1179
1183
|
await this.ptyProcess.ready;
|
|
@@ -1183,7 +1187,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
1183
1187
|
// ─── Output Handling ────────────────────────────
|
|
1184
1188
|
handleOutput(rawData) {
|
|
1185
1189
|
this.terminalScreen.write(rawData);
|
|
1186
|
-
this.terminalHistory = mergeTerminalHistory(this.terminalHistory, this.terminalScreen.getText());
|
|
1187
1190
|
const cleanData = sanitizeTerminalText(rawData);
|
|
1188
1191
|
if (this.isWaitingForResponse && cleanData) {
|
|
1189
1192
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
@@ -1459,8 +1462,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1459
1462
|
status: this.currentStatus,
|
|
1460
1463
|
messages: [...this.committedMessages],
|
|
1461
1464
|
workingDir: this.workingDir,
|
|
1462
|
-
activeModal: this.activeModal
|
|
1463
|
-
terminalHistory: this.terminalHistory
|
|
1465
|
+
activeModal: this.activeModal
|
|
1464
1466
|
};
|
|
1465
1467
|
}
|
|
1466
1468
|
/**
|
|
@@ -1478,7 +1480,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
1478
1480
|
id: parsed.id || "cli_session",
|
|
1479
1481
|
status: parsed.status || this.currentStatus,
|
|
1480
1482
|
title: parsed.title || this.cliName,
|
|
1481
|
-
terminalHistory: this.terminalHistory,
|
|
1482
1483
|
messages: parsed.messages,
|
|
1483
1484
|
activeModal: parsed.activeModal ?? this.activeModal
|
|
1484
1485
|
};
|
|
@@ -1488,7 +1489,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
1488
1489
|
id: "cli_session",
|
|
1489
1490
|
status: this.currentStatus,
|
|
1490
1491
|
title: this.cliName,
|
|
1491
|
-
terminalHistory: this.terminalHistory,
|
|
1492
1492
|
messages: messages.slice(-50).map((message, index) => ({
|
|
1493
1493
|
id: `msg_${index}`,
|
|
1494
1494
|
role: message.role,
|
|
@@ -1556,10 +1556,9 @@ ${data.message || ""}`.trim();
|
|
|
1556
1556
|
prompt: text,
|
|
1557
1557
|
startedAt: Date.now(),
|
|
1558
1558
|
bufferStart: this.accumulatedBuffer.length,
|
|
1559
|
-
rawBufferStart: this.accumulatedRawBuffer.length
|
|
1560
|
-
terminalHistoryStart: this.terminalHistory.length
|
|
1559
|
+
rawBufferStart: this.accumulatedRawBuffer.length
|
|
1561
1560
|
};
|
|
1562
|
-
LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${this.currentTurnScope.bufferStart} raw=${this.currentTurnScope.rawBufferStart}
|
|
1561
|
+
LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${this.currentTurnScope.bufferStart} raw=${this.currentTurnScope.rawBufferStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
|
|
1563
1562
|
this.submitRetryUsed = false;
|
|
1564
1563
|
this.submitRetryPromptSnippet = extractPromptRetrySnippet(text);
|
|
1565
1564
|
const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet);
|
|
@@ -1744,6 +1743,7 @@ ${data.message || ""}`.trim();
|
|
|
1744
1743
|
this.pendingOutputParseTimer = null;
|
|
1745
1744
|
}
|
|
1746
1745
|
this.pendingOutputParseBuffer = "";
|
|
1746
|
+
this.pendingTerminalQueryTail = "";
|
|
1747
1747
|
if (this.ptyOutputFlushTimer) {
|
|
1748
1748
|
clearTimeout(this.ptyOutputFlushTimer);
|
|
1749
1749
|
this.ptyOutputFlushTimer = null;
|
|
@@ -1783,6 +1783,7 @@ ${data.message || ""}`.trim();
|
|
|
1783
1783
|
this.pendingOutputParseTimer = null;
|
|
1784
1784
|
}
|
|
1785
1785
|
this.pendingOutputParseBuffer = "";
|
|
1786
|
+
this.pendingTerminalQueryTail = "";
|
|
1786
1787
|
if (this.ptyOutputFlushTimer) {
|
|
1787
1788
|
clearTimeout(this.ptyOutputFlushTimer);
|
|
1788
1789
|
this.ptyOutputFlushTimer = null;
|
|
@@ -1809,7 +1810,6 @@ ${data.message || ""}`.trim();
|
|
|
1809
1810
|
this.syncMessageViews();
|
|
1810
1811
|
this.accumulatedBuffer = "";
|
|
1811
1812
|
this.accumulatedRawBuffer = "";
|
|
1812
|
-
this.terminalHistory = "";
|
|
1813
1813
|
this.currentTurnScope = null;
|
|
1814
1814
|
this.submitRetryUsed = false;
|
|
1815
1815
|
this.submitRetryPromptSnippet = "";
|
|
@@ -1818,6 +1818,7 @@ ${data.message || ""}`.trim();
|
|
|
1818
1818
|
this.pendingOutputParseTimer = null;
|
|
1819
1819
|
}
|
|
1820
1820
|
this.pendingOutputParseBuffer = "";
|
|
1821
|
+
this.pendingTerminalQueryTail = "";
|
|
1821
1822
|
if (this.ptyOutputFlushTimer) {
|
|
1822
1823
|
clearTimeout(this.ptyOutputFlushTimer);
|
|
1823
1824
|
this.ptyOutputFlushTimer = null;
|
|
@@ -1879,7 +1880,6 @@ ${data.message || ""}`.trim();
|
|
|
1879
1880
|
structuredMessages: this.structuredMessages.slice(-20),
|
|
1880
1881
|
messageCount: this.committedMessages.length,
|
|
1881
1882
|
screenText: sanitizeTerminalText(this.terminalScreen.getText()).slice(-4e3),
|
|
1882
|
-
terminalHistory: this.terminalHistory.slice(-8e3),
|
|
1883
1883
|
currentTurnScope: this.currentTurnScope,
|
|
1884
1884
|
startupBuffer: this.startupBuffer.slice(-4e3),
|
|
1885
1885
|
recentOutputBuffer: this.recentOutputBuffer.slice(-500),
|
|
@@ -1907,6 +1907,20 @@ ${data.message || ""}`.trim();
|
|
|
1907
1907
|
ptyAlive: !!this.ptyProcess
|
|
1908
1908
|
};
|
|
1909
1909
|
}
|
|
1910
|
+
respondToTerminalQueries(data) {
|
|
1911
|
+
if (!this.ptyProcess || !data) return;
|
|
1912
|
+
const combined = this.pendingTerminalQueryTail + data;
|
|
1913
|
+
const regex = /\x1b\[(\?)?6n/g;
|
|
1914
|
+
let match;
|
|
1915
|
+
while ((match = regex.exec(combined)) !== null) {
|
|
1916
|
+
const cursor = this.terminalScreen.getCursorPosition();
|
|
1917
|
+
const row = Math.max(1, (cursor.row | 0) + 1);
|
|
1918
|
+
const col = Math.max(1, (cursor.col | 0) + 1);
|
|
1919
|
+
const response = match[1] ? `\x1B[?${row};${col}R` : `\x1B[${row};${col}R`;
|
|
1920
|
+
this.ptyProcess.write(response);
|
|
1921
|
+
}
|
|
1922
|
+
this.pendingTerminalQueryTail = computeTerminalQueryTail(combined);
|
|
1923
|
+
}
|
|
1910
1924
|
};
|
|
1911
1925
|
}
|
|
1912
1926
|
});
|
|
@@ -2190,18 +2204,18 @@ function checkPathExists(paths) {
|
|
|
2190
2204
|
return null;
|
|
2191
2205
|
}
|
|
2192
2206
|
async function detectIDEs() {
|
|
2193
|
-
const
|
|
2207
|
+
const os17 = platform();
|
|
2194
2208
|
const results = [];
|
|
2195
2209
|
for (const def of getMergedDefinitions()) {
|
|
2196
2210
|
const cliPath = findCliCommand(def.cli);
|
|
2197
|
-
const appPath = checkPathExists(def.paths[
|
|
2211
|
+
const appPath = checkPathExists(def.paths[os17] || []);
|
|
2198
2212
|
const installed = !!(cliPath || appPath);
|
|
2199
2213
|
let resolvedCli = cliPath;
|
|
2200
|
-
if (!resolvedCli && appPath &&
|
|
2214
|
+
if (!resolvedCli && appPath && os17 === "darwin") {
|
|
2201
2215
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
2202
2216
|
if (existsSync3(bundledCli)) resolvedCli = bundledCli;
|
|
2203
2217
|
}
|
|
2204
|
-
if (!resolvedCli && appPath &&
|
|
2218
|
+
if (!resolvedCli && appPath && os17 === "win32") {
|
|
2205
2219
|
const { dirname: dirname7 } = await import("path");
|
|
2206
2220
|
const appDir = dirname7(appPath);
|
|
2207
2221
|
const candidates = [
|
|
@@ -3927,8 +3941,6 @@ var ChatHistoryWriter = class {
|
|
|
3927
3941
|
lastSeenCounts = /* @__PURE__ */ new Map();
|
|
3928
3942
|
/** Last seen message hash per agent (deduplication) */
|
|
3929
3943
|
lastSeenHashes = /* @__PURE__ */ new Map();
|
|
3930
|
-
/** Last seen append-only terminal transcript per agent */
|
|
3931
|
-
lastSeenTerminal = /* @__PURE__ */ new Map();
|
|
3932
3944
|
rotated = false;
|
|
3933
3945
|
/**
|
|
3934
3946
|
* Append new messages to history
|
|
@@ -3986,51 +3998,10 @@ var ChatHistoryWriter = class {
|
|
|
3986
3998
|
} catch {
|
|
3987
3999
|
}
|
|
3988
4000
|
}
|
|
3989
|
-
appendTerminalHistory(agentType, terminalHistory, sessionTitle, instanceId) {
|
|
3990
|
-
const next = String(terminalHistory || "");
|
|
3991
|
-
if (!next.trim()) return;
|
|
3992
|
-
try {
|
|
3993
|
-
const dedupKey = instanceId ? `${agentType}:${instanceId}:terminal` : `${agentType}:terminal`;
|
|
3994
|
-
const prev = this.lastSeenTerminal.get(dedupKey) || "";
|
|
3995
|
-
if (prev === next) return;
|
|
3996
|
-
let delta = "";
|
|
3997
|
-
if (!prev) {
|
|
3998
|
-
delta = next;
|
|
3999
|
-
} else if (next.startsWith(prev)) {
|
|
4000
|
-
delta = next.slice(prev.length);
|
|
4001
|
-
} else if (prev.includes(next)) {
|
|
4002
|
-
this.lastSeenTerminal.set(dedupKey, next);
|
|
4003
|
-
return;
|
|
4004
|
-
} else {
|
|
4005
|
-
delta = `
|
|
4006
|
-
|
|
4007
|
-
[terminal snapshot reset ${(/* @__PURE__ */ new Date()).toISOString()} | ${sessionTitle || agentType}]
|
|
4008
|
-
${next}`;
|
|
4009
|
-
}
|
|
4010
|
-
if (!delta) {
|
|
4011
|
-
this.lastSeenTerminal.set(dedupKey, next);
|
|
4012
|
-
return;
|
|
4013
|
-
}
|
|
4014
|
-
const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4015
|
-
fs3.mkdirSync(dir, { recursive: true });
|
|
4016
|
-
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4017
|
-
const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
|
|
4018
|
-
const filePath = path4.join(dir, `${filePrefix}${date}.terminal.log`);
|
|
4019
|
-
fs3.appendFileSync(filePath, delta, "utf-8");
|
|
4020
|
-
this.lastSeenTerminal.set(dedupKey, next);
|
|
4021
|
-
if (!this.rotated) {
|
|
4022
|
-
this.rotated = true;
|
|
4023
|
-
this.rotateOldFiles().catch(() => {
|
|
4024
|
-
});
|
|
4025
|
-
}
|
|
4026
|
-
} catch {
|
|
4027
|
-
}
|
|
4028
|
-
}
|
|
4029
4001
|
/** Called when agent session is explicitly changed */
|
|
4030
4002
|
onSessionChange(agentType) {
|
|
4031
4003
|
this.lastSeenHashes.delete(agentType);
|
|
4032
4004
|
this.lastSeenCounts.delete(agentType);
|
|
4033
|
-
this.lastSeenTerminal.delete(`${agentType}:terminal`);
|
|
4034
4005
|
}
|
|
4035
4006
|
/** Delete history files older than 30 days */
|
|
4036
4007
|
async rotateOldFiles() {
|
|
@@ -4883,7 +4854,6 @@ var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
|
|
|
4883
4854
|
var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
|
|
4884
4855
|
var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
|
|
4885
4856
|
var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
|
|
4886
|
-
var STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
|
|
4887
4857
|
var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
|
|
4888
4858
|
var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
|
|
4889
4859
|
var STATUS_MODAL_BUTTON_LIMIT = 120;
|
|
@@ -4892,11 +4862,6 @@ function truncateString(value, maxChars) {
|
|
|
4892
4862
|
if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
|
|
4893
4863
|
return `${value.slice(0, maxChars - 12)}...[truncated]`;
|
|
4894
4864
|
}
|
|
4895
|
-
function truncateStringTail(value, maxChars) {
|
|
4896
|
-
if (value.length <= maxChars) return value;
|
|
4897
|
-
if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
|
|
4898
|
-
return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
|
|
4899
|
-
}
|
|
4900
4865
|
function trimStructuredStrings(value, maxChars) {
|
|
4901
4866
|
if (typeof value === "string") return truncateString(value, maxChars);
|
|
4902
4867
|
if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
|
|
@@ -4970,7 +4935,6 @@ function normalizeActiveChatData(activeChat) {
|
|
|
4970
4935
|
(button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
|
|
4971
4936
|
)
|
|
4972
4937
|
} : activeChat.activeModal,
|
|
4973
|
-
terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
|
|
4974
4938
|
inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
|
|
4975
4939
|
};
|
|
4976
4940
|
}
|
|
@@ -8270,7 +8234,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
8270
8234
|
}
|
|
8271
8235
|
} else if (plat === "win32") {
|
|
8272
8236
|
try {
|
|
8273
|
-
const
|
|
8237
|
+
const fs13 = __require("fs");
|
|
8274
8238
|
const appNameMap = getMacAppIdentifiers();
|
|
8275
8239
|
const appName = appNameMap[ideId];
|
|
8276
8240
|
if (appName) {
|
|
@@ -8279,8 +8243,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
8279
8243
|
appName,
|
|
8280
8244
|
"storage.json"
|
|
8281
8245
|
);
|
|
8282
|
-
if (
|
|
8283
|
-
const data = JSON.parse(
|
|
8246
|
+
if (fs13.existsSync(storagePath)) {
|
|
8247
|
+
const data = JSON.parse(fs13.readFileSync(storagePath, "utf-8"));
|
|
8284
8248
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
8285
8249
|
if (workspaces.length > 0) {
|
|
8286
8250
|
const recent = workspaces[0];
|
|
@@ -8725,8 +8689,191 @@ function buildStatusSnapshot(options) {
|
|
|
8725
8689
|
};
|
|
8726
8690
|
}
|
|
8727
8691
|
|
|
8728
|
-
// src/commands/
|
|
8692
|
+
// src/commands/upgrade-helper.ts
|
|
8693
|
+
import { execFileSync } from "child_process";
|
|
8694
|
+
import { spawn as spawn2 } from "child_process";
|
|
8729
8695
|
import * as fs7 from "fs";
|
|
8696
|
+
import * as os11 from "os";
|
|
8697
|
+
import * as path9 from "path";
|
|
8698
|
+
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
8699
|
+
function getUpgradeLogPath() {
|
|
8700
|
+
const home = os11.homedir();
|
|
8701
|
+
const dir = path9.join(home, ".adhdev");
|
|
8702
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
8703
|
+
return path9.join(dir, "daemon-upgrade.log");
|
|
8704
|
+
}
|
|
8705
|
+
function appendUpgradeLog(message) {
|
|
8706
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
8707
|
+
`;
|
|
8708
|
+
try {
|
|
8709
|
+
fs7.appendFileSync(getUpgradeLogPath(), line, "utf8");
|
|
8710
|
+
} catch {
|
|
8711
|
+
}
|
|
8712
|
+
}
|
|
8713
|
+
function getNpmExecutable() {
|
|
8714
|
+
return process.platform === "win32" ? "npm.cmd" : "npm";
|
|
8715
|
+
}
|
|
8716
|
+
function killPid(pid) {
|
|
8717
|
+
try {
|
|
8718
|
+
if (process.platform === "win32") {
|
|
8719
|
+
execFileSync("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
8720
|
+
} else {
|
|
8721
|
+
process.kill(pid, "SIGTERM");
|
|
8722
|
+
}
|
|
8723
|
+
return true;
|
|
8724
|
+
} catch {
|
|
8725
|
+
return false;
|
|
8726
|
+
}
|
|
8727
|
+
}
|
|
8728
|
+
async function waitForPidExit(pid, timeoutMs) {
|
|
8729
|
+
const start = Date.now();
|
|
8730
|
+
while (Date.now() - start < timeoutMs) {
|
|
8731
|
+
try {
|
|
8732
|
+
process.kill(pid, 0);
|
|
8733
|
+
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
8734
|
+
} catch {
|
|
8735
|
+
return;
|
|
8736
|
+
}
|
|
8737
|
+
}
|
|
8738
|
+
}
|
|
8739
|
+
function stopSessionHostProcesses(appName) {
|
|
8740
|
+
const pidFile = path9.join(os11.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
8741
|
+
try {
|
|
8742
|
+
if (fs7.existsSync(pidFile)) {
|
|
8743
|
+
const pid = Number.parseInt(fs7.readFileSync(pidFile, "utf8").trim(), 10);
|
|
8744
|
+
if (Number.isFinite(pid)) {
|
|
8745
|
+
killPid(pid);
|
|
8746
|
+
}
|
|
8747
|
+
}
|
|
8748
|
+
} catch {
|
|
8749
|
+
} finally {
|
|
8750
|
+
try {
|
|
8751
|
+
fs7.unlinkSync(pidFile);
|
|
8752
|
+
} catch {
|
|
8753
|
+
}
|
|
8754
|
+
}
|
|
8755
|
+
if (process.platform !== "win32") {
|
|
8756
|
+
try {
|
|
8757
|
+
const raw = execFileSync("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
|
|
8758
|
+
for (const line of raw.split("\n")) {
|
|
8759
|
+
const pid = Number.parseInt(line.trim(), 10);
|
|
8760
|
+
if (Number.isFinite(pid)) {
|
|
8761
|
+
killPid(pid);
|
|
8762
|
+
}
|
|
8763
|
+
}
|
|
8764
|
+
} catch {
|
|
8765
|
+
}
|
|
8766
|
+
}
|
|
8767
|
+
}
|
|
8768
|
+
function removeDaemonPidFile() {
|
|
8769
|
+
const pidFile = path9.join(os11.homedir(), ".adhdev", "daemon.pid");
|
|
8770
|
+
try {
|
|
8771
|
+
fs7.unlinkSync(pidFile);
|
|
8772
|
+
} catch {
|
|
8773
|
+
}
|
|
8774
|
+
}
|
|
8775
|
+
function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
8776
|
+
const npmRoot = execFileSync(getNpmExecutable(), ["root", "-g"], { encoding: "utf8" }).trim();
|
|
8777
|
+
if (!npmRoot) return;
|
|
8778
|
+
const npmPrefix = execFileSync(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8" }).trim();
|
|
8779
|
+
const binDir = process.platform === "win32" ? npmPrefix : path9.join(npmPrefix, "bin");
|
|
8780
|
+
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
8781
|
+
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
8782
|
+
if (pkgName === "@adhdev/daemon-standalone") {
|
|
8783
|
+
binNames.add("adhdev-standalone");
|
|
8784
|
+
}
|
|
8785
|
+
if (pkgName.startsWith("@")) {
|
|
8786
|
+
const [scope, name] = pkgName.split("/");
|
|
8787
|
+
const scopeDir = path9.join(npmRoot, scope);
|
|
8788
|
+
if (!fs7.existsSync(scopeDir)) return;
|
|
8789
|
+
for (const entry of fs7.readdirSync(scopeDir)) {
|
|
8790
|
+
if (!entry.startsWith(`.${name}-`)) continue;
|
|
8791
|
+
fs7.rmSync(path9.join(scopeDir, entry), { recursive: true, force: true });
|
|
8792
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path9.join(scopeDir, entry)}`);
|
|
8793
|
+
}
|
|
8794
|
+
} else {
|
|
8795
|
+
for (const entry of fs7.readdirSync(npmRoot)) {
|
|
8796
|
+
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
8797
|
+
fs7.rmSync(path9.join(npmRoot, entry), { recursive: true, force: true });
|
|
8798
|
+
appendUpgradeLog(`Removed stale staging dir: ${path9.join(npmRoot, entry)}`);
|
|
8799
|
+
}
|
|
8800
|
+
}
|
|
8801
|
+
if (fs7.existsSync(binDir)) {
|
|
8802
|
+
for (const entry of fs7.readdirSync(binDir)) {
|
|
8803
|
+
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
8804
|
+
fs7.rmSync(path9.join(binDir, entry), { recursive: true, force: true });
|
|
8805
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path9.join(binDir, entry)}`);
|
|
8806
|
+
}
|
|
8807
|
+
}
|
|
8808
|
+
}
|
|
8809
|
+
function spawnDetachedDaemonUpgradeHelper(payload) {
|
|
8810
|
+
const env = { ...process.env, [UPGRADE_HELPER_ENV]: JSON.stringify(payload) };
|
|
8811
|
+
const child = spawn2(process.execPath, process.argv.slice(1), {
|
|
8812
|
+
detached: true,
|
|
8813
|
+
stdio: "ignore",
|
|
8814
|
+
windowsHide: true,
|
|
8815
|
+
cwd: payload.cwd || process.cwd(),
|
|
8816
|
+
env
|
|
8817
|
+
});
|
|
8818
|
+
child.unref();
|
|
8819
|
+
}
|
|
8820
|
+
async function runDaemonUpgradeHelper(payload) {
|
|
8821
|
+
const restartArgv = Array.isArray(payload.restartArgv) ? payload.restartArgv : [];
|
|
8822
|
+
const sessionHostAppName = payload.sessionHostAppName || process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
8823
|
+
appendUpgradeLog(`Upgrade helper started for ${payload.packageName}@${payload.targetVersion}`);
|
|
8824
|
+
if (Number.isFinite(payload.parentPid) && payload.parentPid > 0) {
|
|
8825
|
+
appendUpgradeLog(`Waiting for parent pid ${payload.parentPid} to exit`);
|
|
8826
|
+
await waitForPidExit(payload.parentPid, 15e3);
|
|
8827
|
+
}
|
|
8828
|
+
stopSessionHostProcesses(sessionHostAppName);
|
|
8829
|
+
removeDaemonPidFile();
|
|
8830
|
+
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
8831
|
+
const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
|
|
8832
|
+
appendUpgradeLog(`Installing ${spec}`);
|
|
8833
|
+
const installOutput = execFileSync(
|
|
8834
|
+
getNpmExecutable(),
|
|
8835
|
+
["install", "-g", spec, "--force"],
|
|
8836
|
+
{
|
|
8837
|
+
encoding: "utf8",
|
|
8838
|
+
stdio: "pipe",
|
|
8839
|
+
maxBuffer: 20 * 1024 * 1024
|
|
8840
|
+
}
|
|
8841
|
+
);
|
|
8842
|
+
if (installOutput.trim()) {
|
|
8843
|
+
appendUpgradeLog(installOutput.trim());
|
|
8844
|
+
}
|
|
8845
|
+
if (restartArgv.length > 0) {
|
|
8846
|
+
const env = { ...process.env };
|
|
8847
|
+
delete env[UPGRADE_HELPER_ENV];
|
|
8848
|
+
appendUpgradeLog(`Restarting daemon with args: ${restartArgv.join(" ")}`);
|
|
8849
|
+
const child = spawn2(process.execPath, restartArgv, {
|
|
8850
|
+
detached: true,
|
|
8851
|
+
stdio: "ignore",
|
|
8852
|
+
windowsHide: true,
|
|
8853
|
+
cwd: payload.cwd || process.cwd(),
|
|
8854
|
+
env
|
|
8855
|
+
});
|
|
8856
|
+
child.unref();
|
|
8857
|
+
} else {
|
|
8858
|
+
appendUpgradeLog("No restart argv provided; upgrade completed without restart");
|
|
8859
|
+
}
|
|
8860
|
+
}
|
|
8861
|
+
async function maybeRunDaemonUpgradeHelperFromEnv() {
|
|
8862
|
+
const raw = process.env[UPGRADE_HELPER_ENV];
|
|
8863
|
+
if (!raw) return false;
|
|
8864
|
+
delete process.env[UPGRADE_HELPER_ENV];
|
|
8865
|
+
try {
|
|
8866
|
+
const payload = JSON.parse(raw);
|
|
8867
|
+
await runDaemonUpgradeHelper(payload);
|
|
8868
|
+
process.exit(0);
|
|
8869
|
+
} catch (error) {
|
|
8870
|
+
appendUpgradeLog(`Upgrade helper failed: ${error?.stack || error?.message || String(error)}`);
|
|
8871
|
+
process.exit(1);
|
|
8872
|
+
}
|
|
8873
|
+
}
|
|
8874
|
+
|
|
8875
|
+
// src/commands/router.ts
|
|
8876
|
+
import * as fs8 from "fs";
|
|
8730
8877
|
var CHAT_COMMANDS = [
|
|
8731
8878
|
"send_chat",
|
|
8732
8879
|
"new_chat",
|
|
@@ -8797,8 +8944,8 @@ var DaemonCommandRouter = class {
|
|
|
8797
8944
|
if (logs.length > 0) {
|
|
8798
8945
|
return { success: true, logs, totalBuffered: logs.length };
|
|
8799
8946
|
}
|
|
8800
|
-
if (
|
|
8801
|
-
const content =
|
|
8947
|
+
if (fs8.existsSync(LOG_PATH)) {
|
|
8948
|
+
const content = fs8.readFileSync(LOG_PATH, "utf-8");
|
|
8802
8949
|
const allLines = content.split("\n");
|
|
8803
8950
|
const recent = allLines.slice(-count).join("\n");
|
|
8804
8951
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
@@ -8946,31 +9093,35 @@ var DaemonCommandRouter = class {
|
|
|
8946
9093
|
const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
|
|
8947
9094
|
const latest = execSync7(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
8948
9095
|
LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
9096
|
+
let currentInstalled = null;
|
|
9097
|
+
try {
|
|
9098
|
+
const currentJson = execSync7(`npm ls -g ${pkgName} --depth=0 --json`, {
|
|
9099
|
+
encoding: "utf-8",
|
|
9100
|
+
timeout: 1e4,
|
|
9101
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
9102
|
+
}).trim();
|
|
9103
|
+
const parsed = JSON.parse(currentJson);
|
|
9104
|
+
currentInstalled = parsed?.dependencies?.[pkgName]?.version || null;
|
|
9105
|
+
} catch {
|
|
9106
|
+
}
|
|
9107
|
+
if (currentInstalled === latest) {
|
|
9108
|
+
LOG.info("Upgrade", `Already on latest version v${latest}; skipping install`);
|
|
9109
|
+
return { success: true, upgraded: false, alreadyLatest: true, version: latest };
|
|
9110
|
+
}
|
|
9111
|
+
spawnDetachedDaemonUpgradeHelper({
|
|
9112
|
+
packageName: pkgName,
|
|
9113
|
+
targetVersion: latest,
|
|
9114
|
+
parentPid: process.pid,
|
|
9115
|
+
restartArgv: process.argv.slice(1),
|
|
9116
|
+
cwd: process.cwd(),
|
|
9117
|
+
sessionHostAppName: process.env.ADHDEV_SESSION_HOST_NAME || "adhdev"
|
|
8953
9118
|
});
|
|
8954
|
-
LOG.info("Upgrade",
|
|
9119
|
+
LOG.info("Upgrade", `Scheduled detached upgrade to v${latest}`);
|
|
8955
9120
|
setTimeout(() => {
|
|
8956
|
-
LOG.info("Upgrade", "
|
|
8957
|
-
try {
|
|
8958
|
-
const path15 = __require("path");
|
|
8959
|
-
const fs12 = __require("fs");
|
|
8960
|
-
const pidFile = path15.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
|
|
8961
|
-
if (fs12.existsSync(pidFile)) fs12.unlinkSync(pidFile);
|
|
8962
|
-
} catch {
|
|
8963
|
-
}
|
|
8964
|
-
const { spawn: spawn3 } = __require("child_process");
|
|
8965
|
-
const child = spawn3(process.execPath, process.argv.slice(1), {
|
|
8966
|
-
detached: true,
|
|
8967
|
-
stdio: "ignore",
|
|
8968
|
-
env: { ...process.env }
|
|
8969
|
-
});
|
|
8970
|
-
child.unref();
|
|
9121
|
+
LOG.info("Upgrade", "Exiting daemon so detached upgrader can continue...");
|
|
8971
9122
|
process.exit(0);
|
|
8972
9123
|
}, 3e3);
|
|
8973
|
-
return { success: true, upgraded: true, version: latest };
|
|
9124
|
+
return { success: true, upgraded: true, version: latest, restarting: true };
|
|
8974
9125
|
} catch (e) {
|
|
8975
9126
|
LOG.error("Upgrade", `Failed: ${e.message}`);
|
|
8976
9127
|
return { success: false, error: e.message };
|
|
@@ -9267,8 +9418,8 @@ init_logger();
|
|
|
9267
9418
|
|
|
9268
9419
|
// src/commands/cli-manager.ts
|
|
9269
9420
|
init_provider_cli_adapter();
|
|
9270
|
-
import * as
|
|
9271
|
-
import * as
|
|
9421
|
+
import * as os14 from "os";
|
|
9422
|
+
import * as path11 from "path";
|
|
9272
9423
|
import * as crypto4 from "crypto";
|
|
9273
9424
|
import chalk from "chalk";
|
|
9274
9425
|
init_config();
|
|
@@ -9284,7 +9435,7 @@ var CliProviderInstance = class {
|
|
|
9284
9435
|
this.cliArgs = cliArgs;
|
|
9285
9436
|
this.type = provider.type;
|
|
9286
9437
|
this.instanceId = instanceId || crypto3.randomUUID();
|
|
9287
|
-
this.presentationMode = "
|
|
9438
|
+
this.presentationMode = "chat";
|
|
9288
9439
|
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
9289
9440
|
this.monitor = new StatusMonitor();
|
|
9290
9441
|
this.historyWriter = new ChatHistoryWriter();
|
|
@@ -9331,14 +9482,6 @@ var CliProviderInstance = class {
|
|
|
9331
9482
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
9332
9483
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
9333
9484
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
9334
|
-
if (adapterStatus.terminalHistory?.trim()) {
|
|
9335
|
-
this.historyWriter.appendTerminalHistory(
|
|
9336
|
-
this.type,
|
|
9337
|
-
adapterStatus.terminalHistory,
|
|
9338
|
-
`${this.provider.name} \xB7 ${dirName}`,
|
|
9339
|
-
this.instanceId
|
|
9340
|
-
);
|
|
9341
|
-
}
|
|
9342
9485
|
return {
|
|
9343
9486
|
type: this.type,
|
|
9344
9487
|
name: this.provider.name,
|
|
@@ -9351,7 +9494,6 @@ var CliProviderInstance = class {
|
|
|
9351
9494
|
status: parsedStatus?.status || adapterStatus.status,
|
|
9352
9495
|
messages: Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [],
|
|
9353
9496
|
activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
9354
|
-
terminalHistory: adapterStatus.terminalHistory,
|
|
9355
9497
|
inputContent: ""
|
|
9356
9498
|
},
|
|
9357
9499
|
workspace: this.workingDir,
|
|
@@ -9523,7 +9665,7 @@ var CliProviderInstance = class {
|
|
|
9523
9665
|
|
|
9524
9666
|
// src/providers/acp-provider-instance.ts
|
|
9525
9667
|
import { Readable, Writable } from "stream";
|
|
9526
|
-
import { spawn as
|
|
9668
|
+
import { spawn as spawn3 } from "child_process";
|
|
9527
9669
|
import {
|
|
9528
9670
|
ClientSideConnection,
|
|
9529
9671
|
ndJsonStream,
|
|
@@ -9858,7 +10000,7 @@ var AcpProviderInstance = class {
|
|
|
9858
10000
|
this.errorMessage = null;
|
|
9859
10001
|
this.errorReason = null;
|
|
9860
10002
|
this.stderrBuffer = [];
|
|
9861
|
-
this.process =
|
|
10003
|
+
this.process = spawn3(command, args, {
|
|
9862
10004
|
cwd: this.workingDir,
|
|
9863
10005
|
env,
|
|
9864
10006
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -10541,7 +10683,7 @@ var DaemonCliManager = class {
|
|
|
10541
10683
|
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
10542
10684
|
const trimmed = (workingDir || "").trim();
|
|
10543
10685
|
if (!trimmed) throw new Error("working directory required");
|
|
10544
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/,
|
|
10686
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os14.homedir()) : path11.resolve(trimmed);
|
|
10545
10687
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10546
10688
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
10547
10689
|
const key = crypto4.randomUUID();
|
|
@@ -11738,12 +11880,12 @@ var ProviderInstanceManager = class {
|
|
|
11738
11880
|
};
|
|
11739
11881
|
|
|
11740
11882
|
// src/providers/version-archive.ts
|
|
11741
|
-
import * as
|
|
11742
|
-
import * as
|
|
11743
|
-
import * as
|
|
11883
|
+
import * as fs9 from "fs";
|
|
11884
|
+
import * as path12 from "path";
|
|
11885
|
+
import * as os15 from "os";
|
|
11744
11886
|
import { execSync as execSync5 } from "child_process";
|
|
11745
11887
|
import { platform as platform8 } from "os";
|
|
11746
|
-
var ARCHIVE_PATH =
|
|
11888
|
+
var ARCHIVE_PATH = path12.join(os15.homedir(), ".adhdev", "version-history.json");
|
|
11747
11889
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
11748
11890
|
var VersionArchive = class {
|
|
11749
11891
|
history = {};
|
|
@@ -11752,8 +11894,8 @@ var VersionArchive = class {
|
|
|
11752
11894
|
}
|
|
11753
11895
|
load() {
|
|
11754
11896
|
try {
|
|
11755
|
-
if (
|
|
11756
|
-
this.history = JSON.parse(
|
|
11897
|
+
if (fs9.existsSync(ARCHIVE_PATH)) {
|
|
11898
|
+
this.history = JSON.parse(fs9.readFileSync(ARCHIVE_PATH, "utf-8"));
|
|
11757
11899
|
}
|
|
11758
11900
|
} catch {
|
|
11759
11901
|
this.history = {};
|
|
@@ -11790,8 +11932,8 @@ var VersionArchive = class {
|
|
|
11790
11932
|
}
|
|
11791
11933
|
save() {
|
|
11792
11934
|
try {
|
|
11793
|
-
|
|
11794
|
-
|
|
11935
|
+
fs9.mkdirSync(path12.dirname(ARCHIVE_PATH), { recursive: true });
|
|
11936
|
+
fs9.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
11795
11937
|
} catch {
|
|
11796
11938
|
}
|
|
11797
11939
|
}
|
|
@@ -11830,19 +11972,19 @@ function getVersion(binary, versionCommand) {
|
|
|
11830
11972
|
function checkPathExists2(paths) {
|
|
11831
11973
|
for (const p of paths) {
|
|
11832
11974
|
if (p.includes("*")) {
|
|
11833
|
-
const home =
|
|
11834
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
11835
|
-
if (
|
|
11975
|
+
const home = os15.homedir();
|
|
11976
|
+
const resolved = p.replace(/\*/g, home.split(path12.sep).pop() || "");
|
|
11977
|
+
if (fs9.existsSync(resolved)) return resolved;
|
|
11836
11978
|
} else {
|
|
11837
|
-
if (
|
|
11979
|
+
if (fs9.existsSync(p)) return p;
|
|
11838
11980
|
}
|
|
11839
11981
|
}
|
|
11840
11982
|
return null;
|
|
11841
11983
|
}
|
|
11842
11984
|
function getMacAppVersion(appPath) {
|
|
11843
11985
|
if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
11844
|
-
const plistPath =
|
|
11845
|
-
if (!
|
|
11986
|
+
const plistPath = path12.join(appPath, "Contents", "Info.plist");
|
|
11987
|
+
if (!fs9.existsSync(plistPath)) return null;
|
|
11846
11988
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
11847
11989
|
return raw || null;
|
|
11848
11990
|
}
|
|
@@ -11868,8 +12010,8 @@ async function detectAllVersions(loader, archive) {
|
|
|
11868
12010
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
11869
12011
|
let resolvedBin = cliBin;
|
|
11870
12012
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
11871
|
-
const bundled =
|
|
11872
|
-
if (provider.cli &&
|
|
12013
|
+
const bundled = path12.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
12014
|
+
if (provider.cli && fs9.existsSync(bundled)) resolvedBin = bundled;
|
|
11873
12015
|
}
|
|
11874
12016
|
info.installed = !!(appPath || resolvedBin);
|
|
11875
12017
|
info.path = appPath || null;
|
|
@@ -11908,8 +12050,8 @@ async function detectAllVersions(loader, archive) {
|
|
|
11908
12050
|
|
|
11909
12051
|
// src/daemon/dev-server.ts
|
|
11910
12052
|
import * as http2 from "http";
|
|
11911
|
-
import * as
|
|
11912
|
-
import * as
|
|
12053
|
+
import * as fs12 from "fs";
|
|
12054
|
+
import * as path15 from "path";
|
|
11913
12055
|
|
|
11914
12056
|
// src/daemon/scaffold-template.ts
|
|
11915
12057
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -12245,8 +12387,8 @@ init_logger();
|
|
|
12245
12387
|
|
|
12246
12388
|
// src/daemon/dev-cdp-handlers.ts
|
|
12247
12389
|
init_logger();
|
|
12248
|
-
import * as
|
|
12249
|
-
import * as
|
|
12390
|
+
import * as fs10 from "fs";
|
|
12391
|
+
import * as path13 from "path";
|
|
12250
12392
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
12251
12393
|
const body = await ctx.readBody(req);
|
|
12252
12394
|
const { expression, timeout, ideType } = body;
|
|
@@ -12424,18 +12566,18 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
12424
12566
|
return;
|
|
12425
12567
|
}
|
|
12426
12568
|
let scriptsPath = "";
|
|
12427
|
-
const directScripts =
|
|
12428
|
-
if (
|
|
12569
|
+
const directScripts = path13.join(dir, "scripts.js");
|
|
12570
|
+
if (fs10.existsSync(directScripts)) {
|
|
12429
12571
|
scriptsPath = directScripts;
|
|
12430
12572
|
} else {
|
|
12431
|
-
const scriptsDir =
|
|
12432
|
-
if (
|
|
12433
|
-
const versions =
|
|
12434
|
-
return
|
|
12573
|
+
const scriptsDir = path13.join(dir, "scripts");
|
|
12574
|
+
if (fs10.existsSync(scriptsDir)) {
|
|
12575
|
+
const versions = fs10.readdirSync(scriptsDir).filter((d) => {
|
|
12576
|
+
return fs10.statSync(path13.join(scriptsDir, d)).isDirectory();
|
|
12435
12577
|
}).sort().reverse();
|
|
12436
12578
|
for (const ver of versions) {
|
|
12437
|
-
const p =
|
|
12438
|
-
if (
|
|
12579
|
+
const p = path13.join(scriptsDir, ver, "scripts.js");
|
|
12580
|
+
if (fs10.existsSync(p)) {
|
|
12439
12581
|
scriptsPath = p;
|
|
12440
12582
|
break;
|
|
12441
12583
|
}
|
|
@@ -12447,7 +12589,7 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
12447
12589
|
return;
|
|
12448
12590
|
}
|
|
12449
12591
|
try {
|
|
12450
|
-
const source =
|
|
12592
|
+
const source = fs10.readFileSync(scriptsPath, "utf-8");
|
|
12451
12593
|
const hints = {};
|
|
12452
12594
|
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
12453
12595
|
let match;
|
|
@@ -13488,9 +13630,9 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
13488
13630
|
}
|
|
13489
13631
|
|
|
13490
13632
|
// src/daemon/dev-auto-implement.ts
|
|
13491
|
-
import * as
|
|
13492
|
-
import * as
|
|
13493
|
-
import * as
|
|
13633
|
+
import * as fs11 from "fs";
|
|
13634
|
+
import * as path14 from "path";
|
|
13635
|
+
import * as os16 from "os";
|
|
13494
13636
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
13495
13637
|
if (category === "cli") {
|
|
13496
13638
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -13506,45 +13648,45 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
13506
13648
|
return fallback?.type || null;
|
|
13507
13649
|
}
|
|
13508
13650
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
13509
|
-
if (!
|
|
13510
|
-
const versions =
|
|
13651
|
+
if (!fs11.existsSync(scriptsDir)) return null;
|
|
13652
|
+
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
13511
13653
|
try {
|
|
13512
|
-
return
|
|
13654
|
+
return fs11.statSync(path14.join(scriptsDir, d)).isDirectory();
|
|
13513
13655
|
} catch {
|
|
13514
13656
|
return false;
|
|
13515
13657
|
}
|
|
13516
13658
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
13517
13659
|
if (versions.length === 0) return null;
|
|
13518
|
-
return
|
|
13660
|
+
return path14.join(scriptsDir, versions[0]);
|
|
13519
13661
|
}
|
|
13520
13662
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
13521
|
-
const canonicalUserDir =
|
|
13522
|
-
const desiredDir = requestedDir ?
|
|
13523
|
-
const upstreamRoot =
|
|
13524
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
13663
|
+
const canonicalUserDir = path14.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
13664
|
+
const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
|
|
13665
|
+
const upstreamRoot = path14.resolve(ctx.providerLoader.getUpstreamDir());
|
|
13666
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
|
|
13525
13667
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
13526
13668
|
}
|
|
13527
|
-
if (
|
|
13669
|
+
if (path14.basename(desiredDir) !== type) {
|
|
13528
13670
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
13529
13671
|
}
|
|
13530
13672
|
const sourceDir = ctx.findProviderDir(type);
|
|
13531
13673
|
if (!sourceDir) {
|
|
13532
13674
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
13533
13675
|
}
|
|
13534
|
-
if (!
|
|
13535
|
-
|
|
13536
|
-
|
|
13676
|
+
if (!fs11.existsSync(desiredDir)) {
|
|
13677
|
+
fs11.mkdirSync(path14.dirname(desiredDir), { recursive: true });
|
|
13678
|
+
fs11.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
13537
13679
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
13538
13680
|
}
|
|
13539
|
-
const providerJson =
|
|
13540
|
-
if (!
|
|
13681
|
+
const providerJson = path14.join(desiredDir, "provider.json");
|
|
13682
|
+
if (!fs11.existsSync(providerJson)) {
|
|
13541
13683
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
13542
13684
|
}
|
|
13543
13685
|
try {
|
|
13544
|
-
const providerData = JSON.parse(
|
|
13686
|
+
const providerData = JSON.parse(fs11.readFileSync(providerJson, "utf-8"));
|
|
13545
13687
|
if (providerData.disableUpstream !== true) {
|
|
13546
13688
|
providerData.disableUpstream = true;
|
|
13547
|
-
|
|
13689
|
+
fs11.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
13548
13690
|
}
|
|
13549
13691
|
} catch (error) {
|
|
13550
13692
|
return {
|
|
@@ -13557,15 +13699,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
13557
13699
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
13558
13700
|
if (!referenceType) return {};
|
|
13559
13701
|
const refDir = ctx.findProviderDir(referenceType);
|
|
13560
|
-
if (!refDir || !
|
|
13702
|
+
if (!refDir || !fs11.existsSync(refDir)) return {};
|
|
13561
13703
|
const referenceScripts = {};
|
|
13562
|
-
const scriptsDir =
|
|
13704
|
+
const scriptsDir = path14.join(refDir, "scripts");
|
|
13563
13705
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
13564
13706
|
if (!latestDir) return referenceScripts;
|
|
13565
|
-
for (const file of
|
|
13707
|
+
for (const file of fs11.readdirSync(latestDir)) {
|
|
13566
13708
|
if (!file.endsWith(".js")) continue;
|
|
13567
13709
|
try {
|
|
13568
|
-
referenceScripts[file] =
|
|
13710
|
+
referenceScripts[file] = fs11.readFileSync(path14.join(latestDir, file), "utf-8");
|
|
13569
13711
|
} catch {
|
|
13570
13712
|
}
|
|
13571
13713
|
}
|
|
@@ -13616,16 +13758,16 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13616
13758
|
});
|
|
13617
13759
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
13618
13760
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
13619
|
-
const tmpDir =
|
|
13620
|
-
if (!
|
|
13621
|
-
const promptFile =
|
|
13622
|
-
|
|
13761
|
+
const tmpDir = path14.join(os16.tmpdir(), "adhdev-autoimpl");
|
|
13762
|
+
if (!fs11.existsSync(tmpDir)) fs11.mkdirSync(tmpDir, { recursive: true });
|
|
13763
|
+
const promptFile = path14.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
13764
|
+
fs11.writeFileSync(promptFile, prompt, "utf-8");
|
|
13623
13765
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
13624
13766
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
13625
|
-
const
|
|
13626
|
-
if (!
|
|
13767
|
+
const spawn4 = agentProvider?.spawn;
|
|
13768
|
+
if (!spawn4?.command) {
|
|
13627
13769
|
try {
|
|
13628
|
-
|
|
13770
|
+
fs11.unlinkSync(promptFile);
|
|
13629
13771
|
} catch {
|
|
13630
13772
|
}
|
|
13631
13773
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -13633,21 +13775,21 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13633
13775
|
}
|
|
13634
13776
|
const agentCategory = agentProvider?.category;
|
|
13635
13777
|
if (agentCategory === "acp") {
|
|
13636
|
-
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${
|
|
13778
|
+
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn4.command} ${(spawn4.args || []).join(" ")}` } });
|
|
13637
13779
|
ctx.autoImplStatus = { running: true, type, progress: [] };
|
|
13638
13780
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await import("@agentclientprotocol/sdk");
|
|
13639
13781
|
const { Readable: Readable2, Writable: Writable2 } = await import("stream");
|
|
13640
13782
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
13641
|
-
const acpArgs = [...
|
|
13783
|
+
const acpArgs = [...spawn4.args || []];
|
|
13642
13784
|
if (model) {
|
|
13643
13785
|
acpArgs.push("--model", model);
|
|
13644
13786
|
ctx.log(`Auto-implement ACP using model: ${model}`);
|
|
13645
13787
|
}
|
|
13646
|
-
const child2 = spawnFn2(
|
|
13788
|
+
const child2 = spawnFn2(spawn4.command, acpArgs, {
|
|
13647
13789
|
cwd: providerDir,
|
|
13648
13790
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13649
|
-
shell:
|
|
13650
|
-
env: { ...process.env, ...
|
|
13791
|
+
shell: spawn4.shell ?? false,
|
|
13792
|
+
env: { ...process.env, ...spawn4.env || {} }
|
|
13651
13793
|
});
|
|
13652
13794
|
ctx.autoImplProcess = child2;
|
|
13653
13795
|
child2.stderr?.on("data", (d) => {
|
|
@@ -13726,7 +13868,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13726
13868
|
} catch {
|
|
13727
13869
|
}
|
|
13728
13870
|
try {
|
|
13729
|
-
|
|
13871
|
+
fs11.unlinkSync(promptFile);
|
|
13730
13872
|
} catch {
|
|
13731
13873
|
}
|
|
13732
13874
|
ctx.log(`Auto-implement (ACP) ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -13757,7 +13899,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13757
13899
|
ctx.json(res, 202, {
|
|
13758
13900
|
started: true,
|
|
13759
13901
|
type,
|
|
13760
|
-
agent:
|
|
13902
|
+
agent: spawn4.command,
|
|
13761
13903
|
functions,
|
|
13762
13904
|
providerDir,
|
|
13763
13905
|
message: "ACP Auto-implement started. Connect to SSE for progress.",
|
|
@@ -13765,11 +13907,11 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13765
13907
|
});
|
|
13766
13908
|
return;
|
|
13767
13909
|
}
|
|
13768
|
-
const command =
|
|
13910
|
+
const command = spawn4.command;
|
|
13769
13911
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
13770
|
-
const baseArgs = [...
|
|
13912
|
+
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
13771
13913
|
let shellCmd;
|
|
13772
|
-
const isWin =
|
|
13914
|
+
const isWin = os16.platform() === "win32";
|
|
13773
13915
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
13774
13916
|
if (command === "claude") {
|
|
13775
13917
|
const args = [...baseArgs, "--dangerously-skip-permissions"];
|
|
@@ -13812,13 +13954,13 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13812
13954
|
try {
|
|
13813
13955
|
const pty3 = __require("node-pty");
|
|
13814
13956
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
13815
|
-
const isWin2 =
|
|
13957
|
+
const isWin2 = os16.platform() === "win32";
|
|
13816
13958
|
child = pty3.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
13817
13959
|
name: "xterm-256color",
|
|
13818
13960
|
cols: 120,
|
|
13819
13961
|
rows: 40,
|
|
13820
13962
|
cwd: providerDir,
|
|
13821
|
-
env: { ...process.env, ...
|
|
13963
|
+
env: { ...process.env, ...spawn4.env || {} }
|
|
13822
13964
|
});
|
|
13823
13965
|
isPty = true;
|
|
13824
13966
|
} catch (err) {
|
|
@@ -13830,7 +13972,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13830
13972
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13831
13973
|
env: {
|
|
13832
13974
|
...process.env,
|
|
13833
|
-
...
|
|
13975
|
+
...spawn4.env || {},
|
|
13834
13976
|
...command === "gemini" ? { SANDBOX: "1", GEMINI_CLI_NO_RELAUNCH: "1" } : {}
|
|
13835
13977
|
}
|
|
13836
13978
|
});
|
|
@@ -13906,7 +14048,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13906
14048
|
} catch {
|
|
13907
14049
|
}
|
|
13908
14050
|
try {
|
|
13909
|
-
|
|
14051
|
+
fs11.unlinkSync(promptFile);
|
|
13910
14052
|
} catch {
|
|
13911
14053
|
}
|
|
13912
14054
|
});
|
|
@@ -13942,7 +14084,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13942
14084
|
} catch {
|
|
13943
14085
|
}
|
|
13944
14086
|
try {
|
|
13945
|
-
|
|
14087
|
+
fs11.unlinkSync(promptFile);
|
|
13946
14088
|
} catch {
|
|
13947
14089
|
}
|
|
13948
14090
|
ctx.log(`Auto-implement ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -13989,7 +14131,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
13989
14131
|
setMode: "set_mode.js"
|
|
13990
14132
|
};
|
|
13991
14133
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
13992
|
-
const scriptsDir =
|
|
14134
|
+
const scriptsDir = path14.join(providerDir, "scripts");
|
|
13993
14135
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
13994
14136
|
if (latestScriptsDir) {
|
|
13995
14137
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -13997,10 +14139,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
13997
14139
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
13998
14140
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
13999
14141
|
lines.push("");
|
|
14000
|
-
for (const file of
|
|
14142
|
+
for (const file of fs11.readdirSync(latestScriptsDir)) {
|
|
14001
14143
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
14002
14144
|
try {
|
|
14003
|
-
const content =
|
|
14145
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14004
14146
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
14005
14147
|
lines.push("```javascript");
|
|
14006
14148
|
lines.push(content);
|
|
@@ -14010,14 +14152,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
14010
14152
|
}
|
|
14011
14153
|
}
|
|
14012
14154
|
}
|
|
14013
|
-
const refFiles =
|
|
14155
|
+
const refFiles = fs11.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
14014
14156
|
if (refFiles.length > 0) {
|
|
14015
14157
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
14016
14158
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
14017
14159
|
lines.push("");
|
|
14018
14160
|
for (const file of refFiles) {
|
|
14019
14161
|
try {
|
|
14020
|
-
const content =
|
|
14162
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14021
14163
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
14022
14164
|
lines.push("```javascript");
|
|
14023
14165
|
lines.push(content);
|
|
@@ -14058,11 +14200,11 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
14058
14200
|
lines.push("");
|
|
14059
14201
|
}
|
|
14060
14202
|
}
|
|
14061
|
-
const docsDir =
|
|
14203
|
+
const docsDir = path14.join(providerDir, "../../docs");
|
|
14062
14204
|
const loadGuide = (name) => {
|
|
14063
14205
|
try {
|
|
14064
|
-
const p =
|
|
14065
|
-
if (
|
|
14206
|
+
const p = path14.join(docsDir, name);
|
|
14207
|
+
if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
|
|
14066
14208
|
} catch {
|
|
14067
14209
|
}
|
|
14068
14210
|
return null;
|
|
@@ -14235,7 +14377,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14235
14377
|
parseApproval: "parse_approval.js"
|
|
14236
14378
|
};
|
|
14237
14379
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
14238
|
-
const scriptsDir =
|
|
14380
|
+
const scriptsDir = path14.join(providerDir, "scripts");
|
|
14239
14381
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
14240
14382
|
if (latestScriptsDir) {
|
|
14241
14383
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -14243,11 +14385,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14243
14385
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
14244
14386
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
14245
14387
|
lines.push("");
|
|
14246
|
-
for (const file of
|
|
14388
|
+
for (const file of fs11.readdirSync(latestScriptsDir)) {
|
|
14247
14389
|
if (!file.endsWith(".js")) continue;
|
|
14248
14390
|
if (!targetFileNames.has(file)) continue;
|
|
14249
14391
|
try {
|
|
14250
|
-
const content =
|
|
14392
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14251
14393
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
14252
14394
|
lines.push("```javascript");
|
|
14253
14395
|
lines.push(content);
|
|
@@ -14256,14 +14398,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14256
14398
|
} catch {
|
|
14257
14399
|
}
|
|
14258
14400
|
}
|
|
14259
|
-
const refFiles =
|
|
14401
|
+
const refFiles = fs11.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
14260
14402
|
if (refFiles.length > 0) {
|
|
14261
14403
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
14262
14404
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
14263
14405
|
lines.push("");
|
|
14264
14406
|
for (const file of refFiles) {
|
|
14265
14407
|
try {
|
|
14266
|
-
const content =
|
|
14408
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14267
14409
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
14268
14410
|
lines.push("```javascript");
|
|
14269
14411
|
lines.push(content);
|
|
@@ -14296,11 +14438,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14296
14438
|
lines.push("");
|
|
14297
14439
|
}
|
|
14298
14440
|
}
|
|
14299
|
-
const docsDir =
|
|
14441
|
+
const docsDir = path14.join(providerDir, "../../docs");
|
|
14300
14442
|
const loadGuide = (name) => {
|
|
14301
14443
|
try {
|
|
14302
|
-
const p =
|
|
14303
|
-
if (
|
|
14444
|
+
const p = path14.join(docsDir, name);
|
|
14445
|
+
if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
|
|
14304
14446
|
} catch {
|
|
14305
14447
|
}
|
|
14306
14448
|
return null;
|
|
@@ -14557,8 +14699,8 @@ var DevServer = class _DevServer {
|
|
|
14557
14699
|
}
|
|
14558
14700
|
getEndpointList() {
|
|
14559
14701
|
return this.routes.map((r) => {
|
|
14560
|
-
const
|
|
14561
|
-
return `${r.method.padEnd(5)} ${
|
|
14702
|
+
const path16 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
14703
|
+
return `${r.method.padEnd(5)} ${path16}`;
|
|
14562
14704
|
});
|
|
14563
14705
|
}
|
|
14564
14706
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -14659,16 +14801,16 @@ var DevServer = class _DevServer {
|
|
|
14659
14801
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
14660
14802
|
return;
|
|
14661
14803
|
}
|
|
14662
|
-
const
|
|
14663
|
-
if (!
|
|
14804
|
+
const spawn4 = provider.spawn;
|
|
14805
|
+
if (!spawn4) {
|
|
14664
14806
|
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
14665
14807
|
return;
|
|
14666
14808
|
}
|
|
14667
14809
|
const { spawn: spawnFn } = await import("child_process");
|
|
14668
14810
|
const start = Date.now();
|
|
14669
14811
|
try {
|
|
14670
|
-
const child = spawnFn(
|
|
14671
|
-
shell:
|
|
14812
|
+
const child = spawnFn(spawn4.command, [...spawn4.args || []], {
|
|
14813
|
+
shell: spawn4.shell ?? false,
|
|
14672
14814
|
timeout: 5e3,
|
|
14673
14815
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14674
14816
|
});
|
|
@@ -14700,7 +14842,7 @@ var DevServer = class _DevServer {
|
|
|
14700
14842
|
const elapsed = Date.now() - start;
|
|
14701
14843
|
this.json(res, 200, {
|
|
14702
14844
|
success: true,
|
|
14703
|
-
command: `${
|
|
14845
|
+
command: `${spawn4.command} ${(spawn4.args || []).join(" ")}`,
|
|
14704
14846
|
elapsed,
|
|
14705
14847
|
stdout: stdout.trim(),
|
|
14706
14848
|
stderr: stderr.trim(),
|
|
@@ -14710,7 +14852,7 @@ var DevServer = class _DevServer {
|
|
|
14710
14852
|
const elapsed = Date.now() - start;
|
|
14711
14853
|
this.json(res, 200, {
|
|
14712
14854
|
success: false,
|
|
14713
|
-
command: `${
|
|
14855
|
+
command: `${spawn4.command} ${(spawn4.args || []).join(" ")}`,
|
|
14714
14856
|
elapsed,
|
|
14715
14857
|
error: e.message
|
|
14716
14858
|
});
|
|
@@ -14840,12 +14982,12 @@ var DevServer = class _DevServer {
|
|
|
14840
14982
|
// ─── DevConsole SPA ───
|
|
14841
14983
|
getConsoleDistDir() {
|
|
14842
14984
|
const candidates = [
|
|
14843
|
-
|
|
14844
|
-
|
|
14845
|
-
|
|
14985
|
+
path15.resolve(__dirname, "../../web-devconsole/dist"),
|
|
14986
|
+
path15.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
14987
|
+
path15.join(process.cwd(), "packages/web-devconsole/dist")
|
|
14846
14988
|
];
|
|
14847
14989
|
for (const dir of candidates) {
|
|
14848
|
-
if (
|
|
14990
|
+
if (fs12.existsSync(path15.join(dir, "index.html"))) return dir;
|
|
14849
14991
|
}
|
|
14850
14992
|
return null;
|
|
14851
14993
|
}
|
|
@@ -14855,9 +14997,9 @@ var DevServer = class _DevServer {
|
|
|
14855
14997
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
14856
14998
|
return;
|
|
14857
14999
|
}
|
|
14858
|
-
const htmlPath =
|
|
15000
|
+
const htmlPath = path15.join(distDir, "index.html");
|
|
14859
15001
|
try {
|
|
14860
|
-
const html =
|
|
15002
|
+
const html = fs12.readFileSync(htmlPath, "utf-8");
|
|
14861
15003
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
14862
15004
|
res.end(html);
|
|
14863
15005
|
} catch (e) {
|
|
@@ -14880,15 +15022,15 @@ var DevServer = class _DevServer {
|
|
|
14880
15022
|
this.json(res, 404, { error: "Not found" });
|
|
14881
15023
|
return;
|
|
14882
15024
|
}
|
|
14883
|
-
const safePath =
|
|
14884
|
-
const filePath =
|
|
15025
|
+
const safePath = path15.normalize(pathname).replace(/^\.\.\//, "");
|
|
15026
|
+
const filePath = path15.join(distDir, safePath);
|
|
14885
15027
|
if (!filePath.startsWith(distDir)) {
|
|
14886
15028
|
this.json(res, 403, { error: "Forbidden" });
|
|
14887
15029
|
return;
|
|
14888
15030
|
}
|
|
14889
15031
|
try {
|
|
14890
|
-
const content =
|
|
14891
|
-
const ext =
|
|
15032
|
+
const content = fs12.readFileSync(filePath);
|
|
15033
|
+
const ext = path15.extname(filePath);
|
|
14892
15034
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
14893
15035
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
14894
15036
|
res.end(content);
|
|
@@ -14996,14 +15138,14 @@ var DevServer = class _DevServer {
|
|
|
14996
15138
|
const files = [];
|
|
14997
15139
|
const scan = (d, prefix) => {
|
|
14998
15140
|
try {
|
|
14999
|
-
for (const entry of
|
|
15141
|
+
for (const entry of fs12.readdirSync(d, { withFileTypes: true })) {
|
|
15000
15142
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
15001
15143
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
15002
15144
|
if (entry.isDirectory()) {
|
|
15003
15145
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
15004
|
-
scan(
|
|
15146
|
+
scan(path15.join(d, entry.name), rel);
|
|
15005
15147
|
} else {
|
|
15006
|
-
const stat =
|
|
15148
|
+
const stat = fs12.statSync(path15.join(d, entry.name));
|
|
15007
15149
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
15008
15150
|
}
|
|
15009
15151
|
}
|
|
@@ -15026,16 +15168,16 @@ var DevServer = class _DevServer {
|
|
|
15026
15168
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
15027
15169
|
return;
|
|
15028
15170
|
}
|
|
15029
|
-
const fullPath =
|
|
15171
|
+
const fullPath = path15.resolve(dir, path15.normalize(filePath));
|
|
15030
15172
|
if (!fullPath.startsWith(dir)) {
|
|
15031
15173
|
this.json(res, 403, { error: "Forbidden" });
|
|
15032
15174
|
return;
|
|
15033
15175
|
}
|
|
15034
|
-
if (!
|
|
15176
|
+
if (!fs12.existsSync(fullPath) || fs12.statSync(fullPath).isDirectory()) {
|
|
15035
15177
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
15036
15178
|
return;
|
|
15037
15179
|
}
|
|
15038
|
-
const content =
|
|
15180
|
+
const content = fs12.readFileSync(fullPath, "utf-8");
|
|
15039
15181
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
15040
15182
|
}
|
|
15041
15183
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -15051,15 +15193,15 @@ var DevServer = class _DevServer {
|
|
|
15051
15193
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
15052
15194
|
return;
|
|
15053
15195
|
}
|
|
15054
|
-
const fullPath =
|
|
15196
|
+
const fullPath = path15.resolve(dir, path15.normalize(filePath));
|
|
15055
15197
|
if (!fullPath.startsWith(dir)) {
|
|
15056
15198
|
this.json(res, 403, { error: "Forbidden" });
|
|
15057
15199
|
return;
|
|
15058
15200
|
}
|
|
15059
15201
|
try {
|
|
15060
|
-
if (
|
|
15061
|
-
|
|
15062
|
-
|
|
15202
|
+
if (fs12.existsSync(fullPath)) fs12.copyFileSync(fullPath, fullPath + ".bak");
|
|
15203
|
+
fs12.mkdirSync(path15.dirname(fullPath), { recursive: true });
|
|
15204
|
+
fs12.writeFileSync(fullPath, content, "utf-8");
|
|
15063
15205
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
15064
15206
|
this.providerLoader.reload();
|
|
15065
15207
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -15075,9 +15217,9 @@ var DevServer = class _DevServer {
|
|
|
15075
15217
|
return;
|
|
15076
15218
|
}
|
|
15077
15219
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
15078
|
-
const p =
|
|
15079
|
-
if (
|
|
15080
|
-
const source =
|
|
15220
|
+
const p = path15.join(dir, name);
|
|
15221
|
+
if (fs12.existsSync(p)) {
|
|
15222
|
+
const source = fs12.readFileSync(p, "utf-8");
|
|
15081
15223
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
15082
15224
|
return;
|
|
15083
15225
|
}
|
|
@@ -15096,11 +15238,11 @@ var DevServer = class _DevServer {
|
|
|
15096
15238
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
15097
15239
|
return;
|
|
15098
15240
|
}
|
|
15099
|
-
const target =
|
|
15100
|
-
const targetPath =
|
|
15241
|
+
const target = fs12.existsSync(path15.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
15242
|
+
const targetPath = path15.join(dir, target);
|
|
15101
15243
|
try {
|
|
15102
|
-
if (
|
|
15103
|
-
|
|
15244
|
+
if (fs12.existsSync(targetPath)) fs12.copyFileSync(targetPath, targetPath + ".bak");
|
|
15245
|
+
fs12.writeFileSync(targetPath, source, "utf-8");
|
|
15104
15246
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
15105
15247
|
this.providerLoader.reload();
|
|
15106
15248
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -15179,20 +15321,20 @@ var DevServer = class _DevServer {
|
|
|
15179
15321
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
15180
15322
|
return;
|
|
15181
15323
|
}
|
|
15182
|
-
const
|
|
15183
|
-
if (!
|
|
15324
|
+
const spawn4 = provider.spawn;
|
|
15325
|
+
if (!spawn4) {
|
|
15184
15326
|
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
15185
15327
|
return;
|
|
15186
15328
|
}
|
|
15187
15329
|
const { spawn: spawnFn } = await import("child_process");
|
|
15188
15330
|
const start = Date.now();
|
|
15189
15331
|
try {
|
|
15190
|
-
const args = [...
|
|
15191
|
-
const child = spawnFn(
|
|
15192
|
-
shell:
|
|
15332
|
+
const args = [...spawn4.args || [], message];
|
|
15333
|
+
const child = spawnFn(spawn4.command, args, {
|
|
15334
|
+
shell: spawn4.shell ?? false,
|
|
15193
15335
|
timeout,
|
|
15194
15336
|
stdio: ["pipe", "pipe", "pipe"],
|
|
15195
|
-
env: { ...process.env, ...
|
|
15337
|
+
env: { ...process.env, ...spawn4.env || {} }
|
|
15196
15338
|
});
|
|
15197
15339
|
let stdout = "";
|
|
15198
15340
|
let stderr = "";
|
|
@@ -15257,21 +15399,21 @@ var DevServer = class _DevServer {
|
|
|
15257
15399
|
}
|
|
15258
15400
|
let targetDir;
|
|
15259
15401
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
15260
|
-
const jsonPath =
|
|
15261
|
-
if (
|
|
15402
|
+
const jsonPath = path15.join(targetDir, "provider.json");
|
|
15403
|
+
if (fs12.existsSync(jsonPath)) {
|
|
15262
15404
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
15263
15405
|
return;
|
|
15264
15406
|
}
|
|
15265
15407
|
try {
|
|
15266
15408
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version, osPaths, processNames });
|
|
15267
|
-
|
|
15268
|
-
|
|
15409
|
+
fs12.mkdirSync(targetDir, { recursive: true });
|
|
15410
|
+
fs12.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
15269
15411
|
const createdFiles = ["provider.json"];
|
|
15270
15412
|
if (result.files) {
|
|
15271
15413
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
15272
|
-
const fullPath =
|
|
15273
|
-
|
|
15274
|
-
|
|
15414
|
+
const fullPath = path15.join(targetDir, relPath);
|
|
15415
|
+
fs12.mkdirSync(path15.dirname(fullPath), { recursive: true });
|
|
15416
|
+
fs12.writeFileSync(fullPath, content, "utf-8");
|
|
15275
15417
|
createdFiles.push(relPath);
|
|
15276
15418
|
}
|
|
15277
15419
|
}
|
|
@@ -15320,45 +15462,45 @@ var DevServer = class _DevServer {
|
|
|
15320
15462
|
}
|
|
15321
15463
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
15322
15464
|
getLatestScriptVersionDir(scriptsDir) {
|
|
15323
|
-
if (!
|
|
15324
|
-
const versions =
|
|
15465
|
+
if (!fs12.existsSync(scriptsDir)) return null;
|
|
15466
|
+
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
15325
15467
|
try {
|
|
15326
|
-
return
|
|
15468
|
+
return fs12.statSync(path15.join(scriptsDir, d)).isDirectory();
|
|
15327
15469
|
} catch {
|
|
15328
15470
|
return false;
|
|
15329
15471
|
}
|
|
15330
15472
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
15331
15473
|
if (versions.length === 0) return null;
|
|
15332
|
-
return
|
|
15474
|
+
return path15.join(scriptsDir, versions[0]);
|
|
15333
15475
|
}
|
|
15334
15476
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
15335
|
-
const canonicalUserDir =
|
|
15336
|
-
const desiredDir = requestedDir ?
|
|
15337
|
-
const upstreamRoot =
|
|
15338
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
15477
|
+
const canonicalUserDir = path15.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
15478
|
+
const desiredDir = requestedDir ? path15.resolve(requestedDir) : canonicalUserDir;
|
|
15479
|
+
const upstreamRoot = path15.resolve(this.providerLoader.getUpstreamDir());
|
|
15480
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path15.sep}`)) {
|
|
15339
15481
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
15340
15482
|
}
|
|
15341
|
-
if (
|
|
15483
|
+
if (path15.basename(desiredDir) !== type) {
|
|
15342
15484
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
15343
15485
|
}
|
|
15344
15486
|
const sourceDir = this.findProviderDir(type);
|
|
15345
15487
|
if (!sourceDir) {
|
|
15346
15488
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
15347
15489
|
}
|
|
15348
|
-
if (!
|
|
15349
|
-
|
|
15350
|
-
|
|
15490
|
+
if (!fs12.existsSync(desiredDir)) {
|
|
15491
|
+
fs12.mkdirSync(path15.dirname(desiredDir), { recursive: true });
|
|
15492
|
+
fs12.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
15351
15493
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
15352
15494
|
}
|
|
15353
|
-
const providerJson =
|
|
15354
|
-
if (!
|
|
15495
|
+
const providerJson = path15.join(desiredDir, "provider.json");
|
|
15496
|
+
if (!fs12.existsSync(providerJson)) {
|
|
15355
15497
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
15356
15498
|
}
|
|
15357
15499
|
try {
|
|
15358
|
-
const providerData = JSON.parse(
|
|
15500
|
+
const providerData = JSON.parse(fs12.readFileSync(providerJson, "utf-8"));
|
|
15359
15501
|
if (providerData.disableUpstream !== true) {
|
|
15360
15502
|
providerData.disableUpstream = true;
|
|
15361
|
-
|
|
15503
|
+
fs12.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
15362
15504
|
}
|
|
15363
15505
|
} catch (error) {
|
|
15364
15506
|
return {
|
|
@@ -15398,7 +15540,7 @@ var DevServer = class _DevServer {
|
|
|
15398
15540
|
setMode: "set_mode.js"
|
|
15399
15541
|
};
|
|
15400
15542
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
15401
|
-
const scriptsDir =
|
|
15543
|
+
const scriptsDir = path15.join(providerDir, "scripts");
|
|
15402
15544
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
15403
15545
|
if (latestScriptsDir) {
|
|
15404
15546
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -15406,10 +15548,10 @@ var DevServer = class _DevServer {
|
|
|
15406
15548
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
15407
15549
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
15408
15550
|
lines.push("");
|
|
15409
|
-
for (const file of
|
|
15551
|
+
for (const file of fs12.readdirSync(latestScriptsDir)) {
|
|
15410
15552
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
15411
15553
|
try {
|
|
15412
|
-
const content =
|
|
15554
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15413
15555
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
15414
15556
|
lines.push("```javascript");
|
|
15415
15557
|
lines.push(content);
|
|
@@ -15419,14 +15561,14 @@ var DevServer = class _DevServer {
|
|
|
15419
15561
|
}
|
|
15420
15562
|
}
|
|
15421
15563
|
}
|
|
15422
|
-
const refFiles =
|
|
15564
|
+
const refFiles = fs12.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
15423
15565
|
if (refFiles.length > 0) {
|
|
15424
15566
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
15425
15567
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
15426
15568
|
lines.push("");
|
|
15427
15569
|
for (const file of refFiles) {
|
|
15428
15570
|
try {
|
|
15429
|
-
const content =
|
|
15571
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15430
15572
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
15431
15573
|
lines.push("```javascript");
|
|
15432
15574
|
lines.push(content);
|
|
@@ -15467,11 +15609,11 @@ var DevServer = class _DevServer {
|
|
|
15467
15609
|
lines.push("");
|
|
15468
15610
|
}
|
|
15469
15611
|
}
|
|
15470
|
-
const docsDir =
|
|
15612
|
+
const docsDir = path15.join(providerDir, "../../docs");
|
|
15471
15613
|
const loadGuide = (name) => {
|
|
15472
15614
|
try {
|
|
15473
|
-
const p =
|
|
15474
|
-
if (
|
|
15615
|
+
const p = path15.join(docsDir, name);
|
|
15616
|
+
if (fs12.existsSync(p)) return fs12.readFileSync(p, "utf-8");
|
|
15475
15617
|
} catch {
|
|
15476
15618
|
}
|
|
15477
15619
|
return null;
|
|
@@ -15644,7 +15786,7 @@ var DevServer = class _DevServer {
|
|
|
15644
15786
|
parseApproval: "parse_approval.js"
|
|
15645
15787
|
};
|
|
15646
15788
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
15647
|
-
const scriptsDir =
|
|
15789
|
+
const scriptsDir = path15.join(providerDir, "scripts");
|
|
15648
15790
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
15649
15791
|
if (latestScriptsDir) {
|
|
15650
15792
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -15652,11 +15794,11 @@ var DevServer = class _DevServer {
|
|
|
15652
15794
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
15653
15795
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
15654
15796
|
lines.push("");
|
|
15655
|
-
for (const file of
|
|
15797
|
+
for (const file of fs12.readdirSync(latestScriptsDir)) {
|
|
15656
15798
|
if (!file.endsWith(".js")) continue;
|
|
15657
15799
|
if (!targetFileNames.has(file)) continue;
|
|
15658
15800
|
try {
|
|
15659
|
-
const content =
|
|
15801
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15660
15802
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
15661
15803
|
lines.push("```javascript");
|
|
15662
15804
|
lines.push(content);
|
|
@@ -15665,14 +15807,14 @@ var DevServer = class _DevServer {
|
|
|
15665
15807
|
} catch {
|
|
15666
15808
|
}
|
|
15667
15809
|
}
|
|
15668
|
-
const refFiles =
|
|
15810
|
+
const refFiles = fs12.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
15669
15811
|
if (refFiles.length > 0) {
|
|
15670
15812
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
15671
15813
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
15672
15814
|
lines.push("");
|
|
15673
15815
|
for (const file of refFiles) {
|
|
15674
15816
|
try {
|
|
15675
|
-
const content =
|
|
15817
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15676
15818
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
15677
15819
|
lines.push("```javascript");
|
|
15678
15820
|
lines.push(content);
|
|
@@ -15705,11 +15847,11 @@ var DevServer = class _DevServer {
|
|
|
15705
15847
|
lines.push("");
|
|
15706
15848
|
}
|
|
15707
15849
|
}
|
|
15708
|
-
const docsDir =
|
|
15850
|
+
const docsDir = path15.join(providerDir, "../../docs");
|
|
15709
15851
|
const loadGuide = (name) => {
|
|
15710
15852
|
try {
|
|
15711
|
-
const p =
|
|
15712
|
-
if (
|
|
15853
|
+
const p = path15.join(docsDir, name);
|
|
15854
|
+
if (fs12.existsSync(p)) return fs12.readFileSync(p, "utf-8");
|
|
15713
15855
|
} catch {
|
|
15714
15856
|
}
|
|
15715
15857
|
return null;
|
|
@@ -15942,6 +16084,7 @@ var SessionHostRuntimeTransport = class {
|
|
|
15942
16084
|
this.ready = this.boot();
|
|
15943
16085
|
}
|
|
15944
16086
|
ready;
|
|
16087
|
+
terminalQueriesHandled = true;
|
|
15945
16088
|
client;
|
|
15946
16089
|
dataCallbacks = /* @__PURE__ */ new Set();
|
|
15947
16090
|
exitCallbacks = /* @__PURE__ */ new Set();
|
|
@@ -16447,8 +16590,8 @@ async function installExtension(ide, extension) {
|
|
|
16447
16590
|
const res = await fetch(extension.vsixUrl);
|
|
16448
16591
|
if (res.ok) {
|
|
16449
16592
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
16450
|
-
const
|
|
16451
|
-
|
|
16593
|
+
const fs13 = await import("fs");
|
|
16594
|
+
fs13.writeFileSync(vsixPath, buffer);
|
|
16452
16595
|
return new Promise((resolve9) => {
|
|
16453
16596
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
16454
16597
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
@@ -16815,6 +16958,7 @@ export {
|
|
|
16815
16958
|
loadConfig,
|
|
16816
16959
|
logCommand,
|
|
16817
16960
|
markSetupComplete,
|
|
16961
|
+
maybeRunDaemonUpgradeHelperFromEnv,
|
|
16818
16962
|
normalizeActiveChatData,
|
|
16819
16963
|
normalizeManagedStatus,
|
|
16820
16964
|
probeCdpPort,
|