@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.
Files changed (63) hide show
  1. package/dist/agent-stream/manager.d.ts +1 -0
  2. package/dist/agent-stream/provider-adapter.d.ts +1 -0
  3. package/dist/agent-stream/types.d.ts +3 -0
  4. package/dist/boot/daemon-lifecycle.d.ts +2 -1
  5. package/dist/cdp/manager.d.ts +2 -0
  6. package/dist/cli-adapter-types.d.ts +34 -5
  7. package/dist/cli-adapters/provider-cli-adapter.d.ts +4 -158
  8. package/dist/cli-adapters/provider-cli-config.d.ts +30 -0
  9. package/dist/cli-adapters/provider-cli-parse.d.ts +42 -0
  10. package/dist/cli-adapters/provider-cli-runtime.d.ts +29 -0
  11. package/dist/cli-adapters/provider-cli-shared.d.ts +158 -0
  12. package/dist/commands/handler.d.ts +4 -3
  13. package/dist/config/config.d.ts +4 -3
  14. package/dist/index.js +1033 -621
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +1035 -624
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/providers/acp-provider-instance.d.ts +1 -0
  19. package/dist/providers/approval-utils.d.ts +7 -0
  20. package/dist/providers/cli-provider-instance.d.ts +2 -0
  21. package/dist/providers/contracts.d.ts +12 -1
  22. package/dist/providers/ide-provider-instance.d.ts +1 -0
  23. package/dist/providers/provider-loader.d.ts +3 -0
  24. package/dist/status/reporter.d.ts +2 -3
  25. package/dist/status/snapshot.d.ts +2 -1
  26. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  27. package/package.json +3 -1
  28. package/src/agent-stream/manager.ts +8 -2
  29. package/src/agent-stream/poller.ts +57 -6
  30. package/src/agent-stream/provider-adapter.ts +11 -7
  31. package/src/agent-stream/types.ts +3 -0
  32. package/src/boot/daemon-lifecycle.ts +7 -6
  33. package/src/cdp/initializer.ts +2 -2
  34. package/src/cdp/manager.ts +5 -0
  35. package/src/cdp/setup.ts +1 -1
  36. package/src/cli-adapter-types.ts +37 -5
  37. package/src/cli-adapters/provider-cli-adapter.ts +212 -795
  38. package/src/cli-adapters/provider-cli-config.ts +66 -0
  39. package/src/cli-adapters/provider-cli-parse.ts +202 -0
  40. package/src/cli-adapters/provider-cli-runtime.ts +142 -0
  41. package/src/cli-adapters/provider-cli-shared.ts +439 -0
  42. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +1 -1
  43. package/src/commands/cdp-commands.ts +6 -1
  44. package/src/commands/chat-commands.ts +45 -29
  45. package/src/commands/cli-manager.ts +28 -9
  46. package/src/commands/handler.ts +14 -10
  47. package/src/commands/router.ts +23 -10
  48. package/src/commands/stream-commands.ts +11 -5
  49. package/src/config/config.ts +4 -10
  50. package/src/daemon/dev-auto-implement.ts +22 -18
  51. package/src/daemon/dev-cli-debug.ts +59 -16
  52. package/src/daemon/dev-server.ts +67 -43
  53. package/src/providers/acp-provider-instance.ts +18 -3
  54. package/src/providers/approval-utils.ts +66 -0
  55. package/src/providers/cli-provider-instance.ts +32 -6
  56. package/src/providers/contracts.d.ts +1 -0
  57. package/src/providers/contracts.ts +15 -2
  58. package/src/providers/extension-provider-instance.ts +1 -1
  59. package/src/providers/ide-provider-instance.ts +67 -41
  60. package/src/providers/provider-loader.ts +110 -55
  61. package/src/providers/version-archive.ts +23 -5
  62. package/src/status/reporter.ts +18 -14
  63. 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-adapter.ts
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?.patterns || {};
1008
+ const patterns = raw && typeof raw === "object" ? raw.patterns : void 0;
1024
1009
  return {
1025
1010
  patterns: {
1026
- approval: coercePatternArray(patterns.approval)
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, ProviderCliAdapter;
1031
- var init_provider_cli_adapter = __esm({
1032
- "src/cli-adapters/provider-cli-adapter.ts"() {
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
- init_spawn_env();
1041
- buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
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(/^~/, os8.homedir()) : workingDir;
1050
- const t = provider.timeouts || {};
1051
- this.timeouts = {
1052
- ptyFlush: t.ptyFlush ?? 50,
1053
- dialogAccept: t.dialogAccept ?? 300,
1054
- approvalCooldown: t.approvalCooldown ?? 3e3,
1055
- generatingIdle: t.generatingIdle ?? 6e3,
1056
- idleFinish: t.idleFinish ?? 5e3,
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 = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
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
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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 = Object.keys(scripts).filter((k) => typeof scripts[k] === "function");
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 { spawn: spawnConfig } = this.provider;
1390
- const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
1391
- const binaryPath = findBinary(configuredCommand);
1392
- const isWin = os8.platform() === "win32";
1393
- const allArgs = [...spawnConfig.args, ...this.extraArgs];
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: ptyOpts.cwd,
1435
- cols: ptyOpts.cols,
1436
- rows: ptyOpts.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(shellCmd, shellArgs, ptyOpts);
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
- shellCmd = process.env.SHELL || "/bin/zsh";
1446
- const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
1447
- shellArgs = ["-l", "-c", fullCmd];
1448
- this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
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
- if (isWin) {
1451
- const hint = /error code 267|ERROR_DIRECTORY/i.test(msg) ? " (working directory does not exist or is not a directory)" : /error code 740|elevation/i.test(msg) ? " (requires administrator privileges)" : /error code 2|ENOENT|not found/i.test(msg) ? ` (executable not found: ${shellCmd})` : "";
1452
- if (hint) {
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.respondToTerminalQueries(data);
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: this.summarizeTraceText(rawData, 300),
1542
- cleanPreview: this.summarizeTraceText(cleanData, 300),
1543
- screenText: this.summarizeTraceText(this.terminalScreen.getText(), 1200)
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(this.summarizeTraceText(screenText, 220)).slice(0, 260)}`
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(this.summarizeTraceText(finalScreenText, 240)).slice(0, 280)}`
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) ? this.normalizeParsedMessages(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: this.summarizeTraceText(tail, 500),
1816
- screenText: this.summarizeTraceText(screenText, 1200),
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 ? this.summarizeTraceText(lastParsedAssistant.content, 280) : "",
1945
+ parsedLastAssistant: lastParsedAssistant ? summarizeCliTraceText(lastParsedAssistant.content, 280) : "",
1821
1946
  parsedActiveModal: parsedTranscript?.activeModal ?? null,
1822
1947
  approval: modal,
1823
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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(this.summarizeTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(this.summarizeTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
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
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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: this.summarizeTraceText(commitResult.assistantContent, 220),
2030
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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 = this.normalizeParsedMessages(parsed.messages, this.currentTurnScope);
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 ? this.summarizeTraceText(lastAssistant.content, 320) : "",
2093
- messages: this.summarizeTraceMessages(this.committedMessages),
2094
- ...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
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(this.summarizeTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
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
- })) : this.hydrateParsedMessages(parsed.messages, this.currentTurnScope);
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 = this.buildParseInput(
2223
- this.committedMessages,
2224
- this.responseBuffer,
2225
- this.currentTurnScope
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 = this.buildParseInput(baseMessages, partialResponse, scope);
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: this.summarizeTraceText(text, 500),
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: this.summarizeTraceText(this.terminalScreen.getText(), 500)
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: this.summarizeTraceText(screenText, 500)
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: this.summarizeTraceText(text, 500),
2575
+ text: summarizeCliTraceText(text, 500),
2393
2576
  sendKey: this.sendKey,
2394
- screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
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: this.summarizeTraceText(screenText, 500)
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: this.summarizeTraceText(text, 500),
2607
+ text: summarizeCliTraceText(text, 500),
2425
2608
  sendKey: this.sendKey,
2426
- screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
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: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
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: this.summarizeTraceText(this.terminalScreen.getText(), 4e3),
2779
- recentOutputBuffer: this.summarizeTraceText(this.recentOutputBuffer, 1e3),
2780
- responseBuffer: this.summarizeTraceText(this.responseBuffer, 1200),
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: this.summarizeTraceMessages(this.committedMessages, 5)
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 os18 = (0, import_os2.platform)();
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[os18] || []) || []);
3456
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os20] || []) || []);
3288
3457
  let resolvedCli = cliPath;
3289
- if (!resolvedCli && appPath && os18 === "darwin") {
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 && os18 === "win32") {
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 = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
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 platform9 = os2.platform();
3372
- const whichCmd = platform9 === "win32" ? "where" : "which";
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 platform9 = os2.platform();
3416
- const whichCmd = platform9 === "win32" ? "where" : "which";
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: this.currentStatus,
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 || this.currentStatus,
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
- let { activeModal } = raw;
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
- for (const msg of raw.messages || []) {
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 (raw.messages?.length > 0) {
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
- raw.messages = raw.messages.filter((m) => !hiddenKinds.has(m.kind));
6285
+ chat.messages = messages.filter((m) => !hiddenKinds.has(m.kind || ""));
6060
6286
  }
6061
6287
  }
6062
- const controlValues = extractProviderControlValues(this.provider.controls, raw);
6063
- if (controlValues) raw.controlValues = controlValues;
6064
- this.cachedChat = { ...raw, activeModal };
6065
- this.detectAgentTransitions(raw, now);
6066
- if (raw.messages?.length > 0) {
6067
- let toSave = raw.messages;
6068
- if (raw.status === "generating" || raw.status === "long_generating") {
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
- raw.title,
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 typeof scripts.readChat === "function" ? scripts.readChat({}) : scripts.readChat;
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 agentStatus = chatStatus === "streaming" || chatStatus === "generating" ? "generating" : chatStatus === "waiting_approval" ? "waiting_approval" : "idle";
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 (agentStatus === "waiting_approval" && this.settings.autoApprove && !this.autoApproveBusy) {
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
- let targetButton = _chatData?.activeModal?.buttons?.[0] || "Run";
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(text);
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(text);
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
- if (adapter) {
7791
- const acpInstance = adapter._acpInstance;
7792
- if (acpInstance && typeof acpInstance.setMode === "function") {
7793
- await acpInstance.setMode(mode);
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
- if (adapter) {
7849
- const acpInstance = adapter._acpInstance;
7850
- if (acpInstance && typeof acpInstance.setConfigOption === "function") {
7851
- await acpInstance.setConfigOption("model", model);
7852
- LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
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
- adapter.resize(cols - 1, rows);
8438
- setTimeout(() => adapter.resize(cols, rows), 50);
8673
+ resize(cols - 1, rows);
8674
+ setTimeout(() => resize(cols, rows), 50);
8439
8675
  } else {
8440
- adapter.resize(cols, rows);
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 = fn(firstVal);
9161
+ const legacyScript = callScript(firstVal);
8925
9162
  if (legacyScript) return legacyScript;
8926
9163
  }
8927
- const script = fn(params);
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 = fn(firstVal);
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 = fn();
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 os10 = __toESM(require("os"));
9319
- var path11 = __toESM(require("path"));
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 os9 = __toESM(require("os"));
9327
- var path10 = __toESM(require("path"));
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)(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
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(/^~/, os9.homedir());
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: adapterStatus.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 || adapterStatus.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 newStatus = adapterStatus.status;
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
- this.log.info(`[${this.type}] Auto-approving: ${tc.title || tc.toolCallId}`);
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 chalkApi = import_chalk.default?.yellow ? import_chalk.default : import_chalk.default?.default || null;
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(/^~/, os10.homedir()) : path11.resolve(trimmed);
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 os12 = __toESM(require("os"));
11580
- var path13 = __toESM(require("path"));
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 path12 = __toESM(require("path"));
11585
- var os11 = __toESM(require("os"));
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 = path12.join(os11.homedir(), ".adhdev", "providers");
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 = path12.resolve(__dirname, "../../../../../adhdev-providers");
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 = path12.join(defaultProvidersDir, ".upstream");
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 path12.join(root, category, type);
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 path12.join(dir, ...segments);
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(path12.join(this.upstreamDir, d)).isDirectory()
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 verCmdConfig = p.versionCommand;
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 { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
11813
- const config = loadConfig2();
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
- saveConfig3(config);
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 (Array.isArray(base.compatibility)) {
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 = path12.join(providerDir, entry.scriptDir);
12033
- resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
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 = path12.join(providerDir, base.defaultScriptDir);
12049
- resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
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 = path12.join(providerDir, dirOverride);
12067
- resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
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 (Array.isArray(base.compatibility) && base.defaultScriptDir) {
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 = path12.join(providerDir, base.defaultScriptDir);
12084
- resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
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 = path12.join(providerDir, scriptDir);
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 = path12.join(dir, "scripts.js");
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: ${path12.basename(filePath)}, reloading...`);
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 = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
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 = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
12274
- const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
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(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
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 = path12.join(tmpExtract, rootDir);
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 = path12.join(src, entry.name);
12359
- const destPath = path12.join(dest, entry.name);
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(path12.dirname(metaPath), { recursive: true });
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(path12.join(d, entry.name));
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
- try {
12422
- const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
12423
- const config = loadConfig2();
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
- saveConfig3(config);
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
- return {
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(path12.join(candidate, "provider.json"))) return candidate;
12531
- const catDir = path12.join(root, cat);
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 = path12.join(catDir, entry.name, "provider.json");
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 path12.join(catDir, entry.name);
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 = path12.join(dir, "scripts.js");
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 = path12.join(dir, file);
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 = path12.join(d, "provider.json");
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 (mod.extensionIdPattern && typeof mod.extensionIdPattern === "string") {
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 hasCompatibility = Array.isArray(mod.compatibility);
12644
- const scriptsPath = path12.join(d, "scripts.js");
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
- mod.scripts = scripts;
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(mod.type);
12655
- this.providers.set(mod.type, mod);
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"} ${mod.type} (${mod.category}) \u2014 ${mod.name} [${source}]${overrideWarning}`);
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(path12.join(d, entry.name));
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, platform9) {
13065
+ function getPreferredLaunchMethod(ideId, platform10) {
12741
13066
  const prefer = getProviderMeta(ideId)?.launch?.prefer;
12742
- const value = prefer?.[platform9];
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 = os12.platform();
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 = os12.platform();
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 = os12.platform();
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 = path13.join(
12929
- process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
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 platform9 = os12.platform();
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 (platform9 === "darwin") {
13345
+ if (platform10 === "darwin") {
13021
13346
  await launchMacOS(targetIde, port, workspace, options.newWindow);
13022
- } else if (platform9 === "win32") {
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 path14 = __toESM(require("path"));
13108
- var os13 = __toESM(require("os"));
13109
- var LOG_DIR2 = process.platform === "win32" ? path14.join(process.env.LOCALAPPDATA || process.env.APPDATA || path14.join(os13.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path14.join(os13.homedir(), "Library", "Logs", "adhdev") : path14.join(os13.homedir(), ".local", "share", "adhdev", "logs");
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 = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
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 = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
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(path14.join(LOG_DIR2, file));
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 os14 = __toESM(require("os"));
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: os14.hostname(),
13365
- platform: os14.platform(),
13366
- arch: os14.arch(),
13367
- cpus: os14.cpus().length,
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: os14.loadavg(),
13372
- uptime: os14.uptime(),
13373
- release: os14.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 os15 = __toESM(require("os"));
13395
- var path15 = __toESM(require("path"));
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 = os15.homedir();
13399
- const dir = path15.join(home, ".adhdev");
13723
+ const home = os17.homedir();
13724
+ const dir = path16.join(home, ".adhdev");
13400
13725
  fs8.mkdirSync(dir, { recursive: true });
13401
- return path15.join(dir, "daemon-upgrade.log");
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 = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
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 = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
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 : path15.join(npmPrefix, "bin");
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 = path15.join(npmRoot, scope);
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(path15.join(scopeDir, entry), { recursive: true, force: true });
13494
- appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
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(path15.join(npmRoot, entry), { recursive: true, force: true });
13500
- appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
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(path15.join(binDir, entry), { recursive: true, force: true });
13507
- appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, 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 { success: result.success, ...result };
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
- const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
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
- const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
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
- if (hashTarget.machine) {
14603
+ const hashPayload = hashTarget.machine ? (() => {
14268
14604
  const { freeMem: _f, availableMem: _a, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
14269
- hashTarget.machine = stableMachine;
14270
- }
14271
- const h = this.simpleHash(JSON.stringify(hashTarget));
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 = typeof state.title === "string" ? state.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
- LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ""}${state.status === "error" ? " error=" + JSON.stringify(state.error || state._error || "unknown") : ""}`);
14682
- const stateError = String(state.error || state._error || "");
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
- const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
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 path16 = __toESM(require("path"));
15216
- var os16 = __toESM(require("os"));
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 = path16.join(os16.homedir(), ".adhdev", "version-history.json");
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(path16.dirname(ARCHIVE_PATH), { recursive: true });
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 = os16.homedir();
15307
- const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
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 = path16.join(appPath, "Contents", "Info.plist");
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 verCmdConfig = provider.versionCommand;
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 = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
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 path20 = __toESM(require("path"));
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 path17 = __toESM(require("path"));
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 = path17.join(dir, "scripts.js");
16295
+ const directScripts = path18.join(dir, "scripts.js");
15901
16296
  if (fs11.existsSync(directScripts)) {
15902
16297
  scriptsPath = directScripts;
15903
16298
  } else {
15904
- const scriptsDir = path17.join(dir, "scripts");
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(path17.join(scriptsDir, d)).isDirectory();
16302
+ return fs11.statSync(path18.join(scriptsDir, d)).isDirectory();
15908
16303
  }).sort().reverse();
15909
16304
  for (const ver of versions) {
15910
- const p = path17.join(scriptsDir, ver, "scripts.js");
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 path18 = __toESM(require("path"));
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 path18.join(providerDir, "fixtures");
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 = path18.join(fixtureDir, `${name}.json`);
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((s) => s.category === "cli" || s.category === "acp");
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.getAdapter?.() || instance.adapter;
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.getAdapter?.() || instance.adapter;
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.getAdapter?.() || instance.adapter;
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 = path18.join(fixtureDir, `${name}.json`);
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 = path18.join(fixtureDir, file);
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?.getAdapter?.() || instance?.adapter;
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?.getAdapter?.() || instance?.adapter;
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 path19 = __toESM(require("path"));
17663
- var os17 = __toESM(require("os"));
18066
+ var path20 = __toESM(require("path"));
18067
+ var os19 = __toESM(require("os"));
17664
18068
  function getAutoImplPid(ctx) {
17665
- const proc = ctx.autoImplProcess;
17666
- return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
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(path19.join(scriptsDir, d)).isDirectory();
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 path19.join(scriptsDir, versions[0]);
18119
+ return path20.join(scriptsDir, versions[0]);
17709
18120
  }
17710
18121
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
17711
- const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
17712
- const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
17713
- const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
17714
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
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 (path19.basename(desiredDir) !== type) {
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(path19.dirname(desiredDir), { recursive: true });
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 = path19.join(desiredDir, "provider.json");
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 = path19.join(refDir, "scripts");
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(path19.join(latestDir, file), "utf-8");
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 = path19.join(os17.tmpdir(), "adhdev-autoimpl");
18277
+ const tmpDir = path20.join(os19.tmpdir(), "adhdev-autoimpl");
17867
18278
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
17868
- const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
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 = os17.platform() === "win32";
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 = os17.platform() === "win32";
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
- const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
18104
- const normalized = normalizeCliProviderForRuntime2(agentProvider);
18105
- approvalPatterns = normalized.patterns.approval;
18106
- approvalKeys = agentProvider?.approvalKeys || { 0: "y\r", 1: "a\r" };
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
- try {
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
- try {
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 = path19.join(providerDir, "scripts");
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(path19.join(latestScriptsDir, file), "utf-8");
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(path19.join(latestScriptsDir, file), "utf-8");
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 = path19.join(providerDir, "../../docs");
18771
+ const docsDir = path20.join(providerDir, "../../docs");
18365
18772
  const loadGuide = (name) => {
18366
18773
  try {
18367
- const p = path19.join(docsDir, name);
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 = path19.join(providerDir, "scripts");
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(path19.join(latestScriptsDir, file), "utf-8");
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(path19.join(latestScriptsDir, file), "utf-8");
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 = path19.join(providerDir, "../../docs");
19070
+ const docsDir = path20.join(providerDir, "../../docs");
18664
19071
  const loadGuide = (name) => {
18665
19072
  try {
18666
- const p = path19.join(docsDir, name);
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 path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
19078
- return `${r.method.padEnd(5)} ${path21}`;
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((p) => {
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._targetId = null;
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
- path20.resolve(__dirname, "../../web-devconsole/dist"),
19361
- path20.resolve(__dirname, "../../../web-devconsole/dist"),
19362
- path20.join(process.cwd(), "packages/web-devconsole/dist")
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(path20.join(dir, "index.html"))) return dir;
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 = path20.join(distDir, "index.html");
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 = path20.normalize(pathname).replace(/^\.\.\//, "");
19401
- const filePath = path20.join(distDir, safePath);
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 = path20.extname(filePath);
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(path20.join(d, entry.name), rel);
19933
+ scan(path21.join(d, entry.name), rel);
19522
19934
  } else {
19523
- const stat = fs14.statSync(path20.join(d, entry.name));
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 = path20.resolve(dir, path20.normalize(filePath));
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 = path20.resolve(dir, path20.normalize(filePath));
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(path20.dirname(fullPath), { recursive: true });
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 = path20.join(dir, name);
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(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
19617
- const targetPath = path20.join(dir, target);
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 = path20.join(targetDir, "provider.json");
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 = path20.join(targetDir, relPath);
19790
- fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
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(path20.join(scriptsDir, d)).isDirectory();
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 path20.join(scriptsDir, versions[0]);
20261
+ return path21.join(scriptsDir, versions[0]);
19850
20262
  }
19851
20263
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
19852
- const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
19853
- const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
19854
- const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
19855
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
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 (path20.basename(desiredDir) !== type) {
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(path20.dirname(desiredDir), { recursive: true });
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 = path20.join(desiredDir, "provider.json");
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 = path20.join(providerDir, "scripts");
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(path20.join(latestScriptsDir, file), "utf-8");
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(path20.join(latestScriptsDir, file), "utf-8");
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 = path20.join(providerDir, "../../docs");
20399
+ const docsDir = path21.join(providerDir, "../../docs");
19988
20400
  const loadGuide = (name) => {
19989
20401
  try {
19990
- const p = path20.join(docsDir, name);
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 = path20.join(providerDir, "scripts");
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(path20.join(latestScriptsDir, file), "utf-8");
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(path20.join(latestScriptsDir, file), "utf-8");
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 = path20.join(providerDir, "../../docs");
20637
+ const docsDir = path21.join(providerDir, "../../docs");
20226
20638
  const loadGuide = (name) => {
20227
20639
  try {
20228
- const p = path20.join(docsDir, name);
20640
+ const p = path21.join(docsDir, name);
20229
20641
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
20230
20642
  } catch {
20231
20643
  }