@adhdev/daemon-core 0.8.29 → 0.8.31
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/agent-stream/manager.d.ts +1 -0
- package/dist/agent-stream/provider-adapter.d.ts +1 -0
- package/dist/agent-stream/types.d.ts +3 -0
- package/dist/boot/daemon-lifecycle.d.ts +2 -1
- package/dist/cdp/manager.d.ts +2 -0
- package/dist/cli-adapter-types.d.ts +34 -5
- package/dist/cli-adapters/provider-cli-adapter.d.ts +4 -158
- package/dist/cli-adapters/provider-cli-config.d.ts +30 -0
- package/dist/cli-adapters/provider-cli-parse.d.ts +42 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +29 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +158 -0
- package/dist/commands/handler.d.ts +4 -3
- package/dist/config/config.d.ts +4 -3
- package/dist/index.js +1033 -621
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1035 -624
- package/dist/index.mjs.map +1 -1
- package/dist/providers/acp-provider-instance.d.ts +1 -0
- package/dist/providers/approval-utils.d.ts +7 -0
- package/dist/providers/cli-provider-instance.d.ts +2 -0
- package/dist/providers/contracts.d.ts +12 -1
- package/dist/providers/ide-provider-instance.d.ts +1 -0
- package/dist/providers/provider-loader.d.ts +3 -0
- package/dist/status/reporter.d.ts +2 -3
- package/dist/status/snapshot.d.ts +2 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +3 -1
- package/src/agent-stream/manager.ts +8 -2
- package/src/agent-stream/poller.ts +57 -6
- package/src/agent-stream/provider-adapter.ts +11 -7
- package/src/agent-stream/types.ts +3 -0
- package/src/boot/daemon-lifecycle.ts +7 -6
- package/src/cdp/initializer.ts +2 -2
- package/src/cdp/manager.ts +5 -0
- package/src/cdp/setup.ts +1 -1
- package/src/cli-adapter-types.ts +37 -5
- package/src/cli-adapters/provider-cli-adapter.ts +212 -795
- package/src/cli-adapters/provider-cli-config.ts +66 -0
- package/src/cli-adapters/provider-cli-parse.ts +202 -0
- package/src/cli-adapters/provider-cli-runtime.ts +142 -0
- package/src/cli-adapters/provider-cli-shared.ts +439 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +1 -1
- package/src/commands/cdp-commands.ts +6 -1
- package/src/commands/chat-commands.ts +45 -29
- package/src/commands/cli-manager.ts +28 -9
- package/src/commands/handler.ts +14 -10
- package/src/commands/router.ts +23 -10
- package/src/commands/stream-commands.ts +11 -5
- package/src/config/config.ts +4 -10
- package/src/daemon/dev-auto-implement.ts +22 -18
- package/src/daemon/dev-cli-debug.ts +59 -16
- package/src/daemon/dev-server.ts +67 -43
- package/src/providers/acp-provider-instance.ts +18 -3
- package/src/providers/approval-utils.ts +66 -0
- package/src/providers/cli-provider-instance.ts +32 -6
- package/src/providers/contracts.d.ts +1 -0
- package/src/providers/contracts.ts +15 -2
- package/src/providers/extension-provider-instance.ts +1 -1
- package/src/providers/ide-provider-instance.ts +67 -41
- package/src/providers/provider-loader.ts +110 -55
- package/src/providers/version-archive.ts +23 -5
- package/src/status/reporter.ts +18 -14
- package/src/status/snapshot.ts +5 -4
package/dist/index.js
CHANGED
|
@@ -94,12 +94,10 @@ function ensureMachineId(config) {
|
|
|
94
94
|
if (isStableMachineId(config.machineId)) {
|
|
95
95
|
return { config, changed: false };
|
|
96
96
|
}
|
|
97
|
-
const legacyRegisteredMachineId = !config.registeredMachineId && config.machineSecret && config.machineId ? config.machineId : config.registeredMachineId;
|
|
98
97
|
return {
|
|
99
98
|
config: {
|
|
100
99
|
...config,
|
|
101
|
-
machineId: generateMachineId()
|
|
102
|
-
registeredMachineId: legacyRegisteredMachineId
|
|
100
|
+
machineId: generateMachineId()
|
|
103
101
|
},
|
|
104
102
|
changed: true
|
|
105
103
|
};
|
|
@@ -455,7 +453,7 @@ var init_logger = __esm({
|
|
|
455
453
|
function isModuleNotFoundError(error, ref) {
|
|
456
454
|
if (!(error instanceof Error)) return false;
|
|
457
455
|
const message = error.message || "";
|
|
458
|
-
const code = error.code;
|
|
456
|
+
const code = "code" in error ? error.code : void 0;
|
|
459
457
|
return code === "MODULE_NOT_FOUND" && message.includes(ref);
|
|
460
458
|
}
|
|
461
459
|
function normalizeBinding(mod, ref) {
|
|
@@ -797,12 +795,7 @@ var init_pty_transport = __esm({
|
|
|
797
795
|
}
|
|
798
796
|
});
|
|
799
797
|
|
|
800
|
-
// src/cli-adapters/provider-cli-
|
|
801
|
-
var provider_cli_adapter_exports = {};
|
|
802
|
-
__export(provider_cli_adapter_exports, {
|
|
803
|
-
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
804
|
-
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
805
|
-
});
|
|
798
|
+
// src/cli-adapters/provider-cli-shared.ts
|
|
806
799
|
function stripAnsi(str) {
|
|
807
800
|
return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
|
|
808
801
|
}
|
|
@@ -812,6 +805,10 @@ function stripTerminalNoise(str) {
|
|
|
812
805
|
function sanitizeTerminalText(str) {
|
|
813
806
|
return stripTerminalNoise(stripAnsi(str));
|
|
814
807
|
}
|
|
808
|
+
function listCliScriptNames(scripts) {
|
|
809
|
+
if (!scripts) return [];
|
|
810
|
+
return Object.entries(scripts).filter(([, fn]) => typeof fn === "function").map(([name]) => name);
|
|
811
|
+
}
|
|
815
812
|
function splitCliScreenLines(text) {
|
|
816
813
|
return String(text || "").replace(/\u0007/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n").map((line) => line.replace(/\s+$/, ""));
|
|
817
814
|
}
|
|
@@ -859,18 +856,6 @@ function buildCliScreenSnapshot(text) {
|
|
|
859
856
|
linesBelowPrompt: promptLineIndex >= 0 ? lines.slice(promptLineIndex + 1) : []
|
|
860
857
|
};
|
|
861
858
|
}
|
|
862
|
-
function computeTerminalQueryTail(buffer) {
|
|
863
|
-
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
864
|
-
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
865
|
-
const start = Math.max(0, buffer.length - maxLength);
|
|
866
|
-
for (let i = start; i < buffer.length; i++) {
|
|
867
|
-
const suffix = buffer.slice(i);
|
|
868
|
-
if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {
|
|
869
|
-
return suffix;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
return "";
|
|
873
|
-
}
|
|
874
859
|
function findBinary(name) {
|
|
875
860
|
const trimmed = String(name || "").trim();
|
|
876
861
|
if (!trimmed) return trimmed;
|
|
@@ -1020,25 +1005,306 @@ function coercePatternArray(raw) {
|
|
|
1020
1005
|
return raw.map(parsePatternEntry).filter((r) => r != null);
|
|
1021
1006
|
}
|
|
1022
1007
|
function normalizeCliProviderForRuntime(raw) {
|
|
1023
|
-
const patterns = raw
|
|
1008
|
+
const patterns = raw && typeof raw === "object" ? raw.patterns : void 0;
|
|
1024
1009
|
return {
|
|
1025
1010
|
patterns: {
|
|
1026
|
-
approval: coercePatternArray(
|
|
1011
|
+
approval: coercePatternArray(
|
|
1012
|
+
patterns && typeof patterns === "object" ? patterns.approval : void 0
|
|
1013
|
+
)
|
|
1027
1014
|
}
|
|
1028
1015
|
};
|
|
1029
1016
|
}
|
|
1030
|
-
var os8, path9, import_child_process4, buildCliSpawnEnv
|
|
1031
|
-
var
|
|
1032
|
-
"src/cli-adapters/provider-cli-
|
|
1017
|
+
var os8, path9, import_child_process4, buildCliSpawnEnv;
|
|
1018
|
+
var init_provider_cli_shared = __esm({
|
|
1019
|
+
"src/cli-adapters/provider-cli-shared.ts"() {
|
|
1033
1020
|
"use strict";
|
|
1034
1021
|
os8 = __toESM(require("os"));
|
|
1035
1022
|
path9 = __toESM(require("path"));
|
|
1036
1023
|
import_child_process4 = require("child_process");
|
|
1024
|
+
init_spawn_env();
|
|
1025
|
+
buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
// src/cli-adapters/provider-cli-parse.ts
|
|
1030
|
+
function sliceFromOffset(text, start) {
|
|
1031
|
+
if (!text) return "";
|
|
1032
|
+
if (!Number.isFinite(start) || start <= 0) return text;
|
|
1033
|
+
if (start >= text.length) return "";
|
|
1034
|
+
return text.slice(start);
|
|
1035
|
+
}
|
|
1036
|
+
function hydrateCliParsedMessages(parsedMessages, options) {
|
|
1037
|
+
const { committedMessages, scope, lastOutputAt } = options;
|
|
1038
|
+
const referenceMessages = [...committedMessages];
|
|
1039
|
+
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
1040
|
+
const now = options.now ?? Date.now();
|
|
1041
|
+
const findReferenceTimestamp = (role, content, parsedIndex) => {
|
|
1042
|
+
const normalizedContent = normalizeComparableMessageContent(content);
|
|
1043
|
+
if (!normalizedContent) return void 0;
|
|
1044
|
+
const sameIndex = referenceMessages[parsedIndex];
|
|
1045
|
+
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && normalizeComparableMessageContent(sameIndex.content) === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
|
|
1046
|
+
usedReferenceIndexes.add(parsedIndex);
|
|
1047
|
+
return sameIndex.timestamp;
|
|
1048
|
+
}
|
|
1049
|
+
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1050
|
+
if (usedReferenceIndexes.has(i)) continue;
|
|
1051
|
+
const candidate = referenceMessages[i];
|
|
1052
|
+
if (!candidate || candidate.role !== role) continue;
|
|
1053
|
+
const candidateContent = normalizeComparableMessageContent(candidate.content);
|
|
1054
|
+
if (!candidateContent) continue;
|
|
1055
|
+
const exactMatch = candidateContent === normalizedContent;
|
|
1056
|
+
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
1057
|
+
if (!exactMatch && !fuzzyMatch) continue;
|
|
1058
|
+
if (typeof candidate.timestamp === "number" && Number.isFinite(candidate.timestamp)) {
|
|
1059
|
+
usedReferenceIndexes.add(i);
|
|
1060
|
+
return candidate.timestamp;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
return void 0;
|
|
1064
|
+
};
|
|
1065
|
+
return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
|
|
1066
|
+
const role = message.role;
|
|
1067
|
+
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
1068
|
+
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
1069
|
+
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
|
|
1070
|
+
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
|
|
1071
|
+
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
1072
|
+
return {
|
|
1073
|
+
...message,
|
|
1074
|
+
role,
|
|
1075
|
+
content,
|
|
1076
|
+
timestamp,
|
|
1077
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
|
|
1078
|
+
};
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
function normalizeCliParsedMessages(parsedMessages, options) {
|
|
1082
|
+
return hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
1083
|
+
role: message.role,
|
|
1084
|
+
content: message.content,
|
|
1085
|
+
timestamp: message.timestamp,
|
|
1086
|
+
receivedAt: message.receivedAt,
|
|
1087
|
+
kind: message.kind,
|
|
1088
|
+
id: message.id,
|
|
1089
|
+
index: message.index,
|
|
1090
|
+
meta: message.meta,
|
|
1091
|
+
senderName: message.senderName
|
|
1092
|
+
}));
|
|
1093
|
+
}
|
|
1094
|
+
function buildCliParseInput(options) {
|
|
1095
|
+
const {
|
|
1096
|
+
accumulatedBuffer,
|
|
1097
|
+
accumulatedRawBuffer,
|
|
1098
|
+
recentOutputBuffer,
|
|
1099
|
+
terminalScreenText,
|
|
1100
|
+
baseMessages,
|
|
1101
|
+
partialResponse,
|
|
1102
|
+
scope,
|
|
1103
|
+
runtimeSettings
|
|
1104
|
+
} = options;
|
|
1105
|
+
const buffer = scope ? sliceFromOffset(accumulatedBuffer, scope.bufferStart) || accumulatedBuffer : accumulatedBuffer;
|
|
1106
|
+
const rawBuffer = scope ? sliceFromOffset(accumulatedRawBuffer, scope.rawBufferStart) || accumulatedRawBuffer : accumulatedRawBuffer;
|
|
1107
|
+
const screenText = terminalScreenText;
|
|
1108
|
+
const recentBuffer = buffer.slice(-1e3) || recentOutputBuffer;
|
|
1109
|
+
return {
|
|
1110
|
+
buffer,
|
|
1111
|
+
rawBuffer,
|
|
1112
|
+
recentBuffer,
|
|
1113
|
+
screenText,
|
|
1114
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
1115
|
+
bufferScreen: buildCliScreenSnapshot(buffer),
|
|
1116
|
+
recentScreen: buildCliScreenSnapshot(recentBuffer),
|
|
1117
|
+
messages: [...baseMessages],
|
|
1118
|
+
partialResponse,
|
|
1119
|
+
promptText: scope?.prompt || "",
|
|
1120
|
+
settings: { ...runtimeSettings }
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function summarizeCliTraceText(text, max = 800) {
|
|
1124
|
+
const value = sanitizeTerminalText(String(text || ""));
|
|
1125
|
+
if (value.length <= max) return value;
|
|
1126
|
+
return `\u2026${value.slice(-max)}`;
|
|
1127
|
+
}
|
|
1128
|
+
function summarizeCliTraceMessages(messages, limit = 3) {
|
|
1129
|
+
return messages.slice(-limit).map((message) => ({
|
|
1130
|
+
role: message.role,
|
|
1131
|
+
content: summarizeCliTraceText(message.content, 240),
|
|
1132
|
+
timestamp: message.timestamp
|
|
1133
|
+
}));
|
|
1134
|
+
}
|
|
1135
|
+
function buildCliTraceParseSnapshot(options) {
|
|
1136
|
+
const { accumulatedBuffer, accumulatedRawBuffer, responseBuffer, partialResponse, scope } = options;
|
|
1137
|
+
const scopedBuffer = scope ? sliceFromOffset(accumulatedBuffer, scope.bufferStart) || accumulatedBuffer : accumulatedBuffer;
|
|
1138
|
+
const scopedRawBuffer = scope ? sliceFromOffset(accumulatedRawBuffer, scope.rawBufferStart) || accumulatedRawBuffer : accumulatedRawBuffer;
|
|
1139
|
+
return {
|
|
1140
|
+
currentTurnScope: scope || null,
|
|
1141
|
+
responseBuffer: summarizeCliTraceText(responseBuffer, 1200),
|
|
1142
|
+
partialResponse: summarizeCliTraceText(partialResponse || responseBuffer, 1200),
|
|
1143
|
+
turnBuffer: summarizeCliTraceText(scopedBuffer, 1600),
|
|
1144
|
+
turnRawPreview: summarizeCliTraceText(scopedRawBuffer, 1600),
|
|
1145
|
+
turnSanitizedRawPreview: summarizeCliTraceText(sanitizeTerminalText(scopedRawBuffer), 1600)
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
var init_provider_cli_parse = __esm({
|
|
1149
|
+
"src/cli-adapters/provider-cli-parse.ts"() {
|
|
1150
|
+
"use strict";
|
|
1151
|
+
init_provider_cli_shared();
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
// src/cli-adapters/provider-cli-config.ts
|
|
1156
|
+
function resolveCliAdapterConfig(provider) {
|
|
1157
|
+
const t = provider.timeouts || {};
|
|
1158
|
+
const rawKeys = provider.approvalKeys;
|
|
1159
|
+
return {
|
|
1160
|
+
timeouts: {
|
|
1161
|
+
ptyFlush: t.ptyFlush ?? 50,
|
|
1162
|
+
dialogAccept: t.dialogAccept ?? 300,
|
|
1163
|
+
approvalCooldown: t.approvalCooldown ?? 3e3,
|
|
1164
|
+
generatingIdle: t.generatingIdle ?? 6e3,
|
|
1165
|
+
idleFinish: t.idleFinish ?? 5e3,
|
|
1166
|
+
maxResponse: t.maxResponse ?? 3e5,
|
|
1167
|
+
shutdownGrace: t.shutdownGrace ?? 1e3,
|
|
1168
|
+
outputSettle: t.outputSettle ?? 300
|
|
1169
|
+
},
|
|
1170
|
+
approvalKeys: rawKeys && typeof rawKeys === "object" ? rawKeys : {},
|
|
1171
|
+
sendDelayMs: typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0,
|
|
1172
|
+
sendKey: typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r",
|
|
1173
|
+
submitStrategy: provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo",
|
|
1174
|
+
providerResolutionMeta: {
|
|
1175
|
+
type: provider.type,
|
|
1176
|
+
name: provider.name,
|
|
1177
|
+
resolvedVersion: provider._resolvedVersion || null,
|
|
1178
|
+
resolvedOs: provider._resolvedOs || null,
|
|
1179
|
+
providerDir: provider._resolvedProviderDir || null,
|
|
1180
|
+
scriptDir: provider._resolvedScriptDir || null,
|
|
1181
|
+
scriptsPath: provider._resolvedScriptsPath || null,
|
|
1182
|
+
scriptsSource: provider._resolvedScriptsSource || null,
|
|
1183
|
+
versionWarning: provider._versionWarning || null
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
var init_provider_cli_config = __esm({
|
|
1188
|
+
"src/cli-adapters/provider-cli-config.ts"() {
|
|
1189
|
+
"use strict";
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1193
|
+
// src/cli-adapters/provider-cli-runtime.ts
|
|
1194
|
+
function resolveCliSpawnPlan(options) {
|
|
1195
|
+
const { provider, runtimeSettings, workingDir, extraArgs } = options;
|
|
1196
|
+
const { spawn: spawnConfig } = provider;
|
|
1197
|
+
const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
1198
|
+
const binaryPath = findBinary(configuredCommand);
|
|
1199
|
+
const isWin = os9.platform() === "win32";
|
|
1200
|
+
const allArgs = [...spawnConfig.args, ...extraArgs];
|
|
1201
|
+
let shellCmd;
|
|
1202
|
+
let shellArgs;
|
|
1203
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1204
|
+
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1205
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1206
|
+
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1207
|
+
if (useShell) {
|
|
1208
|
+
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
1209
|
+
if (isWin) {
|
|
1210
|
+
shellArgs = ["/c", binaryPath, ...allArgs];
|
|
1211
|
+
} else {
|
|
1212
|
+
const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
|
|
1213
|
+
shellArgs = ["-l", "-c", fullCmd];
|
|
1214
|
+
}
|
|
1215
|
+
} else {
|
|
1216
|
+
shellCmd = binaryPath;
|
|
1217
|
+
shellArgs = allArgs;
|
|
1218
|
+
}
|
|
1219
|
+
return {
|
|
1220
|
+
binaryPath,
|
|
1221
|
+
allArgs,
|
|
1222
|
+
shellCmd,
|
|
1223
|
+
shellArgs,
|
|
1224
|
+
isWin,
|
|
1225
|
+
useShell,
|
|
1226
|
+
ptyOptions: {
|
|
1227
|
+
cols: 80,
|
|
1228
|
+
rows: 24,
|
|
1229
|
+
cwd: workingDir,
|
|
1230
|
+
env: buildCliSpawnEnv(process.env, spawnConfig.env)
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
function buildCliLoginShellRetry(plan) {
|
|
1235
|
+
const shellCmd = process.env.SHELL || "/bin/zsh";
|
|
1236
|
+
const fullCmd = [plan.binaryPath, ...plan.allArgs].map(shSingleQuote).join(" ");
|
|
1237
|
+
return {
|
|
1238
|
+
shellCmd,
|
|
1239
|
+
shellArgs: ["-l", "-c", fullCmd]
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
function getCliSpawnErrorHint(message, shellCmd, isWin) {
|
|
1243
|
+
if (!isWin) return null;
|
|
1244
|
+
if (/error code 267|ERROR_DIRECTORY/i.test(message)) {
|
|
1245
|
+
return " (working directory does not exist or is not a directory)";
|
|
1246
|
+
}
|
|
1247
|
+
if (/error code 740|elevation/i.test(message)) {
|
|
1248
|
+
return " (requires administrator privileges)";
|
|
1249
|
+
}
|
|
1250
|
+
if (/error code 2|ENOENT|not found/i.test(message)) {
|
|
1251
|
+
return ` (executable not found: ${shellCmd})`;
|
|
1252
|
+
}
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
function respondToCliTerminalQueries(options) {
|
|
1256
|
+
const { ptyProcess, pendingTail, data, terminalScreen } = options;
|
|
1257
|
+
if (!ptyProcess || !data) return pendingTail;
|
|
1258
|
+
const combined = pendingTail + data;
|
|
1259
|
+
const regex = /\x1b\[(\?)?6n/g;
|
|
1260
|
+
let match;
|
|
1261
|
+
while ((match = regex.exec(combined)) !== null) {
|
|
1262
|
+
const cursor = terminalScreen.getCursorPosition();
|
|
1263
|
+
const row = Math.max(1, (cursor.row | 0) + 1);
|
|
1264
|
+
const col = Math.max(1, (cursor.col | 0) + 1);
|
|
1265
|
+
const response = match[1] ? `\x1B[?${row};${col}R` : `\x1B[${row};${col}R`;
|
|
1266
|
+
ptyProcess.write(response);
|
|
1267
|
+
}
|
|
1268
|
+
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
1269
|
+
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
1270
|
+
const start = Math.max(0, combined.length - maxLength);
|
|
1271
|
+
for (let i = start; i < combined.length; i++) {
|
|
1272
|
+
const suffix = combined.slice(i);
|
|
1273
|
+
if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {
|
|
1274
|
+
return suffix;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
return "";
|
|
1278
|
+
}
|
|
1279
|
+
var os9, path10;
|
|
1280
|
+
var init_provider_cli_runtime = __esm({
|
|
1281
|
+
"src/cli-adapters/provider-cli-runtime.ts"() {
|
|
1282
|
+
"use strict";
|
|
1283
|
+
os9 = __toESM(require("os"));
|
|
1284
|
+
path10 = __toESM(require("path"));
|
|
1285
|
+
init_provider_cli_shared();
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
// src/cli-adapters/provider-cli-adapter.ts
|
|
1290
|
+
var provider_cli_adapter_exports = {};
|
|
1291
|
+
__export(provider_cli_adapter_exports, {
|
|
1292
|
+
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
1293
|
+
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
1294
|
+
});
|
|
1295
|
+
var os10, ProviderCliAdapter;
|
|
1296
|
+
var init_provider_cli_adapter = __esm({
|
|
1297
|
+
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
1298
|
+
"use strict";
|
|
1299
|
+
os10 = __toESM(require("os"));
|
|
1037
1300
|
init_logger();
|
|
1038
1301
|
init_terminal_screen();
|
|
1039
1302
|
init_pty_transport();
|
|
1040
|
-
|
|
1041
|
-
|
|
1303
|
+
init_provider_cli_shared();
|
|
1304
|
+
init_provider_cli_parse();
|
|
1305
|
+
init_provider_cli_config();
|
|
1306
|
+
init_provider_cli_runtime();
|
|
1307
|
+
init_provider_cli_shared();
|
|
1042
1308
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
1043
1309
|
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
1044
1310
|
this.extraArgs = extraArgs;
|
|
@@ -1046,36 +1312,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
1046
1312
|
this.transportFactory = transportFactory;
|
|
1047
1313
|
this.cliType = provider.type;
|
|
1048
1314
|
this.cliName = provider.name;
|
|
1049
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
1050
|
-
const
|
|
1051
|
-
this.timeouts =
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
maxResponse: t.maxResponse ?? 3e5,
|
|
1058
|
-
shutdownGrace: t.shutdownGrace ?? 1e3,
|
|
1059
|
-
outputSettle: t.outputSettle ?? 300
|
|
1060
|
-
};
|
|
1061
|
-
const rawKeys = provider.approvalKeys;
|
|
1062
|
-
this.approvalKeys = rawKeys && typeof rawKeys === "object" ? rawKeys : {};
|
|
1063
|
-
this.sendDelayMs = typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0;
|
|
1064
|
-
this.sendKey = typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r";
|
|
1065
|
-
this.submitStrategy = provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo";
|
|
1066
|
-
this.providerResolutionMeta = {
|
|
1067
|
-
type: provider.type,
|
|
1068
|
-
name: provider.name,
|
|
1069
|
-
resolvedVersion: provider._resolvedVersion || null,
|
|
1070
|
-
resolvedOs: provider._resolvedOs || null,
|
|
1071
|
-
providerDir: provider._resolvedProviderDir || null,
|
|
1072
|
-
scriptDir: provider._resolvedScriptDir || null,
|
|
1073
|
-
scriptsPath: provider._resolvedScriptsPath || null,
|
|
1074
|
-
scriptsSource: provider._resolvedScriptsSource || null,
|
|
1075
|
-
versionWarning: provider._versionWarning || null
|
|
1076
|
-
};
|
|
1315
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os10.homedir()) : workingDir;
|
|
1316
|
+
const resolvedConfig = resolveCliAdapterConfig(provider);
|
|
1317
|
+
this.timeouts = resolvedConfig.timeouts;
|
|
1318
|
+
this.approvalKeys = resolvedConfig.approvalKeys;
|
|
1319
|
+
this.sendDelayMs = resolvedConfig.sendDelayMs;
|
|
1320
|
+
this.sendKey = resolvedConfig.sendKey;
|
|
1321
|
+
this.submitStrategy = resolvedConfig.submitStrategy;
|
|
1322
|
+
this.providerResolutionMeta = resolvedConfig.providerResolutionMeta;
|
|
1077
1323
|
this.cliScripts = provider.scripts || {};
|
|
1078
|
-
const scriptNames =
|
|
1324
|
+
const scriptNames = listCliScriptNames(this.cliScripts);
|
|
1079
1325
|
if (scriptNames.length > 0) {
|
|
1080
1326
|
LOG.info("CLI", `[${this.cliType}] CLI scripts: [${scriptNames.join(", ")}]`);
|
|
1081
1327
|
LOG.info(
|
|
@@ -1172,88 +1418,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
1172
1418
|
this.messages = [...this.committedMessages];
|
|
1173
1419
|
this.structuredMessages = [...this.committedMessages];
|
|
1174
1420
|
}
|
|
1175
|
-
hydrateParsedMessages(parsedMessages, scope) {
|
|
1176
|
-
const referenceMessages = [...this.committedMessages];
|
|
1177
|
-
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
1178
|
-
const now = Date.now();
|
|
1179
|
-
const findReferenceTimestamp = (role, content, parsedIndex) => {
|
|
1180
|
-
const normalizedContent = normalizeComparableMessageContent(content);
|
|
1181
|
-
if (!normalizedContent) return void 0;
|
|
1182
|
-
const sameIndex = referenceMessages[parsedIndex];
|
|
1183
|
-
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && normalizeComparableMessageContent(sameIndex.content) === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
|
|
1184
|
-
usedReferenceIndexes.add(parsedIndex);
|
|
1185
|
-
return sameIndex.timestamp;
|
|
1186
|
-
}
|
|
1187
|
-
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1188
|
-
if (usedReferenceIndexes.has(i)) continue;
|
|
1189
|
-
const candidate = referenceMessages[i];
|
|
1190
|
-
if (!candidate || candidate.role !== role) continue;
|
|
1191
|
-
const candidateContent = normalizeComparableMessageContent(candidate.content);
|
|
1192
|
-
if (!candidateContent) continue;
|
|
1193
|
-
const exactMatch = candidateContent === normalizedContent;
|
|
1194
|
-
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
1195
|
-
if (!exactMatch && !fuzzyMatch) continue;
|
|
1196
|
-
if (typeof candidate.timestamp === "number" && Number.isFinite(candidate.timestamp)) {
|
|
1197
|
-
usedReferenceIndexes.add(i);
|
|
1198
|
-
return candidate.timestamp;
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
return void 0;
|
|
1202
|
-
};
|
|
1203
|
-
return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
|
|
1204
|
-
const role = message.role;
|
|
1205
|
-
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
1206
|
-
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
1207
|
-
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
|
|
1208
|
-
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : this.lastOutputAt || scope?.startedAt || now;
|
|
1209
|
-
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
1210
|
-
return {
|
|
1211
|
-
...message,
|
|
1212
|
-
role,
|
|
1213
|
-
content,
|
|
1214
|
-
timestamp,
|
|
1215
|
-
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
|
|
1216
|
-
};
|
|
1217
|
-
});
|
|
1218
|
-
}
|
|
1219
|
-
normalizeParsedMessages(parsedMessages, scope) {
|
|
1220
|
-
return this.hydrateParsedMessages(parsedMessages, scope).map((message) => ({
|
|
1221
|
-
role: message.role,
|
|
1222
|
-
content: message.content,
|
|
1223
|
-
timestamp: message.timestamp,
|
|
1224
|
-
receivedAt: message.receivedAt,
|
|
1225
|
-
kind: message.kind,
|
|
1226
|
-
id: message.id,
|
|
1227
|
-
index: message.index,
|
|
1228
|
-
meta: message.meta,
|
|
1229
|
-
senderName: message.senderName
|
|
1230
|
-
}));
|
|
1231
|
-
}
|
|
1232
|
-
sliceFromOffset(text, start) {
|
|
1233
|
-
if (!text) return "";
|
|
1234
|
-
if (!Number.isFinite(start) || start <= 0) return text;
|
|
1235
|
-
if (start >= text.length) return "";
|
|
1236
|
-
return text.slice(start);
|
|
1237
|
-
}
|
|
1238
|
-
buildParseInput(baseMessages, partialResponse, scope) {
|
|
1239
|
-
const buffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
1240
|
-
const rawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
1241
|
-
const screenText = this.terminalScreen.getText();
|
|
1242
|
-
const recentBuffer = buffer.slice(-1e3) || this.recentOutputBuffer;
|
|
1243
|
-
return {
|
|
1244
|
-
buffer,
|
|
1245
|
-
rawBuffer,
|
|
1246
|
-
recentBuffer,
|
|
1247
|
-
screenText,
|
|
1248
|
-
screen: buildCliScreenSnapshot(screenText),
|
|
1249
|
-
bufferScreen: buildCliScreenSnapshot(buffer),
|
|
1250
|
-
recentScreen: buildCliScreenSnapshot(recentBuffer),
|
|
1251
|
-
messages: [...baseMessages],
|
|
1252
|
-
partialResponse,
|
|
1253
|
-
promptText: scope?.prompt || "",
|
|
1254
|
-
settings: { ...this.runtimeSettings }
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
1421
|
setStatus(status, trigger) {
|
|
1258
1422
|
const prev = this.currentStatus;
|
|
1259
1423
|
if (prev === status) return;
|
|
@@ -1286,7 +1450,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
1286
1450
|
this.recordTrace("idle_candidate_armed", {
|
|
1287
1451
|
confirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
|
|
1288
1452
|
candidate: this.idleFinishCandidate,
|
|
1289
|
-
...
|
|
1453
|
+
...buildCliTraceParseSnapshot({
|
|
1454
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
1455
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
1456
|
+
responseBuffer: this.responseBuffer,
|
|
1457
|
+
partialResponse: this.responseBuffer,
|
|
1458
|
+
scope: this.currentTurnScope
|
|
1459
|
+
})
|
|
1290
1460
|
});
|
|
1291
1461
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
1292
1462
|
this.settleTimer = setTimeout(() => {
|
|
@@ -1295,30 +1465,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
1295
1465
|
this.evaluateSettled();
|
|
1296
1466
|
}, _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
|
|
1297
1467
|
}
|
|
1298
|
-
summarizeTraceText(text, max = 800) {
|
|
1299
|
-
const value = sanitizeTerminalText(String(text || ""));
|
|
1300
|
-
if (value.length <= max) return value;
|
|
1301
|
-
return `\u2026${value.slice(-max)}`;
|
|
1302
|
-
}
|
|
1303
|
-
summarizeTraceMessages(messages, limit = 3) {
|
|
1304
|
-
return messages.slice(-limit).map((message) => ({
|
|
1305
|
-
role: message.role,
|
|
1306
|
-
content: this.summarizeTraceText(message.content, 240),
|
|
1307
|
-
timestamp: message.timestamp
|
|
1308
|
-
}));
|
|
1309
|
-
}
|
|
1310
|
-
buildTraceParseSnapshot(scope, partialResponse = "") {
|
|
1311
|
-
const scopedBuffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
1312
|
-
const scopedRawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
1313
|
-
return {
|
|
1314
|
-
currentTurnScope: scope || null,
|
|
1315
|
-
responseBuffer: this.summarizeTraceText(this.responseBuffer, 1200),
|
|
1316
|
-
partialResponse: this.summarizeTraceText(partialResponse || this.responseBuffer, 1200),
|
|
1317
|
-
turnBuffer: this.summarizeTraceText(scopedBuffer, 1600),
|
|
1318
|
-
turnRawPreview: this.summarizeTraceText(scopedRawBuffer, 1600),
|
|
1319
|
-
turnSanitizedRawPreview: this.summarizeTraceText(sanitizeTerminalText(scopedRawBuffer), 1600)
|
|
1320
|
-
};
|
|
1321
|
-
}
|
|
1322
1468
|
recordTrace(type, payload = {}) {
|
|
1323
1469
|
const entry = {
|
|
1324
1470
|
id: ++this.traceSeq,
|
|
@@ -1354,7 +1500,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1354
1500
|
/** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
|
|
1355
1501
|
setCliScripts(scripts) {
|
|
1356
1502
|
this.cliScripts = scripts;
|
|
1357
|
-
const scriptNames =
|
|
1503
|
+
const scriptNames = listCliScriptNames(scripts);
|
|
1358
1504
|
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
1359
1505
|
}
|
|
1360
1506
|
updateRuntimeSettings(settings) {
|
|
@@ -1386,72 +1532,42 @@ var init_provider_cli_adapter = __esm({
|
|
|
1386
1532
|
}
|
|
1387
1533
|
async spawn() {
|
|
1388
1534
|
if (this.ptyProcess) return;
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1535
|
+
const spawnPlan = resolveCliSpawnPlan({
|
|
1536
|
+
provider: this.provider,
|
|
1537
|
+
runtimeSettings: this.runtimeSettings,
|
|
1538
|
+
workingDir: this.workingDir,
|
|
1539
|
+
extraArgs: this.extraArgs
|
|
1540
|
+
});
|
|
1394
1541
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1395
1542
|
this.resetTraceSession();
|
|
1396
|
-
let shellCmd;
|
|
1397
|
-
let shellArgs;
|
|
1398
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1399
|
-
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1400
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1401
|
-
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1402
|
-
if (useShell) {
|
|
1403
|
-
if (!spawnConfig.shell && !isWin) {
|
|
1404
|
-
LOG.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
|
|
1405
|
-
}
|
|
1406
|
-
if (isCmdShim) {
|
|
1407
|
-
LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell for .cmd/.bat shim: ${binaryPath}`);
|
|
1408
|
-
} else if (isWin) {
|
|
1409
|
-
LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell on Windows: ${binaryPath}`);
|
|
1410
|
-
}
|
|
1411
|
-
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
1412
|
-
if (isWin) {
|
|
1413
|
-
shellArgs = ["/c", binaryPath, ...allArgs];
|
|
1414
|
-
} else {
|
|
1415
|
-
const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
|
|
1416
|
-
shellArgs = ["-l", "-c", fullCmd];
|
|
1417
|
-
}
|
|
1418
|
-
} else {
|
|
1419
|
-
if (isWin && spawnConfig.shell) {
|
|
1420
|
-
LOG.info("CLI", `[${this.cliType}] Spawning Windows binary directly without cmd.exe: ${binaryPath}`);
|
|
1421
|
-
}
|
|
1422
|
-
shellCmd = binaryPath;
|
|
1423
|
-
shellArgs = allArgs;
|
|
1424
|
-
}
|
|
1425
|
-
const ptyOpts = {
|
|
1426
|
-
cols: 80,
|
|
1427
|
-
rows: 24,
|
|
1428
|
-
cwd: this.workingDir,
|
|
1429
|
-
env: buildCliSpawnEnv(process.env, spawnConfig.env)
|
|
1430
|
-
};
|
|
1431
1543
|
this.recordTrace("spawn", {
|
|
1432
|
-
shellCommand: shellCmd,
|
|
1433
|
-
shellArgs,
|
|
1434
|
-
cwd:
|
|
1435
|
-
cols:
|
|
1436
|
-
rows:
|
|
1544
|
+
shellCommand: spawnPlan.shellCmd,
|
|
1545
|
+
shellArgs: spawnPlan.shellArgs,
|
|
1546
|
+
cwd: spawnPlan.ptyOptions.cwd,
|
|
1547
|
+
cols: spawnPlan.ptyOptions.cols,
|
|
1548
|
+
rows: spawnPlan.ptyOptions.rows,
|
|
1437
1549
|
providerResolution: this.providerResolutionMeta
|
|
1438
1550
|
});
|
|
1439
1551
|
try {
|
|
1440
|
-
this.ptyProcess = this.transportFactory.spawn(
|
|
1552
|
+
this.ptyProcess = this.transportFactory.spawn(
|
|
1553
|
+
spawnPlan.shellCmd,
|
|
1554
|
+
spawnPlan.shellArgs,
|
|
1555
|
+
spawnPlan.ptyOptions
|
|
1556
|
+
);
|
|
1441
1557
|
} catch (err) {
|
|
1442
1558
|
const msg = err?.message || String(err);
|
|
1443
|
-
if (!isWin && !useShell && /posix_spawn|spawn/i.test(msg)) {
|
|
1559
|
+
if (!spawnPlan.isWin && !spawnPlan.useShell && /posix_spawn|spawn/i.test(msg)) {
|
|
1444
1560
|
LOG.warn("CLI", `[${this.cliType}] Direct spawn failed (${msg}), retrying via login shell`);
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1561
|
+
const retryPlan = buildCliLoginShellRetry(spawnPlan);
|
|
1562
|
+
this.ptyProcess = this.transportFactory.spawn(
|
|
1563
|
+
retryPlan.shellCmd,
|
|
1564
|
+
retryPlan.shellArgs,
|
|
1565
|
+
spawnPlan.ptyOptions
|
|
1566
|
+
);
|
|
1449
1567
|
} else {
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
throw new Error(`Failed to spawn CLI${hint}: ${msg}`);
|
|
1454
|
-
}
|
|
1568
|
+
const hint = getCliSpawnErrorHint(msg, spawnPlan.shellCmd, spawnPlan.isWin);
|
|
1569
|
+
if (hint) {
|
|
1570
|
+
throw new Error(`Failed to spawn CLI${hint}: ${msg}`);
|
|
1455
1571
|
}
|
|
1456
1572
|
throw err;
|
|
1457
1573
|
}
|
|
@@ -1459,7 +1575,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
1459
1575
|
this.ptyProcess.onData((data) => {
|
|
1460
1576
|
if (Date.now() < this.resizeSuppressUntil) return;
|
|
1461
1577
|
if (!this.ptyProcess?.terminalQueriesHandled) {
|
|
1462
|
-
this.
|
|
1578
|
+
this.pendingTerminalQueryTail = respondToCliTerminalQueries({
|
|
1579
|
+
ptyProcess: this.ptyProcess,
|
|
1580
|
+
pendingTail: this.pendingTerminalQueryTail,
|
|
1581
|
+
data,
|
|
1582
|
+
terminalScreen: this.terminalScreen
|
|
1583
|
+
});
|
|
1463
1584
|
}
|
|
1464
1585
|
this.pendingOutputParseBuffer += data;
|
|
1465
1586
|
if (!this.pendingOutputParseTimer) {
|
|
@@ -1538,9 +1659,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1538
1659
|
this.recordTrace("output", {
|
|
1539
1660
|
rawLength: rawData.length,
|
|
1540
1661
|
cleanLength: cleanData.length,
|
|
1541
|
-
rawPreview:
|
|
1542
|
-
cleanPreview:
|
|
1543
|
-
screenText:
|
|
1662
|
+
rawPreview: summarizeCliTraceText(rawData, 300),
|
|
1663
|
+
cleanPreview: summarizeCliTraceText(cleanData, 300),
|
|
1664
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 1200)
|
|
1544
1665
|
});
|
|
1545
1666
|
if (this.startupParseGate) {
|
|
1546
1667
|
this.scheduleStartupSettleCheck();
|
|
@@ -1771,7 +1892,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1771
1892
|
loggedWait = true;
|
|
1772
1893
|
LOG.info(
|
|
1773
1894
|
"CLI",
|
|
1774
|
-
`[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(
|
|
1895
|
+
`[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
|
|
1775
1896
|
);
|
|
1776
1897
|
}
|
|
1777
1898
|
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
@@ -1779,7 +1900,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1779
1900
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
1780
1901
|
LOG.warn(
|
|
1781
1902
|
"CLI",
|
|
1782
|
-
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(
|
|
1903
|
+
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
1783
1904
|
);
|
|
1784
1905
|
}
|
|
1785
1906
|
evaluateSettled() {
|
|
@@ -1809,23 +1930,33 @@ var init_provider_cli_adapter = __esm({
|
|
|
1809
1930
|
this.responseBuffer,
|
|
1810
1931
|
this.currentTurnScope
|
|
1811
1932
|
);
|
|
1812
|
-
const parsedMessages = Array.isArray(parsedTranscript?.messages) ?
|
|
1933
|
+
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
1934
|
+
committedMessages: this.committedMessages,
|
|
1935
|
+
scope: this.currentTurnScope,
|
|
1936
|
+
lastOutputAt: this.lastOutputAt
|
|
1937
|
+
}) : [];
|
|
1813
1938
|
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
1814
1939
|
this.recordTrace("settled", {
|
|
1815
|
-
tail:
|
|
1816
|
-
screenText:
|
|
1940
|
+
tail: summarizeCliTraceText(tail, 500),
|
|
1941
|
+
screenText: summarizeCliTraceText(screenText, 1200),
|
|
1817
1942
|
detectStatus: scriptStatus,
|
|
1818
1943
|
parsedStatus: parsedTranscript?.status || null,
|
|
1819
1944
|
parsedMessageCount: parsedMessages.length,
|
|
1820
|
-
parsedLastAssistant: lastParsedAssistant ?
|
|
1945
|
+
parsedLastAssistant: lastParsedAssistant ? summarizeCliTraceText(lastParsedAssistant.content, 280) : "",
|
|
1821
1946
|
parsedActiveModal: parsedTranscript?.activeModal ?? null,
|
|
1822
1947
|
approval: modal,
|
|
1823
|
-
...
|
|
1948
|
+
...buildCliTraceParseSnapshot({
|
|
1949
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
1950
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
1951
|
+
responseBuffer: this.responseBuffer,
|
|
1952
|
+
partialResponse: this.responseBuffer,
|
|
1953
|
+
scope: this.currentTurnScope
|
|
1954
|
+
})
|
|
1824
1955
|
});
|
|
1825
1956
|
if (this.currentTurnScope && !lastParsedAssistant) {
|
|
1826
1957
|
LOG.info(
|
|
1827
1958
|
"CLI",
|
|
1828
|
-
`[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(
|
|
1959
|
+
`[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
|
|
1829
1960
|
);
|
|
1830
1961
|
}
|
|
1831
1962
|
if (!scriptStatus) return;
|
|
@@ -1879,7 +2010,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
1879
2010
|
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
1880
2011
|
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
1881
2012
|
holdMs: _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
|
|
1882
|
-
...
|
|
2013
|
+
...buildCliTraceParseSnapshot({
|
|
2014
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2015
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2016
|
+
responseBuffer: this.responseBuffer,
|
|
2017
|
+
partialResponse: this.responseBuffer,
|
|
2018
|
+
scope: this.currentTurnScope
|
|
2019
|
+
})
|
|
1883
2020
|
});
|
|
1884
2021
|
this.onStatusChange?.();
|
|
1885
2022
|
return;
|
|
@@ -1983,7 +2120,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
1983
2120
|
canFinishImmediately,
|
|
1984
2121
|
submitPendingUntil: this.submitPendingUntil,
|
|
1985
2122
|
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
1986
|
-
...
|
|
2123
|
+
...buildCliTraceParseSnapshot({
|
|
2124
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2125
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2126
|
+
responseBuffer: this.responseBuffer,
|
|
2127
|
+
partialResponse: this.responseBuffer,
|
|
2128
|
+
scope: this.currentTurnScope
|
|
2129
|
+
})
|
|
1987
2130
|
});
|
|
1988
2131
|
if (canFinishImmediately) {
|
|
1989
2132
|
this.clearIdleFinishCandidate("finish_response");
|
|
@@ -2018,7 +2161,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
2018
2161
|
if (this.responseSettleIgnoreUntil > Date.now()) return;
|
|
2019
2162
|
this.clearIdleFinishCandidate("finish_response_enter");
|
|
2020
2163
|
this.recordTrace("finish_response", {
|
|
2021
|
-
...
|
|
2164
|
+
...buildCliTraceParseSnapshot({
|
|
2165
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2166
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2167
|
+
responseBuffer: this.responseBuffer,
|
|
2168
|
+
partialResponse: this.responseBuffer,
|
|
2169
|
+
scope: this.currentTurnScope
|
|
2170
|
+
})
|
|
2022
2171
|
});
|
|
2023
2172
|
const commitResult = this.commitCurrentTranscript();
|
|
2024
2173
|
if (this.shouldRetryFinishResponse(commitResult)) {
|
|
@@ -2026,8 +2175,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
2026
2175
|
this.recordTrace("finish_response_retry", {
|
|
2027
2176
|
retryCount: this.finishRetryCount,
|
|
2028
2177
|
retryDelayMs: _ProviderCliAdapter.FINISH_RETRY_DELAY_MS,
|
|
2029
|
-
assistantContent:
|
|
2030
|
-
...
|
|
2178
|
+
assistantContent: summarizeCliTraceText(commitResult.assistantContent, 220),
|
|
2179
|
+
...buildCliTraceParseSnapshot({
|
|
2180
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2181
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2182
|
+
responseBuffer: this.responseBuffer,
|
|
2183
|
+
partialResponse: this.responseBuffer,
|
|
2184
|
+
scope: this.currentTurnScope
|
|
2185
|
+
})
|
|
2031
2186
|
});
|
|
2032
2187
|
if (this.finishRetryTimer) clearTimeout(this.finishRetryTimer);
|
|
2033
2188
|
this.finishRetryTimer = setTimeout(() => {
|
|
@@ -2076,7 +2231,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
2076
2231
|
this.currentTurnScope
|
|
2077
2232
|
);
|
|
2078
2233
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
2079
|
-
this.committedMessages =
|
|
2234
|
+
this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
|
|
2235
|
+
committedMessages: this.committedMessages,
|
|
2236
|
+
scope: this.currentTurnScope,
|
|
2237
|
+
lastOutputAt: this.lastOutputAt
|
|
2238
|
+
});
|
|
2080
2239
|
const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
|
|
2081
2240
|
if (promptForTrim) {
|
|
2082
2241
|
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
@@ -2089,14 +2248,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
2089
2248
|
this.recordTrace("commit_transcript", {
|
|
2090
2249
|
parsedStatus: parsed.status || null,
|
|
2091
2250
|
messageCount: this.committedMessages.length,
|
|
2092
|
-
lastAssistant: lastAssistant ?
|
|
2093
|
-
messages:
|
|
2094
|
-
...
|
|
2251
|
+
lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : "",
|
|
2252
|
+
messages: summarizeCliTraceMessages(this.committedMessages),
|
|
2253
|
+
...buildCliTraceParseSnapshot({
|
|
2254
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2255
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2256
|
+
responseBuffer: this.responseBuffer,
|
|
2257
|
+
partialResponse: this.responseBuffer,
|
|
2258
|
+
scope: this.currentTurnScope
|
|
2259
|
+
})
|
|
2095
2260
|
});
|
|
2096
2261
|
if (!lastAssistant && this.currentTurnScope) {
|
|
2097
2262
|
LOG.warn(
|
|
2098
2263
|
"CLI",
|
|
2099
|
-
`[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(
|
|
2264
|
+
`[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
2100
2265
|
);
|
|
2101
2266
|
}
|
|
2102
2267
|
return {
|
|
@@ -2188,7 +2353,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
2188
2353
|
index: typeof message.index === "number" ? message.index : index,
|
|
2189
2354
|
kind: message.kind || "standard",
|
|
2190
2355
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
2191
|
-
})) :
|
|
2356
|
+
})) : hydrateCliParsedMessages(parsed.messages, {
|
|
2357
|
+
committedMessages: this.committedMessages,
|
|
2358
|
+
scope: this.currentTurnScope,
|
|
2359
|
+
lastOutputAt: this.lastOutputAt
|
|
2360
|
+
});
|
|
2192
2361
|
return {
|
|
2193
2362
|
id: parsed.id || "cli_session",
|
|
2194
2363
|
status: parsed.status || this.currentStatus,
|
|
@@ -2219,11 +2388,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
2219
2388
|
if (typeof fn !== "function") {
|
|
2220
2389
|
throw new Error(`CLI script '${scriptName}' not available`);
|
|
2221
2390
|
}
|
|
2222
|
-
const input =
|
|
2223
|
-
this.
|
|
2224
|
-
this.
|
|
2225
|
-
this.
|
|
2226
|
-
|
|
2391
|
+
const input = buildCliParseInput({
|
|
2392
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2393
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2394
|
+
recentOutputBuffer: this.recentOutputBuffer,
|
|
2395
|
+
terminalScreenText: this.terminalScreen.getText(),
|
|
2396
|
+
baseMessages: this.committedMessages,
|
|
2397
|
+
partialResponse: this.responseBuffer,
|
|
2398
|
+
scope: this.currentTurnScope,
|
|
2399
|
+
runtimeSettings: this.runtimeSettings
|
|
2400
|
+
});
|
|
2227
2401
|
return await Promise.resolve(fn({
|
|
2228
2402
|
...input,
|
|
2229
2403
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
@@ -2232,7 +2406,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
2232
2406
|
parseCurrentTranscript(baseMessages, partialResponse, scope) {
|
|
2233
2407
|
if (!this.cliScripts?.parseOutput) return null;
|
|
2234
2408
|
try {
|
|
2235
|
-
const input =
|
|
2409
|
+
const input = buildCliParseInput({
|
|
2410
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2411
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2412
|
+
recentOutputBuffer: this.recentOutputBuffer,
|
|
2413
|
+
terminalScreenText: this.terminalScreen.getText(),
|
|
2414
|
+
baseMessages,
|
|
2415
|
+
partialResponse,
|
|
2416
|
+
scope,
|
|
2417
|
+
runtimeSettings: this.runtimeSettings
|
|
2418
|
+
});
|
|
2236
2419
|
const parsed = this.cliScripts.parseOutput(input);
|
|
2237
2420
|
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
2238
2421
|
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
@@ -2322,7 +2505,7 @@ ${data.message || ""}`.trim();
|
|
|
2322
2505
|
rawBufferStart: this.accumulatedRawBuffer.length
|
|
2323
2506
|
};
|
|
2324
2507
|
this.recordTrace("send_message", {
|
|
2325
|
-
text:
|
|
2508
|
+
text: summarizeCliTraceText(text, 500),
|
|
2326
2509
|
estimatedLines: estimatePromptDisplayLines(text),
|
|
2327
2510
|
turnScope: this.currentTurnScope
|
|
2328
2511
|
});
|
|
@@ -2356,7 +2539,7 @@ ${data.message || ""}`.trim();
|
|
|
2356
2539
|
this.recordTrace("submit_write", {
|
|
2357
2540
|
mode: "submit_key",
|
|
2358
2541
|
sendKey: this.sendKey,
|
|
2359
|
-
screenText:
|
|
2542
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
2360
2543
|
});
|
|
2361
2544
|
this.ptyProcess.write(this.sendKey);
|
|
2362
2545
|
const retrySubmitIfStuck = (attempt) => {
|
|
@@ -2373,7 +2556,7 @@ ${data.message || ""}`.trim();
|
|
|
2373
2556
|
mode: "submit_retry",
|
|
2374
2557
|
attempt,
|
|
2375
2558
|
sendKey: this.sendKey,
|
|
2376
|
-
screenText:
|
|
2559
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
2377
2560
|
});
|
|
2378
2561
|
this.ptyProcess.write(this.sendKey);
|
|
2379
2562
|
if (attempt >= 3) {
|
|
@@ -2389,9 +2572,9 @@ ${data.message || ""}`.trim();
|
|
|
2389
2572
|
this.submitPendingUntil = 0;
|
|
2390
2573
|
this.recordTrace("submit_write", {
|
|
2391
2574
|
mode: "immediate",
|
|
2392
|
-
text:
|
|
2575
|
+
text: summarizeCliTraceText(text, 500),
|
|
2393
2576
|
sendKey: this.sendKey,
|
|
2394
|
-
screenText:
|
|
2577
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
2395
2578
|
});
|
|
2396
2579
|
this.ptyProcess.write(text + this.sendKey);
|
|
2397
2580
|
this.submitRetryTimer = setTimeout(() => {
|
|
@@ -2407,7 +2590,7 @@ ${data.message || ""}`.trim();
|
|
|
2407
2590
|
mode: "immediate_retry",
|
|
2408
2591
|
attempt: 1,
|
|
2409
2592
|
sendKey: this.sendKey,
|
|
2410
|
-
screenText:
|
|
2593
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
2411
2594
|
});
|
|
2412
2595
|
this.ptyProcess.write(this.sendKey);
|
|
2413
2596
|
this.submitRetryUsed = true;
|
|
@@ -2421,9 +2604,9 @@ ${data.message || ""}`.trim();
|
|
|
2421
2604
|
this.ptyProcess.write(text);
|
|
2422
2605
|
this.recordTrace("submit_write", {
|
|
2423
2606
|
mode: "type_then_submit",
|
|
2424
|
-
text:
|
|
2607
|
+
text: summarizeCliTraceText(text, 500),
|
|
2425
2608
|
sendKey: this.sendKey,
|
|
2426
|
-
screenText:
|
|
2609
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
2427
2610
|
});
|
|
2428
2611
|
const submitStartedAt = Date.now();
|
|
2429
2612
|
let lastNormalizedScreen = "";
|
|
@@ -2758,7 +2941,7 @@ ${data.message || ""}`.trim();
|
|
|
2758
2941
|
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
2759
2942
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
2760
2943
|
hasCliScripts: this.hasCliScripts(),
|
|
2761
|
-
scriptNames:
|
|
2944
|
+
scriptNames: listCliScriptNames(this.cliScripts),
|
|
2762
2945
|
traceSessionId: this.traceSessionId,
|
|
2763
2946
|
traceEntryCount: this.traceEntries.length,
|
|
2764
2947
|
statusHistory: this.statusHistory.slice(-30),
|
|
@@ -2775,32 +2958,18 @@ ${data.message || ""}`.trim();
|
|
|
2775
2958
|
providerResolution: this.providerResolutionMeta,
|
|
2776
2959
|
entryCount: this.traceEntries.length,
|
|
2777
2960
|
entries: this.traceEntries.slice(-cappedLimit),
|
|
2778
|
-
screenText:
|
|
2779
|
-
recentOutputBuffer:
|
|
2780
|
-
responseBuffer:
|
|
2961
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 4e3),
|
|
2962
|
+
recentOutputBuffer: summarizeCliTraceText(this.recentOutputBuffer, 1e3),
|
|
2963
|
+
responseBuffer: summarizeCliTraceText(this.responseBuffer, 1200),
|
|
2781
2964
|
status: this.currentStatus,
|
|
2782
2965
|
activeModal: this.activeModal,
|
|
2783
2966
|
currentTurnScope: this.currentTurnScope,
|
|
2784
|
-
messages:
|
|
2967
|
+
messages: summarizeCliTraceMessages(this.committedMessages, 5)
|
|
2785
2968
|
};
|
|
2786
2969
|
}
|
|
2787
2970
|
getProviderResolutionMeta() {
|
|
2788
2971
|
return { ...this.providerResolutionMeta };
|
|
2789
2972
|
}
|
|
2790
|
-
respondToTerminalQueries(data) {
|
|
2791
|
-
if (!this.ptyProcess || !data) return;
|
|
2792
|
-
const combined = this.pendingTerminalQueryTail + data;
|
|
2793
|
-
const regex = /\x1b\[(\?)?6n/g;
|
|
2794
|
-
let match;
|
|
2795
|
-
while ((match = regex.exec(combined)) !== null) {
|
|
2796
|
-
const cursor = this.terminalScreen.getCursorPosition();
|
|
2797
|
-
const row = Math.max(1, (cursor.row | 0) + 1);
|
|
2798
|
-
const col = Math.max(1, (cursor.col | 0) + 1);
|
|
2799
|
-
const response = match[1] ? `\x1B[?${row};${col}R` : `\x1B[${row};${col}R`;
|
|
2800
|
-
this.ptyProcess.write(response);
|
|
2801
|
-
}
|
|
2802
|
-
this.pendingTerminalQueryTail = computeTerminalQueryTail(combined);
|
|
2803
|
-
}
|
|
2804
2973
|
};
|
|
2805
2974
|
}
|
|
2806
2975
|
});
|
|
@@ -3280,17 +3449,17 @@ function checkPathExists(paths) {
|
|
|
3280
3449
|
return null;
|
|
3281
3450
|
}
|
|
3282
3451
|
async function detectIDEs(providerLoader) {
|
|
3283
|
-
const
|
|
3452
|
+
const os20 = (0, import_os2.platform)();
|
|
3284
3453
|
const results = [];
|
|
3285
3454
|
for (const def of getMergedDefinitions()) {
|
|
3286
3455
|
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
3287
|
-
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[
|
|
3456
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os20] || []) || []);
|
|
3288
3457
|
let resolvedCli = cliPath;
|
|
3289
|
-
if (!resolvedCli && appPath &&
|
|
3458
|
+
if (!resolvedCli && appPath && os20 === "darwin") {
|
|
3290
3459
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
3291
3460
|
if ((0, import_fs3.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
3292
3461
|
}
|
|
3293
|
-
if (!resolvedCli && appPath &&
|
|
3462
|
+
if (!resolvedCli && appPath && os20 === "win32") {
|
|
3294
3463
|
const { dirname: dirname6 } = await import("path");
|
|
3295
3464
|
const appDir = dirname6(appPath);
|
|
3296
3465
|
const candidates = [
|
|
@@ -3307,7 +3476,7 @@ async function detectIDEs(providerLoader) {
|
|
|
3307
3476
|
}
|
|
3308
3477
|
}
|
|
3309
3478
|
}
|
|
3310
|
-
const installed =
|
|
3479
|
+
const installed = os20 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
3311
3480
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
3312
3481
|
results.push({
|
|
3313
3482
|
id: def.id,
|
|
@@ -3368,8 +3537,8 @@ function execAsync(cmd, timeoutMs = 5e3) {
|
|
|
3368
3537
|
});
|
|
3369
3538
|
}
|
|
3370
3539
|
async function detectCLIs(providerLoader, options) {
|
|
3371
|
-
const
|
|
3372
|
-
const whichCmd =
|
|
3540
|
+
const platform10 = os2.platform();
|
|
3541
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
3373
3542
|
const includeVersion = options?.includeVersion !== false;
|
|
3374
3543
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
3375
3544
|
const results = await Promise.all(
|
|
@@ -3412,8 +3581,8 @@ async function detectCLI(cliId, providerLoader, options) {
|
|
|
3412
3581
|
const cliList = providerLoader.getCliDetectionList();
|
|
3413
3582
|
const target = cliList.find((c) => c.id === resolvedId);
|
|
3414
3583
|
if (target) {
|
|
3415
|
-
const
|
|
3416
|
-
const whichCmd =
|
|
3584
|
+
const platform10 = os2.platform();
|
|
3585
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
3417
3586
|
try {
|
|
3418
3587
|
const explicitPath = resolveCommandPath(target.command);
|
|
3419
3588
|
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
@@ -3534,6 +3703,10 @@ var DaemonCdpManager = class {
|
|
|
3534
3703
|
setTargetFilter(filter) {
|
|
3535
3704
|
this._targetFilter = filter;
|
|
3536
3705
|
}
|
|
3706
|
+
/** Clear a previously pinned target so the next connect can reselect a page. */
|
|
3707
|
+
clearTargetId() {
|
|
3708
|
+
this._targetId = null;
|
|
3709
|
+
}
|
|
3537
3710
|
/**
|
|
3538
3711
|
* Check if a page title should be excluded (non-main page).
|
|
3539
3712
|
* Uses provider-configured titleExcludes, falls back to default pattern.
|
|
@@ -5799,6 +5972,55 @@ ${effect.notification.body || ""}`.trim();
|
|
|
5799
5972
|
|
|
5800
5973
|
// src/providers/ide-provider-instance.ts
|
|
5801
5974
|
init_logger();
|
|
5975
|
+
|
|
5976
|
+
// src/providers/approval-utils.ts
|
|
5977
|
+
var DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
5978
|
+
"run",
|
|
5979
|
+
"approve",
|
|
5980
|
+
"accept",
|
|
5981
|
+
"allow once",
|
|
5982
|
+
"always allow",
|
|
5983
|
+
"allow",
|
|
5984
|
+
"yes",
|
|
5985
|
+
"proceed",
|
|
5986
|
+
"continue",
|
|
5987
|
+
"confirm",
|
|
5988
|
+
"save",
|
|
5989
|
+
"ok",
|
|
5990
|
+
"trust"
|
|
5991
|
+
];
|
|
5992
|
+
function normalizeApprovalLabel(value) {
|
|
5993
|
+
return String(value || "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
5994
|
+
}
|
|
5995
|
+
function getApprovalPositiveHints(provider) {
|
|
5996
|
+
const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
|
|
5997
|
+
return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
|
|
5998
|
+
}
|
|
5999
|
+
function pickApprovalButton(buttons, provider) {
|
|
6000
|
+
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
6001
|
+
if (labels.length === 0) {
|
|
6002
|
+
return { index: 0, label: "Approve" };
|
|
6003
|
+
}
|
|
6004
|
+
const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
|
|
6005
|
+
const hints = getApprovalPositiveHints(provider);
|
|
6006
|
+
for (const hint of hints) {
|
|
6007
|
+
const exactIndex = normalizedButtons.findIndex((label) => label === hint);
|
|
6008
|
+
if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
|
|
6009
|
+
const prefixIndex = normalizedButtons.findIndex((label) => label.startsWith(hint));
|
|
6010
|
+
if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
|
|
6011
|
+
const includeIndex = normalizedButtons.findIndex((label) => label.includes(hint));
|
|
6012
|
+
if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
|
|
6013
|
+
}
|
|
6014
|
+
return { index: 0, label: labels[0] };
|
|
6015
|
+
}
|
|
6016
|
+
function formatAutoApprovalMessage(modalMessage, buttonLabel) {
|
|
6017
|
+
const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
|
|
6018
|
+
const cleanMessage = String(modalMessage || "").trim();
|
|
6019
|
+
if (cleanMessage) lines.push(cleanMessage);
|
|
6020
|
+
return lines.join("\n");
|
|
6021
|
+
}
|
|
6022
|
+
|
|
6023
|
+
// src/providers/ide-provider-instance.ts
|
|
5802
6024
|
var IdeProviderInstance = class {
|
|
5803
6025
|
type;
|
|
5804
6026
|
category = "ide";
|
|
@@ -5865,6 +6087,8 @@ var IdeProviderInstance = class {
|
|
|
5865
6087
|
}
|
|
5866
6088
|
getState() {
|
|
5867
6089
|
const cdp = this.context?.cdp;
|
|
6090
|
+
const autoApproveActive = (this.currentStatus === "waiting_approval" || this.cachedChat?.status === "waiting_approval") && this.canAutoApprove();
|
|
6091
|
+
const visibleStatus = autoApproveActive ? "generating" : this.currentStatus;
|
|
5868
6092
|
const extensionStates = [];
|
|
5869
6093
|
for (const ext of this.extensions.values()) {
|
|
5870
6094
|
extensionStates.push(ext.getState());
|
|
@@ -5873,13 +6097,13 @@ var IdeProviderInstance = class {
|
|
|
5873
6097
|
type: this.type,
|
|
5874
6098
|
name: this.provider.name,
|
|
5875
6099
|
category: "ide",
|
|
5876
|
-
status:
|
|
6100
|
+
status: visibleStatus,
|
|
5877
6101
|
activeChat: this.cachedChat ? {
|
|
5878
6102
|
id: this.cachedChat.id || "active_session",
|
|
5879
6103
|
title: this.cachedChat.title || this.type,
|
|
5880
|
-
status: this.cachedChat.status
|
|
6104
|
+
status: autoApproveActive && this.cachedChat.status === "waiting_approval" ? "generating" : this.cachedChat.status || visibleStatus,
|
|
5881
6105
|
messages: this.mergeConversationMessages(this.cachedChat.messages || []),
|
|
5882
|
-
activeModal: this.cachedChat.activeModal || null,
|
|
6106
|
+
activeModal: autoApproveActive ? null : this.cachedChat.activeModal || null,
|
|
5883
6107
|
inputContent: this.cachedChat.inputContent || ""
|
|
5884
6108
|
} : null,
|
|
5885
6109
|
workspace: this.workspace || null,
|
|
@@ -6026,7 +6250,8 @@ var IdeProviderInstance = class {
|
|
|
6026
6250
|
}
|
|
6027
6251
|
}
|
|
6028
6252
|
if (!raw || typeof raw !== "object") return;
|
|
6029
|
-
|
|
6253
|
+
const chat = raw;
|
|
6254
|
+
let { activeModal } = chat;
|
|
6030
6255
|
if (activeModal) {
|
|
6031
6256
|
const w = activeModal.width ?? Infinity;
|
|
6032
6257
|
const h = activeModal.height ?? Infinity;
|
|
@@ -6046,26 +6271,28 @@ var IdeProviderInstance = class {
|
|
|
6046
6271
|
if (pm.receivedAt) prevByHash.set(h, pm.receivedAt);
|
|
6047
6272
|
}
|
|
6048
6273
|
const now = Date.now();
|
|
6049
|
-
|
|
6274
|
+
const messages = chat.messages || [];
|
|
6275
|
+
for (const msg of messages) {
|
|
6050
6276
|
const h = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
|
|
6051
6277
|
msg.receivedAt = prevByHash.get(h) || now;
|
|
6052
6278
|
}
|
|
6053
|
-
if (
|
|
6279
|
+
if (messages.length > 0) {
|
|
6054
6280
|
const hiddenKinds = /* @__PURE__ */ new Set();
|
|
6055
6281
|
if (this.settings.showThinking === false) hiddenKinds.add("thought");
|
|
6056
6282
|
if (this.settings.showToolCalls === false) hiddenKinds.add("tool");
|
|
6057
6283
|
if (this.settings.showTerminal === false) hiddenKinds.add("terminal");
|
|
6058
6284
|
if (hiddenKinds.size > 0) {
|
|
6059
|
-
|
|
6285
|
+
chat.messages = messages.filter((m) => !hiddenKinds.has(m.kind || ""));
|
|
6060
6286
|
}
|
|
6061
6287
|
}
|
|
6062
|
-
const controlValues = extractProviderControlValues(this.provider.controls,
|
|
6063
|
-
if (controlValues)
|
|
6064
|
-
this.cachedChat = { ...
|
|
6065
|
-
this.detectAgentTransitions(
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6288
|
+
const controlValues = extractProviderControlValues(this.provider.controls, chat);
|
|
6289
|
+
if (controlValues) chat.controlValues = controlValues;
|
|
6290
|
+
this.cachedChat = { ...chat, activeModal };
|
|
6291
|
+
this.detectAgentTransitions(chat, now);
|
|
6292
|
+
const persistedMessages = chat.messages || messages;
|
|
6293
|
+
if (persistedMessages.length > 0) {
|
|
6294
|
+
let toSave = persistedMessages;
|
|
6295
|
+
if (chat.status === "generating" || chat.status === "long_generating") {
|
|
6069
6296
|
const lastIdx = toSave.length - 1;
|
|
6070
6297
|
if (lastIdx >= 0 && toSave[lastIdx].role === "assistant") {
|
|
6071
6298
|
toSave = toSave.slice(0, lastIdx);
|
|
@@ -6075,7 +6302,7 @@ var IdeProviderInstance = class {
|
|
|
6075
6302
|
this.historyWriter.appendNewMessages(
|
|
6076
6303
|
this.type,
|
|
6077
6304
|
toSave,
|
|
6078
|
-
|
|
6305
|
+
chat.title,
|
|
6079
6306
|
this.instanceId
|
|
6080
6307
|
);
|
|
6081
6308
|
}
|
|
@@ -6091,14 +6318,16 @@ var IdeProviderInstance = class {
|
|
|
6091
6318
|
getReadChatScript() {
|
|
6092
6319
|
const scripts = this.provider.scripts;
|
|
6093
6320
|
if (!scripts?.readChat) return null;
|
|
6094
|
-
return
|
|
6321
|
+
return scripts.readChat({});
|
|
6095
6322
|
}
|
|
6096
6323
|
// ─── status transition detect ─────────────────────────────
|
|
6097
6324
|
detectAgentTransitions(chatData, now) {
|
|
6098
6325
|
const chatStatus = chatData?.status;
|
|
6099
6326
|
if (!chatStatus) return;
|
|
6100
6327
|
const agentKey = `${this.type}:native`;
|
|
6101
|
-
const
|
|
6328
|
+
const rawAgentStatus = chatStatus === "streaming" || chatStatus === "generating" ? "generating" : chatStatus === "waiting_approval" ? "waiting_approval" : "idle";
|
|
6329
|
+
const autoApproveActive = rawAgentStatus === "waiting_approval" && this.canAutoApprove();
|
|
6330
|
+
const agentStatus = autoApproveActive ? "generating" : rawAgentStatus;
|
|
6102
6331
|
const lastMsg = Array.isArray(chatData?.messages) && chatData.messages.length > 0 ? chatData.messages[chatData.messages.length - 1] : null;
|
|
6103
6332
|
const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
|
|
6104
6333
|
this.currentStatus = agentStatus;
|
|
@@ -6130,7 +6359,7 @@ var IdeProviderInstance = class {
|
|
|
6130
6359
|
this.applyProviderResponse(chatData, {
|
|
6131
6360
|
phase: agentStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
6132
6361
|
});
|
|
6133
|
-
if (
|
|
6362
|
+
if (rawAgentStatus === "waiting_approval" && autoApproveActive && !this.autoApproveBusy) {
|
|
6134
6363
|
this.autoApproveViaScript(chatData);
|
|
6135
6364
|
}
|
|
6136
6365
|
const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint);
|
|
@@ -6281,6 +6510,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
6281
6510
|
updateCdp(cdp) {
|
|
6282
6511
|
if (this.context) this.context.cdp = cdp;
|
|
6283
6512
|
}
|
|
6513
|
+
canAutoApprove() {
|
|
6514
|
+
return this.settings.autoApprove !== false && typeof this.provider.scripts?.resolveAction === "function" && !!this.context?.cdp?.isConnected;
|
|
6515
|
+
}
|
|
6284
6516
|
// ─── Auto-approve via CDP script ────────────────────
|
|
6285
6517
|
async autoApproveViaScript(_chatData) {
|
|
6286
6518
|
const cdp = this.context?.cdp;
|
|
@@ -6292,17 +6524,15 @@ ${effect.notification.body || ""}`.trim();
|
|
|
6292
6524
|
}
|
|
6293
6525
|
this.autoApproveBusy = true;
|
|
6294
6526
|
try {
|
|
6295
|
-
|
|
6296
|
-
const buttons = _chatData?.activeModal?.buttons || [];
|
|
6297
|
-
for (const b of buttons) {
|
|
6298
|
-
const lower = String(b).toLowerCase().replace(/[^\w]/g, "");
|
|
6299
|
-
if (/^(run|approve|accept|yes|allow|always|proceed|save)/.test(lower)) {
|
|
6300
|
-
targetButton = b;
|
|
6301
|
-
break;
|
|
6302
|
-
}
|
|
6303
|
-
}
|
|
6527
|
+
const { label: targetButton } = pickApprovalButton(_chatData?.activeModal?.buttons, this.provider);
|
|
6304
6528
|
const script = scriptFn({ action: "approve", button: targetButton, buttonText: targetButton });
|
|
6305
6529
|
if (!script) return;
|
|
6530
|
+
const now = Date.now();
|
|
6531
|
+
this.appendRuntimeSystemMessage(
|
|
6532
|
+
formatAutoApprovalMessage(_chatData?.activeModal?.message, targetButton),
|
|
6533
|
+
`auto_approval:${now}:${targetButton}`,
|
|
6534
|
+
now
|
|
6535
|
+
);
|
|
6306
6536
|
LOG.info("IdeInstance", `[IdeInstance:${this.type}] autoApprove: executing resolveAction for "${targetButton}"`);
|
|
6307
6537
|
let rawResult = await cdp.evaluate(script, 1e4);
|
|
6308
6538
|
if (typeof rawResult === "string") {
|
|
@@ -6324,12 +6554,6 @@ ${effect.notification.body || ""}`.trim();
|
|
|
6324
6554
|
LOG.warn("IdeInstance", `[IdeInstance:${this.type}] autoApprove: cdp.send() not available for coordinate click`);
|
|
6325
6555
|
}
|
|
6326
6556
|
}
|
|
6327
|
-
this.pushEvent({
|
|
6328
|
-
event: "agent:auto_approved",
|
|
6329
|
-
chatTitle: _chatData?.title || this.provider.name,
|
|
6330
|
-
timestamp: Date.now(),
|
|
6331
|
-
ideType: this.type
|
|
6332
|
-
});
|
|
6333
6557
|
} catch (e) {
|
|
6334
6558
|
LOG.warn("IdeInstance", `[IdeInstance:${this.type}] autoApprove error: ${e?.message}`);
|
|
6335
6559
|
} finally {
|
|
@@ -7165,7 +7389,7 @@ function getTargetInstance(h, args) {
|
|
|
7165
7389
|
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
7166
7390
|
const sessionId = targetSessionId || h.currentSession?.sessionId || "";
|
|
7167
7391
|
if (!sessionId) return null;
|
|
7168
|
-
return h.ctx.instanceManager?.getInstance(sessionId);
|
|
7392
|
+
return h.ctx.instanceManager?.getInstance(sessionId) || null;
|
|
7169
7393
|
}
|
|
7170
7394
|
function getTargetTransport(h, provider) {
|
|
7171
7395
|
if (h.currentSession?.transport) return h.currentSession.transport;
|
|
@@ -7203,6 +7427,10 @@ function getHistorySessionId(h, args) {
|
|
|
7203
7427
|
const providerSessionId = typeof state?.providerSessionId === "string" ? state.providerSessionId.trim() : "";
|
|
7204
7428
|
return providerSessionId || targetSessionId;
|
|
7205
7429
|
}
|
|
7430
|
+
function callLegacyTextScript(script, text) {
|
|
7431
|
+
if (typeof script !== "function") return null;
|
|
7432
|
+
return script(text);
|
|
7433
|
+
}
|
|
7206
7434
|
function isRecentDuplicateSend(key) {
|
|
7207
7435
|
const now = Date.now();
|
|
7208
7436
|
for (const [candidate, ts2] of recentSendByTarget.entries()) {
|
|
@@ -7292,7 +7520,7 @@ async function handleReadChat(h, args) {
|
|
|
7292
7520
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7293
7521
|
if (adapter) {
|
|
7294
7522
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
7295
|
-
const status = adapter.getStatus
|
|
7523
|
+
const status = adapter.getStatus();
|
|
7296
7524
|
if (status) {
|
|
7297
7525
|
return {
|
|
7298
7526
|
success: true,
|
|
@@ -7532,7 +7760,7 @@ async function handleSendChat(h, args) {
|
|
|
7532
7760
|
}
|
|
7533
7761
|
if (parsed?.needsTypeAndSend && provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
7534
7762
|
try {
|
|
7535
|
-
const webviewScript = provider.scripts.webviewSendMessage
|
|
7763
|
+
const webviewScript = callLegacyTextScript(provider.scripts.webviewSendMessage, text);
|
|
7536
7764
|
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
7537
7765
|
const matchText = provider.webviewMatchText;
|
|
7538
7766
|
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
@@ -7555,7 +7783,7 @@ async function handleSendChat(h, args) {
|
|
|
7555
7783
|
}
|
|
7556
7784
|
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
7557
7785
|
try {
|
|
7558
|
-
const webviewScript = provider.scripts.webviewSendMessage
|
|
7786
|
+
const webviewScript = callLegacyTextScript(provider.scripts.webviewSendMessage, text);
|
|
7559
7787
|
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
7560
7788
|
const matchText = provider.webviewMatchText;
|
|
7561
7789
|
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
@@ -7787,12 +8015,10 @@ async function handleSetMode(h, args) {
|
|
|
7787
8015
|
const mode = args?.mode || "agent";
|
|
7788
8016
|
if (transport === "acp") {
|
|
7789
8017
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
return { success: true, mode };
|
|
7795
|
-
}
|
|
8018
|
+
const acpInstance = adapter?._acpInstance;
|
|
8019
|
+
if (acpInstance && typeof acpInstance.setMode === "function") {
|
|
8020
|
+
await acpInstance.setMode(mode);
|
|
8021
|
+
return { success: true, mode };
|
|
7796
8022
|
}
|
|
7797
8023
|
return { success: false, error: "ACP adapter not found" };
|
|
7798
8024
|
}
|
|
@@ -7845,13 +8071,11 @@ async function handleChangeModel(h, args) {
|
|
|
7845
8071
|
if (transport === "acp") {
|
|
7846
8072
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7847
8073
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
return { success: true, model };
|
|
7854
|
-
}
|
|
8074
|
+
const acpInstance = adapter?._acpInstance;
|
|
8075
|
+
if (acpInstance && typeof acpInstance.setConfigOption === "function") {
|
|
8076
|
+
await acpInstance.setConfigOption("model", model);
|
|
8077
|
+
LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
|
|
8078
|
+
return { success: true, model };
|
|
7855
8079
|
}
|
|
7856
8080
|
return { success: false, error: "ACP adapter not found" };
|
|
7857
8081
|
}
|
|
@@ -7908,6 +8132,9 @@ async function handleSetThoughtLevel(h, args) {
|
|
|
7908
8132
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7909
8133
|
const acpInstance = adapter?._acpInstance;
|
|
7910
8134
|
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
8135
|
+
if (typeof acpInstance.setConfigOption !== "function") {
|
|
8136
|
+
return { success: false, error: "ACP setConfigOption not available" };
|
|
8137
|
+
}
|
|
7911
8138
|
try {
|
|
7912
8139
|
await acpInstance.setConfigOption(configId, value);
|
|
7913
8140
|
LOG.info("Command", `[set_thought_level] ${configId}=${value} for ${provider?.type || "unknown_acp"}`);
|
|
@@ -7934,7 +8161,7 @@ async function handleResolveAction(h, args) {
|
|
|
7934
8161
|
return { success: false, error: `CLI resolveAction failed: ${e.message}` };
|
|
7935
8162
|
}
|
|
7936
8163
|
}
|
|
7937
|
-
const status = adapter.getStatus
|
|
8164
|
+
const status = adapter.getStatus();
|
|
7938
8165
|
if (status?.status !== "waiting_approval") {
|
|
7939
8166
|
return { success: false, error: "Not in approval state" };
|
|
7940
8167
|
}
|
|
@@ -7973,6 +8200,9 @@ async function handleResolveAction(h, args) {
|
|
|
7973
8200
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7974
8201
|
const acpInstance = adapter?._acpInstance;
|
|
7975
8202
|
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
8203
|
+
if (typeof acpInstance.resolvePermission !== "function") {
|
|
8204
|
+
return { success: false, error: "ACP resolvePermission not available" };
|
|
8205
|
+
}
|
|
7976
8206
|
try {
|
|
7977
8207
|
await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
|
|
7978
8208
|
LOG.info("Command", `[resolveAction] ACP \u2192 ${action}`);
|
|
@@ -8134,11 +8364,16 @@ async function handleCdpCommand(h, args) {
|
|
|
8134
8364
|
}
|
|
8135
8365
|
async function handleCdpBatch(h, args) {
|
|
8136
8366
|
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
8137
|
-
const commands = args?.commands;
|
|
8367
|
+
const commands = Array.isArray(args?.commands) ? args.commands : null;
|
|
8138
8368
|
const stopOnError = args?.stopOnError !== false;
|
|
8139
8369
|
if (!commands?.length) return { success: false, error: "commands array required" };
|
|
8140
8370
|
const results = [];
|
|
8141
8371
|
for (const cmd of commands) {
|
|
8372
|
+
if (!cmd || typeof cmd !== "object" || typeof cmd.method !== "string") {
|
|
8373
|
+
results.push({ method: null, success: false, error: "Invalid command entry" });
|
|
8374
|
+
if (stopOnError) break;
|
|
8375
|
+
continue;
|
|
8376
|
+
}
|
|
8142
8377
|
try {
|
|
8143
8378
|
const result = await h.getCdp().sendCdpCommand(cmd.method, cmd.params || {});
|
|
8144
8379
|
results.push({ method: cmd.method, success: true, result });
|
|
@@ -8433,11 +8668,12 @@ function handlePtyResize(h, args) {
|
|
|
8433
8668
|
if (!adapter || typeof adapter.resize !== "function") {
|
|
8434
8669
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
8435
8670
|
}
|
|
8671
|
+
const resize = adapter.resize;
|
|
8436
8672
|
if (force) {
|
|
8437
|
-
|
|
8438
|
-
setTimeout(() =>
|
|
8673
|
+
resize(cols - 1, rows);
|
|
8674
|
+
setTimeout(() => resize(cols, rows), 50);
|
|
8439
8675
|
} else {
|
|
8440
|
-
|
|
8676
|
+
resize(cols, rows);
|
|
8441
8677
|
}
|
|
8442
8678
|
return { success: true };
|
|
8443
8679
|
}
|
|
@@ -8495,7 +8731,7 @@ function parseScriptResult(result) {
|
|
|
8495
8731
|
return { success: true, payload: { result } };
|
|
8496
8732
|
}
|
|
8497
8733
|
}
|
|
8498
|
-
if (result && typeof result === "object" && result.success === false) {
|
|
8734
|
+
if (result && typeof result === "object" && "success" in result && result.success === false) {
|
|
8499
8735
|
return { success: false, payload: result };
|
|
8500
8736
|
}
|
|
8501
8737
|
return { success: true, payload: result };
|
|
@@ -8918,24 +9154,25 @@ var DaemonCommandHandler = class {
|
|
|
8918
9154
|
if (provider?.scripts) {
|
|
8919
9155
|
const fn = provider.scripts[scriptName];
|
|
8920
9156
|
if (typeof fn === "function") {
|
|
9157
|
+
const callScript = fn;
|
|
8921
9158
|
if (params && Object.keys(params).length > 0) {
|
|
8922
9159
|
const firstVal = Object.values(params)[0];
|
|
8923
9160
|
if (scriptName === "sendMessage" && typeof firstVal === "string") {
|
|
8924
|
-
const legacyScript =
|
|
9161
|
+
const legacyScript = callScript(firstVal);
|
|
8925
9162
|
if (legacyScript) return legacyScript;
|
|
8926
9163
|
}
|
|
8927
|
-
const script =
|
|
9164
|
+
const script = callScript(params);
|
|
8928
9165
|
if (script) {
|
|
8929
9166
|
const likelyLegacyObjectLeak = typeof script === "string" && script.includes("[object Object]") && typeof firstVal === "string";
|
|
8930
9167
|
if (!likelyLegacyObjectLeak) return script;
|
|
8931
9168
|
}
|
|
8932
9169
|
if (firstVal !== void 0) {
|
|
8933
|
-
const legacyScript =
|
|
9170
|
+
const legacyScript = callScript(firstVal);
|
|
8934
9171
|
if (legacyScript) return legacyScript;
|
|
8935
9172
|
}
|
|
8936
9173
|
if (script) return script;
|
|
8937
9174
|
} else {
|
|
8938
|
-
const script =
|
|
9175
|
+
const script = callScript();
|
|
8939
9176
|
if (script) return script;
|
|
8940
9177
|
}
|
|
8941
9178
|
}
|
|
@@ -9315,16 +9552,16 @@ var DaemonCommandHandler = class {
|
|
|
9315
9552
|
};
|
|
9316
9553
|
|
|
9317
9554
|
// src/commands/cli-manager.ts
|
|
9318
|
-
var
|
|
9319
|
-
var
|
|
9555
|
+
var os12 = __toESM(require("os"));
|
|
9556
|
+
var path12 = __toESM(require("path"));
|
|
9320
9557
|
var crypto4 = __toESM(require("crypto"));
|
|
9321
9558
|
var import_chalk = __toESM(require("chalk"));
|
|
9322
9559
|
init_provider_cli_adapter();
|
|
9323
9560
|
init_config();
|
|
9324
9561
|
|
|
9325
9562
|
// src/providers/cli-provider-instance.ts
|
|
9326
|
-
var
|
|
9327
|
-
var
|
|
9563
|
+
var os11 = __toESM(require("os"));
|
|
9564
|
+
var path11 = __toESM(require("path"));
|
|
9328
9565
|
var crypto3 = __toESM(require("crypto"));
|
|
9329
9566
|
var fs5 = __toESM(require("fs"));
|
|
9330
9567
|
var import_node_module = require("module");
|
|
@@ -9333,7 +9570,7 @@ init_logger();
|
|
|
9333
9570
|
var CachedDatabaseSync = null;
|
|
9334
9571
|
function getDatabaseSync() {
|
|
9335
9572
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
9336
|
-
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
9573
|
+
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path11.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
9337
9574
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
9338
9575
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
9339
9576
|
if (!CachedDatabaseSync) {
|
|
@@ -9473,7 +9710,7 @@ var CliProviderInstance = class {
|
|
|
9473
9710
|
* Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
|
|
9474
9711
|
*/
|
|
9475
9712
|
probeSessionIdFromConfig(probe) {
|
|
9476
|
-
const resolvedDbPath = probe.dbPath.replace(/^~/,
|
|
9713
|
+
const resolvedDbPath = probe.dbPath.replace(/^~/, os11.homedir());
|
|
9477
9714
|
if (!fs5.existsSync(resolvedDbPath)) return null;
|
|
9478
9715
|
const directories = this.getProbeDirectories();
|
|
9479
9716
|
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
@@ -9497,6 +9734,8 @@ var CliProviderInstance = class {
|
|
|
9497
9734
|
getState() {
|
|
9498
9735
|
const adapterStatus = this.adapter.getStatus();
|
|
9499
9736
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
9737
|
+
const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
9738
|
+
const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
|
|
9500
9739
|
const parsedProviderSessionId = typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId.trim() : "";
|
|
9501
9740
|
if (parsedProviderSessionId) {
|
|
9502
9741
|
this.promoteProviderSessionId(parsedProviderSessionId);
|
|
@@ -9536,14 +9775,14 @@ var CliProviderInstance = class {
|
|
|
9536
9775
|
type: this.type,
|
|
9537
9776
|
name: this.provider.name,
|
|
9538
9777
|
category: "cli",
|
|
9539
|
-
status:
|
|
9778
|
+
status: visibleStatus,
|
|
9540
9779
|
mode: this.presentationMode,
|
|
9541
9780
|
activeChat: {
|
|
9542
9781
|
id: `${this.type}_${this.workingDir}`,
|
|
9543
9782
|
title: parsedStatus?.title || dirName,
|
|
9544
|
-
status: parsedStatus?.status ||
|
|
9783
|
+
status: autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
|
|
9545
9784
|
messages: mergedMessages,
|
|
9546
|
-
activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
9785
|
+
activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
9547
9786
|
inputContent: ""
|
|
9548
9787
|
},
|
|
9549
9788
|
workspace: this.workingDir,
|
|
@@ -9607,7 +9846,16 @@ var CliProviderInstance = class {
|
|
|
9607
9846
|
const now = Date.now();
|
|
9608
9847
|
const adapterStatus = this.adapter.getStatus();
|
|
9609
9848
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
9610
|
-
const
|
|
9849
|
+
const rawStatus = adapterStatus.status;
|
|
9850
|
+
const autoApproveActive = rawStatus === "waiting_approval" && this.shouldAutoApprove();
|
|
9851
|
+
if (autoApproveActive) {
|
|
9852
|
+
const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(adapterStatus.activeModal?.buttons, this.provider);
|
|
9853
|
+
this.recordAutoApproval(adapterStatus.activeModal?.message, buttonLabel, now);
|
|
9854
|
+
setTimeout(() => {
|
|
9855
|
+
this.adapter.resolveModal(buttonIndex);
|
|
9856
|
+
}, 0);
|
|
9857
|
+
}
|
|
9858
|
+
const newStatus = autoApproveActive ? "generating" : rawStatus;
|
|
9611
9859
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
9612
9860
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
9613
9861
|
const partial = this.adapter.getPartialResponse();
|
|
@@ -9817,6 +10065,16 @@ ${effect.notification.body || ""}`.trim();
|
|
|
9817
10065
|
get cliName() {
|
|
9818
10066
|
return this.provider.name;
|
|
9819
10067
|
}
|
|
10068
|
+
shouldAutoApprove() {
|
|
10069
|
+
return this.settings.autoApprove !== false;
|
|
10070
|
+
}
|
|
10071
|
+
recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
|
|
10072
|
+
this.appendRuntimeSystemMessage(
|
|
10073
|
+
formatAutoApprovalMessage(modalMessage, buttonLabel),
|
|
10074
|
+
`auto_approval:${now}:${buttonLabel || "approve"}`,
|
|
10075
|
+
now
|
|
10076
|
+
);
|
|
10077
|
+
}
|
|
9820
10078
|
recordApprovalSelection(buttonText) {
|
|
9821
10079
|
const cleanButton = String(buttonText || "").trim();
|
|
9822
10080
|
if (!cleanButton) return;
|
|
@@ -10390,8 +10648,10 @@ var AcpProviderInstance = class {
|
|
|
10390
10648
|
input: tc.rawInput ? typeof tc.rawInput === "string" ? tc.rawInput : JSON.stringify(tc.rawInput) : void 0
|
|
10391
10649
|
});
|
|
10392
10650
|
}
|
|
10393
|
-
if (this.settings.autoApprove) {
|
|
10394
|
-
|
|
10651
|
+
if (this.settings.autoApprove !== false) {
|
|
10652
|
+
const toolTitle = tc.title || tc.toolCallId || "tool call";
|
|
10653
|
+
this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
|
|
10654
|
+
this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
|
|
10395
10655
|
const allowOption = params.options.find((o) => o.kind === "allow_once") || params.options.find((o) => o.kind === "allow_always");
|
|
10396
10656
|
if (allowOption) {
|
|
10397
10657
|
return { outcome: { outcome: "selected", optionId: allowOption.optionId } };
|
|
@@ -10843,6 +11103,18 @@ var AcpProviderInstance = class {
|
|
|
10843
11103
|
this.events.push(event);
|
|
10844
11104
|
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
10845
11105
|
}
|
|
11106
|
+
appendSystemMessage(content, timestamp = Date.now()) {
|
|
11107
|
+
const normalizedContent = String(content || "").trim();
|
|
11108
|
+
if (!normalizedContent) return;
|
|
11109
|
+
this.messages.push({
|
|
11110
|
+
role: "system",
|
|
11111
|
+
content: normalizedContent,
|
|
11112
|
+
timestamp
|
|
11113
|
+
});
|
|
11114
|
+
if (this.messages.length > 200) {
|
|
11115
|
+
this.messages = this.messages.slice(-100);
|
|
11116
|
+
}
|
|
11117
|
+
}
|
|
10846
11118
|
flushEvents() {
|
|
10847
11119
|
const events = [...this.events];
|
|
10848
11120
|
this.events = [];
|
|
@@ -10863,7 +11135,8 @@ var AcpProviderInstance = class {
|
|
|
10863
11135
|
|
|
10864
11136
|
// src/commands/cli-manager.ts
|
|
10865
11137
|
init_logger();
|
|
10866
|
-
var
|
|
11138
|
+
var chalkModule = import_chalk.default;
|
|
11139
|
+
var chalkApi = typeof chalkModule.yellow === "function" ? chalkModule : chalkModule.default || null;
|
|
10867
11140
|
function colorize(color, text) {
|
|
10868
11141
|
const fn = chalkApi?.[color];
|
|
10869
11142
|
return typeof fn === "function" ? fn(text) : text;
|
|
@@ -11113,7 +11386,7 @@ var DaemonCliManager = class {
|
|
|
11113
11386
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
11114
11387
|
const trimmed = (workingDir || "").trim();
|
|
11115
11388
|
if (!trimmed) throw new Error("working directory required");
|
|
11116
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/,
|
|
11389
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path12.resolve(trimmed);
|
|
11117
11390
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
11118
11391
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
11119
11392
|
const key = crypto4.randomUUID();
|
|
@@ -11152,6 +11425,7 @@ ${installInfo}`
|
|
|
11152
11425
|
});
|
|
11153
11426
|
this.adapters.set(key, {
|
|
11154
11427
|
cliType: normalizedType,
|
|
11428
|
+
cliName: provider.name,
|
|
11155
11429
|
workingDir: resolvedDir,
|
|
11156
11430
|
_acpInstance: acpInstance,
|
|
11157
11431
|
spawn: async () => {
|
|
@@ -11170,6 +11444,12 @@ ${installInfo}`
|
|
|
11170
11444
|
activeModal: state.activeChat?.activeModal || null
|
|
11171
11445
|
};
|
|
11172
11446
|
},
|
|
11447
|
+
getPartialResponse: () => "",
|
|
11448
|
+
cancel: () => {
|
|
11449
|
+
instanceManager2.removeInstance(key);
|
|
11450
|
+
},
|
|
11451
|
+
isProcessing: () => false,
|
|
11452
|
+
isReady: () => true,
|
|
11173
11453
|
setOnStatusChange: () => {
|
|
11174
11454
|
},
|
|
11175
11455
|
setOnPtyData: () => {
|
|
@@ -11576,13 +11856,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
11576
11856
|
// src/launch.ts
|
|
11577
11857
|
var import_child_process6 = require("child_process");
|
|
11578
11858
|
var net = __toESM(require("net"));
|
|
11579
|
-
var
|
|
11580
|
-
var
|
|
11859
|
+
var os14 = __toESM(require("os"));
|
|
11860
|
+
var path14 = __toESM(require("path"));
|
|
11581
11861
|
|
|
11582
11862
|
// src/providers/provider-loader.ts
|
|
11583
11863
|
var fs6 = __toESM(require("fs"));
|
|
11584
|
-
var
|
|
11585
|
-
var
|
|
11864
|
+
var path13 = __toESM(require("path"));
|
|
11865
|
+
var os13 = __toESM(require("os"));
|
|
11586
11866
|
var chokidar = __toESM(require("chokidar"));
|
|
11587
11867
|
init_logger();
|
|
11588
11868
|
var ProviderLoader = class _ProviderLoader {
|
|
@@ -11603,12 +11883,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11603
11883
|
static META_FILE = ".meta.json";
|
|
11604
11884
|
constructor(options) {
|
|
11605
11885
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
11606
|
-
const defaultProvidersDir =
|
|
11886
|
+
const defaultProvidersDir = path13.join(os13.homedir(), ".adhdev", "providers");
|
|
11607
11887
|
if (options?.userDir) {
|
|
11608
11888
|
this.userDir = options.userDir;
|
|
11609
11889
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
11610
11890
|
} else {
|
|
11611
|
-
const localRepoPath =
|
|
11891
|
+
const localRepoPath = path13.resolve(__dirname, "../../../../../adhdev-providers");
|
|
11612
11892
|
if (fs6.existsSync(localRepoPath)) {
|
|
11613
11893
|
this.userDir = localRepoPath;
|
|
11614
11894
|
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
@@ -11617,7 +11897,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11617
11897
|
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
11618
11898
|
}
|
|
11619
11899
|
}
|
|
11620
|
-
this.upstreamDir =
|
|
11900
|
+
this.upstreamDir = path13.join(defaultProvidersDir, ".upstream");
|
|
11621
11901
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
11622
11902
|
}
|
|
11623
11903
|
log(msg) {
|
|
@@ -11647,7 +11927,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11647
11927
|
* Canonical provider directory shape for a given root.
|
|
11648
11928
|
*/
|
|
11649
11929
|
getProviderDir(root, category, type) {
|
|
11650
|
-
return
|
|
11930
|
+
return path13.join(root, category, type);
|
|
11651
11931
|
}
|
|
11652
11932
|
/**
|
|
11653
11933
|
* Canonical user override directory for a provider.
|
|
@@ -11674,7 +11954,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11674
11954
|
resolveProviderFile(type, ...segments) {
|
|
11675
11955
|
const dir = this.findProviderDirInternal(type);
|
|
11676
11956
|
if (!dir) return null;
|
|
11677
|
-
return
|
|
11957
|
+
return path13.join(dir, ...segments);
|
|
11678
11958
|
}
|
|
11679
11959
|
/**
|
|
11680
11960
|
* Load all providers (3-tier priority)
|
|
@@ -11713,7 +11993,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11713
11993
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
11714
11994
|
try {
|
|
11715
11995
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
11716
|
-
(d) => fs6.statSync(
|
|
11996
|
+
(d) => fs6.statSync(path13.join(this.upstreamDir, d)).isDirectory()
|
|
11717
11997
|
);
|
|
11718
11998
|
} catch {
|
|
11719
11999
|
return false;
|
|
@@ -11754,8 +12034,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11754
12034
|
const result = [];
|
|
11755
12035
|
for (const p of this.providers.values()) {
|
|
11756
12036
|
if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
|
|
11757
|
-
const
|
|
11758
|
-
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
|
|
12037
|
+
const versionCommand = this.getPlatformVersionCommand(p.versionCommand);
|
|
11759
12038
|
const command = this.getSpawnCommand(p.type, p.spawn.command);
|
|
11760
12039
|
result.push({
|
|
11761
12040
|
id: p.type,
|
|
@@ -11809,8 +12088,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11809
12088
|
* that runtime attach/remove uses.
|
|
11810
12089
|
*/
|
|
11811
12090
|
getIdeExtensionEnabledState(ideType, extensionType) {
|
|
11812
|
-
const
|
|
11813
|
-
|
|
12091
|
+
const config = this.readConfig();
|
|
12092
|
+
if (!config) return false;
|
|
11814
12093
|
const baseIdeType = ideType.split("_")[0];
|
|
11815
12094
|
const val = config.ideSettings?.[baseIdeType]?.extensions?.[extensionType]?.enabled;
|
|
11816
12095
|
return val === true;
|
|
@@ -11819,15 +12098,15 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11819
12098
|
* Save IDE extension enabled setting
|
|
11820
12099
|
*/
|
|
11821
12100
|
setIdeExtensionEnabled(ideType, extensionType, enabled) {
|
|
12101
|
+
const config = this.readConfig();
|
|
12102
|
+
if (!config) return false;
|
|
11822
12103
|
try {
|
|
11823
|
-
const { loadConfig: loadConfig2, saveConfig: saveConfig3 } = (init_config(), __toCommonJS(config_exports));
|
|
11824
|
-
const config = loadConfig2();
|
|
11825
12104
|
const baseIdeType = ideType.split("_")[0];
|
|
11826
12105
|
if (!config.ideSettings) config.ideSettings = {};
|
|
11827
12106
|
if (!config.ideSettings[baseIdeType]) config.ideSettings[baseIdeType] = {};
|
|
11828
12107
|
if (!config.ideSettings[baseIdeType].extensions) config.ideSettings[baseIdeType].extensions = {};
|
|
11829
12108
|
config.ideSettings[baseIdeType].extensions[extensionType] = { enabled };
|
|
11830
|
-
|
|
12109
|
+
this.writeConfig(config);
|
|
11831
12110
|
this.log(`IDE extension setting: ${ideType}.${extensionType}.enabled = ${enabled}`);
|
|
11832
12111
|
return true;
|
|
11833
12112
|
} catch (e) {
|
|
@@ -12017,7 +12296,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12017
12296
|
}
|
|
12018
12297
|
if (currentVersion) {
|
|
12019
12298
|
resolved._resolvedVersion = currentVersion;
|
|
12020
|
-
if (
|
|
12299
|
+
if (base.compatibility) {
|
|
12021
12300
|
const compat = base.compatibility;
|
|
12022
12301
|
let matched = false;
|
|
12023
12302
|
for (const entry of compat) {
|
|
@@ -12029,8 +12308,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12029
12308
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
12030
12309
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
12031
12310
|
if (providerDir) {
|
|
12032
|
-
const fullDir =
|
|
12033
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
12311
|
+
const fullDir = path13.join(providerDir, entry.scriptDir);
|
|
12312
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
12034
12313
|
}
|
|
12035
12314
|
matched = true;
|
|
12036
12315
|
}
|
|
@@ -12045,8 +12324,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12045
12324
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
12046
12325
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
12047
12326
|
if (providerDir) {
|
|
12048
|
-
const fullDir =
|
|
12049
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
12327
|
+
const fullDir = path13.join(providerDir, base.defaultScriptDir);
|
|
12328
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
12050
12329
|
}
|
|
12051
12330
|
}
|
|
12052
12331
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -12063,8 +12342,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12063
12342
|
resolved._resolvedScriptDir = dirOverride;
|
|
12064
12343
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
12065
12344
|
if (providerDir) {
|
|
12066
|
-
const fullDir =
|
|
12067
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
12345
|
+
const fullDir = path13.join(providerDir, dirOverride);
|
|
12346
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
12068
12347
|
}
|
|
12069
12348
|
}
|
|
12070
12349
|
} else if (override.scripts) {
|
|
@@ -12072,7 +12351,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12072
12351
|
}
|
|
12073
12352
|
}
|
|
12074
12353
|
}
|
|
12075
|
-
} else if (
|
|
12354
|
+
} else if (base.compatibility && base.defaultScriptDir) {
|
|
12076
12355
|
const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
|
|
12077
12356
|
if (loaded) {
|
|
12078
12357
|
resolved.scripts = loaded;
|
|
@@ -12080,8 +12359,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12080
12359
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
12081
12360
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
12082
12361
|
if (providerDir) {
|
|
12083
|
-
const fullDir =
|
|
12084
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
12362
|
+
const fullDir = path13.join(providerDir, base.defaultScriptDir);
|
|
12363
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
12085
12364
|
}
|
|
12086
12365
|
}
|
|
12087
12366
|
}
|
|
@@ -12106,14 +12385,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12106
12385
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
12107
12386
|
return null;
|
|
12108
12387
|
}
|
|
12109
|
-
const dir =
|
|
12388
|
+
const dir = path13.join(providerDir, scriptDir);
|
|
12110
12389
|
if (!fs6.existsSync(dir)) {
|
|
12111
12390
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
12112
12391
|
return null;
|
|
12113
12392
|
}
|
|
12114
12393
|
const cached = this.scriptsCache.get(dir);
|
|
12115
12394
|
if (cached) return cached;
|
|
12116
|
-
const scriptsJs =
|
|
12395
|
+
const scriptsJs = path13.join(dir, "scripts.js");
|
|
12117
12396
|
if (fs6.existsSync(scriptsJs)) {
|
|
12118
12397
|
try {
|
|
12119
12398
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -12155,7 +12434,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12155
12434
|
return;
|
|
12156
12435
|
}
|
|
12157
12436
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
12158
|
-
this.log(`File changed: ${
|
|
12437
|
+
this.log(`File changed: ${path13.basename(filePath)}, reloading...`);
|
|
12159
12438
|
this.reload();
|
|
12160
12439
|
}
|
|
12161
12440
|
};
|
|
@@ -12210,7 +12489,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12210
12489
|
}
|
|
12211
12490
|
const https = require("https");
|
|
12212
12491
|
const { execSync: execSync7 } = require("child_process");
|
|
12213
|
-
const metaPath =
|
|
12492
|
+
const metaPath = path13.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
12214
12493
|
let prevEtag = "";
|
|
12215
12494
|
let prevTimestamp = 0;
|
|
12216
12495
|
try {
|
|
@@ -12270,17 +12549,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12270
12549
|
return { updated: false };
|
|
12271
12550
|
}
|
|
12272
12551
|
this.log("Downloading latest providers from GitHub...");
|
|
12273
|
-
const tmpTar =
|
|
12274
|
-
const tmpExtract =
|
|
12552
|
+
const tmpTar = path13.join(os13.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
12553
|
+
const tmpExtract = path13.join(os13.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
12275
12554
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
12276
12555
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
12277
12556
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
12278
12557
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
12279
12558
|
const rootDir = extracted.find(
|
|
12280
|
-
(d) => fs6.statSync(
|
|
12559
|
+
(d) => fs6.statSync(path13.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
12281
12560
|
);
|
|
12282
12561
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
12283
|
-
const sourceDir =
|
|
12562
|
+
const sourceDir = path13.join(tmpExtract, rootDir);
|
|
12284
12563
|
const backupDir = this.upstreamDir + ".bak";
|
|
12285
12564
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
12286
12565
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -12355,8 +12634,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12355
12634
|
copyDirRecursive(src, dest) {
|
|
12356
12635
|
fs6.mkdirSync(dest, { recursive: true });
|
|
12357
12636
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
12358
|
-
const srcPath =
|
|
12359
|
-
const destPath =
|
|
12637
|
+
const srcPath = path13.join(src, entry.name);
|
|
12638
|
+
const destPath = path13.join(dest, entry.name);
|
|
12360
12639
|
if (entry.isDirectory()) {
|
|
12361
12640
|
this.copyDirRecursive(srcPath, destPath);
|
|
12362
12641
|
} else {
|
|
@@ -12367,7 +12646,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12367
12646
|
/** .meta.json save */
|
|
12368
12647
|
writeMeta(metaPath, etag, timestamp) {
|
|
12369
12648
|
try {
|
|
12370
|
-
fs6.mkdirSync(
|
|
12649
|
+
fs6.mkdirSync(path13.dirname(metaPath), { recursive: true });
|
|
12371
12650
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
12372
12651
|
etag,
|
|
12373
12652
|
timestamp,
|
|
@@ -12384,7 +12663,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12384
12663
|
const scan = (d) => {
|
|
12385
12664
|
try {
|
|
12386
12665
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
12387
|
-
if (entry.isDirectory()) scan(
|
|
12666
|
+
if (entry.isDirectory()) scan(path13.join(d, entry.name));
|
|
12388
12667
|
else if (entry.name === "provider.json") count++;
|
|
12389
12668
|
}
|
|
12390
12669
|
} catch {
|
|
@@ -12417,15 +12696,10 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12417
12696
|
*/
|
|
12418
12697
|
getSettingValue(type, key) {
|
|
12419
12698
|
const schemaDef = this.getSettingsSchema(type)[key];
|
|
12420
|
-
const defaultVal = schemaDef ? schemaDef.default : void 0;
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
const userVal = config.providerSettings?.[type]?.[key];
|
|
12425
|
-
return userVal !== void 0 ? userVal : defaultVal;
|
|
12426
|
-
} catch {
|
|
12427
|
-
return defaultVal;
|
|
12428
|
-
}
|
|
12699
|
+
const defaultVal = schemaDef ? key === "autoApprove" && schemaDef.type === "boolean" ? true : schemaDef.default : void 0;
|
|
12700
|
+
const config = this.readConfig();
|
|
12701
|
+
const userVal = config?.providerSettings?.[type]?.[key];
|
|
12702
|
+
return userVal !== void 0 ? userVal : defaultVal;
|
|
12429
12703
|
}
|
|
12430
12704
|
/**
|
|
12431
12705
|
* All resolved settings for a provider (default + user override)
|
|
@@ -12453,13 +12727,13 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12453
12727
|
if (schemaDef.max !== void 0 && value > schemaDef.max) return false;
|
|
12454
12728
|
}
|
|
12455
12729
|
if (schemaDef.type === "select" && schemaDef.options && !schemaDef.options.includes(value)) return false;
|
|
12730
|
+
const config = this.readConfig();
|
|
12731
|
+
if (!config) return false;
|
|
12456
12732
|
try {
|
|
12457
|
-
const { loadConfig: loadConfig2, saveConfig: saveConfig3 } = (init_config(), __toCommonJS(config_exports));
|
|
12458
|
-
const config = loadConfig2();
|
|
12459
12733
|
if (!config.providerSettings) config.providerSettings = {};
|
|
12460
12734
|
if (!config.providerSettings[type]) config.providerSettings[type] = {};
|
|
12461
12735
|
config.providerSettings[type][key] = value;
|
|
12462
|
-
|
|
12736
|
+
this.writeConfig(config);
|
|
12463
12737
|
this.log(`Setting updated: ${type}.${key} = ${JSON.stringify(value)}`);
|
|
12464
12738
|
return true;
|
|
12465
12739
|
} catch (e) {
|
|
@@ -12473,16 +12747,63 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12473
12747
|
const trimmed = value.trim();
|
|
12474
12748
|
return trimmed ? trimmed : null;
|
|
12475
12749
|
}
|
|
12750
|
+
readConfig() {
|
|
12751
|
+
try {
|
|
12752
|
+
const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
12753
|
+
return loadConfig2();
|
|
12754
|
+
} catch {
|
|
12755
|
+
return null;
|
|
12756
|
+
}
|
|
12757
|
+
}
|
|
12758
|
+
writeConfig(config) {
|
|
12759
|
+
const { saveConfig: saveConfig3 } = (init_config(), __toCommonJS(config_exports));
|
|
12760
|
+
saveConfig3(config);
|
|
12761
|
+
}
|
|
12762
|
+
getPlatformVersionCommand(versionCommand) {
|
|
12763
|
+
if (!versionCommand) return void 0;
|
|
12764
|
+
if (typeof versionCommand === "string") {
|
|
12765
|
+
const trimmed = versionCommand.trim();
|
|
12766
|
+
return trimmed || void 0;
|
|
12767
|
+
}
|
|
12768
|
+
const platformValue = versionCommand[process.platform];
|
|
12769
|
+
if (typeof platformValue === "string" && platformValue.trim()) {
|
|
12770
|
+
return platformValue.trim();
|
|
12771
|
+
}
|
|
12772
|
+
const defaultValue = versionCommand.default;
|
|
12773
|
+
if (typeof defaultValue === "string" && defaultValue.trim()) {
|
|
12774
|
+
return defaultValue.trim();
|
|
12775
|
+
}
|
|
12776
|
+
return void 0;
|
|
12777
|
+
}
|
|
12476
12778
|
getSettingsSchema(type) {
|
|
12477
12779
|
const provider = this.providers.get(type);
|
|
12478
12780
|
if (!provider) return {};
|
|
12479
|
-
|
|
12781
|
+
const result = {
|
|
12480
12782
|
...this.getSyntheticSettings(type, provider),
|
|
12481
12783
|
...provider.settings || {}
|
|
12482
12784
|
};
|
|
12785
|
+
if (result.autoApprove?.type === "boolean") {
|
|
12786
|
+
result.autoApprove = {
|
|
12787
|
+
...result.autoApprove,
|
|
12788
|
+
default: true,
|
|
12789
|
+
public: true,
|
|
12790
|
+
label: result.autoApprove.label || "Auto Approve",
|
|
12791
|
+
description: result.autoApprove.description || "Automatically approve actionable prompts without sending approval alerts."
|
|
12792
|
+
};
|
|
12793
|
+
}
|
|
12794
|
+
return result;
|
|
12483
12795
|
}
|
|
12484
12796
|
getSyntheticSettings(type, provider) {
|
|
12485
12797
|
const result = {};
|
|
12798
|
+
if (!provider.settings?.autoApprove) {
|
|
12799
|
+
result.autoApprove = {
|
|
12800
|
+
type: "boolean",
|
|
12801
|
+
default: true,
|
|
12802
|
+
public: true,
|
|
12803
|
+
label: "Auto Approve",
|
|
12804
|
+
description: "Automatically approve actionable prompts without sending approval alerts."
|
|
12805
|
+
};
|
|
12806
|
+
}
|
|
12486
12807
|
if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
|
|
12487
12808
|
result.executablePath = {
|
|
12488
12809
|
type: "string",
|
|
@@ -12527,17 +12848,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12527
12848
|
for (const root of searchRoots) {
|
|
12528
12849
|
if (!fs6.existsSync(root)) continue;
|
|
12529
12850
|
const candidate = this.getProviderDir(root, cat, type);
|
|
12530
|
-
if (fs6.existsSync(
|
|
12531
|
-
const catDir =
|
|
12851
|
+
if (fs6.existsSync(path13.join(candidate, "provider.json"))) return candidate;
|
|
12852
|
+
const catDir = path13.join(root, cat);
|
|
12532
12853
|
if (fs6.existsSync(catDir)) {
|
|
12533
12854
|
try {
|
|
12534
12855
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
12535
12856
|
if (!entry.isDirectory()) continue;
|
|
12536
|
-
const jsonPath =
|
|
12857
|
+
const jsonPath = path13.join(catDir, entry.name, "provider.json");
|
|
12537
12858
|
if (fs6.existsSync(jsonPath)) {
|
|
12538
12859
|
try {
|
|
12539
12860
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
12540
|
-
if (data.type === type) return
|
|
12861
|
+
if (data.type === type) return path13.join(catDir, entry.name);
|
|
12541
12862
|
} catch {
|
|
12542
12863
|
}
|
|
12543
12864
|
}
|
|
@@ -12554,7 +12875,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12554
12875
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
12555
12876
|
*/
|
|
12556
12877
|
buildScriptWrappersFromDir(dir) {
|
|
12557
|
-
const scriptsJs =
|
|
12878
|
+
const scriptsJs = path13.join(dir, "scripts.js");
|
|
12558
12879
|
if (fs6.existsSync(scriptsJs)) {
|
|
12559
12880
|
try {
|
|
12560
12881
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -12568,7 +12889,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12568
12889
|
for (const file of fs6.readdirSync(dir)) {
|
|
12569
12890
|
if (!file.endsWith(".js")) continue;
|
|
12570
12891
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
12571
|
-
const filePath =
|
|
12892
|
+
const filePath = path13.join(dir, file);
|
|
12572
12893
|
result[scriptName] = (...args) => {
|
|
12573
12894
|
try {
|
|
12574
12895
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -12628,35 +12949,39 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12628
12949
|
}
|
|
12629
12950
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
12630
12951
|
if (hasJson) {
|
|
12631
|
-
const jsonPath =
|
|
12952
|
+
const jsonPath = path13.join(d, "provider.json");
|
|
12632
12953
|
try {
|
|
12633
12954
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
12634
12955
|
const mod = JSON.parse(raw);
|
|
12635
12956
|
if (!mod.type || !mod.name || !mod.category) {
|
|
12636
12957
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: missing type/name/category`);
|
|
12637
12958
|
} else {
|
|
12638
|
-
if (
|
|
12959
|
+
if (typeof mod.extensionIdPattern === "string") {
|
|
12639
12960
|
const flags = mod.extensionIdPattern_flags || "";
|
|
12640
12961
|
mod.extensionIdPattern = new RegExp(mod.extensionIdPattern, flags);
|
|
12641
|
-
delete mod.extensionIdPattern_flags;
|
|
12642
12962
|
}
|
|
12643
|
-
const
|
|
12644
|
-
const
|
|
12963
|
+
const { extensionIdPattern_flags, extensionIdPattern, ...providerFields } = mod;
|
|
12964
|
+
const normalizedProvider = {
|
|
12965
|
+
...providerFields,
|
|
12966
|
+
...extensionIdPattern instanceof RegExp ? { extensionIdPattern } : {}
|
|
12967
|
+
};
|
|
12968
|
+
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
12969
|
+
const scriptsPath = path13.join(d, "scripts.js");
|
|
12645
12970
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
12646
12971
|
try {
|
|
12647
12972
|
delete require.cache[require.resolve(scriptsPath)];
|
|
12648
12973
|
const scripts = require(scriptsPath);
|
|
12649
|
-
|
|
12974
|
+
normalizedProvider.scripts = scripts;
|
|
12650
12975
|
} catch (e) {
|
|
12651
12976
|
this.log(`\u26A0 Failed to load scripts: ${scriptsPath}: ${e.message}`);
|
|
12652
12977
|
}
|
|
12653
12978
|
}
|
|
12654
|
-
const existed = this.providers.has(
|
|
12655
|
-
this.providers.set(
|
|
12979
|
+
const existed = this.providers.has(normalizedProvider.type);
|
|
12980
|
+
this.providers.set(normalizedProvider.type, normalizedProvider);
|
|
12656
12981
|
count++;
|
|
12657
12982
|
const source = d.startsWith(this.userDir) && !d.includes(".upstream") ? "user" : "upstream";
|
|
12658
12983
|
const overrideWarning = existed && source === "user" ? " \u26A0 OVERRIDES upstream" : "";
|
|
12659
|
-
this.log(` ${existed ? "\u{1F504}" : "\u2705"} ${
|
|
12984
|
+
this.log(` ${existed ? "\u{1F504}" : "\u2705"} ${normalizedProvider.type} (${normalizedProvider.category}) \u2014 ${normalizedProvider.name} [${source}]${overrideWarning}`);
|
|
12660
12985
|
}
|
|
12661
12986
|
} catch (e) {
|
|
12662
12987
|
this.log(`\u26A0 Failed to load ${jsonPath}: ${e.message}`);
|
|
@@ -12667,7 +12992,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12667
12992
|
if (!entry.isDirectory()) continue;
|
|
12668
12993
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
12669
12994
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
12670
|
-
scan(
|
|
12995
|
+
scan(path13.join(d, entry.name));
|
|
12671
12996
|
}
|
|
12672
12997
|
}
|
|
12673
12998
|
};
|
|
@@ -12737,9 +13062,9 @@ function getWinProcessNames() {
|
|
|
12737
13062
|
function getProviderMeta(ideId) {
|
|
12738
13063
|
return getProviderLoader().getMeta(ideId);
|
|
12739
13064
|
}
|
|
12740
|
-
function getPreferredLaunchMethod(ideId,
|
|
13065
|
+
function getPreferredLaunchMethod(ideId, platform10) {
|
|
12741
13066
|
const prefer = getProviderMeta(ideId)?.launch?.prefer;
|
|
12742
|
-
const value = prefer?.[
|
|
13067
|
+
const value = prefer?.[platform10];
|
|
12743
13068
|
return value === "cli" || value === "app" || value === "auto" ? value : "auto";
|
|
12744
13069
|
}
|
|
12745
13070
|
function getCdpStartupTimeoutMs(ideId) {
|
|
@@ -12796,7 +13121,7 @@ async function isCdpActive(port) {
|
|
|
12796
13121
|
});
|
|
12797
13122
|
}
|
|
12798
13123
|
async function killIdeProcess(ideId) {
|
|
12799
|
-
const plat =
|
|
13124
|
+
const plat = os14.platform();
|
|
12800
13125
|
const appName = getMacAppIdentifiers()[ideId];
|
|
12801
13126
|
const winProcesses = getWinProcessNames()[ideId];
|
|
12802
13127
|
try {
|
|
@@ -12855,7 +13180,7 @@ async function killIdeProcess(ideId) {
|
|
|
12855
13180
|
}
|
|
12856
13181
|
}
|
|
12857
13182
|
function isIdeRunning(ideId) {
|
|
12858
|
-
const plat =
|
|
13183
|
+
const plat = os14.platform();
|
|
12859
13184
|
try {
|
|
12860
13185
|
if (plat === "darwin") {
|
|
12861
13186
|
const appName = getMacAppIdentifiers()[ideId];
|
|
@@ -12906,7 +13231,7 @@ function isIdeRunning(ideId) {
|
|
|
12906
13231
|
}
|
|
12907
13232
|
}
|
|
12908
13233
|
function detectCurrentWorkspace(ideId) {
|
|
12909
|
-
const plat =
|
|
13234
|
+
const plat = os14.platform();
|
|
12910
13235
|
if (plat === "darwin") {
|
|
12911
13236
|
try {
|
|
12912
13237
|
const appName = getMacAppIdentifiers()[ideId];
|
|
@@ -12925,8 +13250,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12925
13250
|
const appNameMap = getMacAppIdentifiers();
|
|
12926
13251
|
const appName = appNameMap[ideId];
|
|
12927
13252
|
if (appName) {
|
|
12928
|
-
const storagePath =
|
|
12929
|
-
process.env.APPDATA ||
|
|
13253
|
+
const storagePath = path14.join(
|
|
13254
|
+
process.env.APPDATA || path14.join(os14.homedir(), "AppData", "Roaming"),
|
|
12930
13255
|
appName,
|
|
12931
13256
|
"storage.json"
|
|
12932
13257
|
);
|
|
@@ -12948,7 +13273,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12948
13273
|
return void 0;
|
|
12949
13274
|
}
|
|
12950
13275
|
async function launchWithCdp(options = {}) {
|
|
12951
|
-
const
|
|
13276
|
+
const platform10 = os14.platform();
|
|
12952
13277
|
let targetIde;
|
|
12953
13278
|
const ides = await detectIDEs(getProviderLoader());
|
|
12954
13279
|
if (options.ideId) {
|
|
@@ -13017,9 +13342,9 @@ async function launchWithCdp(options = {}) {
|
|
|
13017
13342
|
}
|
|
13018
13343
|
const port = await findFreePort(portPair);
|
|
13019
13344
|
try {
|
|
13020
|
-
if (
|
|
13345
|
+
if (platform10 === "darwin") {
|
|
13021
13346
|
await launchMacOS(targetIde, port, workspace, options.newWindow);
|
|
13022
|
-
} else if (
|
|
13347
|
+
} else if (platform10 === "win32") {
|
|
13023
13348
|
await launchWindows(targetIde, port, workspace, options.newWindow);
|
|
13024
13349
|
} else {
|
|
13025
13350
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
@@ -13104,9 +13429,9 @@ init_logger();
|
|
|
13104
13429
|
|
|
13105
13430
|
// src/logging/command-log.ts
|
|
13106
13431
|
var fs7 = __toESM(require("fs"));
|
|
13107
|
-
var
|
|
13108
|
-
var
|
|
13109
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
13432
|
+
var path15 = __toESM(require("path"));
|
|
13433
|
+
var os15 = __toESM(require("os"));
|
|
13434
|
+
var LOG_DIR2 = process.platform === "win32" ? path15.join(process.env.LOCALAPPDATA || process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path15.join(os15.homedir(), "Library", "Logs", "adhdev") : path15.join(os15.homedir(), ".local", "share", "adhdev", "logs");
|
|
13110
13435
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
13111
13436
|
var MAX_DAYS = 7;
|
|
13112
13437
|
try {
|
|
@@ -13144,13 +13469,13 @@ function getDateStr2() {
|
|
|
13144
13469
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
13145
13470
|
}
|
|
13146
13471
|
var currentDate2 = getDateStr2();
|
|
13147
|
-
var currentFile =
|
|
13472
|
+
var currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
13148
13473
|
var writeCount2 = 0;
|
|
13149
13474
|
function checkRotation() {
|
|
13150
13475
|
const today = getDateStr2();
|
|
13151
13476
|
if (today !== currentDate2) {
|
|
13152
13477
|
currentDate2 = today;
|
|
13153
|
-
currentFile =
|
|
13478
|
+
currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
13154
13479
|
cleanOldFiles();
|
|
13155
13480
|
}
|
|
13156
13481
|
}
|
|
@@ -13164,7 +13489,7 @@ function cleanOldFiles() {
|
|
|
13164
13489
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
13165
13490
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
13166
13491
|
try {
|
|
13167
|
-
fs7.unlinkSync(
|
|
13492
|
+
fs7.unlinkSync(path15.join(LOG_DIR2, file));
|
|
13168
13493
|
} catch {
|
|
13169
13494
|
}
|
|
13170
13495
|
}
|
|
@@ -13241,7 +13566,7 @@ cleanOldFiles();
|
|
|
13241
13566
|
init_logger();
|
|
13242
13567
|
|
|
13243
13568
|
// src/status/snapshot.ts
|
|
13244
|
-
var
|
|
13569
|
+
var os16 = __toESM(require("os"));
|
|
13245
13570
|
init_config();
|
|
13246
13571
|
init_terminal_screen();
|
|
13247
13572
|
init_logger();
|
|
@@ -13361,16 +13686,16 @@ function buildStatusSnapshot(options) {
|
|
|
13361
13686
|
version: options.version,
|
|
13362
13687
|
daemonMode: options.daemonMode,
|
|
13363
13688
|
machine: {
|
|
13364
|
-
hostname:
|
|
13365
|
-
platform:
|
|
13366
|
-
arch:
|
|
13367
|
-
cpus:
|
|
13689
|
+
hostname: os16.hostname(),
|
|
13690
|
+
platform: os16.platform(),
|
|
13691
|
+
arch: os16.arch(),
|
|
13692
|
+
cpus: os16.cpus().length,
|
|
13368
13693
|
totalMem: memSnap.totalMem,
|
|
13369
13694
|
freeMem: memSnap.freeMem,
|
|
13370
13695
|
availableMem: memSnap.availableMem,
|
|
13371
|
-
loadavg:
|
|
13372
|
-
uptime:
|
|
13373
|
-
release:
|
|
13696
|
+
loadavg: os16.loadavg(),
|
|
13697
|
+
uptime: os16.uptime(),
|
|
13698
|
+
release: os16.release()
|
|
13374
13699
|
},
|
|
13375
13700
|
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
13376
13701
|
timestamp: options.timestamp ?? Date.now(),
|
|
@@ -13391,14 +13716,14 @@ function buildStatusSnapshot(options) {
|
|
|
13391
13716
|
var import_child_process7 = require("child_process");
|
|
13392
13717
|
var import_child_process8 = require("child_process");
|
|
13393
13718
|
var fs8 = __toESM(require("fs"));
|
|
13394
|
-
var
|
|
13395
|
-
var
|
|
13719
|
+
var os17 = __toESM(require("os"));
|
|
13720
|
+
var path16 = __toESM(require("path"));
|
|
13396
13721
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
13397
13722
|
function getUpgradeLogPath() {
|
|
13398
|
-
const home =
|
|
13399
|
-
const dir =
|
|
13723
|
+
const home = os17.homedir();
|
|
13724
|
+
const dir = path16.join(home, ".adhdev");
|
|
13400
13725
|
fs8.mkdirSync(dir, { recursive: true });
|
|
13401
|
-
return
|
|
13726
|
+
return path16.join(dir, "daemon-upgrade.log");
|
|
13402
13727
|
}
|
|
13403
13728
|
function appendUpgradeLog(message) {
|
|
13404
13729
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -13438,7 +13763,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
13438
13763
|
}
|
|
13439
13764
|
}
|
|
13440
13765
|
function stopSessionHostProcesses(appName) {
|
|
13441
|
-
const pidFile =
|
|
13766
|
+
const pidFile = path16.join(os17.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
13442
13767
|
try {
|
|
13443
13768
|
if (fs8.existsSync(pidFile)) {
|
|
13444
13769
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -13467,7 +13792,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
13467
13792
|
}
|
|
13468
13793
|
}
|
|
13469
13794
|
function removeDaemonPidFile() {
|
|
13470
|
-
const pidFile =
|
|
13795
|
+
const pidFile = path16.join(os17.homedir(), ".adhdev", "daemon.pid");
|
|
13471
13796
|
try {
|
|
13472
13797
|
fs8.unlinkSync(pidFile);
|
|
13473
13798
|
} catch {
|
|
@@ -13478,7 +13803,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
13478
13803
|
const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
13479
13804
|
if (!npmRoot) return;
|
|
13480
13805
|
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
13481
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
13806
|
+
const binDir = process.platform === "win32" ? npmPrefix : path16.join(npmPrefix, "bin");
|
|
13482
13807
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
13483
13808
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
13484
13809
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -13486,25 +13811,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
13486
13811
|
}
|
|
13487
13812
|
if (pkgName.startsWith("@")) {
|
|
13488
13813
|
const [scope, name] = pkgName.split("/");
|
|
13489
|
-
const scopeDir =
|
|
13814
|
+
const scopeDir = path16.join(npmRoot, scope);
|
|
13490
13815
|
if (!fs8.existsSync(scopeDir)) return;
|
|
13491
13816
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
13492
13817
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
13493
|
-
fs8.rmSync(
|
|
13494
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
13818
|
+
fs8.rmSync(path16.join(scopeDir, entry), { recursive: true, force: true });
|
|
13819
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path16.join(scopeDir, entry)}`);
|
|
13495
13820
|
}
|
|
13496
13821
|
} else {
|
|
13497
13822
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
13498
13823
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
13499
|
-
fs8.rmSync(
|
|
13500
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
13824
|
+
fs8.rmSync(path16.join(npmRoot, entry), { recursive: true, force: true });
|
|
13825
|
+
appendUpgradeLog(`Removed stale staging dir: ${path16.join(npmRoot, entry)}`);
|
|
13501
13826
|
}
|
|
13502
13827
|
}
|
|
13503
13828
|
if (fs8.existsSync(binDir)) {
|
|
13504
13829
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
13505
13830
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
13506
|
-
fs8.rmSync(
|
|
13507
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
13831
|
+
fs8.rmSync(path16.join(binDir, entry), { recursive: true, force: true });
|
|
13832
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path16.join(binDir, entry)}`);
|
|
13508
13833
|
}
|
|
13509
13834
|
}
|
|
13510
13835
|
}
|
|
@@ -13590,6 +13915,18 @@ var CHAT_COMMANDS = [
|
|
|
13590
13915
|
"change_model"
|
|
13591
13916
|
];
|
|
13592
13917
|
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
13918
|
+
function normalizeCommandSource(source) {
|
|
13919
|
+
switch (source) {
|
|
13920
|
+
case "ws":
|
|
13921
|
+
case "p2p":
|
|
13922
|
+
case "ext":
|
|
13923
|
+
case "api":
|
|
13924
|
+
case "standalone":
|
|
13925
|
+
return source;
|
|
13926
|
+
default:
|
|
13927
|
+
return "unknown";
|
|
13928
|
+
}
|
|
13929
|
+
}
|
|
13593
13930
|
function toHostedCliRuntimeDescriptor(record) {
|
|
13594
13931
|
if (!record || typeof record !== "object") return null;
|
|
13595
13932
|
const runtimeId = typeof record.sessionId === "string" ? record.sessionId : "";
|
|
@@ -13627,20 +13964,21 @@ var DaemonCommandRouter = class {
|
|
|
13627
13964
|
*/
|
|
13628
13965
|
async execute(cmd, args, source = "unknown") {
|
|
13629
13966
|
const cmdStart = Date.now();
|
|
13967
|
+
const logSource = normalizeCommandSource(source);
|
|
13630
13968
|
try {
|
|
13631
13969
|
const daemonResult = await this.executeDaemonCommand(cmd, args);
|
|
13632
13970
|
if (daemonResult) {
|
|
13633
|
-
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
|
|
13971
|
+
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source: logSource, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
|
|
13634
13972
|
return daemonResult;
|
|
13635
13973
|
}
|
|
13636
13974
|
const handlerResult = await this.deps.commandHandler.handle(cmd, args);
|
|
13637
|
-
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
|
|
13975
|
+
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source: logSource, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
|
|
13638
13976
|
if (CHAT_COMMANDS.includes(cmd) && this.deps.onPostChatCommand) {
|
|
13639
13977
|
this.deps.onPostChatCommand();
|
|
13640
13978
|
}
|
|
13641
13979
|
return handlerResult;
|
|
13642
13980
|
} catch (e) {
|
|
13643
|
-
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
|
|
13981
|
+
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source: logSource, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
|
|
13644
13982
|
throw e;
|
|
13645
13983
|
}
|
|
13646
13984
|
}
|
|
@@ -13910,7 +14248,7 @@ var DaemonCommandRouter = class {
|
|
|
13910
14248
|
} catch {
|
|
13911
14249
|
}
|
|
13912
14250
|
}
|
|
13913
|
-
return {
|
|
14251
|
+
return { ...result };
|
|
13914
14252
|
}
|
|
13915
14253
|
// ─── Detect IDEs ───
|
|
13916
14254
|
case "detect_ides": {
|
|
@@ -14040,16 +14378,14 @@ var DaemonCommandRouter = class {
|
|
|
14040
14378
|
}
|
|
14041
14379
|
}
|
|
14042
14380
|
for (const instanceKey of keysToRemove) {
|
|
14043
|
-
|
|
14044
|
-
if (ideInstance) {
|
|
14381
|
+
if (this.deps.instanceManager.getInstance(instanceKey)) {
|
|
14045
14382
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
14046
14383
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
14047
14384
|
}
|
|
14048
14385
|
}
|
|
14049
14386
|
if (keysToRemove.length === 0) {
|
|
14050
14387
|
const instanceKey = `ide:${ideType}`;
|
|
14051
|
-
|
|
14052
|
-
if (ideInstance) {
|
|
14388
|
+
if (this.deps.instanceManager.getInstance(instanceKey)) {
|
|
14053
14389
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
14054
14390
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
14055
14391
|
}
|
|
@@ -14264,11 +14600,11 @@ var DaemonStatusReporter = class {
|
|
|
14264
14600
|
// ─── P2P ─────────────────────────────────────────
|
|
14265
14601
|
sendP2PPayload(payload) {
|
|
14266
14602
|
const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
|
|
14267
|
-
|
|
14603
|
+
const hashPayload = hashTarget.machine ? (() => {
|
|
14268
14604
|
const { freeMem: _f, availableMem: _a, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
|
|
14269
|
-
hashTarget
|
|
14270
|
-
}
|
|
14271
|
-
const h = this.simpleHash(JSON.stringify(
|
|
14605
|
+
return { ...hashTarget, machine: stableMachine };
|
|
14606
|
+
})() : hashTarget;
|
|
14607
|
+
const h = this.simpleHash(JSON.stringify(hashPayload));
|
|
14272
14608
|
if (h !== this.lastP2PStatusHash) {
|
|
14273
14609
|
this.lastP2PStatusHash = h;
|
|
14274
14610
|
this.deps.p2p?.sendStatus(payload);
|
|
@@ -14316,6 +14652,9 @@ var ProviderStreamAdapter = class {
|
|
|
14316
14652
|
hasScript(name) {
|
|
14317
14653
|
return typeof this.provider.scripts?.[name] === "function";
|
|
14318
14654
|
}
|
|
14655
|
+
getStateTitle(state) {
|
|
14656
|
+
return typeof state.title === "string" ? state.title : "";
|
|
14657
|
+
}
|
|
14319
14658
|
parseMaybeJson(raw) {
|
|
14320
14659
|
if (typeof raw !== "string") return raw;
|
|
14321
14660
|
try {
|
|
@@ -14519,7 +14858,7 @@ var ProviderStreamAdapter = class {
|
|
|
14519
14858
|
for (let attempt = 0; attempt < 6; attempt += 1) {
|
|
14520
14859
|
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
14521
14860
|
const state = await this.readChat(evaluate);
|
|
14522
|
-
const title =
|
|
14861
|
+
const title = this.getStateTitle(state);
|
|
14523
14862
|
if (this.titlesMatch(title, sessionId)) return true;
|
|
14524
14863
|
}
|
|
14525
14864
|
return false;
|
|
@@ -14616,6 +14955,11 @@ var DaemonAgentStreamManager = class {
|
|
|
14616
14955
|
const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.transport === "cdp-webview" && entry.providerType === agentType);
|
|
14617
14956
|
return child?.sessionId || null;
|
|
14618
14957
|
}
|
|
14958
|
+
getStateError(state) {
|
|
14959
|
+
if (typeof state.error === "string" && state.error.trim()) return state.error.trim();
|
|
14960
|
+
if (typeof state._error === "string" && state._error.trim()) return state._error.trim();
|
|
14961
|
+
return "unknown";
|
|
14962
|
+
}
|
|
14619
14963
|
async connectManagedSession(cdp, parentSessionId, runtimeSessionId) {
|
|
14620
14964
|
const target = this.getSessionTarget(runtimeSessionId);
|
|
14621
14965
|
if (!target || target.transport !== "cdp-webview") return null;
|
|
@@ -14678,8 +15022,8 @@ var DaemonAgentStreamManager = class {
|
|
|
14678
15022
|
try {
|
|
14679
15023
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
14680
15024
|
const state = await agent.adapter.readChat(evaluate);
|
|
14681
|
-
|
|
14682
|
-
|
|
15025
|
+
const stateError = this.getStateError(state);
|
|
15026
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ""}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
14683
15027
|
if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
14684
15028
|
throw new Error(stateError);
|
|
14685
15029
|
}
|
|
@@ -14968,7 +15312,43 @@ var AgentStreamPoller = class {
|
|
|
14968
15312
|
}
|
|
14969
15313
|
try {
|
|
14970
15314
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
14971
|
-
|
|
15315
|
+
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
15316
|
+
if (stream?.status === "waiting_approval") {
|
|
15317
|
+
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
15318
|
+
if (autoApprove && resolvedActiveSessionId) {
|
|
15319
|
+
const provider = providerLoader.getMeta(stream.agentType);
|
|
15320
|
+
const { label: buttonLabel } = pickApprovalButton(stream.activeModal?.buttons, provider);
|
|
15321
|
+
const approved = await agentStreamManager.resolveSessionAction(cdp, resolvedActiveSessionId, "approve", buttonLabel);
|
|
15322
|
+
if (approved) {
|
|
15323
|
+
const effectId = [
|
|
15324
|
+
"auto_approval",
|
|
15325
|
+
resolvedActiveSessionId,
|
|
15326
|
+
String(stream.messages?.length || 0),
|
|
15327
|
+
buttonLabel,
|
|
15328
|
+
String(stream.activeModal?.message || "").trim()
|
|
15329
|
+
].join(":");
|
|
15330
|
+
stream = {
|
|
15331
|
+
...stream,
|
|
15332
|
+
status: "streaming",
|
|
15333
|
+
activeModal: void 0,
|
|
15334
|
+
effects: [
|
|
15335
|
+
...stream.effects || [],
|
|
15336
|
+
{
|
|
15337
|
+
type: "message",
|
|
15338
|
+
id: effectId,
|
|
15339
|
+
persist: true,
|
|
15340
|
+
message: {
|
|
15341
|
+
role: "system",
|
|
15342
|
+
senderName: "System",
|
|
15343
|
+
kind: "system",
|
|
15344
|
+
content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel)
|
|
15345
|
+
}
|
|
15346
|
+
}
|
|
15347
|
+
]
|
|
15348
|
+
};
|
|
15349
|
+
}
|
|
15350
|
+
}
|
|
15351
|
+
}
|
|
14972
15352
|
this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
|
|
14973
15353
|
} catch {
|
|
14974
15354
|
}
|
|
@@ -15212,11 +15592,11 @@ var ProviderInstanceManager = class {
|
|
|
15212
15592
|
|
|
15213
15593
|
// src/providers/version-archive.ts
|
|
15214
15594
|
var fs10 = __toESM(require("fs"));
|
|
15215
|
-
var
|
|
15216
|
-
var
|
|
15595
|
+
var path17 = __toESM(require("path"));
|
|
15596
|
+
var os18 = __toESM(require("os"));
|
|
15217
15597
|
var import_child_process9 = require("child_process");
|
|
15218
15598
|
var import_os3 = require("os");
|
|
15219
|
-
var ARCHIVE_PATH =
|
|
15599
|
+
var ARCHIVE_PATH = path17.join(os18.homedir(), ".adhdev", "version-history.json");
|
|
15220
15600
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
15221
15601
|
var VersionArchive = class {
|
|
15222
15602
|
history = {};
|
|
@@ -15263,7 +15643,7 @@ var VersionArchive = class {
|
|
|
15263
15643
|
}
|
|
15264
15644
|
save() {
|
|
15265
15645
|
try {
|
|
15266
|
-
fs10.mkdirSync(
|
|
15646
|
+
fs10.mkdirSync(path17.dirname(ARCHIVE_PATH), { recursive: true });
|
|
15267
15647
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
15268
15648
|
} catch {
|
|
15269
15649
|
}
|
|
@@ -15289,6 +15669,22 @@ function parseVersion2(raw) {
|
|
|
15289
15669
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
15290
15670
|
return match ? match[1] : raw.split("\n")[0].substring(0, 100);
|
|
15291
15671
|
}
|
|
15672
|
+
function getPlatformVersionCommand(versionCommand, currentOs) {
|
|
15673
|
+
if (!versionCommand) return void 0;
|
|
15674
|
+
if (typeof versionCommand === "string") {
|
|
15675
|
+
const trimmed = versionCommand.trim();
|
|
15676
|
+
return trimmed || void 0;
|
|
15677
|
+
}
|
|
15678
|
+
const platformValue = versionCommand[currentOs];
|
|
15679
|
+
if (typeof platformValue === "string" && platformValue.trim()) {
|
|
15680
|
+
return platformValue.trim();
|
|
15681
|
+
}
|
|
15682
|
+
const defaultValue = versionCommand.default;
|
|
15683
|
+
if (typeof defaultValue === "string" && defaultValue.trim()) {
|
|
15684
|
+
return defaultValue.trim();
|
|
15685
|
+
}
|
|
15686
|
+
return void 0;
|
|
15687
|
+
}
|
|
15292
15688
|
function getVersion(binary, versionCommand) {
|
|
15293
15689
|
if (versionCommand) {
|
|
15294
15690
|
const raw = runCommand(versionCommand);
|
|
@@ -15303,8 +15699,8 @@ function getVersion(binary, versionCommand) {
|
|
|
15303
15699
|
function checkPathExists2(paths) {
|
|
15304
15700
|
for (const p of paths) {
|
|
15305
15701
|
if (p.includes("*")) {
|
|
15306
|
-
const home =
|
|
15307
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
15702
|
+
const home = os18.homedir();
|
|
15703
|
+
const resolved = p.replace(/\*/g, home.split(path17.sep).pop() || "");
|
|
15308
15704
|
if (fs10.existsSync(resolved)) return resolved;
|
|
15309
15705
|
} else {
|
|
15310
15706
|
if (fs10.existsSync(p)) return p;
|
|
@@ -15314,7 +15710,7 @@ function checkPathExists2(paths) {
|
|
|
15314
15710
|
}
|
|
15315
15711
|
function getMacAppVersion(appPath) {
|
|
15316
15712
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
15317
|
-
const plistPath =
|
|
15713
|
+
const plistPath = path17.join(appPath, "Contents", "Info.plist");
|
|
15318
15714
|
if (!fs10.existsSync(plistPath)) return null;
|
|
15319
15715
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
15320
15716
|
return raw || null;
|
|
@@ -15333,15 +15729,14 @@ async function detectAllVersions(loader, archive) {
|
|
|
15333
15729
|
binary: null,
|
|
15334
15730
|
detectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15335
15731
|
};
|
|
15336
|
-
const
|
|
15337
|
-
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[currentOs] : verCmdConfig;
|
|
15732
|
+
const versionCommand = getPlatformVersionCommand(provider.versionCommand, currentOs);
|
|
15338
15733
|
if (provider.category === "ide") {
|
|
15339
15734
|
const osPaths = provider.paths?.[currentOs] || [];
|
|
15340
15735
|
const appPath = checkPathExists2(osPaths);
|
|
15341
15736
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
15342
15737
|
let resolvedBin = cliBin;
|
|
15343
15738
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
15344
|
-
const bundled =
|
|
15739
|
+
const bundled = path17.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
15345
15740
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
15346
15741
|
}
|
|
15347
15742
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -15382,7 +15777,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
15382
15777
|
// src/daemon/dev-server.ts
|
|
15383
15778
|
var http2 = __toESM(require("http"));
|
|
15384
15779
|
var fs14 = __toESM(require("fs"));
|
|
15385
|
-
var
|
|
15780
|
+
var path21 = __toESM(require("path"));
|
|
15386
15781
|
|
|
15387
15782
|
// src/daemon/scaffold-template.ts
|
|
15388
15783
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -15718,7 +16113,7 @@ init_logger();
|
|
|
15718
16113
|
|
|
15719
16114
|
// src/daemon/dev-cdp-handlers.ts
|
|
15720
16115
|
var fs11 = __toESM(require("fs"));
|
|
15721
|
-
var
|
|
16116
|
+
var path18 = __toESM(require("path"));
|
|
15722
16117
|
init_logger();
|
|
15723
16118
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
15724
16119
|
const body = await ctx.readBody(req);
|
|
@@ -15897,17 +16292,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
15897
16292
|
return;
|
|
15898
16293
|
}
|
|
15899
16294
|
let scriptsPath = "";
|
|
15900
|
-
const directScripts =
|
|
16295
|
+
const directScripts = path18.join(dir, "scripts.js");
|
|
15901
16296
|
if (fs11.existsSync(directScripts)) {
|
|
15902
16297
|
scriptsPath = directScripts;
|
|
15903
16298
|
} else {
|
|
15904
|
-
const scriptsDir =
|
|
16299
|
+
const scriptsDir = path18.join(dir, "scripts");
|
|
15905
16300
|
if (fs11.existsSync(scriptsDir)) {
|
|
15906
16301
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
15907
|
-
return fs11.statSync(
|
|
16302
|
+
return fs11.statSync(path18.join(scriptsDir, d)).isDirectory();
|
|
15908
16303
|
}).sort().reverse();
|
|
15909
16304
|
for (const ver of versions) {
|
|
15910
|
-
const p =
|
|
16305
|
+
const p = path18.join(scriptsDir, ver, "scripts.js");
|
|
15911
16306
|
if (fs11.existsSync(p)) {
|
|
15912
16307
|
scriptsPath = p;
|
|
15913
16308
|
break;
|
|
@@ -16726,7 +17121,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
16726
17121
|
|
|
16727
17122
|
// src/daemon/dev-cli-debug.ts
|
|
16728
17123
|
var fs12 = __toESM(require("fs"));
|
|
16729
|
-
var
|
|
17124
|
+
var path19 = __toESM(require("path"));
|
|
16730
17125
|
function slugifyFixtureName(value) {
|
|
16731
17126
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
16732
17127
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -16736,11 +17131,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
16736
17131
|
if (!providerDir) {
|
|
16737
17132
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
16738
17133
|
}
|
|
16739
|
-
return
|
|
17134
|
+
return path19.join(providerDir, "fixtures");
|
|
16740
17135
|
}
|
|
16741
17136
|
function readCliFixture(ctx, type, name) {
|
|
16742
17137
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
16743
|
-
const filePath =
|
|
17138
|
+
const filePath = path19.join(fixtureDir, `${name}.json`);
|
|
16744
17139
|
if (!fs12.existsSync(filePath)) {
|
|
16745
17140
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
16746
17141
|
}
|
|
@@ -16866,6 +17261,15 @@ function validateCliFixtureResult(result, assertions) {
|
|
|
16866
17261
|
}
|
|
16867
17262
|
return failures;
|
|
16868
17263
|
}
|
|
17264
|
+
function isCliTargetState(state) {
|
|
17265
|
+
return state.category === "cli" || state.category === "acp";
|
|
17266
|
+
}
|
|
17267
|
+
function getCliAdapterFromInstance(instance) {
|
|
17268
|
+
if (!instance) return null;
|
|
17269
|
+
const candidate = instance;
|
|
17270
|
+
if (typeof candidate.getAdapter === "function") return candidate.getAdapter();
|
|
17271
|
+
return candidate.adapter || null;
|
|
17272
|
+
}
|
|
16869
17273
|
function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
16870
17274
|
const adapterMeta = typeof adapter?.getProviderResolutionMeta === "function" ? adapter.getProviderResolutionMeta() : adapter?.getDebugState?.()?.providerResolution || null;
|
|
16871
17275
|
const resolvedProvider = ctx.providerLoader.resolve(type);
|
|
@@ -16883,7 +17287,7 @@ function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
|
16883
17287
|
}
|
|
16884
17288
|
function findCliTarget(ctx, type, instanceId) {
|
|
16885
17289
|
if (!ctx.instanceManager) return null;
|
|
16886
|
-
const cliStates = ctx.instanceManager.collectAllStates().filter(
|
|
17290
|
+
const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
|
|
16887
17291
|
if (instanceId) return cliStates.find((s) => s.instanceId === instanceId) || null;
|
|
16888
17292
|
if (!type) return cliStates[cliStates.length - 1] || null;
|
|
16889
17293
|
const matches = cliStates.filter((s) => s.type === type);
|
|
@@ -16895,7 +17299,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
16895
17299
|
if (!target) return null;
|
|
16896
17300
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
16897
17301
|
if (!instance) return null;
|
|
16898
|
-
const adapter = instance
|
|
17302
|
+
const adapter = getCliAdapterFromInstance(instance);
|
|
16899
17303
|
if (!adapter) return null;
|
|
16900
17304
|
return { target, instance, adapter };
|
|
16901
17305
|
}
|
|
@@ -17370,7 +17774,7 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
17370
17774
|
return;
|
|
17371
17775
|
}
|
|
17372
17776
|
try {
|
|
17373
|
-
const adapter = instance
|
|
17777
|
+
const adapter = getCliAdapterFromInstance(instance);
|
|
17374
17778
|
if (adapter && typeof adapter.getDebugState === "function") {
|
|
17375
17779
|
const debugState = adapter.getDebugState();
|
|
17376
17780
|
ctx.json(res, 200, {
|
|
@@ -17417,7 +17821,7 @@ async function handleCliTrace(ctx, type, req, res) {
|
|
|
17417
17821
|
return;
|
|
17418
17822
|
}
|
|
17419
17823
|
try {
|
|
17420
|
-
const adapter = instance
|
|
17824
|
+
const adapter = getCliAdapterFromInstance(instance);
|
|
17421
17825
|
const url = new URL(req.url || "/", "http://127.0.0.1");
|
|
17422
17826
|
const limit = parseInt(url.searchParams.get("limit") || "120", 10);
|
|
17423
17827
|
if (adapter && typeof adapter.getTraceState === "function") {
|
|
@@ -17499,7 +17903,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
17499
17903
|
},
|
|
17500
17904
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
17501
17905
|
};
|
|
17502
|
-
const filePath =
|
|
17906
|
+
const filePath = path19.join(fixtureDir, `${name}.json`);
|
|
17503
17907
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
17504
17908
|
ctx.json(res, 200, {
|
|
17505
17909
|
saved: true,
|
|
@@ -17523,7 +17927,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
17523
17927
|
return;
|
|
17524
17928
|
}
|
|
17525
17929
|
const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
17526
|
-
const fullPath =
|
|
17930
|
+
const fullPath = path19.join(fixtureDir, file);
|
|
17527
17931
|
try {
|
|
17528
17932
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
17529
17933
|
return {
|
|
@@ -17603,7 +18007,7 @@ async function handleCliResolve(ctx, req, res) {
|
|
|
17603
18007
|
return;
|
|
17604
18008
|
}
|
|
17605
18009
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
17606
|
-
const adapter = instance
|
|
18010
|
+
const adapter = getCliAdapterFromInstance(instance);
|
|
17607
18011
|
if (!adapter) {
|
|
17608
18012
|
ctx.json(res, 404, { error: `Adapter not found for instance: ${target.instanceId}` });
|
|
17609
18013
|
return;
|
|
@@ -17640,7 +18044,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
17640
18044
|
return;
|
|
17641
18045
|
}
|
|
17642
18046
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
17643
|
-
const adapter = instance
|
|
18047
|
+
const adapter = getCliAdapterFromInstance(instance);
|
|
17644
18048
|
if (!adapter) {
|
|
17645
18049
|
ctx.json(res, 404, { error: `Adapter not found for instance: ${target.instanceId}` });
|
|
17646
18050
|
return;
|
|
@@ -17659,11 +18063,11 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
17659
18063
|
|
|
17660
18064
|
// src/daemon/dev-auto-implement.ts
|
|
17661
18065
|
var fs13 = __toESM(require("fs"));
|
|
17662
|
-
var
|
|
17663
|
-
var
|
|
18066
|
+
var path20 = __toESM(require("path"));
|
|
18067
|
+
var os19 = __toESM(require("os"));
|
|
17664
18068
|
function getAutoImplPid(ctx) {
|
|
17665
|
-
const
|
|
17666
|
-
return
|
|
18069
|
+
const pid = ctx.autoImplProcess?.pid;
|
|
18070
|
+
return typeof pid === "number" && pid > 0 ? pid : null;
|
|
17667
18071
|
}
|
|
17668
18072
|
function isPidAlive(pid) {
|
|
17669
18073
|
try {
|
|
@@ -17681,6 +18085,13 @@ function clearStaleAutoImplState(ctx, reason) {
|
|
|
17681
18085
|
ctx.autoImplProcess = null;
|
|
17682
18086
|
ctx.autoImplStatus.running = false;
|
|
17683
18087
|
}
|
|
18088
|
+
function tryKillAutoImplProcess(processRef, signal) {
|
|
18089
|
+
if (!processRef) return;
|
|
18090
|
+
try {
|
|
18091
|
+
processRef.kill(signal);
|
|
18092
|
+
} catch {
|
|
18093
|
+
}
|
|
18094
|
+
}
|
|
17684
18095
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
17685
18096
|
if (category === "cli") {
|
|
17686
18097
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -17699,22 +18110,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
17699
18110
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
17700
18111
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
17701
18112
|
try {
|
|
17702
|
-
return fs13.statSync(
|
|
18113
|
+
return fs13.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
17703
18114
|
} catch {
|
|
17704
18115
|
return false;
|
|
17705
18116
|
}
|
|
17706
18117
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
17707
18118
|
if (versions.length === 0) return null;
|
|
17708
|
-
return
|
|
18119
|
+
return path20.join(scriptsDir, versions[0]);
|
|
17709
18120
|
}
|
|
17710
18121
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
17711
|
-
const canonicalUserDir =
|
|
17712
|
-
const desiredDir = requestedDir ?
|
|
17713
|
-
const upstreamRoot =
|
|
17714
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
18122
|
+
const canonicalUserDir = path20.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
18123
|
+
const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
|
|
18124
|
+
const upstreamRoot = path20.resolve(ctx.providerLoader.getUpstreamDir());
|
|
18125
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
|
|
17715
18126
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
17716
18127
|
}
|
|
17717
|
-
if (
|
|
18128
|
+
if (path20.basename(desiredDir) !== type) {
|
|
17718
18129
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
17719
18130
|
}
|
|
17720
18131
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -17722,11 +18133,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
17722
18133
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
17723
18134
|
}
|
|
17724
18135
|
if (!fs13.existsSync(desiredDir)) {
|
|
17725
|
-
fs13.mkdirSync(
|
|
18136
|
+
fs13.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
17726
18137
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
17727
18138
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
17728
18139
|
}
|
|
17729
|
-
const providerJson =
|
|
18140
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
17730
18141
|
if (!fs13.existsSync(providerJson)) {
|
|
17731
18142
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
17732
18143
|
}
|
|
@@ -17749,13 +18160,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
17749
18160
|
const refDir = ctx.findProviderDir(referenceType);
|
|
17750
18161
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
17751
18162
|
const referenceScripts = {};
|
|
17752
|
-
const scriptsDir =
|
|
18163
|
+
const scriptsDir = path20.join(refDir, "scripts");
|
|
17753
18164
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
17754
18165
|
if (!latestDir) return referenceScripts;
|
|
17755
18166
|
for (const file of fs13.readdirSync(latestDir)) {
|
|
17756
18167
|
if (!file.endsWith(".js")) continue;
|
|
17757
18168
|
try {
|
|
17758
|
-
referenceScripts[file] = fs13.readFileSync(
|
|
18169
|
+
referenceScripts[file] = fs13.readFileSync(path20.join(latestDir, file), "utf-8");
|
|
17759
18170
|
} catch {
|
|
17760
18171
|
}
|
|
17761
18172
|
}
|
|
@@ -17863,9 +18274,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
17863
18274
|
});
|
|
17864
18275
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
17865
18276
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
17866
|
-
const tmpDir =
|
|
18277
|
+
const tmpDir = path20.join(os19.tmpdir(), "adhdev-autoimpl");
|
|
17867
18278
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
17868
|
-
const promptFile =
|
|
18279
|
+
const promptFile = path20.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
17869
18280
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
17870
18281
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
17871
18282
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -18017,7 +18428,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
18017
18428
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
18018
18429
|
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
18019
18430
|
let shellCmd;
|
|
18020
|
-
const isWin =
|
|
18431
|
+
const isWin = os19.platform() === "win32";
|
|
18021
18432
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
18022
18433
|
if (command === "claude") {
|
|
18023
18434
|
const args = [...baseArgs, "--dangerously-skip-permissions"];
|
|
@@ -18061,7 +18472,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
18061
18472
|
try {
|
|
18062
18473
|
const pty = require("node-pty");
|
|
18063
18474
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
18064
|
-
const isWin2 =
|
|
18475
|
+
const isWin2 = os19.platform() === "win32";
|
|
18065
18476
|
child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
18066
18477
|
name: "xterm-256color",
|
|
18067
18478
|
cols: 120,
|
|
@@ -18100,10 +18511,12 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
18100
18511
|
let autoStopTimer = null;
|
|
18101
18512
|
let autoStopIssued = false;
|
|
18102
18513
|
try {
|
|
18103
|
-
|
|
18104
|
-
|
|
18105
|
-
|
|
18106
|
-
|
|
18514
|
+
if (agentProvider?.category === "cli") {
|
|
18515
|
+
const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
|
|
18516
|
+
const normalized = normalizeCliProviderForRuntime2(agentProvider);
|
|
18517
|
+
approvalPatterns = normalized.patterns.approval;
|
|
18518
|
+
approvalKeys = agentProvider.approvalKeys || { 0: "y\r", 1: "a\r" };
|
|
18519
|
+
}
|
|
18107
18520
|
} catch (err) {
|
|
18108
18521
|
ctx.log(`Failed to load approval patterns: ${err.message}`);
|
|
18109
18522
|
}
|
|
@@ -18118,10 +18531,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
18118
18531
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
18119
18532
|
`, stream: "stdout" } });
|
|
18120
18533
|
approvalBuffer = "";
|
|
18121
|
-
|
|
18122
|
-
ctx.autoImplProcess.kill("SIGINT");
|
|
18123
|
-
} catch {
|
|
18124
|
-
}
|
|
18534
|
+
tryKillAutoImplProcess(ctx.autoImplProcess, "SIGINT");
|
|
18125
18535
|
return;
|
|
18126
18536
|
}
|
|
18127
18537
|
if (Date.now() - lastApprovalTime < 2e3) return;
|
|
@@ -18158,10 +18568,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
18158
18568
|
stream: "stdout"
|
|
18159
18569
|
}
|
|
18160
18570
|
});
|
|
18161
|
-
|
|
18162
|
-
ctx.autoImplProcess.kill("SIGINT");
|
|
18163
|
-
} catch {
|
|
18164
|
-
}
|
|
18571
|
+
tryKillAutoImplProcess(ctx.autoImplProcess, "SIGINT");
|
|
18165
18572
|
}, 3e4);
|
|
18166
18573
|
};
|
|
18167
18574
|
const finalizeCliAutoImpl = async (code) => {
|
|
@@ -18292,7 +18699,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
18292
18699
|
setMode: "set_mode.js"
|
|
18293
18700
|
};
|
|
18294
18701
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
18295
|
-
const scriptsDir =
|
|
18702
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
18296
18703
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
18297
18704
|
if (latestScriptsDir) {
|
|
18298
18705
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -18303,7 +18710,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
18303
18710
|
for (const file of fs13.readdirSync(latestScriptsDir)) {
|
|
18304
18711
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
18305
18712
|
try {
|
|
18306
|
-
const content = fs13.readFileSync(
|
|
18713
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
18307
18714
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
18308
18715
|
lines.push("```javascript");
|
|
18309
18716
|
lines.push(content);
|
|
@@ -18320,7 +18727,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
18320
18727
|
lines.push("");
|
|
18321
18728
|
for (const file of refFiles) {
|
|
18322
18729
|
try {
|
|
18323
|
-
const content = fs13.readFileSync(
|
|
18730
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
18324
18731
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
18325
18732
|
lines.push("```javascript");
|
|
18326
18733
|
lines.push(content);
|
|
@@ -18361,10 +18768,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
18361
18768
|
lines.push("");
|
|
18362
18769
|
}
|
|
18363
18770
|
}
|
|
18364
|
-
const docsDir =
|
|
18771
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
18365
18772
|
const loadGuide = (name) => {
|
|
18366
18773
|
try {
|
|
18367
|
-
const p =
|
|
18774
|
+
const p = path20.join(docsDir, name);
|
|
18368
18775
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
18369
18776
|
} catch {
|
|
18370
18777
|
}
|
|
@@ -18599,7 +19006,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18599
19006
|
parseApproval: "parse_approval.js"
|
|
18600
19007
|
};
|
|
18601
19008
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
18602
|
-
const scriptsDir =
|
|
19009
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
18603
19010
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
18604
19011
|
if (latestScriptsDir) {
|
|
18605
19012
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -18611,7 +19018,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18611
19018
|
if (!file.endsWith(".js")) continue;
|
|
18612
19019
|
if (!targetFileNames.has(file)) continue;
|
|
18613
19020
|
try {
|
|
18614
|
-
const content = fs13.readFileSync(
|
|
19021
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
18615
19022
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
18616
19023
|
lines.push("```javascript");
|
|
18617
19024
|
lines.push(content);
|
|
@@ -18627,7 +19034,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18627
19034
|
lines.push("");
|
|
18628
19035
|
for (const file of refFiles) {
|
|
18629
19036
|
try {
|
|
18630
|
-
const content = fs13.readFileSync(
|
|
19037
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
18631
19038
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
18632
19039
|
lines.push("```javascript");
|
|
18633
19040
|
lines.push(content);
|
|
@@ -18660,10 +19067,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18660
19067
|
lines.push("");
|
|
18661
19068
|
}
|
|
18662
19069
|
}
|
|
18663
|
-
const docsDir =
|
|
19070
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
18664
19071
|
const loadGuide = (name) => {
|
|
18665
19072
|
try {
|
|
18666
|
-
const p =
|
|
19073
|
+
const p = path20.join(docsDir, name);
|
|
18667
19074
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
18668
19075
|
} catch {
|
|
18669
19076
|
}
|
|
@@ -18978,6 +19385,38 @@ data: ${JSON.stringify(msg.data)}
|
|
|
18978
19385
|
|
|
18979
19386
|
// src/daemon/dev-server.ts
|
|
18980
19387
|
var DEV_SERVER_PORT = 19280;
|
|
19388
|
+
function getScriptNames(scripts) {
|
|
19389
|
+
if (!scripts) return [];
|
|
19390
|
+
return Object.entries(scripts).filter(([, value]) => typeof value === "function").map(([name]) => name);
|
|
19391
|
+
}
|
|
19392
|
+
function toProviderListEntry(provider) {
|
|
19393
|
+
const base = {
|
|
19394
|
+
type: provider.type,
|
|
19395
|
+
name: provider.name,
|
|
19396
|
+
category: provider.category,
|
|
19397
|
+
icon: provider.icon || null,
|
|
19398
|
+
displayName: provider.displayName || provider.name
|
|
19399
|
+
};
|
|
19400
|
+
if (provider.category === "ide" || provider.category === "extension") {
|
|
19401
|
+
base.scripts = getScriptNames(provider.scripts);
|
|
19402
|
+
base.inputMethod = provider.inputMethod || null;
|
|
19403
|
+
base.inputSelector = provider.inputSelector || null;
|
|
19404
|
+
base.extensionId = provider.extensionId || null;
|
|
19405
|
+
base.cdpPorts = provider.cdpPorts || [];
|
|
19406
|
+
}
|
|
19407
|
+
if (provider.category === "acp") {
|
|
19408
|
+
base.spawn = provider.spawn || null;
|
|
19409
|
+
base.auth = provider.auth || null;
|
|
19410
|
+
base.install = provider.install || null;
|
|
19411
|
+
base.hasSettings = !!provider.settings;
|
|
19412
|
+
base.settingsCount = provider.settings ? Object.keys(provider.settings).length : 0;
|
|
19413
|
+
}
|
|
19414
|
+
if (provider.category === "cli") {
|
|
19415
|
+
base.spawn = provider.spawn || null;
|
|
19416
|
+
base.install = provider.install || null;
|
|
19417
|
+
}
|
|
19418
|
+
return base;
|
|
19419
|
+
}
|
|
18981
19420
|
var DevServer = class _DevServer {
|
|
18982
19421
|
server = null;
|
|
18983
19422
|
providerLoader;
|
|
@@ -19074,8 +19513,8 @@ var DevServer = class _DevServer {
|
|
|
19074
19513
|
}
|
|
19075
19514
|
getEndpointList() {
|
|
19076
19515
|
return this.routes.map((r) => {
|
|
19077
|
-
const
|
|
19078
|
-
return `${r.method.padEnd(5)} ${
|
|
19516
|
+
const path22 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
19517
|
+
return `${r.method.padEnd(5)} ${path22}`;
|
|
19079
19518
|
});
|
|
19080
19519
|
}
|
|
19081
19520
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -19127,34 +19566,7 @@ var DevServer = class _DevServer {
|
|
|
19127
19566
|
}
|
|
19128
19567
|
// ─── Handlers ───
|
|
19129
19568
|
async handleListProviders(_req, res) {
|
|
19130
|
-
const providers = this.providerLoader.getAll().map(
|
|
19131
|
-
const base = {
|
|
19132
|
-
type: p.type,
|
|
19133
|
-
name: p.name,
|
|
19134
|
-
category: p.category,
|
|
19135
|
-
icon: p.icon || null,
|
|
19136
|
-
displayName: p.displayName || p.name
|
|
19137
|
-
};
|
|
19138
|
-
if (p.category === "ide" || p.category === "extension") {
|
|
19139
|
-
base.scripts = p.scripts ? Object.keys(p.scripts).filter((k) => typeof p.scripts[k] === "function") : [];
|
|
19140
|
-
base.inputMethod = p.inputMethod || null;
|
|
19141
|
-
base.inputSelector = p.inputSelector || null;
|
|
19142
|
-
base.extensionId = p.extensionId || null;
|
|
19143
|
-
base.cdpPorts = p.cdpPorts || [];
|
|
19144
|
-
}
|
|
19145
|
-
if (p.category === "acp") {
|
|
19146
|
-
base.spawn = p.spawn || null;
|
|
19147
|
-
base.auth = p.auth || null;
|
|
19148
|
-
base.install = p.install || null;
|
|
19149
|
-
base.hasSettings = !!p.settings;
|
|
19150
|
-
base.settingsCount = p.settings ? Object.keys(p.settings).length : 0;
|
|
19151
|
-
}
|
|
19152
|
-
if (p.category === "cli") {
|
|
19153
|
-
base.spawn = p.spawn || null;
|
|
19154
|
-
base.install = p.install || null;
|
|
19155
|
-
}
|
|
19156
|
-
return base;
|
|
19157
|
-
});
|
|
19569
|
+
const providers = this.providerLoader.getAll().map(toProviderListEntry);
|
|
19158
19570
|
this.json(res, 200, { providers, count: providers.length });
|
|
19159
19571
|
}
|
|
19160
19572
|
async handleProviderConfig(type, _req, res) {
|
|
@@ -19346,7 +19758,7 @@ var DevServer = class _DevServer {
|
|
|
19346
19758
|
}));
|
|
19347
19759
|
for (const cdp of this.cdpManagers.values()) {
|
|
19348
19760
|
if (!cdp.isConnected) {
|
|
19349
|
-
cdp.
|
|
19761
|
+
cdp.clearTargetId();
|
|
19350
19762
|
}
|
|
19351
19763
|
}
|
|
19352
19764
|
this.json(res, 200, { reloaded: true, providers });
|
|
@@ -19357,12 +19769,12 @@ var DevServer = class _DevServer {
|
|
|
19357
19769
|
// ─── DevConsole SPA ───
|
|
19358
19770
|
getConsoleDistDir() {
|
|
19359
19771
|
const candidates = [
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19772
|
+
path21.resolve(__dirname, "../../web-devconsole/dist"),
|
|
19773
|
+
path21.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
19774
|
+
path21.join(process.cwd(), "packages/web-devconsole/dist")
|
|
19363
19775
|
];
|
|
19364
19776
|
for (const dir of candidates) {
|
|
19365
|
-
if (fs14.existsSync(
|
|
19777
|
+
if (fs14.existsSync(path21.join(dir, "index.html"))) return dir;
|
|
19366
19778
|
}
|
|
19367
19779
|
return null;
|
|
19368
19780
|
}
|
|
@@ -19372,7 +19784,7 @@ var DevServer = class _DevServer {
|
|
|
19372
19784
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
19373
19785
|
return;
|
|
19374
19786
|
}
|
|
19375
|
-
const htmlPath =
|
|
19787
|
+
const htmlPath = path21.join(distDir, "index.html");
|
|
19376
19788
|
try {
|
|
19377
19789
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
19378
19790
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -19397,15 +19809,15 @@ var DevServer = class _DevServer {
|
|
|
19397
19809
|
this.json(res, 404, { error: "Not found" });
|
|
19398
19810
|
return;
|
|
19399
19811
|
}
|
|
19400
|
-
const safePath =
|
|
19401
|
-
const filePath =
|
|
19812
|
+
const safePath = path21.normalize(pathname).replace(/^\.\.\//, "");
|
|
19813
|
+
const filePath = path21.join(distDir, safePath);
|
|
19402
19814
|
if (!filePath.startsWith(distDir)) {
|
|
19403
19815
|
this.json(res, 403, { error: "Forbidden" });
|
|
19404
19816
|
return;
|
|
19405
19817
|
}
|
|
19406
19818
|
try {
|
|
19407
19819
|
const content = fs14.readFileSync(filePath);
|
|
19408
|
-
const ext =
|
|
19820
|
+
const ext = path21.extname(filePath);
|
|
19409
19821
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
19410
19822
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
19411
19823
|
res.end(content);
|
|
@@ -19518,9 +19930,9 @@ var DevServer = class _DevServer {
|
|
|
19518
19930
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
19519
19931
|
if (entry.isDirectory()) {
|
|
19520
19932
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
19521
|
-
scan(
|
|
19933
|
+
scan(path21.join(d, entry.name), rel);
|
|
19522
19934
|
} else {
|
|
19523
|
-
const stat = fs14.statSync(
|
|
19935
|
+
const stat = fs14.statSync(path21.join(d, entry.name));
|
|
19524
19936
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
19525
19937
|
}
|
|
19526
19938
|
}
|
|
@@ -19543,7 +19955,7 @@ var DevServer = class _DevServer {
|
|
|
19543
19955
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
19544
19956
|
return;
|
|
19545
19957
|
}
|
|
19546
|
-
const fullPath =
|
|
19958
|
+
const fullPath = path21.resolve(dir, path21.normalize(filePath));
|
|
19547
19959
|
if (!fullPath.startsWith(dir)) {
|
|
19548
19960
|
this.json(res, 403, { error: "Forbidden" });
|
|
19549
19961
|
return;
|
|
@@ -19568,14 +19980,14 @@ var DevServer = class _DevServer {
|
|
|
19568
19980
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
19569
19981
|
return;
|
|
19570
19982
|
}
|
|
19571
|
-
const fullPath =
|
|
19983
|
+
const fullPath = path21.resolve(dir, path21.normalize(filePath));
|
|
19572
19984
|
if (!fullPath.startsWith(dir)) {
|
|
19573
19985
|
this.json(res, 403, { error: "Forbidden" });
|
|
19574
19986
|
return;
|
|
19575
19987
|
}
|
|
19576
19988
|
try {
|
|
19577
19989
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
19578
|
-
fs14.mkdirSync(
|
|
19990
|
+
fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
|
|
19579
19991
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
19580
19992
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
19581
19993
|
this.providerLoader.reload();
|
|
@@ -19592,7 +20004,7 @@ var DevServer = class _DevServer {
|
|
|
19592
20004
|
return;
|
|
19593
20005
|
}
|
|
19594
20006
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
19595
|
-
const p =
|
|
20007
|
+
const p = path21.join(dir, name);
|
|
19596
20008
|
if (fs14.existsSync(p)) {
|
|
19597
20009
|
const source = fs14.readFileSync(p, "utf-8");
|
|
19598
20010
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -19613,8 +20025,8 @@ var DevServer = class _DevServer {
|
|
|
19613
20025
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
19614
20026
|
return;
|
|
19615
20027
|
}
|
|
19616
|
-
const target = fs14.existsSync(
|
|
19617
|
-
const targetPath =
|
|
20028
|
+
const target = fs14.existsSync(path21.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
20029
|
+
const targetPath = path21.join(dir, target);
|
|
19618
20030
|
try {
|
|
19619
20031
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
19620
20032
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -19774,7 +20186,7 @@ var DevServer = class _DevServer {
|
|
|
19774
20186
|
}
|
|
19775
20187
|
let targetDir;
|
|
19776
20188
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
19777
|
-
const jsonPath =
|
|
20189
|
+
const jsonPath = path21.join(targetDir, "provider.json");
|
|
19778
20190
|
if (fs14.existsSync(jsonPath)) {
|
|
19779
20191
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
19780
20192
|
return;
|
|
@@ -19786,8 +20198,8 @@ var DevServer = class _DevServer {
|
|
|
19786
20198
|
const createdFiles = ["provider.json"];
|
|
19787
20199
|
if (result.files) {
|
|
19788
20200
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
19789
|
-
const fullPath =
|
|
19790
|
-
fs14.mkdirSync(
|
|
20201
|
+
const fullPath = path21.join(targetDir, relPath);
|
|
20202
|
+
fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
|
|
19791
20203
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
19792
20204
|
createdFiles.push(relPath);
|
|
19793
20205
|
}
|
|
@@ -19840,22 +20252,22 @@ var DevServer = class _DevServer {
|
|
|
19840
20252
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
19841
20253
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
19842
20254
|
try {
|
|
19843
|
-
return fs14.statSync(
|
|
20255
|
+
return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
|
|
19844
20256
|
} catch {
|
|
19845
20257
|
return false;
|
|
19846
20258
|
}
|
|
19847
20259
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
19848
20260
|
if (versions.length === 0) return null;
|
|
19849
|
-
return
|
|
20261
|
+
return path21.join(scriptsDir, versions[0]);
|
|
19850
20262
|
}
|
|
19851
20263
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
19852
|
-
const canonicalUserDir =
|
|
19853
|
-
const desiredDir = requestedDir ?
|
|
19854
|
-
const upstreamRoot =
|
|
19855
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
20264
|
+
const canonicalUserDir = path21.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
20265
|
+
const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
|
|
20266
|
+
const upstreamRoot = path21.resolve(this.providerLoader.getUpstreamDir());
|
|
20267
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
|
|
19856
20268
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
19857
20269
|
}
|
|
19858
|
-
if (
|
|
20270
|
+
if (path21.basename(desiredDir) !== type) {
|
|
19859
20271
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
19860
20272
|
}
|
|
19861
20273
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -19863,11 +20275,11 @@ var DevServer = class _DevServer {
|
|
|
19863
20275
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
19864
20276
|
}
|
|
19865
20277
|
if (!fs14.existsSync(desiredDir)) {
|
|
19866
|
-
fs14.mkdirSync(
|
|
20278
|
+
fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
|
|
19867
20279
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
19868
20280
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
19869
20281
|
}
|
|
19870
|
-
const providerJson =
|
|
20282
|
+
const providerJson = path21.join(desiredDir, "provider.json");
|
|
19871
20283
|
if (!fs14.existsSync(providerJson)) {
|
|
19872
20284
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
19873
20285
|
}
|
|
@@ -19915,7 +20327,7 @@ var DevServer = class _DevServer {
|
|
|
19915
20327
|
setMode: "set_mode.js"
|
|
19916
20328
|
};
|
|
19917
20329
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19918
|
-
const scriptsDir =
|
|
20330
|
+
const scriptsDir = path21.join(providerDir, "scripts");
|
|
19919
20331
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19920
20332
|
if (latestScriptsDir) {
|
|
19921
20333
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19926,7 +20338,7 @@ var DevServer = class _DevServer {
|
|
|
19926
20338
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
19927
20339
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
19928
20340
|
try {
|
|
19929
|
-
const content = fs14.readFileSync(
|
|
20341
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
19930
20342
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19931
20343
|
lines.push("```javascript");
|
|
19932
20344
|
lines.push(content);
|
|
@@ -19943,7 +20355,7 @@ var DevServer = class _DevServer {
|
|
|
19943
20355
|
lines.push("");
|
|
19944
20356
|
for (const file of refFiles) {
|
|
19945
20357
|
try {
|
|
19946
|
-
const content = fs14.readFileSync(
|
|
20358
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
19947
20359
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19948
20360
|
lines.push("```javascript");
|
|
19949
20361
|
lines.push(content);
|
|
@@ -19984,10 +20396,10 @@ var DevServer = class _DevServer {
|
|
|
19984
20396
|
lines.push("");
|
|
19985
20397
|
}
|
|
19986
20398
|
}
|
|
19987
|
-
const docsDir =
|
|
20399
|
+
const docsDir = path21.join(providerDir, "../../docs");
|
|
19988
20400
|
const loadGuide = (name) => {
|
|
19989
20401
|
try {
|
|
19990
|
-
const p =
|
|
20402
|
+
const p = path21.join(docsDir, name);
|
|
19991
20403
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19992
20404
|
} catch {
|
|
19993
20405
|
}
|
|
@@ -20161,7 +20573,7 @@ var DevServer = class _DevServer {
|
|
|
20161
20573
|
parseApproval: "parse_approval.js"
|
|
20162
20574
|
};
|
|
20163
20575
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
20164
|
-
const scriptsDir =
|
|
20576
|
+
const scriptsDir = path21.join(providerDir, "scripts");
|
|
20165
20577
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
20166
20578
|
if (latestScriptsDir) {
|
|
20167
20579
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -20173,7 +20585,7 @@ var DevServer = class _DevServer {
|
|
|
20173
20585
|
if (!file.endsWith(".js")) continue;
|
|
20174
20586
|
if (!targetFileNames.has(file)) continue;
|
|
20175
20587
|
try {
|
|
20176
|
-
const content = fs14.readFileSync(
|
|
20588
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
20177
20589
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
20178
20590
|
lines.push("```javascript");
|
|
20179
20591
|
lines.push(content);
|
|
@@ -20189,7 +20601,7 @@ var DevServer = class _DevServer {
|
|
|
20189
20601
|
lines.push("");
|
|
20190
20602
|
for (const file of refFiles) {
|
|
20191
20603
|
try {
|
|
20192
|
-
const content = fs14.readFileSync(
|
|
20604
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
20193
20605
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
20194
20606
|
lines.push("```javascript");
|
|
20195
20607
|
lines.push(content);
|
|
@@ -20222,10 +20634,10 @@ var DevServer = class _DevServer {
|
|
|
20222
20634
|
lines.push("");
|
|
20223
20635
|
}
|
|
20224
20636
|
}
|
|
20225
|
-
const docsDir =
|
|
20637
|
+
const docsDir = path21.join(providerDir, "../../docs");
|
|
20226
20638
|
const loadGuide = (name) => {
|
|
20227
20639
|
try {
|
|
20228
|
-
const p =
|
|
20640
|
+
const p = path21.join(docsDir, name);
|
|
20229
20641
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
20230
20642
|
} catch {
|
|
20231
20643
|
}
|