@adhdev/daemon-core 0.7.43 → 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/commands/upgrade-helper.d.ts +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +437 -248
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +425 -237
- package/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/commands/router.ts +29 -23
- package/src/commands/upgrade-helper.ts +214 -0
- package/src/index.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -691,11 +691,11 @@ var init_terminal_screen = __esm({
|
|
|
691
691
|
});
|
|
692
692
|
|
|
693
693
|
// src/cli-adapters/pty-transport.ts
|
|
694
|
-
var
|
|
694
|
+
var os12, pty, NodePtyRuntimeTransport, NodePtyTransportFactory;
|
|
695
695
|
var init_pty_transport = __esm({
|
|
696
696
|
"src/cli-adapters/pty-transport.ts"() {
|
|
697
697
|
"use strict";
|
|
698
|
-
|
|
698
|
+
os12 = __toESM(require("os"));
|
|
699
699
|
try {
|
|
700
700
|
pty = require("node-pty");
|
|
701
701
|
} catch {
|
|
@@ -733,7 +733,7 @@ var init_pty_transport = __esm({
|
|
|
733
733
|
spawn(command, args, options) {
|
|
734
734
|
if (!pty) throw new Error("node-pty is not installed");
|
|
735
735
|
const handle = pty.spawn(command, args, {
|
|
736
|
-
name:
|
|
736
|
+
name: os12.platform() === "win32" ? "xterm-color" : "xterm-256color",
|
|
737
737
|
cols: options.cols,
|
|
738
738
|
rows: options.rows,
|
|
739
739
|
cwd: options.cwd,
|
|
@@ -787,23 +787,23 @@ function computeTerminalQueryTail(buffer) {
|
|
|
787
787
|
return "";
|
|
788
788
|
}
|
|
789
789
|
function findBinary(name) {
|
|
790
|
-
const isWin =
|
|
790
|
+
const isWin = os13.platform() === "win32";
|
|
791
791
|
try {
|
|
792
792
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
793
|
-
return (0,
|
|
793
|
+
return (0, import_child_process7.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
794
794
|
} catch {
|
|
795
795
|
return isWin ? `${name}.cmd` : name;
|
|
796
796
|
}
|
|
797
797
|
}
|
|
798
798
|
function isScriptBinary(binaryPath) {
|
|
799
|
-
if (!
|
|
799
|
+
if (!path10.isAbsolute(binaryPath)) return false;
|
|
800
800
|
try {
|
|
801
|
-
const
|
|
802
|
-
const resolved =
|
|
801
|
+
const fs13 = require("fs");
|
|
802
|
+
const resolved = fs13.realpathSync(binaryPath);
|
|
803
803
|
const head = Buffer.alloc(8);
|
|
804
|
-
const fd =
|
|
805
|
-
|
|
806
|
-
|
|
804
|
+
const fd = fs13.openSync(resolved, "r");
|
|
805
|
+
fs13.readSync(fd, head, 0, 8, 0);
|
|
806
|
+
fs13.closeSync(fd);
|
|
807
807
|
let i = 0;
|
|
808
808
|
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
809
809
|
return head[i] === 35 && head[i + 1] === 33;
|
|
@@ -812,14 +812,14 @@ function isScriptBinary(binaryPath) {
|
|
|
812
812
|
}
|
|
813
813
|
}
|
|
814
814
|
function looksLikeMachOOrElf(filePath) {
|
|
815
|
-
if (!
|
|
815
|
+
if (!path10.isAbsolute(filePath)) return false;
|
|
816
816
|
try {
|
|
817
|
-
const
|
|
818
|
-
const resolved =
|
|
817
|
+
const fs13 = require("fs");
|
|
818
|
+
const resolved = fs13.realpathSync(filePath);
|
|
819
819
|
const buf = Buffer.alloc(8);
|
|
820
|
-
const fd =
|
|
821
|
-
|
|
822
|
-
|
|
820
|
+
const fd = fs13.openSync(resolved, "r");
|
|
821
|
+
fs13.readSync(fd, buf, 0, 8, 0);
|
|
822
|
+
fs13.closeSync(fd);
|
|
823
823
|
let i = 0;
|
|
824
824
|
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
825
825
|
const b = buf.subarray(i);
|
|
@@ -835,7 +835,7 @@ function looksLikeMachOOrElf(filePath) {
|
|
|
835
835
|
}
|
|
836
836
|
function shSingleQuote(arg) {
|
|
837
837
|
if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
|
|
838
|
-
if (
|
|
838
|
+
if (os13.platform() === "win32") {
|
|
839
839
|
return `"${arg.replace(/"/g, '""')}"`;
|
|
840
840
|
}
|
|
841
841
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
@@ -896,28 +896,28 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
896
896
|
}
|
|
897
897
|
};
|
|
898
898
|
}
|
|
899
|
-
var
|
|
899
|
+
var os13, path10, import_child_process7, pty2, ProviderCliAdapter;
|
|
900
900
|
var init_provider_cli_adapter = __esm({
|
|
901
901
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
902
902
|
"use strict";
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
903
|
+
os13 = __toESM(require("os"));
|
|
904
|
+
path10 = __toESM(require("path"));
|
|
905
|
+
import_child_process7 = require("child_process");
|
|
906
906
|
init_logger();
|
|
907
907
|
init_terminal_screen();
|
|
908
908
|
init_pty_transport();
|
|
909
909
|
try {
|
|
910
910
|
pty2 = require("node-pty");
|
|
911
|
-
if (
|
|
911
|
+
if (os13.platform() !== "win32") {
|
|
912
912
|
try {
|
|
913
|
-
const
|
|
914
|
-
const ptyDir =
|
|
915
|
-
const platformArch = `${
|
|
916
|
-
const helper =
|
|
917
|
-
if (
|
|
918
|
-
const stat =
|
|
913
|
+
const fs13 = require("fs");
|
|
914
|
+
const ptyDir = path10.resolve(path10.dirname(require.resolve("node-pty")), "..");
|
|
915
|
+
const platformArch = `${os13.platform()}-${os13.arch()}`;
|
|
916
|
+
const helper = path10.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
917
|
+
if (fs13.existsSync(helper)) {
|
|
918
|
+
const stat = fs13.statSync(helper);
|
|
919
919
|
if (!(stat.mode & 73)) {
|
|
920
|
-
|
|
920
|
+
fs13.chmodSync(helper, stat.mode | 493);
|
|
921
921
|
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
922
922
|
}
|
|
923
923
|
}
|
|
@@ -934,7 +934,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
934
934
|
this.transportFactory = transportFactory;
|
|
935
935
|
this.cliType = provider.type;
|
|
936
936
|
this.cliName = provider.name;
|
|
937
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
937
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os13.homedir()) : workingDir;
|
|
938
938
|
const t = provider.timeouts || {};
|
|
939
939
|
this.timeouts = {
|
|
940
940
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -1101,12 +1101,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
1101
1101
|
if (this.ptyProcess) return;
|
|
1102
1102
|
const { spawn: spawnConfig } = this.provider;
|
|
1103
1103
|
const binaryPath = findBinary(spawnConfig.command);
|
|
1104
|
-
const isWin =
|
|
1104
|
+
const isWin = os13.platform() === "win32";
|
|
1105
1105
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
1106
1106
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1107
1107
|
let shellCmd;
|
|
1108
1108
|
let shellArgs;
|
|
1109
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1109
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1110
1110
|
const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
|
|
1111
1111
|
if (useShell) {
|
|
1112
1112
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -1991,6 +1991,7 @@ __export(index_exports, {
|
|
|
1991
1991
|
loadConfig: () => loadConfig,
|
|
1992
1992
|
logCommand: () => logCommand,
|
|
1993
1993
|
markSetupComplete: () => markSetupComplete,
|
|
1994
|
+
maybeRunDaemonUpgradeHelperFromEnv: () => maybeRunDaemonUpgradeHelperFromEnv,
|
|
1994
1995
|
normalizeActiveChatData: () => normalizeActiveChatData,
|
|
1995
1996
|
normalizeManagedStatus: () => normalizeManagedStatus,
|
|
1996
1997
|
probeCdpPort: () => probeCdpPort,
|
|
@@ -2283,18 +2284,18 @@ function checkPathExists(paths) {
|
|
|
2283
2284
|
return null;
|
|
2284
2285
|
}
|
|
2285
2286
|
async function detectIDEs() {
|
|
2286
|
-
const
|
|
2287
|
+
const os17 = (0, import_os2.platform)();
|
|
2287
2288
|
const results = [];
|
|
2288
2289
|
for (const def of getMergedDefinitions()) {
|
|
2289
2290
|
const cliPath = findCliCommand(def.cli);
|
|
2290
|
-
const appPath = checkPathExists(def.paths[
|
|
2291
|
+
const appPath = checkPathExists(def.paths[os17] || []);
|
|
2291
2292
|
const installed = !!(cliPath || appPath);
|
|
2292
2293
|
let resolvedCli = cliPath;
|
|
2293
|
-
if (!resolvedCli && appPath &&
|
|
2294
|
+
if (!resolvedCli && appPath && os17 === "darwin") {
|
|
2294
2295
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
2295
2296
|
if ((0, import_fs2.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
2296
2297
|
}
|
|
2297
|
-
if (!resolvedCli && appPath &&
|
|
2298
|
+
if (!resolvedCli && appPath && os17 === "win32") {
|
|
2298
2299
|
const { dirname: dirname7 } = await import("path");
|
|
2299
2300
|
const appDir = dirname7(appPath);
|
|
2300
2301
|
const candidates = [
|
|
@@ -8313,7 +8314,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
8313
8314
|
}
|
|
8314
8315
|
} else if (plat === "win32") {
|
|
8315
8316
|
try {
|
|
8316
|
-
const
|
|
8317
|
+
const fs13 = require("fs");
|
|
8317
8318
|
const appNameMap = getMacAppIdentifiers();
|
|
8318
8319
|
const appName = appNameMap[ideId];
|
|
8319
8320
|
if (appName) {
|
|
@@ -8322,8 +8323,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
8322
8323
|
appName,
|
|
8323
8324
|
"storage.json"
|
|
8324
8325
|
);
|
|
8325
|
-
if (
|
|
8326
|
-
const data = JSON.parse(
|
|
8326
|
+
if (fs13.existsSync(storagePath)) {
|
|
8327
|
+
const data = JSON.parse(fs13.readFileSync(storagePath, "utf-8"));
|
|
8327
8328
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
8328
8329
|
if (workspaces.length > 0) {
|
|
8329
8330
|
const recent = workspaces[0];
|
|
@@ -8768,8 +8769,191 @@ function buildStatusSnapshot(options) {
|
|
|
8768
8769
|
};
|
|
8769
8770
|
}
|
|
8770
8771
|
|
|
8771
|
-
// src/commands/
|
|
8772
|
+
// src/commands/upgrade-helper.ts
|
|
8773
|
+
var import_child_process5 = require("child_process");
|
|
8774
|
+
var import_child_process6 = require("child_process");
|
|
8772
8775
|
var fs7 = __toESM(require("fs"));
|
|
8776
|
+
var os11 = __toESM(require("os"));
|
|
8777
|
+
var path9 = __toESM(require("path"));
|
|
8778
|
+
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
8779
|
+
function getUpgradeLogPath() {
|
|
8780
|
+
const home = os11.homedir();
|
|
8781
|
+
const dir = path9.join(home, ".adhdev");
|
|
8782
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
8783
|
+
return path9.join(dir, "daemon-upgrade.log");
|
|
8784
|
+
}
|
|
8785
|
+
function appendUpgradeLog(message) {
|
|
8786
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
8787
|
+
`;
|
|
8788
|
+
try {
|
|
8789
|
+
fs7.appendFileSync(getUpgradeLogPath(), line, "utf8");
|
|
8790
|
+
} catch {
|
|
8791
|
+
}
|
|
8792
|
+
}
|
|
8793
|
+
function getNpmExecutable() {
|
|
8794
|
+
return process.platform === "win32" ? "npm.cmd" : "npm";
|
|
8795
|
+
}
|
|
8796
|
+
function killPid(pid) {
|
|
8797
|
+
try {
|
|
8798
|
+
if (process.platform === "win32") {
|
|
8799
|
+
(0, import_child_process5.execFileSync)("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
8800
|
+
} else {
|
|
8801
|
+
process.kill(pid, "SIGTERM");
|
|
8802
|
+
}
|
|
8803
|
+
return true;
|
|
8804
|
+
} catch {
|
|
8805
|
+
return false;
|
|
8806
|
+
}
|
|
8807
|
+
}
|
|
8808
|
+
async function waitForPidExit(pid, timeoutMs) {
|
|
8809
|
+
const start = Date.now();
|
|
8810
|
+
while (Date.now() - start < timeoutMs) {
|
|
8811
|
+
try {
|
|
8812
|
+
process.kill(pid, 0);
|
|
8813
|
+
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
8814
|
+
} catch {
|
|
8815
|
+
return;
|
|
8816
|
+
}
|
|
8817
|
+
}
|
|
8818
|
+
}
|
|
8819
|
+
function stopSessionHostProcesses(appName) {
|
|
8820
|
+
const pidFile = path9.join(os11.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
8821
|
+
try {
|
|
8822
|
+
if (fs7.existsSync(pidFile)) {
|
|
8823
|
+
const pid = Number.parseInt(fs7.readFileSync(pidFile, "utf8").trim(), 10);
|
|
8824
|
+
if (Number.isFinite(pid)) {
|
|
8825
|
+
killPid(pid);
|
|
8826
|
+
}
|
|
8827
|
+
}
|
|
8828
|
+
} catch {
|
|
8829
|
+
} finally {
|
|
8830
|
+
try {
|
|
8831
|
+
fs7.unlinkSync(pidFile);
|
|
8832
|
+
} catch {
|
|
8833
|
+
}
|
|
8834
|
+
}
|
|
8835
|
+
if (process.platform !== "win32") {
|
|
8836
|
+
try {
|
|
8837
|
+
const raw = (0, import_child_process5.execFileSync)("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
|
|
8838
|
+
for (const line of raw.split("\n")) {
|
|
8839
|
+
const pid = Number.parseInt(line.trim(), 10);
|
|
8840
|
+
if (Number.isFinite(pid)) {
|
|
8841
|
+
killPid(pid);
|
|
8842
|
+
}
|
|
8843
|
+
}
|
|
8844
|
+
} catch {
|
|
8845
|
+
}
|
|
8846
|
+
}
|
|
8847
|
+
}
|
|
8848
|
+
function removeDaemonPidFile() {
|
|
8849
|
+
const pidFile = path9.join(os11.homedir(), ".adhdev", "daemon.pid");
|
|
8850
|
+
try {
|
|
8851
|
+
fs7.unlinkSync(pidFile);
|
|
8852
|
+
} catch {
|
|
8853
|
+
}
|
|
8854
|
+
}
|
|
8855
|
+
function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
8856
|
+
const npmRoot = (0, import_child_process5.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8" }).trim();
|
|
8857
|
+
if (!npmRoot) return;
|
|
8858
|
+
const npmPrefix = (0, import_child_process5.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8" }).trim();
|
|
8859
|
+
const binDir = process.platform === "win32" ? npmPrefix : path9.join(npmPrefix, "bin");
|
|
8860
|
+
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
8861
|
+
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
8862
|
+
if (pkgName === "@adhdev/daemon-standalone") {
|
|
8863
|
+
binNames.add("adhdev-standalone");
|
|
8864
|
+
}
|
|
8865
|
+
if (pkgName.startsWith("@")) {
|
|
8866
|
+
const [scope, name] = pkgName.split("/");
|
|
8867
|
+
const scopeDir = path9.join(npmRoot, scope);
|
|
8868
|
+
if (!fs7.existsSync(scopeDir)) return;
|
|
8869
|
+
for (const entry of fs7.readdirSync(scopeDir)) {
|
|
8870
|
+
if (!entry.startsWith(`.${name}-`)) continue;
|
|
8871
|
+
fs7.rmSync(path9.join(scopeDir, entry), { recursive: true, force: true });
|
|
8872
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path9.join(scopeDir, entry)}`);
|
|
8873
|
+
}
|
|
8874
|
+
} else {
|
|
8875
|
+
for (const entry of fs7.readdirSync(npmRoot)) {
|
|
8876
|
+
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
8877
|
+
fs7.rmSync(path9.join(npmRoot, entry), { recursive: true, force: true });
|
|
8878
|
+
appendUpgradeLog(`Removed stale staging dir: ${path9.join(npmRoot, entry)}`);
|
|
8879
|
+
}
|
|
8880
|
+
}
|
|
8881
|
+
if (fs7.existsSync(binDir)) {
|
|
8882
|
+
for (const entry of fs7.readdirSync(binDir)) {
|
|
8883
|
+
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
8884
|
+
fs7.rmSync(path9.join(binDir, entry), { recursive: true, force: true });
|
|
8885
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path9.join(binDir, entry)}`);
|
|
8886
|
+
}
|
|
8887
|
+
}
|
|
8888
|
+
}
|
|
8889
|
+
function spawnDetachedDaemonUpgradeHelper(payload) {
|
|
8890
|
+
const env = { ...process.env, [UPGRADE_HELPER_ENV]: JSON.stringify(payload) };
|
|
8891
|
+
const child = (0, import_child_process6.spawn)(process.execPath, process.argv.slice(1), {
|
|
8892
|
+
detached: true,
|
|
8893
|
+
stdio: "ignore",
|
|
8894
|
+
windowsHide: true,
|
|
8895
|
+
cwd: payload.cwd || process.cwd(),
|
|
8896
|
+
env
|
|
8897
|
+
});
|
|
8898
|
+
child.unref();
|
|
8899
|
+
}
|
|
8900
|
+
async function runDaemonUpgradeHelper(payload) {
|
|
8901
|
+
const restartArgv = Array.isArray(payload.restartArgv) ? payload.restartArgv : [];
|
|
8902
|
+
const sessionHostAppName = payload.sessionHostAppName || process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
8903
|
+
appendUpgradeLog(`Upgrade helper started for ${payload.packageName}@${payload.targetVersion}`);
|
|
8904
|
+
if (Number.isFinite(payload.parentPid) && payload.parentPid > 0) {
|
|
8905
|
+
appendUpgradeLog(`Waiting for parent pid ${payload.parentPid} to exit`);
|
|
8906
|
+
await waitForPidExit(payload.parentPid, 15e3);
|
|
8907
|
+
}
|
|
8908
|
+
stopSessionHostProcesses(sessionHostAppName);
|
|
8909
|
+
removeDaemonPidFile();
|
|
8910
|
+
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
8911
|
+
const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
|
|
8912
|
+
appendUpgradeLog(`Installing ${spec}`);
|
|
8913
|
+
const installOutput = (0, import_child_process5.execFileSync)(
|
|
8914
|
+
getNpmExecutable(),
|
|
8915
|
+
["install", "-g", spec, "--force"],
|
|
8916
|
+
{
|
|
8917
|
+
encoding: "utf8",
|
|
8918
|
+
stdio: "pipe",
|
|
8919
|
+
maxBuffer: 20 * 1024 * 1024
|
|
8920
|
+
}
|
|
8921
|
+
);
|
|
8922
|
+
if (installOutput.trim()) {
|
|
8923
|
+
appendUpgradeLog(installOutput.trim());
|
|
8924
|
+
}
|
|
8925
|
+
if (restartArgv.length > 0) {
|
|
8926
|
+
const env = { ...process.env };
|
|
8927
|
+
delete env[UPGRADE_HELPER_ENV];
|
|
8928
|
+
appendUpgradeLog(`Restarting daemon with args: ${restartArgv.join(" ")}`);
|
|
8929
|
+
const child = (0, import_child_process6.spawn)(process.execPath, restartArgv, {
|
|
8930
|
+
detached: true,
|
|
8931
|
+
stdio: "ignore",
|
|
8932
|
+
windowsHide: true,
|
|
8933
|
+
cwd: payload.cwd || process.cwd(),
|
|
8934
|
+
env
|
|
8935
|
+
});
|
|
8936
|
+
child.unref();
|
|
8937
|
+
} else {
|
|
8938
|
+
appendUpgradeLog("No restart argv provided; upgrade completed without restart");
|
|
8939
|
+
}
|
|
8940
|
+
}
|
|
8941
|
+
async function maybeRunDaemonUpgradeHelperFromEnv() {
|
|
8942
|
+
const raw = process.env[UPGRADE_HELPER_ENV];
|
|
8943
|
+
if (!raw) return false;
|
|
8944
|
+
delete process.env[UPGRADE_HELPER_ENV];
|
|
8945
|
+
try {
|
|
8946
|
+
const payload = JSON.parse(raw);
|
|
8947
|
+
await runDaemonUpgradeHelper(payload);
|
|
8948
|
+
process.exit(0);
|
|
8949
|
+
} catch (error) {
|
|
8950
|
+
appendUpgradeLog(`Upgrade helper failed: ${error?.stack || error?.message || String(error)}`);
|
|
8951
|
+
process.exit(1);
|
|
8952
|
+
}
|
|
8953
|
+
}
|
|
8954
|
+
|
|
8955
|
+
// src/commands/router.ts
|
|
8956
|
+
var fs8 = __toESM(require("fs"));
|
|
8773
8957
|
var CHAT_COMMANDS = [
|
|
8774
8958
|
"send_chat",
|
|
8775
8959
|
"new_chat",
|
|
@@ -8840,8 +9024,8 @@ var DaemonCommandRouter = class {
|
|
|
8840
9024
|
if (logs.length > 0) {
|
|
8841
9025
|
return { success: true, logs, totalBuffered: logs.length };
|
|
8842
9026
|
}
|
|
8843
|
-
if (
|
|
8844
|
-
const content =
|
|
9027
|
+
if (fs8.existsSync(LOG_PATH)) {
|
|
9028
|
+
const content = fs8.readFileSync(LOG_PATH, "utf-8");
|
|
8845
9029
|
const allLines = content.split("\n");
|
|
8846
9030
|
const recent = allLines.slice(-count).join("\n");
|
|
8847
9031
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
@@ -8989,31 +9173,35 @@ var DaemonCommandRouter = class {
|
|
|
8989
9173
|
const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
|
|
8990
9174
|
const latest = execSync7(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
8991
9175
|
LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
9176
|
+
let currentInstalled = null;
|
|
9177
|
+
try {
|
|
9178
|
+
const currentJson = execSync7(`npm ls -g ${pkgName} --depth=0 --json`, {
|
|
9179
|
+
encoding: "utf-8",
|
|
9180
|
+
timeout: 1e4,
|
|
9181
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
9182
|
+
}).trim();
|
|
9183
|
+
const parsed = JSON.parse(currentJson);
|
|
9184
|
+
currentInstalled = parsed?.dependencies?.[pkgName]?.version || null;
|
|
9185
|
+
} catch {
|
|
9186
|
+
}
|
|
9187
|
+
if (currentInstalled === latest) {
|
|
9188
|
+
LOG.info("Upgrade", `Already on latest version v${latest}; skipping install`);
|
|
9189
|
+
return { success: true, upgraded: false, alreadyLatest: true, version: latest };
|
|
9190
|
+
}
|
|
9191
|
+
spawnDetachedDaemonUpgradeHelper({
|
|
9192
|
+
packageName: pkgName,
|
|
9193
|
+
targetVersion: latest,
|
|
9194
|
+
parentPid: process.pid,
|
|
9195
|
+
restartArgv: process.argv.slice(1),
|
|
9196
|
+
cwd: process.cwd(),
|
|
9197
|
+
sessionHostAppName: process.env.ADHDEV_SESSION_HOST_NAME || "adhdev"
|
|
8996
9198
|
});
|
|
8997
|
-
LOG.info("Upgrade",
|
|
9199
|
+
LOG.info("Upgrade", `Scheduled detached upgrade to v${latest}`);
|
|
8998
9200
|
setTimeout(() => {
|
|
8999
|
-
LOG.info("Upgrade", "
|
|
9000
|
-
try {
|
|
9001
|
-
const path15 = require("path");
|
|
9002
|
-
const fs12 = require("fs");
|
|
9003
|
-
const pidFile = path15.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
|
|
9004
|
-
if (fs12.existsSync(pidFile)) fs12.unlinkSync(pidFile);
|
|
9005
|
-
} catch {
|
|
9006
|
-
}
|
|
9007
|
-
const { spawn: spawn3 } = require("child_process");
|
|
9008
|
-
const child = spawn3(process.execPath, process.argv.slice(1), {
|
|
9009
|
-
detached: true,
|
|
9010
|
-
stdio: "ignore",
|
|
9011
|
-
env: { ...process.env }
|
|
9012
|
-
});
|
|
9013
|
-
child.unref();
|
|
9201
|
+
LOG.info("Upgrade", "Exiting daemon so detached upgrader can continue...");
|
|
9014
9202
|
process.exit(0);
|
|
9015
9203
|
}, 3e3);
|
|
9016
|
-
return { success: true, upgraded: true, version: latest };
|
|
9204
|
+
return { success: true, upgraded: true, version: latest, restarting: true };
|
|
9017
9205
|
} catch (e) {
|
|
9018
9206
|
LOG.error("Upgrade", `Failed: ${e.message}`);
|
|
9019
9207
|
return { success: false, error: e.message };
|
|
@@ -9309,8 +9497,8 @@ var DaemonStatusReporter = class {
|
|
|
9309
9497
|
init_logger();
|
|
9310
9498
|
|
|
9311
9499
|
// src/commands/cli-manager.ts
|
|
9312
|
-
var
|
|
9313
|
-
var
|
|
9500
|
+
var os14 = __toESM(require("os"));
|
|
9501
|
+
var path11 = __toESM(require("path"));
|
|
9314
9502
|
var crypto4 = __toESM(require("crypto"));
|
|
9315
9503
|
var import_chalk = __toESM(require("chalk"));
|
|
9316
9504
|
init_provider_cli_adapter();
|
|
@@ -9557,7 +9745,7 @@ var CliProviderInstance = class {
|
|
|
9557
9745
|
|
|
9558
9746
|
// src/providers/acp-provider-instance.ts
|
|
9559
9747
|
var import_stream = require("stream");
|
|
9560
|
-
var
|
|
9748
|
+
var import_child_process8 = require("child_process");
|
|
9561
9749
|
var import_sdk = require("@agentclientprotocol/sdk");
|
|
9562
9750
|
|
|
9563
9751
|
// src/providers/contracts.ts
|
|
@@ -9887,7 +10075,7 @@ var AcpProviderInstance = class {
|
|
|
9887
10075
|
this.errorMessage = null;
|
|
9888
10076
|
this.errorReason = null;
|
|
9889
10077
|
this.stderrBuffer = [];
|
|
9890
|
-
this.process = (0,
|
|
10078
|
+
this.process = (0, import_child_process8.spawn)(command, args, {
|
|
9891
10079
|
cwd: this.workingDir,
|
|
9892
10080
|
env,
|
|
9893
10081
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -10570,7 +10758,7 @@ var DaemonCliManager = class {
|
|
|
10570
10758
|
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
10571
10759
|
const trimmed = (workingDir || "").trim();
|
|
10572
10760
|
if (!trimmed) throw new Error("working directory required");
|
|
10573
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/,
|
|
10761
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os14.homedir()) : path11.resolve(trimmed);
|
|
10574
10762
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10575
10763
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
10576
10764
|
const key = crypto4.randomUUID();
|
|
@@ -11767,12 +11955,12 @@ var ProviderInstanceManager = class {
|
|
|
11767
11955
|
};
|
|
11768
11956
|
|
|
11769
11957
|
// src/providers/version-archive.ts
|
|
11770
|
-
var
|
|
11771
|
-
var
|
|
11772
|
-
var
|
|
11773
|
-
var
|
|
11958
|
+
var fs9 = __toESM(require("fs"));
|
|
11959
|
+
var path12 = __toESM(require("path"));
|
|
11960
|
+
var os15 = __toESM(require("os"));
|
|
11961
|
+
var import_child_process9 = require("child_process");
|
|
11774
11962
|
var import_os3 = require("os");
|
|
11775
|
-
var ARCHIVE_PATH =
|
|
11963
|
+
var ARCHIVE_PATH = path12.join(os15.homedir(), ".adhdev", "version-history.json");
|
|
11776
11964
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
11777
11965
|
var VersionArchive = class {
|
|
11778
11966
|
history = {};
|
|
@@ -11781,8 +11969,8 @@ var VersionArchive = class {
|
|
|
11781
11969
|
}
|
|
11782
11970
|
load() {
|
|
11783
11971
|
try {
|
|
11784
|
-
if (
|
|
11785
|
-
this.history = JSON.parse(
|
|
11972
|
+
if (fs9.existsSync(ARCHIVE_PATH)) {
|
|
11973
|
+
this.history = JSON.parse(fs9.readFileSync(ARCHIVE_PATH, "utf-8"));
|
|
11786
11974
|
}
|
|
11787
11975
|
} catch {
|
|
11788
11976
|
this.history = {};
|
|
@@ -11819,15 +12007,15 @@ var VersionArchive = class {
|
|
|
11819
12007
|
}
|
|
11820
12008
|
save() {
|
|
11821
12009
|
try {
|
|
11822
|
-
|
|
11823
|
-
|
|
12010
|
+
fs9.mkdirSync(path12.dirname(ARCHIVE_PATH), { recursive: true });
|
|
12011
|
+
fs9.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
11824
12012
|
} catch {
|
|
11825
12013
|
}
|
|
11826
12014
|
}
|
|
11827
12015
|
};
|
|
11828
12016
|
function runCommand(cmd, timeout = 1e4) {
|
|
11829
12017
|
try {
|
|
11830
|
-
return (0,
|
|
12018
|
+
return (0, import_child_process9.execSync)(cmd, {
|
|
11831
12019
|
encoding: "utf-8",
|
|
11832
12020
|
timeout,
|
|
11833
12021
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -11859,19 +12047,19 @@ function getVersion(binary, versionCommand) {
|
|
|
11859
12047
|
function checkPathExists2(paths) {
|
|
11860
12048
|
for (const p of paths) {
|
|
11861
12049
|
if (p.includes("*")) {
|
|
11862
|
-
const home =
|
|
11863
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
11864
|
-
if (
|
|
12050
|
+
const home = os15.homedir();
|
|
12051
|
+
const resolved = p.replace(/\*/g, home.split(path12.sep).pop() || "");
|
|
12052
|
+
if (fs9.existsSync(resolved)) return resolved;
|
|
11865
12053
|
} else {
|
|
11866
|
-
if (
|
|
12054
|
+
if (fs9.existsSync(p)) return p;
|
|
11867
12055
|
}
|
|
11868
12056
|
}
|
|
11869
12057
|
return null;
|
|
11870
12058
|
}
|
|
11871
12059
|
function getMacAppVersion(appPath) {
|
|
11872
12060
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
11873
|
-
const plistPath =
|
|
11874
|
-
if (!
|
|
12061
|
+
const plistPath = path12.join(appPath, "Contents", "Info.plist");
|
|
12062
|
+
if (!fs9.existsSync(plistPath)) return null;
|
|
11875
12063
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
11876
12064
|
return raw || null;
|
|
11877
12065
|
}
|
|
@@ -11897,8 +12085,8 @@ async function detectAllVersions(loader, archive) {
|
|
|
11897
12085
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
11898
12086
|
let resolvedBin = cliBin;
|
|
11899
12087
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
11900
|
-
const bundled =
|
|
11901
|
-
if (provider.cli &&
|
|
12088
|
+
const bundled = path12.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
12089
|
+
if (provider.cli && fs9.existsSync(bundled)) resolvedBin = bundled;
|
|
11902
12090
|
}
|
|
11903
12091
|
info.installed = !!(appPath || resolvedBin);
|
|
11904
12092
|
info.path = appPath || null;
|
|
@@ -11937,8 +12125,8 @@ async function detectAllVersions(loader, archive) {
|
|
|
11937
12125
|
|
|
11938
12126
|
// src/daemon/dev-server.ts
|
|
11939
12127
|
var http2 = __toESM(require("http"));
|
|
11940
|
-
var
|
|
11941
|
-
var
|
|
12128
|
+
var fs12 = __toESM(require("fs"));
|
|
12129
|
+
var path15 = __toESM(require("path"));
|
|
11942
12130
|
|
|
11943
12131
|
// src/daemon/scaffold-template.ts
|
|
11944
12132
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -12273,8 +12461,8 @@ async (params) => {
|
|
|
12273
12461
|
init_logger();
|
|
12274
12462
|
|
|
12275
12463
|
// src/daemon/dev-cdp-handlers.ts
|
|
12276
|
-
var
|
|
12277
|
-
var
|
|
12464
|
+
var fs10 = __toESM(require("fs"));
|
|
12465
|
+
var path13 = __toESM(require("path"));
|
|
12278
12466
|
init_logger();
|
|
12279
12467
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
12280
12468
|
const body = await ctx.readBody(req);
|
|
@@ -12453,18 +12641,18 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
12453
12641
|
return;
|
|
12454
12642
|
}
|
|
12455
12643
|
let scriptsPath = "";
|
|
12456
|
-
const directScripts =
|
|
12457
|
-
if (
|
|
12644
|
+
const directScripts = path13.join(dir, "scripts.js");
|
|
12645
|
+
if (fs10.existsSync(directScripts)) {
|
|
12458
12646
|
scriptsPath = directScripts;
|
|
12459
12647
|
} else {
|
|
12460
|
-
const scriptsDir =
|
|
12461
|
-
if (
|
|
12462
|
-
const versions =
|
|
12463
|
-
return
|
|
12648
|
+
const scriptsDir = path13.join(dir, "scripts");
|
|
12649
|
+
if (fs10.existsSync(scriptsDir)) {
|
|
12650
|
+
const versions = fs10.readdirSync(scriptsDir).filter((d) => {
|
|
12651
|
+
return fs10.statSync(path13.join(scriptsDir, d)).isDirectory();
|
|
12464
12652
|
}).sort().reverse();
|
|
12465
12653
|
for (const ver of versions) {
|
|
12466
|
-
const p =
|
|
12467
|
-
if (
|
|
12654
|
+
const p = path13.join(scriptsDir, ver, "scripts.js");
|
|
12655
|
+
if (fs10.existsSync(p)) {
|
|
12468
12656
|
scriptsPath = p;
|
|
12469
12657
|
break;
|
|
12470
12658
|
}
|
|
@@ -12476,7 +12664,7 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
12476
12664
|
return;
|
|
12477
12665
|
}
|
|
12478
12666
|
try {
|
|
12479
|
-
const source =
|
|
12667
|
+
const source = fs10.readFileSync(scriptsPath, "utf-8");
|
|
12480
12668
|
const hints = {};
|
|
12481
12669
|
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
12482
12670
|
let match;
|
|
@@ -13517,9 +13705,9 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
13517
13705
|
}
|
|
13518
13706
|
|
|
13519
13707
|
// src/daemon/dev-auto-implement.ts
|
|
13520
|
-
var
|
|
13521
|
-
var
|
|
13522
|
-
var
|
|
13708
|
+
var fs11 = __toESM(require("fs"));
|
|
13709
|
+
var path14 = __toESM(require("path"));
|
|
13710
|
+
var os16 = __toESM(require("os"));
|
|
13523
13711
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
13524
13712
|
if (category === "cli") {
|
|
13525
13713
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -13535,45 +13723,45 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
13535
13723
|
return fallback?.type || null;
|
|
13536
13724
|
}
|
|
13537
13725
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
13538
|
-
if (!
|
|
13539
|
-
const versions =
|
|
13726
|
+
if (!fs11.existsSync(scriptsDir)) return null;
|
|
13727
|
+
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
13540
13728
|
try {
|
|
13541
|
-
return
|
|
13729
|
+
return fs11.statSync(path14.join(scriptsDir, d)).isDirectory();
|
|
13542
13730
|
} catch {
|
|
13543
13731
|
return false;
|
|
13544
13732
|
}
|
|
13545
13733
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
13546
13734
|
if (versions.length === 0) return null;
|
|
13547
|
-
return
|
|
13735
|
+
return path14.join(scriptsDir, versions[0]);
|
|
13548
13736
|
}
|
|
13549
13737
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
13550
|
-
const canonicalUserDir =
|
|
13551
|
-
const desiredDir = requestedDir ?
|
|
13552
|
-
const upstreamRoot =
|
|
13553
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
13738
|
+
const canonicalUserDir = path14.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
13739
|
+
const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
|
|
13740
|
+
const upstreamRoot = path14.resolve(ctx.providerLoader.getUpstreamDir());
|
|
13741
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
|
|
13554
13742
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
13555
13743
|
}
|
|
13556
|
-
if (
|
|
13744
|
+
if (path14.basename(desiredDir) !== type) {
|
|
13557
13745
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
13558
13746
|
}
|
|
13559
13747
|
const sourceDir = ctx.findProviderDir(type);
|
|
13560
13748
|
if (!sourceDir) {
|
|
13561
13749
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
13562
13750
|
}
|
|
13563
|
-
if (!
|
|
13564
|
-
|
|
13565
|
-
|
|
13751
|
+
if (!fs11.existsSync(desiredDir)) {
|
|
13752
|
+
fs11.mkdirSync(path14.dirname(desiredDir), { recursive: true });
|
|
13753
|
+
fs11.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
13566
13754
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
13567
13755
|
}
|
|
13568
|
-
const providerJson =
|
|
13569
|
-
if (!
|
|
13756
|
+
const providerJson = path14.join(desiredDir, "provider.json");
|
|
13757
|
+
if (!fs11.existsSync(providerJson)) {
|
|
13570
13758
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
13571
13759
|
}
|
|
13572
13760
|
try {
|
|
13573
|
-
const providerData = JSON.parse(
|
|
13761
|
+
const providerData = JSON.parse(fs11.readFileSync(providerJson, "utf-8"));
|
|
13574
13762
|
if (providerData.disableUpstream !== true) {
|
|
13575
13763
|
providerData.disableUpstream = true;
|
|
13576
|
-
|
|
13764
|
+
fs11.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
13577
13765
|
}
|
|
13578
13766
|
} catch (error) {
|
|
13579
13767
|
return {
|
|
@@ -13586,15 +13774,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
13586
13774
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
13587
13775
|
if (!referenceType) return {};
|
|
13588
13776
|
const refDir = ctx.findProviderDir(referenceType);
|
|
13589
|
-
if (!refDir || !
|
|
13777
|
+
if (!refDir || !fs11.existsSync(refDir)) return {};
|
|
13590
13778
|
const referenceScripts = {};
|
|
13591
|
-
const scriptsDir =
|
|
13779
|
+
const scriptsDir = path14.join(refDir, "scripts");
|
|
13592
13780
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
13593
13781
|
if (!latestDir) return referenceScripts;
|
|
13594
|
-
for (const file of
|
|
13782
|
+
for (const file of fs11.readdirSync(latestDir)) {
|
|
13595
13783
|
if (!file.endsWith(".js")) continue;
|
|
13596
13784
|
try {
|
|
13597
|
-
referenceScripts[file] =
|
|
13785
|
+
referenceScripts[file] = fs11.readFileSync(path14.join(latestDir, file), "utf-8");
|
|
13598
13786
|
} catch {
|
|
13599
13787
|
}
|
|
13600
13788
|
}
|
|
@@ -13645,16 +13833,16 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13645
13833
|
});
|
|
13646
13834
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
13647
13835
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
13648
|
-
const tmpDir =
|
|
13649
|
-
if (!
|
|
13650
|
-
const promptFile =
|
|
13651
|
-
|
|
13836
|
+
const tmpDir = path14.join(os16.tmpdir(), "adhdev-autoimpl");
|
|
13837
|
+
if (!fs11.existsSync(tmpDir)) fs11.mkdirSync(tmpDir, { recursive: true });
|
|
13838
|
+
const promptFile = path14.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
13839
|
+
fs11.writeFileSync(promptFile, prompt, "utf-8");
|
|
13652
13840
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
13653
13841
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
13654
|
-
const
|
|
13655
|
-
if (!
|
|
13842
|
+
const spawn4 = agentProvider?.spawn;
|
|
13843
|
+
if (!spawn4?.command) {
|
|
13656
13844
|
try {
|
|
13657
|
-
|
|
13845
|
+
fs11.unlinkSync(promptFile);
|
|
13658
13846
|
} catch {
|
|
13659
13847
|
}
|
|
13660
13848
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -13662,21 +13850,21 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13662
13850
|
}
|
|
13663
13851
|
const agentCategory = agentProvider?.category;
|
|
13664
13852
|
if (agentCategory === "acp") {
|
|
13665
|
-
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${
|
|
13853
|
+
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn4.command} ${(spawn4.args || []).join(" ")}` } });
|
|
13666
13854
|
ctx.autoImplStatus = { running: true, type, progress: [] };
|
|
13667
13855
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await import("@agentclientprotocol/sdk");
|
|
13668
13856
|
const { Readable: Readable2, Writable: Writable2 } = await import("stream");
|
|
13669
13857
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
13670
|
-
const acpArgs = [...
|
|
13858
|
+
const acpArgs = [...spawn4.args || []];
|
|
13671
13859
|
if (model) {
|
|
13672
13860
|
acpArgs.push("--model", model);
|
|
13673
13861
|
ctx.log(`Auto-implement ACP using model: ${model}`);
|
|
13674
13862
|
}
|
|
13675
|
-
const child2 = spawnFn2(
|
|
13863
|
+
const child2 = spawnFn2(spawn4.command, acpArgs, {
|
|
13676
13864
|
cwd: providerDir,
|
|
13677
13865
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13678
|
-
shell:
|
|
13679
|
-
env: { ...process.env, ...
|
|
13866
|
+
shell: spawn4.shell ?? false,
|
|
13867
|
+
env: { ...process.env, ...spawn4.env || {} }
|
|
13680
13868
|
});
|
|
13681
13869
|
ctx.autoImplProcess = child2;
|
|
13682
13870
|
child2.stderr?.on("data", (d) => {
|
|
@@ -13755,7 +13943,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13755
13943
|
} catch {
|
|
13756
13944
|
}
|
|
13757
13945
|
try {
|
|
13758
|
-
|
|
13946
|
+
fs11.unlinkSync(promptFile);
|
|
13759
13947
|
} catch {
|
|
13760
13948
|
}
|
|
13761
13949
|
ctx.log(`Auto-implement (ACP) ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -13786,7 +13974,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13786
13974
|
ctx.json(res, 202, {
|
|
13787
13975
|
started: true,
|
|
13788
13976
|
type,
|
|
13789
|
-
agent:
|
|
13977
|
+
agent: spawn4.command,
|
|
13790
13978
|
functions,
|
|
13791
13979
|
providerDir,
|
|
13792
13980
|
message: "ACP Auto-implement started. Connect to SSE for progress.",
|
|
@@ -13794,11 +13982,11 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13794
13982
|
});
|
|
13795
13983
|
return;
|
|
13796
13984
|
}
|
|
13797
|
-
const command =
|
|
13985
|
+
const command = spawn4.command;
|
|
13798
13986
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
13799
|
-
const baseArgs = [...
|
|
13987
|
+
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
13800
13988
|
let shellCmd;
|
|
13801
|
-
const isWin =
|
|
13989
|
+
const isWin = os16.platform() === "win32";
|
|
13802
13990
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
13803
13991
|
if (command === "claude") {
|
|
13804
13992
|
const args = [...baseArgs, "--dangerously-skip-permissions"];
|
|
@@ -13841,13 +14029,13 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13841
14029
|
try {
|
|
13842
14030
|
const pty3 = require("node-pty");
|
|
13843
14031
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
13844
|
-
const isWin2 =
|
|
14032
|
+
const isWin2 = os16.platform() === "win32";
|
|
13845
14033
|
child = pty3.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
13846
14034
|
name: "xterm-256color",
|
|
13847
14035
|
cols: 120,
|
|
13848
14036
|
rows: 40,
|
|
13849
14037
|
cwd: providerDir,
|
|
13850
|
-
env: { ...process.env, ...
|
|
14038
|
+
env: { ...process.env, ...spawn4.env || {} }
|
|
13851
14039
|
});
|
|
13852
14040
|
isPty = true;
|
|
13853
14041
|
} catch (err) {
|
|
@@ -13859,7 +14047,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13859
14047
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13860
14048
|
env: {
|
|
13861
14049
|
...process.env,
|
|
13862
|
-
...
|
|
14050
|
+
...spawn4.env || {},
|
|
13863
14051
|
...command === "gemini" ? { SANDBOX: "1", GEMINI_CLI_NO_RELAUNCH: "1" } : {}
|
|
13864
14052
|
}
|
|
13865
14053
|
});
|
|
@@ -13935,7 +14123,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13935
14123
|
} catch {
|
|
13936
14124
|
}
|
|
13937
14125
|
try {
|
|
13938
|
-
|
|
14126
|
+
fs11.unlinkSync(promptFile);
|
|
13939
14127
|
} catch {
|
|
13940
14128
|
}
|
|
13941
14129
|
});
|
|
@@ -13971,7 +14159,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13971
14159
|
} catch {
|
|
13972
14160
|
}
|
|
13973
14161
|
try {
|
|
13974
|
-
|
|
14162
|
+
fs11.unlinkSync(promptFile);
|
|
13975
14163
|
} catch {
|
|
13976
14164
|
}
|
|
13977
14165
|
ctx.log(`Auto-implement ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -14018,7 +14206,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
14018
14206
|
setMode: "set_mode.js"
|
|
14019
14207
|
};
|
|
14020
14208
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
14021
|
-
const scriptsDir =
|
|
14209
|
+
const scriptsDir = path14.join(providerDir, "scripts");
|
|
14022
14210
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
14023
14211
|
if (latestScriptsDir) {
|
|
14024
14212
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -14026,10 +14214,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
14026
14214
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
14027
14215
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
14028
14216
|
lines.push("");
|
|
14029
|
-
for (const file of
|
|
14217
|
+
for (const file of fs11.readdirSync(latestScriptsDir)) {
|
|
14030
14218
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
14031
14219
|
try {
|
|
14032
|
-
const content =
|
|
14220
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14033
14221
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
14034
14222
|
lines.push("```javascript");
|
|
14035
14223
|
lines.push(content);
|
|
@@ -14039,14 +14227,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
14039
14227
|
}
|
|
14040
14228
|
}
|
|
14041
14229
|
}
|
|
14042
|
-
const refFiles =
|
|
14230
|
+
const refFiles = fs11.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
14043
14231
|
if (refFiles.length > 0) {
|
|
14044
14232
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
14045
14233
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
14046
14234
|
lines.push("");
|
|
14047
14235
|
for (const file of refFiles) {
|
|
14048
14236
|
try {
|
|
14049
|
-
const content =
|
|
14237
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14050
14238
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
14051
14239
|
lines.push("```javascript");
|
|
14052
14240
|
lines.push(content);
|
|
@@ -14087,11 +14275,11 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
14087
14275
|
lines.push("");
|
|
14088
14276
|
}
|
|
14089
14277
|
}
|
|
14090
|
-
const docsDir =
|
|
14278
|
+
const docsDir = path14.join(providerDir, "../../docs");
|
|
14091
14279
|
const loadGuide = (name) => {
|
|
14092
14280
|
try {
|
|
14093
|
-
const p =
|
|
14094
|
-
if (
|
|
14281
|
+
const p = path14.join(docsDir, name);
|
|
14282
|
+
if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
|
|
14095
14283
|
} catch {
|
|
14096
14284
|
}
|
|
14097
14285
|
return null;
|
|
@@ -14264,7 +14452,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14264
14452
|
parseApproval: "parse_approval.js"
|
|
14265
14453
|
};
|
|
14266
14454
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
14267
|
-
const scriptsDir =
|
|
14455
|
+
const scriptsDir = path14.join(providerDir, "scripts");
|
|
14268
14456
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
14269
14457
|
if (latestScriptsDir) {
|
|
14270
14458
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -14272,11 +14460,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14272
14460
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
14273
14461
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
14274
14462
|
lines.push("");
|
|
14275
|
-
for (const file of
|
|
14463
|
+
for (const file of fs11.readdirSync(latestScriptsDir)) {
|
|
14276
14464
|
if (!file.endsWith(".js")) continue;
|
|
14277
14465
|
if (!targetFileNames.has(file)) continue;
|
|
14278
14466
|
try {
|
|
14279
|
-
const content =
|
|
14467
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14280
14468
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
14281
14469
|
lines.push("```javascript");
|
|
14282
14470
|
lines.push(content);
|
|
@@ -14285,14 +14473,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14285
14473
|
} catch {
|
|
14286
14474
|
}
|
|
14287
14475
|
}
|
|
14288
|
-
const refFiles =
|
|
14476
|
+
const refFiles = fs11.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
14289
14477
|
if (refFiles.length > 0) {
|
|
14290
14478
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
14291
14479
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
14292
14480
|
lines.push("");
|
|
14293
14481
|
for (const file of refFiles) {
|
|
14294
14482
|
try {
|
|
14295
|
-
const content =
|
|
14483
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
14296
14484
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
14297
14485
|
lines.push("```javascript");
|
|
14298
14486
|
lines.push(content);
|
|
@@ -14325,11 +14513,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14325
14513
|
lines.push("");
|
|
14326
14514
|
}
|
|
14327
14515
|
}
|
|
14328
|
-
const docsDir =
|
|
14516
|
+
const docsDir = path14.join(providerDir, "../../docs");
|
|
14329
14517
|
const loadGuide = (name) => {
|
|
14330
14518
|
try {
|
|
14331
|
-
const p =
|
|
14332
|
-
if (
|
|
14519
|
+
const p = path14.join(docsDir, name);
|
|
14520
|
+
if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
|
|
14333
14521
|
} catch {
|
|
14334
14522
|
}
|
|
14335
14523
|
return null;
|
|
@@ -14586,8 +14774,8 @@ var DevServer = class _DevServer {
|
|
|
14586
14774
|
}
|
|
14587
14775
|
getEndpointList() {
|
|
14588
14776
|
return this.routes.map((r) => {
|
|
14589
|
-
const
|
|
14590
|
-
return `${r.method.padEnd(5)} ${
|
|
14777
|
+
const path16 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
14778
|
+
return `${r.method.padEnd(5)} ${path16}`;
|
|
14591
14779
|
});
|
|
14592
14780
|
}
|
|
14593
14781
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -14688,16 +14876,16 @@ var DevServer = class _DevServer {
|
|
|
14688
14876
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
14689
14877
|
return;
|
|
14690
14878
|
}
|
|
14691
|
-
const
|
|
14692
|
-
if (!
|
|
14879
|
+
const spawn4 = provider.spawn;
|
|
14880
|
+
if (!spawn4) {
|
|
14693
14881
|
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
14694
14882
|
return;
|
|
14695
14883
|
}
|
|
14696
14884
|
const { spawn: spawnFn } = await import("child_process");
|
|
14697
14885
|
const start = Date.now();
|
|
14698
14886
|
try {
|
|
14699
|
-
const child = spawnFn(
|
|
14700
|
-
shell:
|
|
14887
|
+
const child = spawnFn(spawn4.command, [...spawn4.args || []], {
|
|
14888
|
+
shell: spawn4.shell ?? false,
|
|
14701
14889
|
timeout: 5e3,
|
|
14702
14890
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14703
14891
|
});
|
|
@@ -14729,7 +14917,7 @@ var DevServer = class _DevServer {
|
|
|
14729
14917
|
const elapsed = Date.now() - start;
|
|
14730
14918
|
this.json(res, 200, {
|
|
14731
14919
|
success: true,
|
|
14732
|
-
command: `${
|
|
14920
|
+
command: `${spawn4.command} ${(spawn4.args || []).join(" ")}`,
|
|
14733
14921
|
elapsed,
|
|
14734
14922
|
stdout: stdout.trim(),
|
|
14735
14923
|
stderr: stderr.trim(),
|
|
@@ -14739,7 +14927,7 @@ var DevServer = class _DevServer {
|
|
|
14739
14927
|
const elapsed = Date.now() - start;
|
|
14740
14928
|
this.json(res, 200, {
|
|
14741
14929
|
success: false,
|
|
14742
|
-
command: `${
|
|
14930
|
+
command: `${spawn4.command} ${(spawn4.args || []).join(" ")}`,
|
|
14743
14931
|
elapsed,
|
|
14744
14932
|
error: e.message
|
|
14745
14933
|
});
|
|
@@ -14869,12 +15057,12 @@ var DevServer = class _DevServer {
|
|
|
14869
15057
|
// ─── DevConsole SPA ───
|
|
14870
15058
|
getConsoleDistDir() {
|
|
14871
15059
|
const candidates = [
|
|
14872
|
-
|
|
14873
|
-
|
|
14874
|
-
|
|
15060
|
+
path15.resolve(__dirname, "../../web-devconsole/dist"),
|
|
15061
|
+
path15.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
15062
|
+
path15.join(process.cwd(), "packages/web-devconsole/dist")
|
|
14875
15063
|
];
|
|
14876
15064
|
for (const dir of candidates) {
|
|
14877
|
-
if (
|
|
15065
|
+
if (fs12.existsSync(path15.join(dir, "index.html"))) return dir;
|
|
14878
15066
|
}
|
|
14879
15067
|
return null;
|
|
14880
15068
|
}
|
|
@@ -14884,9 +15072,9 @@ var DevServer = class _DevServer {
|
|
|
14884
15072
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
14885
15073
|
return;
|
|
14886
15074
|
}
|
|
14887
|
-
const htmlPath =
|
|
15075
|
+
const htmlPath = path15.join(distDir, "index.html");
|
|
14888
15076
|
try {
|
|
14889
|
-
const html =
|
|
15077
|
+
const html = fs12.readFileSync(htmlPath, "utf-8");
|
|
14890
15078
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
14891
15079
|
res.end(html);
|
|
14892
15080
|
} catch (e) {
|
|
@@ -14909,15 +15097,15 @@ var DevServer = class _DevServer {
|
|
|
14909
15097
|
this.json(res, 404, { error: "Not found" });
|
|
14910
15098
|
return;
|
|
14911
15099
|
}
|
|
14912
|
-
const safePath =
|
|
14913
|
-
const filePath =
|
|
15100
|
+
const safePath = path15.normalize(pathname).replace(/^\.\.\//, "");
|
|
15101
|
+
const filePath = path15.join(distDir, safePath);
|
|
14914
15102
|
if (!filePath.startsWith(distDir)) {
|
|
14915
15103
|
this.json(res, 403, { error: "Forbidden" });
|
|
14916
15104
|
return;
|
|
14917
15105
|
}
|
|
14918
15106
|
try {
|
|
14919
|
-
const content =
|
|
14920
|
-
const ext =
|
|
15107
|
+
const content = fs12.readFileSync(filePath);
|
|
15108
|
+
const ext = path15.extname(filePath);
|
|
14921
15109
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
14922
15110
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
14923
15111
|
res.end(content);
|
|
@@ -15025,14 +15213,14 @@ var DevServer = class _DevServer {
|
|
|
15025
15213
|
const files = [];
|
|
15026
15214
|
const scan = (d, prefix) => {
|
|
15027
15215
|
try {
|
|
15028
|
-
for (const entry of
|
|
15216
|
+
for (const entry of fs12.readdirSync(d, { withFileTypes: true })) {
|
|
15029
15217
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
15030
15218
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
15031
15219
|
if (entry.isDirectory()) {
|
|
15032
15220
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
15033
|
-
scan(
|
|
15221
|
+
scan(path15.join(d, entry.name), rel);
|
|
15034
15222
|
} else {
|
|
15035
|
-
const stat =
|
|
15223
|
+
const stat = fs12.statSync(path15.join(d, entry.name));
|
|
15036
15224
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
15037
15225
|
}
|
|
15038
15226
|
}
|
|
@@ -15055,16 +15243,16 @@ var DevServer = class _DevServer {
|
|
|
15055
15243
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
15056
15244
|
return;
|
|
15057
15245
|
}
|
|
15058
|
-
const fullPath =
|
|
15246
|
+
const fullPath = path15.resolve(dir, path15.normalize(filePath));
|
|
15059
15247
|
if (!fullPath.startsWith(dir)) {
|
|
15060
15248
|
this.json(res, 403, { error: "Forbidden" });
|
|
15061
15249
|
return;
|
|
15062
15250
|
}
|
|
15063
|
-
if (!
|
|
15251
|
+
if (!fs12.existsSync(fullPath) || fs12.statSync(fullPath).isDirectory()) {
|
|
15064
15252
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
15065
15253
|
return;
|
|
15066
15254
|
}
|
|
15067
|
-
const content =
|
|
15255
|
+
const content = fs12.readFileSync(fullPath, "utf-8");
|
|
15068
15256
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
15069
15257
|
}
|
|
15070
15258
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -15080,15 +15268,15 @@ var DevServer = class _DevServer {
|
|
|
15080
15268
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
15081
15269
|
return;
|
|
15082
15270
|
}
|
|
15083
|
-
const fullPath =
|
|
15271
|
+
const fullPath = path15.resolve(dir, path15.normalize(filePath));
|
|
15084
15272
|
if (!fullPath.startsWith(dir)) {
|
|
15085
15273
|
this.json(res, 403, { error: "Forbidden" });
|
|
15086
15274
|
return;
|
|
15087
15275
|
}
|
|
15088
15276
|
try {
|
|
15089
|
-
if (
|
|
15090
|
-
|
|
15091
|
-
|
|
15277
|
+
if (fs12.existsSync(fullPath)) fs12.copyFileSync(fullPath, fullPath + ".bak");
|
|
15278
|
+
fs12.mkdirSync(path15.dirname(fullPath), { recursive: true });
|
|
15279
|
+
fs12.writeFileSync(fullPath, content, "utf-8");
|
|
15092
15280
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
15093
15281
|
this.providerLoader.reload();
|
|
15094
15282
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -15104,9 +15292,9 @@ var DevServer = class _DevServer {
|
|
|
15104
15292
|
return;
|
|
15105
15293
|
}
|
|
15106
15294
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
15107
|
-
const p =
|
|
15108
|
-
if (
|
|
15109
|
-
const source =
|
|
15295
|
+
const p = path15.join(dir, name);
|
|
15296
|
+
if (fs12.existsSync(p)) {
|
|
15297
|
+
const source = fs12.readFileSync(p, "utf-8");
|
|
15110
15298
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
15111
15299
|
return;
|
|
15112
15300
|
}
|
|
@@ -15125,11 +15313,11 @@ var DevServer = class _DevServer {
|
|
|
15125
15313
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
15126
15314
|
return;
|
|
15127
15315
|
}
|
|
15128
|
-
const target =
|
|
15129
|
-
const targetPath =
|
|
15316
|
+
const target = fs12.existsSync(path15.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
15317
|
+
const targetPath = path15.join(dir, target);
|
|
15130
15318
|
try {
|
|
15131
|
-
if (
|
|
15132
|
-
|
|
15319
|
+
if (fs12.existsSync(targetPath)) fs12.copyFileSync(targetPath, targetPath + ".bak");
|
|
15320
|
+
fs12.writeFileSync(targetPath, source, "utf-8");
|
|
15133
15321
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
15134
15322
|
this.providerLoader.reload();
|
|
15135
15323
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -15208,20 +15396,20 @@ var DevServer = class _DevServer {
|
|
|
15208
15396
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
15209
15397
|
return;
|
|
15210
15398
|
}
|
|
15211
|
-
const
|
|
15212
|
-
if (!
|
|
15399
|
+
const spawn4 = provider.spawn;
|
|
15400
|
+
if (!spawn4) {
|
|
15213
15401
|
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
15214
15402
|
return;
|
|
15215
15403
|
}
|
|
15216
15404
|
const { spawn: spawnFn } = await import("child_process");
|
|
15217
15405
|
const start = Date.now();
|
|
15218
15406
|
try {
|
|
15219
|
-
const args = [...
|
|
15220
|
-
const child = spawnFn(
|
|
15221
|
-
shell:
|
|
15407
|
+
const args = [...spawn4.args || [], message];
|
|
15408
|
+
const child = spawnFn(spawn4.command, args, {
|
|
15409
|
+
shell: spawn4.shell ?? false,
|
|
15222
15410
|
timeout,
|
|
15223
15411
|
stdio: ["pipe", "pipe", "pipe"],
|
|
15224
|
-
env: { ...process.env, ...
|
|
15412
|
+
env: { ...process.env, ...spawn4.env || {} }
|
|
15225
15413
|
});
|
|
15226
15414
|
let stdout = "";
|
|
15227
15415
|
let stderr = "";
|
|
@@ -15286,21 +15474,21 @@ var DevServer = class _DevServer {
|
|
|
15286
15474
|
}
|
|
15287
15475
|
let targetDir;
|
|
15288
15476
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
15289
|
-
const jsonPath =
|
|
15290
|
-
if (
|
|
15477
|
+
const jsonPath = path15.join(targetDir, "provider.json");
|
|
15478
|
+
if (fs12.existsSync(jsonPath)) {
|
|
15291
15479
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
15292
15480
|
return;
|
|
15293
15481
|
}
|
|
15294
15482
|
try {
|
|
15295
15483
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version, osPaths, processNames });
|
|
15296
|
-
|
|
15297
|
-
|
|
15484
|
+
fs12.mkdirSync(targetDir, { recursive: true });
|
|
15485
|
+
fs12.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
15298
15486
|
const createdFiles = ["provider.json"];
|
|
15299
15487
|
if (result.files) {
|
|
15300
15488
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
15301
|
-
const fullPath =
|
|
15302
|
-
|
|
15303
|
-
|
|
15489
|
+
const fullPath = path15.join(targetDir, relPath);
|
|
15490
|
+
fs12.mkdirSync(path15.dirname(fullPath), { recursive: true });
|
|
15491
|
+
fs12.writeFileSync(fullPath, content, "utf-8");
|
|
15304
15492
|
createdFiles.push(relPath);
|
|
15305
15493
|
}
|
|
15306
15494
|
}
|
|
@@ -15349,45 +15537,45 @@ var DevServer = class _DevServer {
|
|
|
15349
15537
|
}
|
|
15350
15538
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
15351
15539
|
getLatestScriptVersionDir(scriptsDir) {
|
|
15352
|
-
if (!
|
|
15353
|
-
const versions =
|
|
15540
|
+
if (!fs12.existsSync(scriptsDir)) return null;
|
|
15541
|
+
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
15354
15542
|
try {
|
|
15355
|
-
return
|
|
15543
|
+
return fs12.statSync(path15.join(scriptsDir, d)).isDirectory();
|
|
15356
15544
|
} catch {
|
|
15357
15545
|
return false;
|
|
15358
15546
|
}
|
|
15359
15547
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
15360
15548
|
if (versions.length === 0) return null;
|
|
15361
|
-
return
|
|
15549
|
+
return path15.join(scriptsDir, versions[0]);
|
|
15362
15550
|
}
|
|
15363
15551
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
15364
|
-
const canonicalUserDir =
|
|
15365
|
-
const desiredDir = requestedDir ?
|
|
15366
|
-
const upstreamRoot =
|
|
15367
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
15552
|
+
const canonicalUserDir = path15.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
15553
|
+
const desiredDir = requestedDir ? path15.resolve(requestedDir) : canonicalUserDir;
|
|
15554
|
+
const upstreamRoot = path15.resolve(this.providerLoader.getUpstreamDir());
|
|
15555
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path15.sep}`)) {
|
|
15368
15556
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
15369
15557
|
}
|
|
15370
|
-
if (
|
|
15558
|
+
if (path15.basename(desiredDir) !== type) {
|
|
15371
15559
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
15372
15560
|
}
|
|
15373
15561
|
const sourceDir = this.findProviderDir(type);
|
|
15374
15562
|
if (!sourceDir) {
|
|
15375
15563
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
15376
15564
|
}
|
|
15377
|
-
if (!
|
|
15378
|
-
|
|
15379
|
-
|
|
15565
|
+
if (!fs12.existsSync(desiredDir)) {
|
|
15566
|
+
fs12.mkdirSync(path15.dirname(desiredDir), { recursive: true });
|
|
15567
|
+
fs12.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
15380
15568
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
15381
15569
|
}
|
|
15382
|
-
const providerJson =
|
|
15383
|
-
if (!
|
|
15570
|
+
const providerJson = path15.join(desiredDir, "provider.json");
|
|
15571
|
+
if (!fs12.existsSync(providerJson)) {
|
|
15384
15572
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
15385
15573
|
}
|
|
15386
15574
|
try {
|
|
15387
|
-
const providerData = JSON.parse(
|
|
15575
|
+
const providerData = JSON.parse(fs12.readFileSync(providerJson, "utf-8"));
|
|
15388
15576
|
if (providerData.disableUpstream !== true) {
|
|
15389
15577
|
providerData.disableUpstream = true;
|
|
15390
|
-
|
|
15578
|
+
fs12.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
15391
15579
|
}
|
|
15392
15580
|
} catch (error) {
|
|
15393
15581
|
return {
|
|
@@ -15427,7 +15615,7 @@ var DevServer = class _DevServer {
|
|
|
15427
15615
|
setMode: "set_mode.js"
|
|
15428
15616
|
};
|
|
15429
15617
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
15430
|
-
const scriptsDir =
|
|
15618
|
+
const scriptsDir = path15.join(providerDir, "scripts");
|
|
15431
15619
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
15432
15620
|
if (latestScriptsDir) {
|
|
15433
15621
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -15435,10 +15623,10 @@ var DevServer = class _DevServer {
|
|
|
15435
15623
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
15436
15624
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
15437
15625
|
lines.push("");
|
|
15438
|
-
for (const file of
|
|
15626
|
+
for (const file of fs12.readdirSync(latestScriptsDir)) {
|
|
15439
15627
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
15440
15628
|
try {
|
|
15441
|
-
const content =
|
|
15629
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15442
15630
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
15443
15631
|
lines.push("```javascript");
|
|
15444
15632
|
lines.push(content);
|
|
@@ -15448,14 +15636,14 @@ var DevServer = class _DevServer {
|
|
|
15448
15636
|
}
|
|
15449
15637
|
}
|
|
15450
15638
|
}
|
|
15451
|
-
const refFiles =
|
|
15639
|
+
const refFiles = fs12.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
15452
15640
|
if (refFiles.length > 0) {
|
|
15453
15641
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
15454
15642
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
15455
15643
|
lines.push("");
|
|
15456
15644
|
for (const file of refFiles) {
|
|
15457
15645
|
try {
|
|
15458
|
-
const content =
|
|
15646
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15459
15647
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
15460
15648
|
lines.push("```javascript");
|
|
15461
15649
|
lines.push(content);
|
|
@@ -15496,11 +15684,11 @@ var DevServer = class _DevServer {
|
|
|
15496
15684
|
lines.push("");
|
|
15497
15685
|
}
|
|
15498
15686
|
}
|
|
15499
|
-
const docsDir =
|
|
15687
|
+
const docsDir = path15.join(providerDir, "../../docs");
|
|
15500
15688
|
const loadGuide = (name) => {
|
|
15501
15689
|
try {
|
|
15502
|
-
const p =
|
|
15503
|
-
if (
|
|
15690
|
+
const p = path15.join(docsDir, name);
|
|
15691
|
+
if (fs12.existsSync(p)) return fs12.readFileSync(p, "utf-8");
|
|
15504
15692
|
} catch {
|
|
15505
15693
|
}
|
|
15506
15694
|
return null;
|
|
@@ -15673,7 +15861,7 @@ var DevServer = class _DevServer {
|
|
|
15673
15861
|
parseApproval: "parse_approval.js"
|
|
15674
15862
|
};
|
|
15675
15863
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
15676
|
-
const scriptsDir =
|
|
15864
|
+
const scriptsDir = path15.join(providerDir, "scripts");
|
|
15677
15865
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
15678
15866
|
if (latestScriptsDir) {
|
|
15679
15867
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -15681,11 +15869,11 @@ var DevServer = class _DevServer {
|
|
|
15681
15869
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
15682
15870
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
15683
15871
|
lines.push("");
|
|
15684
|
-
for (const file of
|
|
15872
|
+
for (const file of fs12.readdirSync(latestScriptsDir)) {
|
|
15685
15873
|
if (!file.endsWith(".js")) continue;
|
|
15686
15874
|
if (!targetFileNames.has(file)) continue;
|
|
15687
15875
|
try {
|
|
15688
|
-
const content =
|
|
15876
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15689
15877
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
15690
15878
|
lines.push("```javascript");
|
|
15691
15879
|
lines.push(content);
|
|
@@ -15694,14 +15882,14 @@ var DevServer = class _DevServer {
|
|
|
15694
15882
|
} catch {
|
|
15695
15883
|
}
|
|
15696
15884
|
}
|
|
15697
|
-
const refFiles =
|
|
15885
|
+
const refFiles = fs12.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
15698
15886
|
if (refFiles.length > 0) {
|
|
15699
15887
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
15700
15888
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
15701
15889
|
lines.push("");
|
|
15702
15890
|
for (const file of refFiles) {
|
|
15703
15891
|
try {
|
|
15704
|
-
const content =
|
|
15892
|
+
const content = fs12.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
|
|
15705
15893
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
15706
15894
|
lines.push("```javascript");
|
|
15707
15895
|
lines.push(content);
|
|
@@ -15734,11 +15922,11 @@ var DevServer = class _DevServer {
|
|
|
15734
15922
|
lines.push("");
|
|
15735
15923
|
}
|
|
15736
15924
|
}
|
|
15737
|
-
const docsDir =
|
|
15925
|
+
const docsDir = path15.join(providerDir, "../../docs");
|
|
15738
15926
|
const loadGuide = (name) => {
|
|
15739
15927
|
try {
|
|
15740
|
-
const p =
|
|
15741
|
-
if (
|
|
15928
|
+
const p = path15.join(docsDir, name);
|
|
15929
|
+
if (fs12.existsSync(p)) return fs12.readFileSync(p, "utf-8");
|
|
15742
15930
|
} catch {
|
|
15743
15931
|
}
|
|
15744
15932
|
return null;
|
|
@@ -16358,7 +16546,7 @@ async function listHostedCliRuntimes(endpoint) {
|
|
|
16358
16546
|
}
|
|
16359
16547
|
|
|
16360
16548
|
// src/installer.ts
|
|
16361
|
-
var
|
|
16549
|
+
var import_child_process10 = require("child_process");
|
|
16362
16550
|
var EXTENSION_CATALOG = [
|
|
16363
16551
|
// AI Agent extensions
|
|
16364
16552
|
{
|
|
@@ -16435,7 +16623,7 @@ var EXTENSION_CATALOG = [
|
|
|
16435
16623
|
function isExtensionInstalled(ide, marketplaceId) {
|
|
16436
16624
|
if (!ide.cliCommand) return false;
|
|
16437
16625
|
try {
|
|
16438
|
-
const result = (0,
|
|
16626
|
+
const result = (0, import_child_process10.execSync)(`"${ide.cliCommand}" --list-extensions`, {
|
|
16439
16627
|
encoding: "utf-8",
|
|
16440
16628
|
timeout: 15e3,
|
|
16441
16629
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -16472,11 +16660,11 @@ async function installExtension(ide, extension) {
|
|
|
16472
16660
|
const res = await fetch(extension.vsixUrl);
|
|
16473
16661
|
if (res.ok) {
|
|
16474
16662
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
16475
|
-
const
|
|
16476
|
-
|
|
16663
|
+
const fs13 = await import("fs");
|
|
16664
|
+
fs13.writeFileSync(vsixPath, buffer);
|
|
16477
16665
|
return new Promise((resolve9) => {
|
|
16478
16666
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
16479
|
-
(0,
|
|
16667
|
+
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
16480
16668
|
resolve9({
|
|
16481
16669
|
extensionId: extension.id,
|
|
16482
16670
|
marketplaceId: extension.marketplaceId,
|
|
@@ -16492,7 +16680,7 @@ async function installExtension(ide, extension) {
|
|
|
16492
16680
|
}
|
|
16493
16681
|
return new Promise((resolve9) => {
|
|
16494
16682
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
16495
|
-
(0,
|
|
16683
|
+
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
16496
16684
|
if (error) {
|
|
16497
16685
|
resolve9({
|
|
16498
16686
|
extensionId: extension.id,
|
|
@@ -16529,7 +16717,7 @@ function launchIDE(ide, workspacePath) {
|
|
|
16529
16717
|
if (!ide.cliCommand) return false;
|
|
16530
16718
|
try {
|
|
16531
16719
|
const args = workspacePath ? `"${workspacePath}"` : "";
|
|
16532
|
-
(0,
|
|
16720
|
+
(0, import_child_process10.exec)(`"${ide.cliCommand}" ${args}`, { timeout: 1e4 });
|
|
16533
16721
|
return true;
|
|
16534
16722
|
} catch {
|
|
16535
16723
|
return false;
|
|
@@ -16841,6 +17029,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
16841
17029
|
loadConfig,
|
|
16842
17030
|
logCommand,
|
|
16843
17031
|
markSetupComplete,
|
|
17032
|
+
maybeRunDaemonUpgradeHelperFromEnv,
|
|
16844
17033
|
normalizeActiveChatData,
|
|
16845
17034
|
normalizeManagedStatus,
|
|
16846
17035
|
probeCdpPort,
|