@n1creator/openacp-cli 2026.712.4 → 2026.712.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -4996,12 +4996,203 @@ var init_groq = __esm({
4996
4996
  }
4997
4997
  });
4998
4998
 
4999
+ // src/plugins/speech/providers/local-whisper.ts
5000
+ import { execFile } from "child_process";
5001
+ import { existsSync as existsSync2 } from "fs";
5002
+ import { mkdtemp, rm, writeFile } from "fs/promises";
5003
+ import { tmpdir } from "os";
5004
+ import path9 from "path";
5005
+ import { fileURLToPath as fileURLToPath2 } from "url";
5006
+ import { promisify } from "util";
5007
+ function resolveLocalWhisperScriptPath() {
5008
+ const moduleDir = path9.dirname(fileURLToPath2(import.meta.url));
5009
+ const candidates = [
5010
+ path9.resolve(moduleDir, "../scripts/transcribe_audio.sh"),
5011
+ path9.resolve(moduleDir, "speech/transcribe_audio.sh")
5012
+ ];
5013
+ return candidates.find(existsSync2) ?? candidates[0];
5014
+ }
5015
+ function mimeToExt2(mimeType) {
5016
+ const normalized = mimeType.split(";", 1)[0]?.trim().toLowerCase();
5017
+ const extensions = {
5018
+ "audio/ogg": ".ogg",
5019
+ "audio/opus": ".ogg",
5020
+ "audio/wav": ".wav",
5021
+ "audio/x-wav": ".wav",
5022
+ "audio/mpeg": ".mp3",
5023
+ "audio/mp3": ".mp3",
5024
+ "audio/mp4": ".m4a",
5025
+ "audio/aac": ".aac",
5026
+ "audio/webm": ".webm",
5027
+ "audio/flac": ".flac"
5028
+ };
5029
+ return normalized && extensions[normalized] || ".bin";
5030
+ }
5031
+ function parseMetadata(stderr) {
5032
+ const language = /\blanguage=([^\s]+)/.exec(stderr)?.[1];
5033
+ const durationRaw = /\bduration=([0-9.]+)s\b/.exec(stderr)?.[1];
5034
+ const duration = durationRaw ? Number(durationRaw) : void 0;
5035
+ return { language, duration: Number.isFinite(duration) ? duration : void 0 };
5036
+ }
5037
+ function formatExecError(error) {
5038
+ if (!(error instanceof Error)) return String(error);
5039
+ const execError = error;
5040
+ const details = [execError.stderr, execError.stdout].filter(Boolean).join("\n").trim();
5041
+ const code = execError.code === void 0 ? "" : ` (exit ${execError.code})`;
5042
+ return details ? `${error.message}${code}: ${details}` : `${error.message}${code}`;
5043
+ }
5044
+ var execFileAsync, LOCAL_WHISPER_PROVIDER, LOCAL_WHISPER_DEFAULTS, LocalWhisperSTT;
5045
+ var init_local_whisper = __esm({
5046
+ "src/plugins/speech/providers/local-whisper.ts"() {
5047
+ "use strict";
5048
+ execFileAsync = promisify(execFile);
5049
+ LOCAL_WHISPER_PROVIDER = "local-whisper";
5050
+ LOCAL_WHISPER_DEFAULTS = {
5051
+ language: "ru",
5052
+ model: "base",
5053
+ beamSize: 5,
5054
+ vadFilter: false,
5055
+ device: "cpu",
5056
+ computeType: "int8",
5057
+ timeoutMs: 12e4
5058
+ };
5059
+ LocalWhisperSTT = class {
5060
+ name = LOCAL_WHISPER_PROVIDER;
5061
+ config;
5062
+ constructor(options = {}) {
5063
+ this.config = {
5064
+ scriptPath: options.scriptPath ?? resolveLocalWhisperScriptPath(),
5065
+ language: options.language ?? LOCAL_WHISPER_DEFAULTS.language,
5066
+ model: options.model ?? LOCAL_WHISPER_DEFAULTS.model,
5067
+ beamSize: options.beamSize ?? LOCAL_WHISPER_DEFAULTS.beamSize,
5068
+ vadFilter: options.vadFilter ?? LOCAL_WHISPER_DEFAULTS.vadFilter,
5069
+ device: options.device ?? LOCAL_WHISPER_DEFAULTS.device,
5070
+ computeType: options.computeType ?? LOCAL_WHISPER_DEFAULTS.computeType,
5071
+ timeoutMs: options.timeoutMs ?? LOCAL_WHISPER_DEFAULTS.timeoutMs,
5072
+ tempRoot: options.tempRoot
5073
+ };
5074
+ }
5075
+ async transcribe(audioBuffer, mimeType, options) {
5076
+ const tempDir = await mkdtemp(path9.join(this.config.tempRoot ?? tmpdir(), "openacp-local-whisper-"));
5077
+ const audioPath = path9.join(tempDir, `input${mimeToExt2(mimeType)}`);
5078
+ try {
5079
+ await writeFile(audioPath, audioBuffer);
5080
+ const { stdout, stderr } = await execFileAsync(this.config.scriptPath, this.buildArgs(audioPath, options), {
5081
+ timeout: this.config.timeoutMs,
5082
+ maxBuffer: 10 * 1024 * 1024
5083
+ });
5084
+ const text5 = stdout.trim();
5085
+ if (!text5) throw new Error("Local Whisper returned an empty transcript");
5086
+ return { text: text5, ...parseMetadata(stderr) };
5087
+ } catch (error) {
5088
+ throw new Error(`Local Whisper STT failed: ${formatExecError(error)}`);
5089
+ } finally {
5090
+ await rm(tempDir, { recursive: true, force: true });
5091
+ }
5092
+ }
5093
+ buildArgs(audioPath, options) {
5094
+ return [
5095
+ "--model",
5096
+ options?.model ?? this.config.model,
5097
+ "--language",
5098
+ options?.language ?? this.config.language,
5099
+ "--beam-size",
5100
+ String(this.config.beamSize),
5101
+ "--device",
5102
+ this.config.device,
5103
+ "--compute-type",
5104
+ this.config.computeType,
5105
+ this.config.vadFilter ? "--vad-filter" : "--no-vad-filter",
5106
+ audioPath
5107
+ ];
5108
+ }
5109
+ };
5110
+ }
5111
+ });
5112
+
4999
5113
  // src/plugins/speech/exports.ts
5000
5114
  var init_exports = __esm({
5001
5115
  "src/plugins/speech/exports.ts"() {
5002
5116
  "use strict";
5003
5117
  init_speech_service();
5004
5118
  init_groq();
5119
+ init_local_whisper();
5120
+ }
5121
+ });
5122
+
5123
+ // src/plugins/speech/native-stt.ts
5124
+ function readLocalWhisperSettings(raw) {
5125
+ return {
5126
+ scriptPath: readString(raw.localWhisperScriptPath, resolveLocalWhisperScriptPath()),
5127
+ language: readString(raw.localWhisperLanguage, LOCAL_WHISPER_DEFAULTS.language),
5128
+ model: readString(raw.localWhisperModel, LOCAL_WHISPER_DEFAULTS.model),
5129
+ beamSize: readNumber(raw.localWhisperBeamSize, LOCAL_WHISPER_DEFAULTS.beamSize),
5130
+ vadFilter: readBoolean(raw.localWhisperVadFilter, LOCAL_WHISPER_DEFAULTS.vadFilter),
5131
+ device: readString(raw.localWhisperDevice, LOCAL_WHISPER_DEFAULTS.device),
5132
+ computeType: readString(raw.localWhisperComputeType, LOCAL_WHISPER_DEFAULTS.computeType),
5133
+ timeoutMs: readNumber(raw.localWhisperTimeoutMs, LOCAL_WHISPER_DEFAULTS.timeoutMs)
5134
+ };
5135
+ }
5136
+ function buildSpeechServiceConfig(raw) {
5137
+ const groqApiKey = readOptionalString(raw.groqApiKey);
5138
+ const requestedProvider = readOptionalString(raw.sttProvider);
5139
+ const provider = requestedProvider === LOCAL_WHISPER_PROVIDER ? LOCAL_WHISPER_PROVIDER : groqApiKey ? "groq" : null;
5140
+ const providers = {};
5141
+ if (groqApiKey) providers.groq = { apiKey: groqApiKey };
5142
+ if (provider === LOCAL_WHISPER_PROVIDER) {
5143
+ providers[LOCAL_WHISPER_PROVIDER] = {
5144
+ apiKey: "local",
5145
+ ...readLocalWhisperSettings(raw)
5146
+ };
5147
+ }
5148
+ return {
5149
+ stt: { provider, providers },
5150
+ tts: {
5151
+ provider: readOptionalString(raw.ttsProvider) ?? "edge-tts",
5152
+ providers: {}
5153
+ }
5154
+ };
5155
+ }
5156
+ function createNativeSTTProviders(config) {
5157
+ const providers = /* @__PURE__ */ new Map();
5158
+ const groq = config.stt.providers.groq;
5159
+ if (groq?.apiKey) providers.set("groq", new GroqSTT(groq.apiKey, groq.model));
5160
+ const local = config.stt.providers[LOCAL_WHISPER_PROVIDER];
5161
+ if (local?.apiKey !== void 0) {
5162
+ providers.set(LOCAL_WHISPER_PROVIDER, new LocalWhisperSTT({
5163
+ scriptPath: readOptionalString(local.scriptPath),
5164
+ language: readOptionalString(local.language),
5165
+ model: readOptionalString(local.model),
5166
+ beamSize: readOptionalNumber(local.beamSize),
5167
+ vadFilter: typeof local.vadFilter === "boolean" ? local.vadFilter : void 0,
5168
+ device: readOptionalString(local.device),
5169
+ computeType: readOptionalString(local.computeType),
5170
+ timeoutMs: readOptionalNumber(local.timeoutMs)
5171
+ }));
5172
+ }
5173
+ return providers;
5174
+ }
5175
+ function readString(value, fallback) {
5176
+ return readOptionalString(value) ?? fallback;
5177
+ }
5178
+ function readOptionalString(value) {
5179
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
5180
+ }
5181
+ function readNumber(value, fallback) {
5182
+ return readOptionalNumber(value) ?? fallback;
5183
+ }
5184
+ function readOptionalNumber(value) {
5185
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
5186
+ }
5187
+ function readBoolean(value, fallback) {
5188
+ return typeof value === "boolean" ? value : fallback;
5189
+ }
5190
+ var init_native_stt = __esm({
5191
+ "src/plugins/speech/native-stt.ts"() {
5192
+ "use strict";
5193
+ init_groq();
5194
+ init_local_whisper();
5195
+ init_local_whisper();
5005
5196
  }
5006
5197
  });
5007
5198
 
@@ -5011,14 +5202,14 @@ __export(plugin_installer_exports, {
5011
5202
  importFromDir: () => importFromDir,
5012
5203
  installNpmPlugin: () => installNpmPlugin
5013
5204
  });
5014
- import { execFile } from "child_process";
5015
- import { promisify } from "util";
5205
+ import { execFile as execFile2 } from "child_process";
5206
+ import { promisify as promisify2 } from "util";
5016
5207
  import * as fs8 from "fs/promises";
5017
- import * as path9 from "path";
5208
+ import * as path10 from "path";
5018
5209
  import { pathToFileURL } from "url";
5019
5210
  async function importFromDir(packageName, dir) {
5020
- const pkgDir = path9.join(dir, "node_modules", ...packageName.split("/"));
5021
- const pkgJsonPath = path9.join(pkgDir, "package.json");
5211
+ const pkgDir = path10.join(dir, "node_modules", ...packageName.split("/"));
5212
+ const pkgJsonPath = path10.join(pkgDir, "package.json");
5022
5213
  let pkgJson;
5023
5214
  try {
5024
5215
  pkgJson = JSON.parse(await fs8.readFile(pkgJsonPath, "utf-8"));
@@ -5034,7 +5225,7 @@ async function importFromDir(packageName, dir) {
5034
5225
  } else {
5035
5226
  entry = pkgJson.main ?? "index.js";
5036
5227
  }
5037
- const entryPath = path9.join(pkgDir, entry);
5228
+ const entryPath = path10.join(pkgDir, entry);
5038
5229
  try {
5039
5230
  await fs8.access(entryPath);
5040
5231
  } catch {
@@ -5051,16 +5242,16 @@ async function installNpmPlugin(packageName, pluginsDir) {
5051
5242
  return await importFromDir(packageName, dir);
5052
5243
  } catch {
5053
5244
  }
5054
- await execFileAsync("npm", ["install", packageName, "--prefix", dir, "--save", "--ignore-scripts"], {
5245
+ await execFileAsync2("npm", ["install", packageName, "--prefix", dir, "--save", "--ignore-scripts"], {
5055
5246
  timeout: 6e4
5056
5247
  });
5057
5248
  return await importFromDir(packageName, dir);
5058
5249
  }
5059
- var execFileAsync, VALID_NPM_NAME;
5250
+ var execFileAsync2, VALID_NPM_NAME;
5060
5251
  var init_plugin_installer = __esm({
5061
5252
  "src/core/plugin/plugin-installer.ts"() {
5062
5253
  "use strict";
5063
- execFileAsync = promisify(execFile);
5254
+ execFileAsync2 = promisify2(execFile2);
5064
5255
  VALID_NPM_NAME = /^(@[a-z0-9][\w.-]*\/)?[a-z0-9][\w.-]*(@[\w.^~>=<|-]+)?$/i;
5065
5256
  }
5066
5257
  });
@@ -5070,12 +5261,13 @@ var speech_exports = {};
5070
5261
  __export(speech_exports, {
5071
5262
  default: () => speech_default
5072
5263
  });
5073
- import path10 from "path";
5264
+ import path11 from "path";
5074
5265
  var EDGE_TTS_PLUGIN, speechPlugin, speech_default;
5075
5266
  var init_speech = __esm({
5076
5267
  "src/plugins/speech/index.ts"() {
5077
5268
  "use strict";
5078
5269
  init_exports();
5270
+ init_native_stt();
5079
5271
  init_plugin_installer();
5080
5272
  EDGE_TTS_PLUGIN = "@openacp/msedge-tts-plugin";
5081
5273
  speechPlugin = {
@@ -5089,17 +5281,22 @@ var init_speech = __esm({
5089
5281
  inheritableKeys: ["ttsProvider", "ttsVoice"],
5090
5282
  async install(ctx) {
5091
5283
  const { terminal, settings } = ctx;
5092
- const pluginsDir = ctx.instanceRoot ? path10.join(ctx.instanceRoot, "plugins") : void 0;
5284
+ const pluginsDir = ctx.instanceRoot ? path11.join(ctx.instanceRoot, "plugins") : void 0;
5093
5285
  const enableStt = await terminal.confirm({
5094
5286
  message: "Enable speech-to-text (STT)?",
5095
5287
  initialValue: false
5096
5288
  });
5097
5289
  let sttProvider = null;
5098
5290
  let groqApiKey = "";
5291
+ let localWhisperLanguage = LOCAL_WHISPER_DEFAULTS.language;
5292
+ let localWhisperModel = LOCAL_WHISPER_DEFAULTS.model;
5099
5293
  if (enableStt) {
5100
5294
  sttProvider = await terminal.select({
5101
5295
  message: "STT provider:",
5102
- options: [{ value: "groq", label: "Groq (Whisper)", hint: "Fast and affordable" }]
5296
+ options: [
5297
+ { value: LOCAL_WHISPER_PROVIDER, label: "Local faster-whisper", hint: "Private and offline after the first model download" },
5298
+ { value: "groq", label: "Groq (Whisper)", hint: "Hosted API, requires an API key" }
5299
+ ]
5103
5300
  });
5104
5301
  if (sttProvider === "groq") {
5105
5302
  groqApiKey = await terminal.text({
@@ -5107,6 +5304,15 @@ var init_speech = __esm({
5107
5304
  validate: (v) => !v.trim() ? "API key cannot be empty" : void 0
5108
5305
  });
5109
5306
  groqApiKey = groqApiKey.trim();
5307
+ } else {
5308
+ localWhisperLanguage = (await terminal.text({
5309
+ message: "Local Whisper language:",
5310
+ defaultValue: LOCAL_WHISPER_DEFAULTS.language
5311
+ })).trim() || LOCAL_WHISPER_DEFAULTS.language;
5312
+ localWhisperModel = (await terminal.text({
5313
+ message: "Local Whisper model:",
5314
+ defaultValue: LOCAL_WHISPER_DEFAULTS.model
5315
+ })).trim() || LOCAL_WHISPER_DEFAULTS.model;
5110
5316
  }
5111
5317
  }
5112
5318
  const ttsProvider = await terminal.select({
@@ -5134,6 +5340,13 @@ var init_speech = __esm({
5134
5340
  await settings.setAll({
5135
5341
  sttProvider,
5136
5342
  groqApiKey,
5343
+ localWhisperLanguage,
5344
+ localWhisperModel,
5345
+ localWhisperBeamSize: LOCAL_WHISPER_DEFAULTS.beamSize,
5346
+ localWhisperVadFilter: LOCAL_WHISPER_DEFAULTS.vadFilter,
5347
+ localWhisperDevice: LOCAL_WHISPER_DEFAULTS.device,
5348
+ localWhisperComputeType: LOCAL_WHISPER_DEFAULTS.computeType,
5349
+ localWhisperTimeoutMs: LOCAL_WHISPER_DEFAULTS.timeoutMs,
5137
5350
  ttsProvider: ttsProvider === "none" ? null : ttsProvider,
5138
5351
  ttsVoice
5139
5352
  });
@@ -5151,13 +5364,34 @@ var init_speech = __esm({
5151
5364
  ]
5152
5365
  });
5153
5366
  if (choice === "stt") {
5154
- const key = await terminal.text({
5155
- message: "Groq API key (leave blank to disable STT):",
5156
- defaultValue: current.groqApiKey ?? ""
5367
+ const provider = await terminal.select({
5368
+ message: "STT provider:",
5369
+ options: [
5370
+ { value: LOCAL_WHISPER_PROVIDER, label: "Local faster-whisper", hint: "Private and offline after the first model download" },
5371
+ { value: "groq", label: "Groq (Whisper)", hint: "Hosted API, requires an API key" },
5372
+ { value: "none", label: "None (disable STT)" }
5373
+ ]
5157
5374
  });
5158
- const trimmed = key.trim();
5159
- await settings.set("sttProvider", trimmed ? "groq" : null);
5160
- await settings.set("groqApiKey", trimmed);
5375
+ await settings.set("sttProvider", provider === "none" ? null : provider);
5376
+ if (provider === "groq") {
5377
+ const key = await terminal.text({
5378
+ message: "Groq API key:",
5379
+ defaultValue: current.groqApiKey ?? "",
5380
+ validate: (v) => !v.trim() ? "API key cannot be empty" : void 0
5381
+ });
5382
+ await settings.set("groqApiKey", key.trim());
5383
+ } else if (provider === LOCAL_WHISPER_PROVIDER) {
5384
+ const language = await terminal.text({
5385
+ message: "Local Whisper language:",
5386
+ defaultValue: current.localWhisperLanguage ?? LOCAL_WHISPER_DEFAULTS.language
5387
+ });
5388
+ const model = await terminal.text({
5389
+ message: "Local Whisper model:",
5390
+ defaultValue: current.localWhisperModel ?? LOCAL_WHISPER_DEFAULTS.model
5391
+ });
5392
+ await settings.set("localWhisperLanguage", language.trim() || LOCAL_WHISPER_DEFAULTS.language);
5393
+ await settings.set("localWhisperModel", model.trim() || LOCAL_WHISPER_DEFAULTS.model);
5394
+ }
5161
5395
  terminal.log.success("STT settings updated");
5162
5396
  } else if (choice === "tts") {
5163
5397
  const voice = await terminal.text({
@@ -5176,37 +5410,26 @@ var init_speech = __esm({
5176
5410
  },
5177
5411
  async setup(ctx) {
5178
5412
  ctx.registerEditableFields([
5179
- { key: "sttProvider", displayName: "Speech to Text", type: "select", scope: "safe", hotReload: true, options: ["groq"] },
5180
- { key: "groqApiKey", displayName: "STT API Key", type: "string", scope: "sensitive", hotReload: true },
5413
+ { key: "sttProvider", displayName: "Speech to Text", type: "select", scope: "safe", hotReload: true, options: [LOCAL_WHISPER_PROVIDER, "groq"] },
5414
+ { key: "groqApiKey", displayName: "Groq STT API Key", type: "string", scope: "sensitive", hotReload: true },
5415
+ { key: "localWhisperLanguage", displayName: "Local Whisper Language", type: "string", scope: "safe", hotReload: true },
5416
+ { key: "localWhisperModel", displayName: "Local Whisper Model", type: "string", scope: "safe", hotReload: true },
5417
+ { key: "localWhisperBeamSize", displayName: "Local Whisper Beam Size", type: "number", scope: "safe", hotReload: true },
5418
+ { key: "localWhisperVadFilter", displayName: "Local Whisper VAD Filter", type: "toggle", scope: "safe", hotReload: true },
5419
+ { key: "localWhisperDevice", displayName: "Local Whisper Device", type: "select", scope: "safe", hotReload: true, options: ["cpu", "cuda", "auto"] },
5420
+ { key: "localWhisperComputeType", displayName: "Local Whisper Compute Type", type: "string", scope: "safe", hotReload: true },
5421
+ { key: "localWhisperTimeoutMs", displayName: "Local Whisper Timeout (ms)", type: "number", scope: "safe", hotReload: true },
5422
+ { key: "localWhisperScriptPath", displayName: "Local Whisper Script Path", type: "string", scope: "safe", hotReload: true },
5181
5423
  { key: "ttsProvider", displayName: "Text to Speech", type: "select", scope: "safe", hotReload: true, options: ["edge-tts"] }
5182
5424
  ]);
5183
- const pluginsDir = ctx.instanceRoot ? path10.join(ctx.instanceRoot, "plugins") : void 0;
5425
+ const pluginsDir = ctx.instanceRoot ? path11.join(ctx.instanceRoot, "plugins") : void 0;
5184
5426
  const config = ctx.pluginConfig;
5185
- const groqApiKey = config.groqApiKey;
5186
- const sttProvider = groqApiKey ? "groq" : null;
5187
- const speechConfig = {
5188
- stt: {
5189
- provider: sttProvider,
5190
- providers: groqApiKey ? { groq: { apiKey: groqApiKey } } : {}
5191
- },
5192
- tts: {
5193
- provider: config.ttsProvider ?? "edge-tts",
5194
- providers: {}
5195
- }
5196
- };
5427
+ const speechConfig = buildSpeechServiceConfig(config);
5197
5428
  const service = new SpeechService(speechConfig);
5198
- if (groqApiKey) {
5199
- service.registerSTTProvider("groq", new GroqSTT(groqApiKey));
5429
+ for (const [name, provider] of createNativeSTTProviders(speechConfig)) {
5430
+ service.registerSTTProvider(name, provider);
5200
5431
  }
5201
- service.setProviderFactory((cfg) => {
5202
- const sttMap = /* @__PURE__ */ new Map();
5203
- const ttsMap = /* @__PURE__ */ new Map();
5204
- const groqCfg = cfg.stt?.providers?.groq;
5205
- if (groqCfg?.apiKey) {
5206
- sttMap.set("groq", new GroqSTT(groqCfg.apiKey, groqCfg.model));
5207
- }
5208
- return { stt: sttMap, tts: ttsMap };
5209
- });
5432
+ service.setProviderFactory((cfg) => ({ stt: createNativeSTTProviders(cfg), tts: /* @__PURE__ */ new Map() }));
5210
5433
  ctx.registerService("speech", service);
5211
5434
  const setSessionVoiceMode = (pluginCtx, sessionId, voiceMode) => {
5212
5435
  if (!sessionId) return;
@@ -5534,7 +5757,7 @@ __export(agent_dependencies_exports, {
5534
5757
  });
5535
5758
  import { execFileSync as execFileSync2 } from "child_process";
5536
5759
  import * as fs9 from "fs";
5537
- import * as path11 from "path";
5760
+ import * as path12 from "path";
5538
5761
  function getAgentSetup(registryId) {
5539
5762
  return AGENT_SETUP[registryId];
5540
5763
  }
@@ -5558,9 +5781,9 @@ function commandExists(cmd) {
5558
5781
  }
5559
5782
  let dir = process.cwd();
5560
5783
  while (true) {
5561
- const binPath = path11.join(dir, "node_modules", ".bin", cmd);
5784
+ const binPath = path12.join(dir, "node_modules", ".bin", cmd);
5562
5785
  if (fs9.existsSync(binPath)) return true;
5563
- const parent = path11.dirname(dir);
5786
+ const parent = path12.dirname(dir);
5564
5787
  if (parent === dir) break;
5565
5788
  dir = parent;
5566
5789
  }
@@ -5826,7 +6049,7 @@ var init_agent_dependencies = __esm({
5826
6049
 
5827
6050
  // src/core/agents/agent-installer.ts
5828
6051
  import * as fs10 from "fs";
5829
- import * as path12 from "path";
6052
+ import * as path13 from "path";
5830
6053
  import * as os2 from "os";
5831
6054
  import crypto2 from "crypto";
5832
6055
  function validateArchiveContents(entries, destDir) {
@@ -5841,9 +6064,9 @@ function validateArchiveContents(entries, destDir) {
5841
6064
  }
5842
6065
  }
5843
6066
  function validateUninstallPath(binaryPath, agentsDir) {
5844
- const realPath = path12.resolve(binaryPath);
5845
- const realAgentsDir = path12.resolve(agentsDir);
5846
- if (!realPath.startsWith(realAgentsDir + path12.sep) && realPath !== realAgentsDir) {
6067
+ const realPath = path13.resolve(binaryPath);
6068
+ const realAgentsDir = path13.resolve(agentsDir);
6069
+ if (!realPath.startsWith(realAgentsDir + path13.sep) && realPath !== realAgentsDir) {
5847
6070
  throw new Error(`Refusing to delete path outside agents directory: ${realPath}`);
5848
6071
  }
5849
6072
  }
@@ -5897,7 +6120,7 @@ function buildInstalledAgent(registryId, name, version, dist, binaryPath) {
5897
6120
  binaryPath: null
5898
6121
  };
5899
6122
  }
5900
- const absCmd = path12.resolve(binaryPath, dist.cmd);
6123
+ const absCmd = path13.resolve(binaryPath, dist.cmd);
5901
6124
  return {
5902
6125
  registryId,
5903
6126
  name,
@@ -5963,7 +6186,7 @@ Install it with: pip install uv`;
5963
6186
  return { ok: true, agentKey, setupSteps: setupSteps.length > 0 ? setupSteps : void 0 };
5964
6187
  }
5965
6188
  async function downloadAndExtract(agentId, archiveUrl, progress, agentsDir) {
5966
- const destDir = path12.join(agentsDir ?? DEFAULT_AGENTS_DIR, agentId);
6189
+ const destDir = path13.join(agentsDir ?? DEFAULT_AGENTS_DIR, agentId);
5967
6190
  fs10.mkdirSync(destDir, { recursive: true });
5968
6191
  await progress?.onStep("Downloading...");
5969
6192
  log2.info({ agentId, url: archiveUrl }, "Downloading agent binary");
@@ -6010,15 +6233,15 @@ function validateExtractedPaths(destDir) {
6010
6233
  for (const entry of entries) {
6011
6234
  const dirent = entry;
6012
6235
  const parentPath = dirent.parentPath ?? dirent.path ?? destDir;
6013
- const fullPath = path12.join(parentPath, entry.name);
6236
+ const fullPath = path13.join(parentPath, entry.name);
6014
6237
  let realPath;
6015
6238
  try {
6016
6239
  realPath = fs10.realpathSync(fullPath);
6017
6240
  } catch {
6018
6241
  const linkTarget = fs10.readlinkSync(fullPath);
6019
- realPath = path12.resolve(path12.dirname(fullPath), linkTarget);
6242
+ realPath = path13.resolve(path13.dirname(fullPath), linkTarget);
6020
6243
  }
6021
- if (!realPath.startsWith(realDest + path12.sep) && realPath !== realDest) {
6244
+ if (!realPath.startsWith(realDest + path13.sep) && realPath !== realDest) {
6022
6245
  fs10.rmSync(destDir, { recursive: true, force: true });
6023
6246
  throw new Error(`Archive contains unsafe path: ${entry.name}`);
6024
6247
  }
@@ -6026,7 +6249,7 @@ function validateExtractedPaths(destDir) {
6026
6249
  }
6027
6250
  async function extractTarGz(buffer, destDir) {
6028
6251
  const { execFileSync: execFileSync9 } = await import("child_process");
6029
- const tmpFile = path12.join(destDir, "_archive.tar.gz");
6252
+ const tmpFile = path13.join(destDir, "_archive.tar.gz");
6030
6253
  fs10.writeFileSync(tmpFile, buffer);
6031
6254
  try {
6032
6255
  const listing = execFileSync9("tar", ["tf", tmpFile], { stdio: "pipe" }).toString().trim().split("\n").filter(Boolean);
@@ -6039,7 +6262,7 @@ async function extractTarGz(buffer, destDir) {
6039
6262
  }
6040
6263
  async function extractZip(buffer, destDir) {
6041
6264
  const { execFileSync: execFileSync9 } = await import("child_process");
6042
- const tmpFile = path12.join(destDir, "_archive.zip");
6265
+ const tmpFile = path13.join(destDir, "_archive.zip");
6043
6266
  fs10.writeFileSync(tmpFile, buffer);
6044
6267
  try {
6045
6268
  const listing = execFileSync9("unzip", ["-l", tmpFile], { stdio: "pipe" }).toString().trim().split("\n").filter(Boolean);
@@ -6068,7 +6291,7 @@ var init_agent_installer = __esm({
6068
6291
  init_log();
6069
6292
  init_agent_dependencies();
6070
6293
  log2 = createChildLogger({ module: "agent-installer" });
6071
- DEFAULT_AGENTS_DIR = path12.join(os2.homedir(), ".openacp", "agents");
6294
+ DEFAULT_AGENTS_DIR = path13.join(os2.homedir(), ".openacp", "agents");
6072
6295
  MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
6073
6296
  validateTarContents = validateArchiveContents;
6074
6297
  ARCH_MAP = {
@@ -6085,7 +6308,7 @@ var init_agent_installer = __esm({
6085
6308
 
6086
6309
  // src/core/utils/install-binary.ts
6087
6310
  import fs11 from "fs";
6088
- import path13 from "path";
6311
+ import path14 from "path";
6089
6312
  import https from "https";
6090
6313
  import os3 from "os";
6091
6314
  import { execFileSync as execFileSync3 } from "child_process";
@@ -6160,7 +6383,7 @@ function getDownloadUrl(spec) {
6160
6383
  async function ensureBinary(spec, binDir) {
6161
6384
  const resolvedBinDir = binDir ?? DEFAULT_BIN_DIR;
6162
6385
  const binName = IS_WINDOWS ? `${spec.name}.exe` : spec.name;
6163
- const binPath = path13.join(resolvedBinDir, binName);
6386
+ const binPath = path14.join(resolvedBinDir, binName);
6164
6387
  if (commandExists(spec.name)) {
6165
6388
  log3.debug({ name: spec.name }, "Found in PATH");
6166
6389
  return spec.name;
@@ -6174,7 +6397,7 @@ async function ensureBinary(spec, binDir) {
6174
6397
  fs11.mkdirSync(resolvedBinDir, { recursive: true });
6175
6398
  const url = getDownloadUrl(spec);
6176
6399
  const isArchive = spec.isArchive?.(url) ?? false;
6177
- const downloadDest = isArchive ? path13.join(resolvedBinDir, `${spec.name}.tgz`) : binPath;
6400
+ const downloadDest = isArchive ? path14.join(resolvedBinDir, `${spec.name}.tgz`) : binPath;
6178
6401
  await downloadFile(url, downloadDest);
6179
6402
  if (isArchive) {
6180
6403
  const listing = execFileSync3("tar", ["-tf", downloadDest], { stdio: "pipe" }).toString().trim().split("\n").filter(Boolean);
@@ -6202,7 +6425,7 @@ var init_install_binary = __esm({
6202
6425
  init_agent_dependencies();
6203
6426
  init_agent_installer();
6204
6427
  log3 = createChildLogger({ module: "binary-installer" });
6205
- DEFAULT_BIN_DIR = path13.join(os3.homedir(), ".openacp", "bin");
6428
+ DEFAULT_BIN_DIR = path14.join(os3.homedir(), ".openacp", "bin");
6206
6429
  IS_WINDOWS = os3.platform() === "win32";
6207
6430
  }
6208
6431
  });
@@ -6245,7 +6468,7 @@ var init_install_cloudflared = __esm({
6245
6468
  // src/plugins/tunnel/providers/cloudflare.ts
6246
6469
  import { spawn } from "child_process";
6247
6470
  import fs12 from "fs";
6248
- import path14 from "path";
6471
+ import path15 from "path";
6249
6472
  var log4, SIGKILL_TIMEOUT_MS, CloudflareTunnelProvider;
6250
6473
  var init_cloudflare = __esm({
6251
6474
  "src/plugins/tunnel/providers/cloudflare.ts"() {
@@ -6357,7 +6580,7 @@ var init_cloudflare = __esm({
6357
6580
  }
6358
6581
  findBinary() {
6359
6582
  if (commandExists("cloudflared")) return "cloudflared";
6360
- const binPath = path14.join(this.binDir, "cloudflared");
6583
+ const binPath = path15.join(this.binDir, "cloudflared");
6361
6584
  if (fs12.existsSync(binPath)) return binPath;
6362
6585
  return null;
6363
6586
  }
@@ -6713,7 +6936,7 @@ var init_tailscale = __esm({
6713
6936
  // src/plugins/tunnel/providers/openacp.ts
6714
6937
  import { spawn as spawn5 } from "child_process";
6715
6938
  import fs13 from "fs";
6716
- import path15 from "path";
6939
+ import path16 from "path";
6717
6940
  var log8, DEFAULT_WORKER_URL, DEFAULT_API_KEY, HEARTBEAT_INTERVAL_MS, STARTUP_TIMEOUT_MS, SIGKILL_TIMEOUT_MS5, STORAGE_KEY, OpenACPTunnelProvider;
6718
6941
  var init_openacp = __esm({
6719
6942
  "src/plugins/tunnel/providers/openacp.ts"() {
@@ -6915,7 +7138,7 @@ var init_openacp = __esm({
6915
7138
  }
6916
7139
  async resolveBinary() {
6917
7140
  if (commandExists("cloudflared")) return "cloudflared";
6918
- const binPath = path15.join(this.binDir, "cloudflared");
7141
+ const binPath = path16.join(this.binDir, "cloudflared");
6919
7142
  if (fs13.existsSync(binPath)) return binPath;
6920
7143
  log8.warn("cloudflared not found, attempting auto-install...");
6921
7144
  const { ensureCloudflared: ensureCloudflared2 } = await Promise.resolve().then(() => (init_install_cloudflared(), install_cloudflared_exports));
@@ -6927,7 +7150,7 @@ var init_openacp = __esm({
6927
7150
 
6928
7151
  // src/plugins/tunnel/tunnel-registry.ts
6929
7152
  import fs14 from "fs";
6930
- import path16 from "path";
7153
+ import path17 from "path";
6931
7154
  var log9, MAX_RETRIES, BASE_RETRY_DELAY_MS, TunnelRegistry;
6932
7155
  var init_tunnel_registry = __esm({
6933
7156
  "src/plugins/tunnel/tunnel-registry.ts"() {
@@ -7252,7 +7475,7 @@ var init_tunnel_registry = __esm({
7252
7475
  createdAt: l.entry.createdAt
7253
7476
  }));
7254
7477
  try {
7255
- const dir = path16.dirname(this.registryPath);
7478
+ const dir = path17.dirname(this.registryPath);
7256
7479
  fs14.mkdirSync(dir, { recursive: true });
7257
7480
  fs14.writeFileSync(this.registryPath, JSON.stringify(data, null, 2));
7258
7481
  } catch (err) {
@@ -7687,7 +7910,7 @@ var init_output_viewer = __esm({
7687
7910
  });
7688
7911
 
7689
7912
  // src/plugins/tunnel/viewer-routes.ts
7690
- import path17 from "path";
7913
+ import path18 from "path";
7691
7914
  function createViewerRoutes(store) {
7692
7915
  return async (app) => {
7693
7916
  app.get("/view/:id", async (request, reply) => {
@@ -7717,7 +7940,7 @@ function createViewerRoutes(store) {
7717
7940
  return reply.status(404).send({ error: "not found" });
7718
7941
  }
7719
7942
  return reply.send({
7720
- filePath: entry.filePath ? path17.basename(entry.filePath) : null,
7943
+ filePath: entry.filePath ? path18.basename(entry.filePath) : null,
7721
7944
  content: entry.content,
7722
7945
  language: entry.language
7723
7946
  });
@@ -7728,7 +7951,7 @@ function createViewerRoutes(store) {
7728
7951
  return reply.status(404).send({ error: "not found" });
7729
7952
  }
7730
7953
  return reply.send({
7731
- filePath: entry.filePath ? path17.basename(entry.filePath) : null,
7954
+ filePath: entry.filePath ? path18.basename(entry.filePath) : null,
7732
7955
  oldContent: entry.oldContent,
7733
7956
  newContent: entry.content,
7734
7957
  language: entry.language
@@ -7753,7 +7976,7 @@ var init_viewer_routes = __esm({
7753
7976
 
7754
7977
  // src/plugins/tunnel/viewer-store.ts
7755
7978
  import * as fs15 from "fs";
7756
- import * as path18 from "path";
7979
+ import * as path19 from "path";
7757
7980
  import { nanoid as nanoid2 } from "nanoid";
7758
7981
  var log10, MAX_CONTENT_SIZE, EXTENSION_LANGUAGE, ViewerStore;
7759
7982
  var init_viewer_store = __esm({
@@ -7909,24 +8132,24 @@ var init_viewer_store = __esm({
7909
8132
  let resolved;
7910
8133
  let workspace;
7911
8134
  try {
7912
- resolved = fs15.realpathSync(path18.resolve(workingDirectory, filePath));
8135
+ resolved = fs15.realpathSync(path19.resolve(workingDirectory, filePath));
7913
8136
  } catch {
7914
- resolved = path18.resolve(workingDirectory, filePath);
8137
+ resolved = path19.resolve(workingDirectory, filePath);
7915
8138
  }
7916
8139
  try {
7917
- workspace = fs15.realpathSync(path18.resolve(workingDirectory));
8140
+ workspace = fs15.realpathSync(path19.resolve(workingDirectory));
7918
8141
  } catch {
7919
- workspace = path18.resolve(workingDirectory);
8142
+ workspace = path19.resolve(workingDirectory);
7920
8143
  }
7921
8144
  if (caseInsensitive) {
7922
8145
  const rLower = resolved.toLowerCase();
7923
8146
  const wLower = workspace.toLowerCase();
7924
- return rLower.startsWith(wLower + path18.sep) || rLower === wLower;
8147
+ return rLower.startsWith(wLower + path19.sep) || rLower === wLower;
7925
8148
  }
7926
- return resolved.startsWith(workspace + path18.sep) || resolved === workspace;
8149
+ return resolved.startsWith(workspace + path19.sep) || resolved === workspace;
7927
8150
  }
7928
8151
  detectLanguage(filePath) {
7929
- const ext = path18.extname(filePath).toLowerCase();
8152
+ const ext = path19.extname(filePath).toLowerCase();
7930
8153
  return EXTENSION_LANGUAGE[ext];
7931
8154
  }
7932
8155
  destroy() {
@@ -8073,7 +8296,7 @@ var tunnel_exports = {};
8073
8296
  __export(tunnel_exports, {
8074
8297
  default: () => tunnel_default
8075
8298
  });
8076
- import path19 from "path";
8299
+ import path20 from "path";
8077
8300
  function createTunnelPlugin() {
8078
8301
  let service = null;
8079
8302
  return {
@@ -8179,10 +8402,10 @@ function createTunnelPlugin() {
8179
8402
  { key: "provider", displayName: "Provider", type: "select", scope: "safe", hotReload: false, options: ["openacp", "cloudflare", "ngrok", "bore", "tailscale"] }
8180
8403
  ]);
8181
8404
  const { default: fs57 } = await import("fs");
8182
- const settingsPath = path19.join(ctx.instanceRoot, "plugins", "data", ctx.pluginName, "settings.json");
8405
+ const settingsPath = path20.join(ctx.instanceRoot, "plugins", "data", ctx.pluginName, "settings.json");
8183
8406
  if (!fs57.existsSync(settingsPath)) {
8184
8407
  const defaults = { enabled: true, provider: "openacp", maxUserTunnels: 5, auth: { enabled: false } };
8185
- fs57.mkdirSync(path19.dirname(settingsPath), { recursive: true });
8408
+ fs57.mkdirSync(path20.dirname(settingsPath), { recursive: true });
8186
8409
  fs57.writeFileSync(settingsPath, JSON.stringify(defaults, null, 2));
8187
8410
  Object.assign(ctx.pluginConfig, defaults);
8188
8411
  ctx.log.info("Initialized tunnel settings with defaults (openacp provider)");
@@ -8218,8 +8441,8 @@ function createTunnelPlugin() {
8218
8441
  const instanceRoot = ctx.instanceRoot;
8219
8442
  const tunnelSvc = new TunnelService2(
8220
8443
  config,
8221
- path19.join(instanceRoot, "tunnels.json"),
8222
- path19.join(instanceRoot, "bin"),
8444
+ path20.join(instanceRoot, "tunnels.json"),
8445
+ path20.join(instanceRoot, "bin"),
8223
8446
  ctx.storage,
8224
8447
  (event, data) => ctx.emit(event, data)
8225
8448
  );
@@ -8318,7 +8541,7 @@ __export(token_store_exports, {
8318
8541
  TokenStore: () => TokenStore,
8319
8542
  parseDuration: () => parseDuration
8320
8543
  });
8321
- import { readFile as readFile2, writeFile } from "fs/promises";
8544
+ import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
8322
8545
  import { randomBytes as randomBytes2 } from "crypto";
8323
8546
  function generateTokenId() {
8324
8547
  return `tok_${randomBytes2(12).toString("hex")}`;
@@ -8387,7 +8610,7 @@ var init_token_store = __esm({
8387
8610
  tokens: Array.from(this.tokens.values()),
8388
8611
  codes: Array.from(this.codes.values())
8389
8612
  };
8390
- await writeFile(this.filePath, JSON.stringify(data, null, 2), "utf-8");
8613
+ await writeFile2(this.filePath, JSON.stringify(data, null, 2), "utf-8");
8391
8614
  }
8392
8615
  /**
8393
8616
  * Coalesces concurrent writes: if a save is in-flight, sets a pending flag
@@ -8595,22 +8818,22 @@ __export(config_registry_exports, {
8595
8818
  resolveOptions: () => resolveOptions,
8596
8819
  setFieldValueAsync: () => setFieldValueAsync
8597
8820
  });
8598
- function getFieldDef(path71) {
8599
- return CONFIG_REGISTRY.find((f) => f.path === path71);
8821
+ function getFieldDef(path72) {
8822
+ return CONFIG_REGISTRY.find((f) => f.path === path72);
8600
8823
  }
8601
8824
  function getSafeFields() {
8602
8825
  return CONFIG_REGISTRY.filter((f) => f.scope === "safe");
8603
8826
  }
8604
- function isHotReloadable(path71) {
8605
- const def = getFieldDef(path71);
8827
+ function isHotReloadable(path72) {
8828
+ const def = getFieldDef(path72);
8606
8829
  return def?.hotReload ?? false;
8607
8830
  }
8608
8831
  function resolveOptions(def, config) {
8609
8832
  if (!def.options) return void 0;
8610
8833
  return typeof def.options === "function" ? def.options(config) : def.options;
8611
8834
  }
8612
- function getConfigValue(config, path71) {
8613
- const parts = path71.split(".");
8835
+ function getConfigValue(config, path72) {
8836
+ const parts = path72.split(".");
8614
8837
  let current = config;
8615
8838
  for (const part of parts) {
8616
8839
  if (current && typeof current === "object" && part in current) {
@@ -9270,8 +9493,8 @@ __export(static_server_exports, {
9270
9493
  StaticServer: () => StaticServer
9271
9494
  });
9272
9495
  import * as fs16 from "fs";
9273
- import * as path20 from "path";
9274
- import { fileURLToPath as fileURLToPath2 } from "url";
9496
+ import * as path21 from "path";
9497
+ import { fileURLToPath as fileURLToPath3 } from "url";
9275
9498
  var MIME_TYPES, StaticServer;
9276
9499
  var init_static_server = __esm({
9277
9500
  "src/plugins/api-server/static-server.ts"() {
@@ -9293,17 +9516,17 @@ var init_static_server = __esm({
9293
9516
  constructor(uiDir) {
9294
9517
  this.uiDir = uiDir;
9295
9518
  if (!this.uiDir) {
9296
- const __filename = fileURLToPath2(import.meta.url);
9297
- const candidate = path20.resolve(path20.dirname(__filename), "../../ui/dist");
9298
- if (fs16.existsSync(path20.join(candidate, "index.html"))) {
9519
+ const __filename = fileURLToPath3(import.meta.url);
9520
+ const candidate = path21.resolve(path21.dirname(__filename), "../../ui/dist");
9521
+ if (fs16.existsSync(path21.join(candidate, "index.html"))) {
9299
9522
  this.uiDir = candidate;
9300
9523
  }
9301
9524
  if (!this.uiDir) {
9302
- const publishCandidate = path20.resolve(
9303
- path20.dirname(__filename),
9525
+ const publishCandidate = path21.resolve(
9526
+ path21.dirname(__filename),
9304
9527
  "../ui"
9305
9528
  );
9306
- if (fs16.existsSync(path20.join(publishCandidate, "index.html"))) {
9529
+ if (fs16.existsSync(path21.join(publishCandidate, "index.html"))) {
9307
9530
  this.uiDir = publishCandidate;
9308
9531
  }
9309
9532
  }
@@ -9321,9 +9544,9 @@ var init_static_server = __esm({
9321
9544
  serve(req, res) {
9322
9545
  if (!this.uiDir) return false;
9323
9546
  const urlPath = (req.url || "/").split("?")[0];
9324
- const safePath = path20.normalize(urlPath);
9325
- const filePath = path20.join(this.uiDir, safePath);
9326
- if (!filePath.startsWith(this.uiDir + path20.sep) && filePath !== this.uiDir)
9547
+ const safePath = path21.normalize(urlPath);
9548
+ const filePath = path21.join(this.uiDir, safePath);
9549
+ if (!filePath.startsWith(this.uiDir + path21.sep) && filePath !== this.uiDir)
9327
9550
  return false;
9328
9551
  let realFilePath;
9329
9552
  try {
@@ -9333,11 +9556,11 @@ var init_static_server = __esm({
9333
9556
  }
9334
9557
  if (realFilePath !== null) {
9335
9558
  const realUiDir = fs16.realpathSync(this.uiDir);
9336
- if (!realFilePath.startsWith(realUiDir + path20.sep) && realFilePath !== realUiDir)
9559
+ if (!realFilePath.startsWith(realUiDir + path21.sep) && realFilePath !== realUiDir)
9337
9560
  return false;
9338
9561
  }
9339
9562
  if (realFilePath !== null && fs16.existsSync(realFilePath) && fs16.statSync(realFilePath).isFile()) {
9340
- const ext = path20.extname(filePath);
9563
+ const ext = path21.extname(filePath);
9341
9564
  const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
9342
9565
  const isHashed = /\.[a-zA-Z0-9]{8,}\.(js|css)$/.test(filePath);
9343
9566
  const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
@@ -9348,7 +9571,7 @@ var init_static_server = __esm({
9348
9571
  fs16.createReadStream(realFilePath).pipe(res);
9349
9572
  return true;
9350
9573
  }
9351
- const indexPath = path20.join(this.uiDir, "index.html");
9574
+ const indexPath = path21.join(this.uiDir, "index.html");
9352
9575
  if (fs16.existsSync(indexPath)) {
9353
9576
  res.writeHead(200, {
9354
9577
  "Content-Type": "text/html; charset=utf-8",
@@ -10043,15 +10266,23 @@ var init_agent_registry = __esm({
10043
10266
  // src/plugins/api-server/routes/agents.ts
10044
10267
  var agents_exports = {};
10045
10268
  __export(agents_exports, {
10046
- agentRoutes: () => agentRoutes
10269
+ agentRoutes: () => agentRoutes,
10270
+ redactAgentEnv: () => redactAgentEnv
10047
10271
  });
10272
+ function redactAgentEnv(agent) {
10273
+ if (!agent.env) return agent;
10274
+ return {
10275
+ ...agent,
10276
+ env: Object.fromEntries(Object.keys(agent.env).map((key) => [key, "***"]))
10277
+ };
10278
+ }
10048
10279
  async function agentRoutes(app, deps) {
10049
10280
  function loadAndListAgents() {
10050
10281
  deps.core.agentCatalog.load();
10051
10282
  const agents = deps.core.agentManager.getAvailableAgents();
10052
10283
  const defaultAgent = deps.core.configManager.get().defaultAgent;
10053
10284
  const agentsWithCaps = agents.map((a) => ({
10054
- ...a,
10285
+ ...redactAgentEnv(a),
10055
10286
  capabilities: getAgentCapabilities(a.name)
10056
10287
  }));
10057
10288
  return { agents: agentsWithCaps, default: defaultAgent };
@@ -10069,7 +10300,7 @@ async function agentRoutes(app, deps) {
10069
10300
  throw new NotFoundError("AGENT_NOT_FOUND", `Agent "${name}" not found`);
10070
10301
  }
10071
10302
  return {
10072
- ...agent,
10303
+ ...redactAgentEnv(agent),
10073
10304
  key: name,
10074
10305
  capabilities: getAgentCapabilities(name)
10075
10306
  };
@@ -10100,7 +10331,7 @@ var init_config = __esm({
10100
10331
 
10101
10332
  // src/core/config/config-migrations.ts
10102
10333
  import fs18 from "fs";
10103
- import path21 from "path";
10334
+ import path22 from "path";
10104
10335
  import os4 from "os";
10105
10336
  function applyMigrations(raw, migrationList = migrations, ctx) {
10106
10337
  let changed = false;
@@ -10150,7 +10381,7 @@ var init_config_migrations = __esm({
10150
10381
  if (!ctx?.configDir) return false;
10151
10382
  const instanceRoot = ctx.configDir;
10152
10383
  try {
10153
- const registryPath = path21.join(os4.homedir(), ".openacp", "instances.json");
10384
+ const registryPath = path22.join(os4.homedir(), ".openacp", "instances.json");
10154
10385
  const data = JSON.parse(fs18.readFileSync(registryPath, "utf-8"));
10155
10386
  const instances = data?.instances ?? {};
10156
10387
  const entry = Object.values(instances).find(
@@ -10179,13 +10410,13 @@ __export(config_exports, {
10179
10410
  });
10180
10411
  import { z as z4 } from "zod";
10181
10412
  import * as fs19 from "fs";
10182
- import * as path22 from "path";
10413
+ import * as path23 from "path";
10183
10414
  import * as os5 from "os";
10184
10415
  import { randomBytes as randomBytes3 } from "crypto";
10185
10416
  import { EventEmitter } from "events";
10186
10417
  function expandHome2(p2) {
10187
10418
  if (p2.startsWith("~")) {
10188
- return path22.join(os5.homedir(), p2.slice(1));
10419
+ return path23.join(os5.homedir(), p2.slice(1));
10189
10420
  }
10190
10421
  return p2;
10191
10422
  }
@@ -10259,7 +10490,7 @@ var init_config2 = __esm({
10259
10490
  * 4. Validate against Zod schema — exits on failure
10260
10491
  */
10261
10492
  async load() {
10262
- const dir = path22.dirname(this.configPath);
10493
+ const dir = path23.dirname(this.configPath);
10263
10494
  fs19.mkdirSync(dir, { recursive: true });
10264
10495
  if (!fs19.existsSync(this.configPath)) {
10265
10496
  fs19.writeFileSync(
@@ -10273,7 +10504,7 @@ var init_config2 = __esm({
10273
10504
  process.exit(1);
10274
10505
  }
10275
10506
  const raw = JSON.parse(fs19.readFileSync(this.configPath, "utf-8"));
10276
- const { changed: configUpdated } = applyMigrations(raw, void 0, { configDir: path22.dirname(this.configPath) });
10507
+ const { changed: configUpdated } = applyMigrations(raw, void 0, { configDir: path23.dirname(this.configPath) });
10277
10508
  if (configUpdated) {
10278
10509
  fs19.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));
10279
10510
  }
@@ -10353,16 +10584,16 @@ var init_config2 = __esm({
10353
10584
  * (alphanumeric subdirectories under the base).
10354
10585
  */
10355
10586
  resolveWorkspace(input2) {
10356
- const workspaceBase = path22.dirname(path22.dirname(this.configPath));
10587
+ const workspaceBase = path23.dirname(path23.dirname(this.configPath));
10357
10588
  if (!input2) {
10358
10589
  fs19.mkdirSync(workspaceBase, { recursive: true });
10359
10590
  return workspaceBase;
10360
10591
  }
10361
10592
  const expanded = input2.startsWith("~") ? expandHome2(input2) : input2;
10362
- if (path22.isAbsolute(expanded)) {
10363
- const resolved = path22.resolve(expanded);
10364
- const base = path22.resolve(workspaceBase);
10365
- const isInternal = resolved === base || resolved.startsWith(base + path22.sep);
10593
+ if (path23.isAbsolute(expanded)) {
10594
+ const resolved = path23.resolve(expanded);
10595
+ const base = path23.resolve(workspaceBase);
10596
+ const isInternal = resolved === base || resolved.startsWith(base + path23.sep);
10366
10597
  if (!isInternal) {
10367
10598
  if (!this.config.workspace.allowExternalWorkspaces) {
10368
10599
  throw new Error(
@@ -10382,7 +10613,7 @@ var init_config2 = __esm({
10382
10613
  `Invalid workspace name: "${input2}". Only alphanumeric characters, hyphens, and underscores are allowed.`
10383
10614
  );
10384
10615
  }
10385
- const namedPath = path22.join(workspaceBase, input2.toLowerCase());
10616
+ const namedPath = path23.join(workspaceBase, input2.toLowerCase());
10386
10617
  fs19.mkdirSync(namedPath, { recursive: true });
10387
10618
  return namedPath;
10388
10619
  }
@@ -10396,7 +10627,7 @@ var init_config2 = __esm({
10396
10627
  }
10397
10628
  /** Writes a complete config object to disk, creating the directory if needed. Used during initial setup. */
10398
10629
  async writeNew(config) {
10399
- const dir = path22.dirname(this.configPath);
10630
+ const dir = path23.dirname(this.configPath);
10400
10631
  fs19.mkdirSync(dir, { recursive: true });
10401
10632
  fs19.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
10402
10633
  }
@@ -10414,6 +10645,14 @@ var init_config2 = __esm({
10414
10645
  { envVar: "OPENACP_API_PORT", pluginName: "@openacp/api-server", key: "port", transform: (v) => Number(v) },
10415
10646
  { envVar: "OPENACP_SPEECH_STT_PROVIDER", pluginName: "@openacp/speech", key: "sttProvider" },
10416
10647
  { envVar: "OPENACP_SPEECH_GROQ_API_KEY", pluginName: "@openacp/speech", key: "groqApiKey" },
10648
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_LANGUAGE", pluginName: "@openacp/speech", key: "localWhisperLanguage" },
10649
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_MODEL", pluginName: "@openacp/speech", key: "localWhisperModel" },
10650
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_BEAM_SIZE", pluginName: "@openacp/speech", key: "localWhisperBeamSize", transform: (v) => Number(v) },
10651
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_VAD_FILTER", pluginName: "@openacp/speech", key: "localWhisperVadFilter", transform: (v) => v === "true" },
10652
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_DEVICE", pluginName: "@openacp/speech", key: "localWhisperDevice" },
10653
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_COMPUTE_TYPE", pluginName: "@openacp/speech", key: "localWhisperComputeType" },
10654
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_TIMEOUT_MS", pluginName: "@openacp/speech", key: "localWhisperTimeoutMs", transform: (v) => Number(v) },
10655
+ { envVar: "OPENACP_SPEECH_LOCAL_WHISPER_SCRIPT_PATH", pluginName: "@openacp/speech", key: "localWhisperScriptPath" },
10417
10656
  { envVar: "OPENACP_TELEGRAM_BOT_TOKEN", pluginName: "@openacp/telegram", key: "botToken" },
10418
10657
  { envVar: "OPENACP_TELEGRAM_CHAT_ID", pluginName: "@openacp/telegram", key: "chatId", transform: (v) => Number(v) },
10419
10658
  // Future adapters — no-ops if plugin settings don't exist
@@ -11131,7 +11370,7 @@ var plugins_exports = {};
11131
11370
  __export(plugins_exports, {
11132
11371
  pluginRoutes: () => pluginRoutes
11133
11372
  });
11134
- import path23 from "path";
11373
+ import path24 from "path";
11135
11374
  async function pluginRoutes(app, deps) {
11136
11375
  const { lifecycleManager } = deps;
11137
11376
  const admin = [requireScopes("system:admin")];
@@ -11196,7 +11435,7 @@ async function pluginRoutes(app, deps) {
11196
11435
  } else {
11197
11436
  const { importFromDir: importFromDir2 } = await Promise.resolve().then(() => (init_plugin_installer(), plugin_installer_exports));
11198
11437
  const instanceRoot = lifecycleManager.instanceRoot;
11199
- const pluginsDir = path23.join(instanceRoot, "plugins");
11438
+ const pluginsDir = path24.join(instanceRoot, "plugins");
11200
11439
  try {
11201
11440
  const mod = await importFromDir2(name, pluginsDir);
11202
11441
  pluginDef = mod.default ?? mod;
@@ -11272,11 +11511,11 @@ __export(instance_registry_exports, {
11272
11511
  readIdFromConfig: () => readIdFromConfig
11273
11512
  });
11274
11513
  import fs20 from "fs";
11275
- import path24 from "path";
11514
+ import path25 from "path";
11276
11515
  import { randomUUID } from "crypto";
11277
11516
  function readIdFromConfig(instanceRoot) {
11278
11517
  try {
11279
- const raw = JSON.parse(fs20.readFileSync(path24.join(instanceRoot, "config.json"), "utf-8"));
11518
+ const raw = JSON.parse(fs20.readFileSync(path25.join(instanceRoot, "config.json"), "utf-8"));
11280
11519
  return typeof raw.id === "string" && raw.id ? raw.id : null;
11281
11520
  } catch {
11282
11521
  return null;
@@ -11322,7 +11561,7 @@ var init_instance_registry = __esm({
11322
11561
  }
11323
11562
  /** Persist the registry to disk, creating parent directories if needed. */
11324
11563
  save() {
11325
- const dir = path24.dirname(this.registryPath);
11564
+ const dir = path25.dirname(this.registryPath);
11326
11565
  fs20.mkdirSync(dir, { recursive: true });
11327
11566
  fs20.writeFileSync(this.registryPath, JSON.stringify(this.data, null, 2));
11328
11567
  }
@@ -11392,7 +11631,7 @@ __export(instance_context_exports, {
11392
11631
  resolveInstanceRoot: () => resolveInstanceRoot,
11393
11632
  resolveRunningInstance: () => resolveRunningInstance
11394
11633
  });
11395
- import path25 from "path";
11634
+ import path26 from "path";
11396
11635
  import fs21 from "fs";
11397
11636
  import os6 from "os";
11398
11637
  function createInstanceContext(opts) {
@@ -11402,22 +11641,22 @@ function createInstanceContext(opts) {
11402
11641
  id,
11403
11642
  root,
11404
11643
  paths: {
11405
- config: path25.join(root, "config.json"),
11406
- sessions: path25.join(root, "sessions.json"),
11407
- agents: path25.join(root, "agents.json"),
11408
- registryCache: path25.join(globalRoot, "cache", "registry-cache.json"),
11409
- plugins: path25.join(root, "plugins"),
11410
- pluginsData: path25.join(root, "plugins", "data"),
11411
- pluginRegistry: path25.join(root, "plugins.json"),
11412
- logs: path25.join(root, "logs"),
11413
- pid: path25.join(root, "openacp.pid"),
11414
- running: path25.join(root, "running"),
11415
- apiPort: path25.join(root, "api.port"),
11416
- apiSecret: path25.join(root, "api-secret"),
11417
- bin: path25.join(globalRoot, "bin"),
11418
- cache: path25.join(root, "cache"),
11419
- tunnels: path25.join(root, "tunnels.json"),
11420
- agentsDir: path25.join(globalRoot, "agents")
11644
+ config: path26.join(root, "config.json"),
11645
+ sessions: path26.join(root, "sessions.json"),
11646
+ agents: path26.join(root, "agents.json"),
11647
+ registryCache: path26.join(globalRoot, "cache", "registry-cache.json"),
11648
+ plugins: path26.join(root, "plugins"),
11649
+ pluginsData: path26.join(root, "plugins", "data"),
11650
+ pluginRegistry: path26.join(root, "plugins.json"),
11651
+ logs: path26.join(root, "logs"),
11652
+ pid: path26.join(root, "openacp.pid"),
11653
+ running: path26.join(root, "running"),
11654
+ apiPort: path26.join(root, "api.port"),
11655
+ apiSecret: path26.join(root, "api-secret"),
11656
+ bin: path26.join(globalRoot, "bin"),
11657
+ cache: path26.join(root, "cache"),
11658
+ tunnels: path26.join(root, "tunnels.json"),
11659
+ agentsDir: path26.join(globalRoot, "agents")
11421
11660
  }
11422
11661
  };
11423
11662
  }
@@ -11426,50 +11665,50 @@ function generateSlug(name) {
11426
11665
  return slug || "openacp";
11427
11666
  }
11428
11667
  function expandHome3(p2) {
11429
- if (p2.startsWith("~")) return path25.join(os6.homedir(), p2.slice(1));
11668
+ if (p2.startsWith("~")) return path26.join(os6.homedir(), p2.slice(1));
11430
11669
  return p2;
11431
11670
  }
11432
11671
  function resolveInstanceRoot(opts) {
11433
11672
  const cwd = opts.cwd ?? process.cwd();
11434
11673
  const home = os6.homedir();
11435
11674
  const globalRoot = getGlobalRoot();
11436
- if (opts.dir) return path25.join(expandHome3(opts.dir), ".openacp");
11437
- if (opts.local) return path25.join(cwd, ".openacp");
11438
- const cwdRoot = path25.join(cwd, ".openacp");
11439
- if (fs21.existsSync(path25.join(cwdRoot, "config.json"))) return cwdRoot;
11440
- let dir = path25.resolve(cwd);
11675
+ if (opts.dir) return path26.join(expandHome3(opts.dir), ".openacp");
11676
+ if (opts.local) return path26.join(cwd, ".openacp");
11677
+ const cwdRoot = path26.join(cwd, ".openacp");
11678
+ if (fs21.existsSync(path26.join(cwdRoot, "config.json"))) return cwdRoot;
11679
+ let dir = path26.resolve(cwd);
11441
11680
  while (true) {
11442
- const parent = path25.dirname(dir);
11681
+ const parent = path26.dirname(dir);
11443
11682
  if (parent === dir) break;
11444
11683
  dir = parent;
11445
- const candidate = path25.join(dir, ".openacp");
11684
+ const candidate = path26.join(dir, ".openacp");
11446
11685
  if (candidate === globalRoot) {
11447
11686
  if (dir === home) break;
11448
11687
  continue;
11449
11688
  }
11450
- if (fs21.existsSync(path25.join(candidate, "config.json"))) return candidate;
11689
+ if (fs21.existsSync(path26.join(candidate, "config.json"))) return candidate;
11451
11690
  if (dir === home) break;
11452
11691
  }
11453
- if (path25.resolve(cwd) === path25.resolve(home)) {
11454
- const defaultWs = path25.join(home, "openacp-workspace", ".openacp");
11455
- if (fs21.existsSync(path25.join(defaultWs, "config.json"))) return defaultWs;
11692
+ if (path26.resolve(cwd) === path26.resolve(home)) {
11693
+ const defaultWs = path26.join(home, "openacp-workspace", ".openacp");
11694
+ if (fs21.existsSync(path26.join(defaultWs, "config.json"))) return defaultWs;
11456
11695
  }
11457
11696
  if (process.env.OPENACP_INSTANCE_ROOT) return process.env.OPENACP_INSTANCE_ROOT;
11458
11697
  return null;
11459
11698
  }
11460
11699
  function getGlobalRoot() {
11461
- return path25.join(os6.homedir(), ".openacp");
11700
+ return path26.join(os6.homedir(), ".openacp");
11462
11701
  }
11463
11702
  async function resolveRunningInstance(cwd) {
11464
11703
  const globalRoot = getGlobalRoot();
11465
11704
  const home = os6.homedir();
11466
- let dir = path25.resolve(cwd);
11705
+ let dir = path26.resolve(cwd);
11467
11706
  while (true) {
11468
- const candidate = path25.join(dir, ".openacp");
11707
+ const candidate = path26.join(dir, ".openacp");
11469
11708
  if (candidate !== globalRoot && fs21.existsSync(candidate)) {
11470
11709
  if (await isInstanceRunning(candidate)) return candidate;
11471
11710
  }
11472
- const parent = path25.dirname(dir);
11711
+ const parent = path26.dirname(dir);
11473
11712
  if (parent === dir) break;
11474
11713
  if (dir === home) break;
11475
11714
  dir = parent;
@@ -11477,7 +11716,7 @@ async function resolveRunningInstance(cwd) {
11477
11716
  return null;
11478
11717
  }
11479
11718
  async function isInstanceRunning(instanceRoot) {
11480
- const portFile = path25.join(instanceRoot, "api.port");
11719
+ const portFile = path26.join(instanceRoot, "api.port");
11481
11720
  try {
11482
11721
  const content = fs21.readFileSync(portFile, "utf-8").trim();
11483
11722
  const port = parseInt(content, 10);
@@ -11506,14 +11745,14 @@ __export(api_server_exports, {
11506
11745
  });
11507
11746
  import * as fs22 from "fs";
11508
11747
  import * as crypto3 from "crypto";
11509
- import * as path26 from "path";
11748
+ import * as path27 from "path";
11510
11749
  function getVersion() {
11511
11750
  if (cachedVersion) return cachedVersion;
11512
11751
  cachedVersion = getCurrentVersion();
11513
11752
  return cachedVersion;
11514
11753
  }
11515
11754
  function loadOrCreateSecret(secretFilePath) {
11516
- const dir = path26.dirname(secretFilePath);
11755
+ const dir = path27.dirname(secretFilePath);
11517
11756
  fs22.mkdirSync(dir, { recursive: true });
11518
11757
  try {
11519
11758
  const existing = fs22.readFileSync(secretFilePath, "utf-8").trim();
@@ -11539,7 +11778,7 @@ function loadOrCreateSecret(secretFilePath) {
11539
11778
  return secret;
11540
11779
  }
11541
11780
  function writePortFile(portFilePath, port) {
11542
- const dir = path26.dirname(portFilePath);
11781
+ const dir = path27.dirname(portFilePath);
11543
11782
  fs22.mkdirSync(dir, { recursive: true });
11544
11783
  fs22.writeFileSync(portFilePath, String(port));
11545
11784
  }
@@ -11624,10 +11863,10 @@ function createApiServerPlugin() {
11624
11863
  { port: apiConfig.port, host: apiConfig.host, instanceRoot },
11625
11864
  "API server plugin setup \u2014 config loaded"
11626
11865
  );
11627
- portFilePath = path26.join(instanceRoot, "api.port");
11628
- const secretFilePath = path26.join(instanceRoot, "api-secret");
11629
- const jwtSecretFilePath = path26.join(instanceRoot, "jwt-secret");
11630
- const tokensFilePath = path26.join(instanceRoot, "tokens.json");
11866
+ portFilePath = path27.join(instanceRoot, "api.port");
11867
+ const secretFilePath = path27.join(instanceRoot, "api-secret");
11868
+ const jwtSecretFilePath = path27.join(instanceRoot, "jwt-secret");
11869
+ const tokensFilePath = path27.join(instanceRoot, "tokens.json");
11631
11870
  const startedAt = Date.now();
11632
11871
  const secret = loadOrCreateSecret(secretFilePath);
11633
11872
  const jwtSecret = loadOrCreateSecret(jwtSecretFilePath);
@@ -11666,7 +11905,7 @@ function createApiServerPlugin() {
11666
11905
  const { InstanceRegistry: InstanceRegistry2 } = await Promise.resolve().then(() => (init_instance_registry(), instance_registry_exports));
11667
11906
  const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
11668
11907
  const globalRoot = getGlobalRoot2();
11669
- const instanceReg = new InstanceRegistry2(path26.join(globalRoot, "instances.json"));
11908
+ const instanceReg = new InstanceRegistry2(path27.join(globalRoot, "instances.json"));
11670
11909
  instanceReg.load();
11671
11910
  const instanceEntry = instanceReg.getByRoot(instanceRoot);
11672
11911
  const workspaceId = instanceEntry?.id ?? "main";
@@ -11698,7 +11937,7 @@ function createApiServerPlugin() {
11698
11937
  server.registerPlugin("/api/v1/plugins", async (app) => pluginRoutes2(app, deps));
11699
11938
  const appConfig = core.configManager.get();
11700
11939
  const workspaceName = appConfig.instanceName ?? "Main";
11701
- const workspaceDir = path26.dirname(instanceRoot);
11940
+ const workspaceDir = path27.dirname(instanceRoot);
11702
11941
  server.registerPlugin("/api/v1", async (app) => {
11703
11942
  await app.register(workspaceRoute2, {
11704
11943
  id: workspaceId,
@@ -12792,8 +13031,8 @@ function formatToolSummary(name, rawInput, displaySummary) {
12792
13031
  }
12793
13032
  if (lowerName === "grep") {
12794
13033
  const pattern = args2.pattern ?? "";
12795
- const path71 = args2.path ?? "";
12796
- return pattern ? `\u{1F50D} Grep "${pattern}"${path71 ? ` in ${path71}` : ""}` : `\u{1F527} ${name}`;
13034
+ const path72 = args2.path ?? "";
13035
+ return pattern ? `\u{1F50D} Grep "${pattern}"${path72 ? ` in ${path72}` : ""}` : `\u{1F527} ${name}`;
12797
13036
  }
12798
13037
  if (lowerName === "glob") {
12799
13038
  const pattern = args2.pattern ?? "";
@@ -12829,8 +13068,8 @@ function formatToolTitle(name, rawInput, displayTitle) {
12829
13068
  }
12830
13069
  if (lowerName === "grep") {
12831
13070
  const pattern = args2.pattern ?? "";
12832
- const path71 = args2.path ?? "";
12833
- return pattern ? `"${pattern}"${path71 ? ` in ${path71}` : ""}` : name;
13071
+ const path72 = args2.path ?? "";
13072
+ return pattern ? `"${pattern}"${path72 ? ` in ${path72}` : ""}` : name;
12834
13073
  }
12835
13074
  if (lowerName === "glob") {
12836
13075
  return String(args2.pattern ?? name);
@@ -13973,7 +14212,7 @@ __export(integrate_exports, {
13973
14212
  listIntegrations: () => listIntegrations,
13974
14213
  uninstallIntegration: () => uninstallIntegration
13975
14214
  });
13976
- import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, rmdirSync } from "fs";
14215
+ import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, rmdirSync } from "fs";
13977
14216
  import { join as join10, dirname as dirname7 } from "path";
13978
14217
  import { homedir as homedir3 } from "os";
13979
14218
  function isHooksIntegrationSpec(spec) {
@@ -14135,7 +14374,7 @@ function generateOpencodePlugin(spec) {
14135
14374
  function mergeSettingsJson(settingsPath, hookEvent, hookScriptPath) {
14136
14375
  const fullPath = expandPath(settingsPath);
14137
14376
  let settings = {};
14138
- if (existsSync6(fullPath)) {
14377
+ if (existsSync7(fullPath)) {
14139
14378
  const raw = readFileSync5(fullPath, "utf-8");
14140
14379
  writeFileSync5(`${fullPath}.bak`, raw);
14141
14380
  settings = JSON.parse(raw);
@@ -14158,7 +14397,7 @@ function mergeSettingsJson(settingsPath, hookEvent, hookScriptPath) {
14158
14397
  function mergeHooksJson(settingsPath, hookEvent, hookScriptPath) {
14159
14398
  const fullPath = expandPath(settingsPath);
14160
14399
  let config = { version: 1 };
14161
- if (existsSync6(fullPath)) {
14400
+ if (existsSync7(fullPath)) {
14162
14401
  const raw = readFileSync5(fullPath, "utf-8");
14163
14402
  writeFileSync5(`${fullPath}.bak`, raw);
14164
14403
  config = JSON.parse(raw);
@@ -14176,7 +14415,7 @@ function mergeHooksJson(settingsPath, hookEvent, hookScriptPath) {
14176
14415
  }
14177
14416
  function removeFromSettingsJson(settingsPath, hookEvent) {
14178
14417
  const fullPath = expandPath(settingsPath);
14179
- if (!existsSync6(fullPath)) return;
14418
+ if (!existsSync7(fullPath)) return;
14180
14419
  const raw = readFileSync5(fullPath, "utf-8");
14181
14420
  const settings = JSON.parse(raw);
14182
14421
  const hooks = settings.hooks;
@@ -14191,7 +14430,7 @@ function removeFromSettingsJson(settingsPath, hookEvent) {
14191
14430
  }
14192
14431
  function removeFromHooksJson(settingsPath, hookEvent) {
14193
14432
  const fullPath = expandPath(settingsPath);
14194
- if (!existsSync6(fullPath)) return;
14433
+ if (!existsSync7(fullPath)) return;
14195
14434
  const raw = readFileSync5(fullPath, "utf-8");
14196
14435
  const config = JSON.parse(raw);
14197
14436
  const hooks = config.hooks;
@@ -14257,7 +14496,7 @@ async function uninstallHooksIntegration(agentKey, spec) {
14257
14496
  const hooksDir = expandPath(spec.hooksDirPath);
14258
14497
  for (const filename of ["openacp-inject-session.sh", "openacp-handoff.sh"]) {
14259
14498
  const filePath = join10(hooksDir, filename);
14260
- if (existsSync6(filePath)) {
14499
+ if (existsSync7(filePath)) {
14261
14500
  unlinkSync4(filePath);
14262
14501
  logs.push(`Removed ${filePath}`);
14263
14502
  }
@@ -14266,7 +14505,7 @@ async function uninstallHooksIntegration(agentKey, spec) {
14266
14505
  if (spec.commandFormat === "skill") {
14267
14506
  const skillDir = expandPath(join10(spec.commandsPath, spec.handoffCommandName));
14268
14507
  const skillPath = join10(skillDir, "SKILL.md");
14269
- if (existsSync6(skillPath)) {
14508
+ if (existsSync7(skillPath)) {
14270
14509
  unlinkSync4(skillPath);
14271
14510
  try {
14272
14511
  rmdirSync(skillDir);
@@ -14276,7 +14515,7 @@ async function uninstallHooksIntegration(agentKey, spec) {
14276
14515
  }
14277
14516
  } else {
14278
14517
  const cmdPath = expandPath(join10(spec.commandsPath, `${spec.handoffCommandName}.md`));
14279
- if (existsSync6(cmdPath)) {
14518
+ if (existsSync7(cmdPath)) {
14280
14519
  unlinkSync4(cmdPath);
14281
14520
  logs.push(`Removed ${cmdPath}`);
14282
14521
  }
@@ -14303,11 +14542,11 @@ async function installPluginIntegration(_agentKey, spec) {
14303
14542
  const pluginsDir = expandPath(spec.pluginsPath);
14304
14543
  mkdirSync5(pluginsDir, { recursive: true });
14305
14544
  const pluginPath = join10(pluginsDir, spec.pluginFileName);
14306
- if (existsSync6(commandPath) && existsSync6(pluginPath)) {
14545
+ if (existsSync7(commandPath) && existsSync7(pluginPath)) {
14307
14546
  logs.push("Already installed, skipping.");
14308
14547
  return { success: true, logs };
14309
14548
  }
14310
- if (existsSync6(commandPath) || existsSync6(pluginPath)) {
14549
+ if (existsSync7(commandPath) || existsSync7(pluginPath)) {
14311
14550
  logs.push("Overwriting existing files.");
14312
14551
  }
14313
14552
  writeFileSync5(commandPath, generateOpencodeHandoffCommand(spec));
@@ -14325,13 +14564,13 @@ async function uninstallPluginIntegration(_agentKey, spec) {
14325
14564
  try {
14326
14565
  const commandPath = join10(expandPath(spec.commandsPath), spec.handoffCommandFile);
14327
14566
  let removedCount = 0;
14328
- if (existsSync6(commandPath)) {
14567
+ if (existsSync7(commandPath)) {
14329
14568
  unlinkSync4(commandPath);
14330
14569
  logs.push(`Removed ${commandPath}`);
14331
14570
  removedCount += 1;
14332
14571
  }
14333
14572
  const pluginPath = join10(expandPath(spec.pluginsPath), spec.pluginFileName);
14334
- if (existsSync6(pluginPath)) {
14573
+ if (existsSync7(pluginPath)) {
14335
14574
  unlinkSync4(pluginPath);
14336
14575
  logs.push(`Removed ${pluginPath}`);
14337
14576
  removedCount += 1;
@@ -14365,11 +14604,11 @@ function buildHandoffItem(agentKey, spec) {
14365
14604
  isInstalled() {
14366
14605
  if (isHooksIntegrationSpec(spec)) {
14367
14606
  const hooksDir = expandPath(spec.hooksDirPath);
14368
- return existsSync6(join10(hooksDir, "openacp-inject-session.sh")) && existsSync6(join10(hooksDir, "openacp-handoff.sh"));
14607
+ return existsSync7(join10(hooksDir, "openacp-inject-session.sh")) && existsSync7(join10(hooksDir, "openacp-handoff.sh"));
14369
14608
  }
14370
14609
  const commandPath = join10(expandPath(spec.commandsPath), spec.handoffCommandFile);
14371
14610
  const pluginPath = join10(expandPath(spec.pluginsPath), spec.pluginFileName);
14372
- return existsSync6(commandPath) && existsSync6(pluginPath);
14611
+ return existsSync7(commandPath) && existsSync7(pluginPath);
14373
14612
  },
14374
14613
  install: () => installIntegration(agentKey, spec),
14375
14614
  uninstall: () => uninstallIntegration(agentKey, spec)
@@ -14391,7 +14630,7 @@ function buildTunnelItem(spec) {
14391
14630
  name: "Tunnel",
14392
14631
  description: "Expose local ports to the internet via OpenACP tunnel",
14393
14632
  isInstalled() {
14394
- return existsSync6(getTunnelPath());
14633
+ return existsSync7(getTunnelPath());
14395
14634
  },
14396
14635
  async install() {
14397
14636
  const logs = [];
@@ -14410,7 +14649,7 @@ function buildTunnelItem(spec) {
14410
14649
  const logs = [];
14411
14650
  try {
14412
14651
  const skillPath = getTunnelPath();
14413
- if (existsSync6(skillPath)) {
14652
+ if (existsSync7(skillPath)) {
14414
14653
  unlinkSync4(skillPath);
14415
14654
  try {
14416
14655
  rmdirSync(dirname7(skillPath));
@@ -15173,7 +15412,7 @@ var init_config4 = __esm({
15173
15412
  // src/core/doctor/checks/agents.ts
15174
15413
  import { execFileSync as execFileSync4 } from "child_process";
15175
15414
  import * as fs24 from "fs";
15176
- import * as path27 from "path";
15415
+ import * as path28 from "path";
15177
15416
  function commandExists2(cmd) {
15178
15417
  try {
15179
15418
  execFileSync4("which", [cmd], { stdio: "pipe" });
@@ -15182,9 +15421,9 @@ function commandExists2(cmd) {
15182
15421
  }
15183
15422
  let dir = process.cwd();
15184
15423
  while (true) {
15185
- const binPath = path27.join(dir, "node_modules", ".bin", cmd);
15424
+ const binPath = path28.join(dir, "node_modules", ".bin", cmd);
15186
15425
  if (fs24.existsSync(binPath)) return true;
15187
- const parent = path27.dirname(dir);
15426
+ const parent = path28.dirname(dir);
15188
15427
  if (parent === dir) break;
15189
15428
  dir = parent;
15190
15429
  }
@@ -15206,7 +15445,7 @@ var init_agents3 = __esm({
15206
15445
  const defaultAgent = ctx.config.defaultAgent;
15207
15446
  let agents = {};
15208
15447
  try {
15209
- const agentsPath = path27.join(ctx.dataDir, "agents.json");
15448
+ const agentsPath = path28.join(ctx.dataDir, "agents.json");
15210
15449
  if (fs24.existsSync(agentsPath)) {
15211
15450
  const data = JSON.parse(fs24.readFileSync(agentsPath, "utf-8"));
15212
15451
  agents = data.installed ?? {};
@@ -15247,7 +15486,7 @@ __export(settings_manager_exports, {
15247
15486
  SettingsManager: () => SettingsManager
15248
15487
  });
15249
15488
  import fs25 from "fs";
15250
- import path28 from "path";
15489
+ import path29 from "path";
15251
15490
  var SettingsManager, SettingsAPIImpl;
15252
15491
  var init_settings_manager = __esm({
15253
15492
  "src/core/plugin/settings-manager.ts"() {
@@ -15290,7 +15529,7 @@ var init_settings_manager = __esm({
15290
15529
  }
15291
15530
  /** Resolve the absolute path to a plugin's settings.json file. */
15292
15531
  getSettingsPath(pluginName) {
15293
- return path28.join(this.basePath, pluginName, "settings.json");
15532
+ return path29.join(this.basePath, pluginName, "settings.json");
15294
15533
  }
15295
15534
  async getPluginSettings(pluginName) {
15296
15535
  return this.loadSettings(pluginName);
@@ -15320,7 +15559,7 @@ var init_settings_manager = __esm({
15320
15559
  }
15321
15560
  }
15322
15561
  writeFile(data) {
15323
- const dir = path28.dirname(this.settingsPath);
15562
+ const dir = path29.dirname(this.settingsPath);
15324
15563
  fs25.mkdirSync(dir, { recursive: true });
15325
15564
  fs25.writeFileSync(this.settingsPath, JSON.stringify(data, null, 2));
15326
15565
  this.cache = data;
@@ -15357,7 +15596,7 @@ var init_settings_manager = __esm({
15357
15596
  });
15358
15597
 
15359
15598
  // src/core/doctor/checks/telegram.ts
15360
- import * as path29 from "path";
15599
+ import * as path30 from "path";
15361
15600
  var BOT_TOKEN_REGEX, telegramCheck;
15362
15601
  var init_telegram = __esm({
15363
15602
  "src/core/doctor/checks/telegram.ts"() {
@@ -15373,7 +15612,7 @@ var init_telegram = __esm({
15373
15612
  return results;
15374
15613
  }
15375
15614
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
15376
- const sm = new SettingsManager2(path29.join(ctx.pluginsDir, "data"));
15615
+ const sm = new SettingsManager2(path30.join(ctx.pluginsDir, "data"));
15377
15616
  const ps = await sm.loadSettings("@openacp/telegram");
15378
15617
  const botToken = ps.botToken;
15379
15618
  const chatId = ps.chatId;
@@ -15545,7 +15784,7 @@ var init_storage = __esm({
15545
15784
 
15546
15785
  // src/core/doctor/checks/workspace.ts
15547
15786
  import * as fs27 from "fs";
15548
- import * as path30 from "path";
15787
+ import * as path31 from "path";
15549
15788
  var workspaceCheck;
15550
15789
  var init_workspace2 = __esm({
15551
15790
  "src/core/doctor/checks/workspace.ts"() {
@@ -15555,7 +15794,7 @@ var init_workspace2 = __esm({
15555
15794
  order: 5,
15556
15795
  async run(ctx) {
15557
15796
  const results = [];
15558
- const workspace = path30.dirname(ctx.dataDir);
15797
+ const workspace = path31.dirname(ctx.dataDir);
15559
15798
  if (!fs27.existsSync(workspace)) {
15560
15799
  results.push({
15561
15800
  status: "warn",
@@ -15583,7 +15822,7 @@ var init_workspace2 = __esm({
15583
15822
 
15584
15823
  // src/core/doctor/checks/plugins.ts
15585
15824
  import * as fs28 from "fs";
15586
- import * as path31 from "path";
15825
+ import * as path32 from "path";
15587
15826
  var pluginsCheck;
15588
15827
  var init_plugins2 = __esm({
15589
15828
  "src/core/doctor/checks/plugins.ts"() {
@@ -15602,7 +15841,7 @@ var init_plugins2 = __esm({
15602
15841
  fix: async () => {
15603
15842
  fs28.mkdirSync(ctx.pluginsDir, { recursive: true });
15604
15843
  fs28.writeFileSync(
15605
- path31.join(ctx.pluginsDir, "package.json"),
15844
+ path32.join(ctx.pluginsDir, "package.json"),
15606
15845
  JSON.stringify({ name: "openacp-plugins", private: true, dependencies: {} }, null, 2)
15607
15846
  );
15608
15847
  return { success: true, message: "initialized plugins directory" };
@@ -15611,7 +15850,7 @@ var init_plugins2 = __esm({
15611
15850
  return results;
15612
15851
  }
15613
15852
  results.push({ status: "pass", message: "Plugins directory exists" });
15614
- const pkgPath = path31.join(ctx.pluginsDir, "package.json");
15853
+ const pkgPath = path32.join(ctx.pluginsDir, "package.json");
15615
15854
  if (!fs28.existsSync(pkgPath)) {
15616
15855
  results.push({
15617
15856
  status: "warn",
@@ -15758,7 +15997,7 @@ var init_daemon = __esm({
15758
15997
 
15759
15998
  // src/core/doctor/checks/tunnel.ts
15760
15999
  import * as fs30 from "fs";
15761
- import * as path32 from "path";
16000
+ import * as path33 from "path";
15762
16001
  import * as os7 from "os";
15763
16002
  import { execFileSync as execFileSync5 } from "child_process";
15764
16003
  var tunnelCheck;
@@ -15775,7 +16014,7 @@ var init_tunnel3 = __esm({
15775
16014
  return results;
15776
16015
  }
15777
16016
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
15778
- const sm = new SettingsManager2(path32.join(ctx.pluginsDir, "data"));
16017
+ const sm = new SettingsManager2(path33.join(ctx.pluginsDir, "data"));
15779
16018
  const tunnelSettings = await sm.loadSettings("@openacp/tunnel");
15780
16019
  const tunnelEnabled = tunnelSettings.enabled ?? false;
15781
16020
  const provider = tunnelSettings.provider ?? "cloudflare";
@@ -15787,7 +16026,7 @@ var init_tunnel3 = __esm({
15787
16026
  results.push({ status: "pass", message: `Tunnel provider: ${provider}` });
15788
16027
  if (provider === "cloudflare") {
15789
16028
  const binName = os7.platform() === "win32" ? "cloudflared.exe" : "cloudflared";
15790
- const binPath = path32.join(ctx.dataDir, "bin", binName);
16029
+ const binPath = path33.join(ctx.dataDir, "bin", binName);
15791
16030
  let found = false;
15792
16031
  if (fs30.existsSync(binPath)) {
15793
16032
  found = true;
@@ -15835,7 +16074,7 @@ __export(doctor_exports, {
15835
16074
  DoctorEngine: () => DoctorEngine
15836
16075
  });
15837
16076
  import * as fs31 from "fs";
15838
- import * as path33 from "path";
16077
+ import * as path34 from "path";
15839
16078
  var ALL_CHECKS, CHECK_TIMEOUT_MS, DoctorEngine;
15840
16079
  var init_doctor = __esm({
15841
16080
  "src/core/doctor/index.ts"() {
@@ -15923,7 +16162,7 @@ var init_doctor = __esm({
15923
16162
  /** Constructs the shared context used by all checks — loads config if available. */
15924
16163
  async buildContext() {
15925
16164
  const dataDir = this.dataDir;
15926
- const configPath = process.env.OPENACP_CONFIG_PATH || path33.join(dataDir, "config.json");
16165
+ const configPath = process.env.OPENACP_CONFIG_PATH || path34.join(dataDir, "config.json");
15927
16166
  let config = null;
15928
16167
  let rawConfig = null;
15929
16168
  try {
@@ -15934,16 +16173,16 @@ var init_doctor = __esm({
15934
16173
  config = cm.get();
15935
16174
  } catch {
15936
16175
  }
15937
- const logsDir = config ? expandHome2(config.logging.logDir) : path33.join(dataDir, "logs");
16176
+ const logsDir = config ? expandHome2(config.logging.logDir) : path34.join(dataDir, "logs");
15938
16177
  return {
15939
16178
  config,
15940
16179
  rawConfig,
15941
16180
  configPath,
15942
16181
  dataDir,
15943
- sessionsPath: path33.join(dataDir, "sessions.json"),
15944
- pidPath: path33.join(dataDir, "openacp.pid"),
15945
- portFilePath: path33.join(dataDir, "api.port"),
15946
- pluginsDir: path33.join(dataDir, "plugins"),
16182
+ sessionsPath: path34.join(dataDir, "sessions.json"),
16183
+ pidPath: path34.join(dataDir, "openacp.pid"),
16184
+ portFilePath: path34.join(dataDir, "api.port"),
16185
+ pluginsDir: path34.join(dataDir, "plugins"),
15947
16186
  logsDir
15948
16187
  };
15949
16188
  }
@@ -20500,10 +20739,10 @@ var install_context_exports = {};
20500
20739
  __export(install_context_exports, {
20501
20740
  createInstallContext: () => createInstallContext
20502
20741
  });
20503
- import path34 from "path";
20742
+ import path35 from "path";
20504
20743
  function createInstallContext(opts) {
20505
20744
  const { pluginName, settingsManager, basePath, instanceRoot } = opts;
20506
- const dataDir = path34.join(basePath, pluginName, "data");
20745
+ const dataDir = path35.join(basePath, pluginName, "data");
20507
20746
  return {
20508
20747
  pluginName,
20509
20748
  terminal: createTerminalIO(),
@@ -20531,13 +20770,13 @@ __export(api_client_exports, {
20531
20770
  waitForPortFile: () => waitForPortFile
20532
20771
  });
20533
20772
  import * as fs33 from "fs";
20534
- import * as path36 from "path";
20773
+ import * as path37 from "path";
20535
20774
  import { setTimeout as sleep } from "timers/promises";
20536
20775
  function defaultPortFile(root) {
20537
- return path36.join(root, "api.port");
20776
+ return path37.join(root, "api.port");
20538
20777
  }
20539
20778
  function defaultSecretFile(root) {
20540
- return path36.join(root, "api-secret");
20779
+ return path37.join(root, "api-secret");
20541
20780
  }
20542
20781
  async function waitForPortFile(portFilePath, timeoutMs = 5e3, intervalMs = 100) {
20543
20782
  const deadline = Date.now() + timeoutMs;
@@ -20632,9 +20871,9 @@ var init_suggest = __esm({
20632
20871
 
20633
20872
  // src/cli/instance-hint.ts
20634
20873
  import os8 from "os";
20635
- import path37 from "path";
20874
+ import path38 from "path";
20636
20875
  function printInstanceHint(root) {
20637
- const workspaceDir = path37.dirname(root);
20876
+ const workspaceDir = path38.dirname(root);
20638
20877
  const displayPath = workspaceDir.replace(os8.homedir(), "~");
20639
20878
  console.log(` Workspace: ${displayPath}`);
20640
20879
  }
@@ -20650,23 +20889,23 @@ __export(resolve_instance_id_exports, {
20650
20889
  resolveInstanceId: () => resolveInstanceId
20651
20890
  });
20652
20891
  import fs34 from "fs";
20653
- import path38 from "path";
20892
+ import path39 from "path";
20654
20893
  function resolveInstanceId(instanceRoot) {
20655
20894
  try {
20656
- const configPath = path38.join(instanceRoot, "config.json");
20895
+ const configPath = path39.join(instanceRoot, "config.json");
20657
20896
  const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
20658
20897
  if (raw.id && typeof raw.id === "string") return raw.id;
20659
20898
  } catch {
20660
20899
  }
20661
20900
  try {
20662
- const reg = new InstanceRegistry(path38.join(getGlobalRoot(), "instances.json"));
20901
+ const reg = new InstanceRegistry(path39.join(getGlobalRoot(), "instances.json"));
20663
20902
  reg.load();
20664
20903
  const entry = reg.getByRoot(instanceRoot);
20665
20904
  if (entry?.id) return entry.id;
20666
20905
  } catch (err) {
20667
20906
  log31.debug({ err: err.message, instanceRoot }, "Could not read instance registry, using fallback id");
20668
20907
  }
20669
- return path38.basename(path38.dirname(instanceRoot)).replace(/[^a-zA-Z0-9-]/g, "-") || "default";
20908
+ return path39.basename(path39.dirname(instanceRoot)).replace(/[^a-zA-Z0-9-]/g, "-") || "default";
20670
20909
  }
20671
20910
  var log31;
20672
20911
  var init_resolve_instance_id = __esm({
@@ -20698,18 +20937,18 @@ __export(daemon_exports, {
20698
20937
  });
20699
20938
  import { spawn as spawn6 } from "child_process";
20700
20939
  import * as fs35 from "fs";
20701
- import * as path39 from "path";
20940
+ import * as path40 from "path";
20702
20941
  function getPidPath(root) {
20703
- return path39.join(root, "openacp.pid");
20942
+ return path40.join(root, "openacp.pid");
20704
20943
  }
20705
20944
  function getLogDir(root) {
20706
- return path39.join(root, "logs");
20945
+ return path40.join(root, "logs");
20707
20946
  }
20708
20947
  function getRunningMarker(root) {
20709
- return path39.join(root, "running");
20948
+ return path40.join(root, "running");
20710
20949
  }
20711
20950
  function writePidFile(pidPath, pid) {
20712
- const dir = path39.dirname(pidPath);
20951
+ const dir = path40.dirname(pidPath);
20713
20952
  fs35.mkdirSync(dir, { recursive: true });
20714
20953
  fs35.writeFileSync(pidPath, String(pid));
20715
20954
  }
@@ -20758,8 +20997,8 @@ function startDaemon(pidPath, logDir2, instanceRoot) {
20758
20997
  }
20759
20998
  const resolvedLogDir = logDir2 ? expandHome2(logDir2) : getLogDir(instanceRoot);
20760
20999
  fs35.mkdirSync(resolvedLogDir, { recursive: true });
20761
- const logFile = path39.join(resolvedLogDir, "openacp.log");
20762
- const cliPath = path39.resolve(process.argv[1]);
21000
+ const logFile = path40.join(resolvedLogDir, "openacp.log");
21001
+ const cliPath = path40.resolve(process.argv[1]);
20763
21002
  const nodePath = process.execPath;
20764
21003
  const out = fs35.openSync(logFile, "a");
20765
21004
  const err = fs35.openSync(logFile, "a");
@@ -20843,7 +21082,7 @@ async function stopDaemon(pidPath, instanceRoot) {
20843
21082
  }
20844
21083
  function markRunning(root) {
20845
21084
  const marker = getRunningMarker(root);
20846
- fs35.mkdirSync(path39.dirname(marker), { recursive: true });
21085
+ fs35.mkdirSync(path40.dirname(marker), { recursive: true });
20847
21086
  fs35.writeFileSync(marker, "");
20848
21087
  }
20849
21088
  function clearRunning(root) {
@@ -20876,19 +21115,19 @@ __export(autostart_exports, {
20876
21115
  });
20877
21116
  import { execFileSync as execFileSync6 } from "child_process";
20878
21117
  import * as fs36 from "fs";
20879
- import * as path40 from "path";
21118
+ import * as path41 from "path";
20880
21119
  import * as os9 from "os";
20881
21120
  function getLaunchdLabel(instanceId) {
20882
21121
  return `com.openacp.daemon.${instanceId}`;
20883
21122
  }
20884
21123
  function getLaunchdPlistPath(instanceId) {
20885
- return path40.join(os9.homedir(), "Library", "LaunchAgents", `${getLaunchdLabel(instanceId)}.plist`);
21124
+ return path41.join(os9.homedir(), "Library", "LaunchAgents", `${getLaunchdLabel(instanceId)}.plist`);
20886
21125
  }
20887
21126
  function getSystemdServiceName(instanceId) {
20888
21127
  return `openacp-${instanceId}`;
20889
21128
  }
20890
21129
  function getSystemdServicePath(instanceId) {
20891
- return path40.join(os9.homedir(), ".config", "systemd", "user", `${getSystemdServiceName(instanceId)}.service`);
21130
+ return path41.join(os9.homedir(), ".config", "systemd", "user", `${getSystemdServiceName(instanceId)}.service`);
20892
21131
  }
20893
21132
  function isAutoStartSupported() {
20894
21133
  return process.platform === "darwin" || process.platform === "linux";
@@ -20902,7 +21141,7 @@ function escapeSystemdValue(str) {
20902
21141
  }
20903
21142
  function generateLaunchdPlist(nodePath, cliPath, logDir2, instanceRoot, instanceId) {
20904
21143
  const label = getLaunchdLabel(instanceId);
20905
- const logFile = path40.join(logDir2, "openacp.log");
21144
+ const logFile = path41.join(logDir2, "openacp.log");
20906
21145
  return `<?xml version="1.0" encoding="UTF-8"?>
20907
21146
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
20908
21147
  <plist version="1.0">
@@ -20984,14 +21223,14 @@ function installAutoStart(logDir2, instanceRoot, instanceId) {
20984
21223
  return { success: false, error: "Auto-start not supported on this platform" };
20985
21224
  }
20986
21225
  const nodePath = process.execPath;
20987
- const cliPath = path40.resolve(process.argv[1]);
20988
- const resolvedLogDir = logDir2.startsWith("~") ? path40.join(os9.homedir(), logDir2.slice(1)) : logDir2;
21226
+ const cliPath = path41.resolve(process.argv[1]);
21227
+ const resolvedLogDir = logDir2.startsWith("~") ? path41.join(os9.homedir(), logDir2.slice(1)) : logDir2;
20989
21228
  try {
20990
21229
  migrateLegacy();
20991
21230
  if (process.platform === "darwin") {
20992
21231
  const plistPath = getLaunchdPlistPath(instanceId);
20993
21232
  const plist = generateLaunchdPlist(nodePath, cliPath, resolvedLogDir, instanceRoot, instanceId);
20994
- const dir = path40.dirname(plistPath);
21233
+ const dir = path41.dirname(plistPath);
20995
21234
  fs36.mkdirSync(dir, { recursive: true });
20996
21235
  fs36.writeFileSync(plistPath, plist);
20997
21236
  const uid = process.getuid();
@@ -21008,7 +21247,7 @@ function installAutoStart(logDir2, instanceRoot, instanceId) {
21008
21247
  const servicePath = getSystemdServicePath(instanceId);
21009
21248
  const serviceName = getSystemdServiceName(instanceId);
21010
21249
  const unit = generateSystemdUnit(nodePath, cliPath, instanceRoot, instanceId);
21011
- const dir = path40.dirname(servicePath);
21250
+ const dir = path41.dirname(servicePath);
21012
21251
  fs36.mkdirSync(dir, { recursive: true });
21013
21252
  fs36.writeFileSync(servicePath, unit);
21014
21253
  execFileSync6("systemctl", ["--user", "daemon-reload"], { stdio: "pipe" });
@@ -21077,8 +21316,8 @@ var init_autostart = __esm({
21077
21316
  "use strict";
21078
21317
  init_log();
21079
21318
  log32 = createChildLogger({ module: "autostart" });
21080
- LEGACY_LAUNCHD_PLIST_PATH = path40.join(os9.homedir(), "Library", "LaunchAgents", "com.openacp.daemon.plist");
21081
- LEGACY_SYSTEMD_SERVICE_PATH = path40.join(os9.homedir(), ".config", "systemd", "user", "openacp.service");
21319
+ LEGACY_LAUNCHD_PLIST_PATH = path41.join(os9.homedir(), "Library", "LaunchAgents", "com.openacp.daemon.plist");
21320
+ LEGACY_SYSTEMD_SERVICE_PATH = path41.join(os9.homedir(), ".config", "systemd", "user", "openacp.service");
21082
21321
  }
21083
21322
  });
21084
21323
 
@@ -21133,7 +21372,7 @@ var init_stop = __esm({
21133
21372
 
21134
21373
  // src/core/security/path-guard.ts
21135
21374
  import fs37 from "fs";
21136
- import path42 from "path";
21375
+ import path43 from "path";
21137
21376
  import ignore from "ignore";
21138
21377
  var DEFAULT_DENY_PATTERNS, PathGuard;
21139
21378
  var init_path_guard = __esm({
@@ -21162,15 +21401,15 @@ var init_path_guard = __esm({
21162
21401
  ig;
21163
21402
  constructor(options) {
21164
21403
  try {
21165
- this.cwd = fs37.realpathSync(path42.resolve(options.cwd));
21404
+ this.cwd = fs37.realpathSync(path43.resolve(options.cwd));
21166
21405
  } catch {
21167
- this.cwd = path42.resolve(options.cwd);
21406
+ this.cwd = path43.resolve(options.cwd);
21168
21407
  }
21169
21408
  this.allowedPaths = options.allowedPaths.map((p2) => {
21170
21409
  try {
21171
- return fs37.realpathSync(path42.resolve(p2));
21410
+ return fs37.realpathSync(path43.resolve(p2));
21172
21411
  } catch {
21173
- return path42.resolve(p2);
21412
+ return path43.resolve(p2);
21174
21413
  }
21175
21414
  });
21176
21415
  this.ig = ignore();
@@ -21194,19 +21433,19 @@ var init_path_guard = __esm({
21194
21433
  * @returns `{ allowed: true }` or `{ allowed: false, reason: "..." }`
21195
21434
  */
21196
21435
  validatePath(targetPath, operation) {
21197
- const resolved = path42.resolve(targetPath);
21436
+ const resolved = path43.resolve(targetPath);
21198
21437
  let realPath;
21199
21438
  try {
21200
21439
  realPath = fs37.realpathSync(resolved);
21201
21440
  } catch {
21202
21441
  realPath = resolved;
21203
21442
  }
21204
- if (operation === "write" && path42.basename(realPath) === ".openacpignore") {
21443
+ if (operation === "write" && path43.basename(realPath) === ".openacpignore") {
21205
21444
  return { allowed: false, reason: "Cannot write to .openacpignore" };
21206
21445
  }
21207
- const isWithinCwd = realPath === this.cwd || realPath.startsWith(this.cwd + path42.sep);
21446
+ const isWithinCwd = realPath === this.cwd || realPath.startsWith(this.cwd + path43.sep);
21208
21447
  const isWithinAllowed = this.allowedPaths.some(
21209
- (ap) => realPath === ap || realPath.startsWith(ap + path42.sep)
21448
+ (ap) => realPath === ap || realPath.startsWith(ap + path43.sep)
21210
21449
  );
21211
21450
  if (!isWithinCwd && !isWithinAllowed) {
21212
21451
  return {
@@ -21215,7 +21454,7 @@ var init_path_guard = __esm({
21215
21454
  };
21216
21455
  }
21217
21456
  if (isWithinCwd && !isWithinAllowed) {
21218
- const relativePath = path42.relative(this.cwd, realPath);
21457
+ const relativePath = path43.relative(this.cwd, realPath);
21219
21458
  if (relativePath === ".openacpignore") {
21220
21459
  return { allowed: true, reason: "" };
21221
21460
  }
@@ -21231,9 +21470,9 @@ var init_path_guard = __esm({
21231
21470
  /** Adds an additional allowed path at runtime (e.g. for file-service uploads). */
21232
21471
  addAllowedPath(p2) {
21233
21472
  try {
21234
- this.allowedPaths.push(fs37.realpathSync(path42.resolve(p2)));
21473
+ this.allowedPaths.push(fs37.realpathSync(path43.resolve(p2)));
21235
21474
  } catch {
21236
- this.allowedPaths.push(path42.resolve(p2));
21475
+ this.allowedPaths.push(path43.resolve(p2));
21237
21476
  }
21238
21477
  }
21239
21478
  /**
@@ -21241,7 +21480,7 @@ var init_path_guard = __esm({
21241
21480
  * Follows .gitignore syntax — blank lines and lines starting with # are skipped.
21242
21481
  */
21243
21482
  static loadIgnoreFile(cwd) {
21244
- const ignorePath = path42.join(cwd, ".openacpignore");
21483
+ const ignorePath = path43.join(cwd, ".openacpignore");
21245
21484
  try {
21246
21485
  const content = fs37.readFileSync(ignorePath, "utf-8");
21247
21486
  return content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -21718,7 +21957,7 @@ var init_mcp_manager = __esm({
21718
21957
 
21719
21958
  // src/core/utils/debug-tracer.ts
21720
21959
  import fs38 from "fs";
21721
- import path43 from "path";
21960
+ import path44 from "path";
21722
21961
  function createDebugTracer(sessionId, workingDirectory) {
21723
21962
  if (!DEBUG_ENABLED) return null;
21724
21963
  return new DebugTracer(sessionId, workingDirectory);
@@ -21732,7 +21971,7 @@ var init_debug_tracer = __esm({
21732
21971
  constructor(sessionId, workingDirectory) {
21733
21972
  this.sessionId = sessionId;
21734
21973
  this.workingDirectory = workingDirectory;
21735
- this.logDir = path43.join(workingDirectory, ".log");
21974
+ this.logDir = path44.join(workingDirectory, ".log");
21736
21975
  }
21737
21976
  sessionId;
21738
21977
  workingDirectory;
@@ -21750,7 +21989,7 @@ var init_debug_tracer = __esm({
21750
21989
  fs38.mkdirSync(this.logDir, { recursive: true });
21751
21990
  this.dirCreated = true;
21752
21991
  }
21753
- const filePath = path43.join(this.logDir, `${this.sessionId}_${layer}.jsonl`);
21992
+ const filePath = path44.join(this.logDir, `${this.sessionId}_${layer}.jsonl`);
21754
21993
  const seen = /* @__PURE__ */ new WeakSet();
21755
21994
  const line = JSON.stringify({ ts: Date.now(), ...data }, (_key, value) => {
21756
21995
  if (typeof value === "object" && value !== null) {
@@ -21774,21 +22013,21 @@ var init_debug_tracer = __esm({
21774
22013
  import { spawn as spawn8, execFileSync as execFileSync7 } from "child_process";
21775
22014
  import { Transform } from "stream";
21776
22015
  import fs39 from "fs";
21777
- import path44 from "path";
22016
+ import path45 from "path";
21778
22017
  import { ClientSideConnection, ndJsonStream } from "@agentclientprotocol/sdk";
21779
22018
  import { PROTOCOL_VERSION } from "@agentclientprotocol/sdk";
21780
22019
  function findPackageRoot(startDir) {
21781
22020
  let dir = startDir;
21782
- while (dir !== path44.dirname(dir)) {
21783
- if (fs39.existsSync(path44.join(dir, "package.json"))) {
22021
+ while (dir !== path45.dirname(dir)) {
22022
+ if (fs39.existsSync(path45.join(dir, "package.json"))) {
21784
22023
  return dir;
21785
22024
  }
21786
- dir = path44.dirname(dir);
22025
+ dir = path45.dirname(dir);
21787
22026
  }
21788
22027
  return startDir;
21789
22028
  }
21790
22029
  function commandForWindowsScript(filePath) {
21791
- const ext = path44.extname(filePath).toLowerCase();
22030
+ const ext = path45.extname(filePath).toLowerCase();
21792
22031
  if (process.platform === "win32" && (ext === ".cmd" || ext === ".bat")) {
21793
22032
  return { command: process.env.ComSpec ?? "cmd.exe", args: ["/d", "/s", "/c", `"${filePath}"`] };
21794
22033
  }
@@ -21802,8 +22041,8 @@ function resolveAgentCommand(cmd) {
21802
22041
  }
21803
22042
  for (const root of searchRoots) {
21804
22043
  const packageDirs = [
21805
- path44.resolve(root, "node_modules", "@zed-industries", cmd, "dist", "index.js"),
21806
- path44.resolve(root, "node_modules", cmd, "dist", "index.js")
22044
+ path45.resolve(root, "node_modules", "@zed-industries", cmd, "dist", "index.js"),
22045
+ path45.resolve(root, "node_modules", cmd, "dist", "index.js")
21807
22046
  ];
21808
22047
  for (const jsPath of packageDirs) {
21809
22048
  if (fs39.existsSync(jsPath)) {
@@ -21812,7 +22051,7 @@ function resolveAgentCommand(cmd) {
21812
22051
  }
21813
22052
  }
21814
22053
  for (const root of searchRoots) {
21815
- const localBin = path44.resolve(root, "node_modules", ".bin", cmd);
22054
+ const localBin = path45.resolve(root, "node_modules", ".bin", cmd);
21816
22055
  if (fs39.existsSync(localBin)) {
21817
22056
  const content = fs39.readFileSync(localBin, "utf-8");
21818
22057
  if (content.startsWith("#!/usr/bin/env node")) {
@@ -21820,7 +22059,7 @@ function resolveAgentCommand(cmd) {
21820
22059
  }
21821
22060
  const match = content.match(/"([^"]+\.js)"/);
21822
22061
  if (match) {
21823
- const target = path44.resolve(path44.dirname(localBin), match[1]);
22062
+ const target = path45.resolve(path45.dirname(localBin), match[1]);
21824
22063
  if (fs39.existsSync(target)) {
21825
22064
  return { command: process.execPath, args: [target] };
21826
22065
  }
@@ -21836,9 +22075,9 @@ function resolveAgentCommand(cmd) {
21836
22075
  candidates.push(dir);
21837
22076
  }
21838
22077
  };
21839
- addCandidate(path44.dirname(process.execPath));
22078
+ addCandidate(path45.dirname(process.execPath));
21840
22079
  try {
21841
- addCandidate(path44.dirname(fs39.realpathSync(process.execPath)));
22080
+ addCandidate(path45.dirname(fs39.realpathSync(process.execPath)));
21842
22081
  } catch {
21843
22082
  }
21844
22083
  addCandidate("/opt/homebrew/bin");
@@ -21847,8 +22086,8 @@ function resolveAgentCommand(cmd) {
21847
22086
  for (const dir of candidates) {
21848
22087
  if (cmd === "npx") {
21849
22088
  const npxCliCandidates = [
21850
- path44.join(dir, "node_modules", "npm", "bin", "npx-cli.js"),
21851
- path44.join(path44.dirname(dir), "lib", "node_modules", "npm", "bin", "npx-cli.js")
22089
+ path45.join(dir, "node_modules", "npm", "bin", "npx-cli.js"),
22090
+ path45.join(path45.dirname(dir), "lib", "node_modules", "npm", "bin", "npx-cli.js")
21852
22091
  ];
21853
22092
  for (const npxCli of npxCliCandidates) {
21854
22093
  if (fs39.existsSync(npxCli)) {
@@ -21858,7 +22097,7 @@ function resolveAgentCommand(cmd) {
21858
22097
  }
21859
22098
  }
21860
22099
  for (const name of executableNames) {
21861
- const candidate = path44.join(dir, name);
22100
+ const candidate = path45.join(dir, name);
21862
22101
  if (fs39.existsSync(candidate)) {
21863
22102
  const resolved = commandForWindowsScript(candidate);
21864
22103
  log33.info({ cmd, resolved: candidate }, "Resolved package runner from fallback search");
@@ -21870,7 +22109,7 @@ function resolveAgentCommand(cmd) {
21870
22109
  }
21871
22110
  try {
21872
22111
  const fullPath = execFileSync7("which", [cmd], { encoding: "utf-8" }).trim();
21873
- const isUnspawnableWindowsShim = process.platform === "win32" && (cmd === "npx" || cmd === "uvx") && !path44.extname(fullPath);
22112
+ const isUnspawnableWindowsShim = process.platform === "win32" && (cmd === "npx" || cmd === "uvx") && !path45.extname(fullPath);
21874
22113
  if (fullPath && !isUnspawnableWindowsShim) {
21875
22114
  try {
21876
22115
  const content = fs39.readFileSync(fullPath, "utf-8");
@@ -22451,7 +22690,7 @@ ${stderr}`
22451
22690
  writePath = result.path;
22452
22691
  writeContent = result.content;
22453
22692
  }
22454
- await fs39.promises.mkdir(path44.dirname(writePath), { recursive: true });
22693
+ await fs39.promises.mkdir(path45.dirname(writePath), { recursive: true });
22455
22694
  await fs39.promises.writeFile(writePath, writeContent, "utf-8");
22456
22695
  return {};
22457
22696
  },
@@ -24711,7 +24950,7 @@ var init_extract_file_info = __esm({
24711
24950
  });
24712
24951
 
24713
24952
  // src/core/message-transformer.ts
24714
- import * as path45 from "path";
24953
+ import * as path46 from "path";
24715
24954
  function computeLineDiff(oldStr, newStr) {
24716
24955
  const oldLines = oldStr ? oldStr.split("\n") : [];
24717
24956
  const newLines = newStr ? newStr.split("\n") : [];
@@ -25017,7 +25256,7 @@ var init_message_transformer = __esm({
25017
25256
  );
25018
25257
  return;
25019
25258
  }
25020
- const fileExt = path45.extname(fileInfo.filePath).toLowerCase();
25259
+ const fileExt = path46.extname(fileInfo.filePath).toLowerCase();
25021
25260
  if (BINARY_VIEWER_EXTENSIONS.has(fileExt)) {
25022
25261
  log36.debug({ kind, filePath: fileInfo.filePath }, "enrichWithViewerLinks: skipping binary file");
25023
25262
  return;
@@ -25072,7 +25311,7 @@ var init_message_transformer = __esm({
25072
25311
 
25073
25312
  // src/core/sessions/session-store.ts
25074
25313
  import fs41 from "fs";
25075
- import path46 from "path";
25314
+ import path47 from "path";
25076
25315
  var log37, DEBOUNCE_MS3, JsonFileSessionStore;
25077
25316
  var init_session_store = __esm({
25078
25317
  "src/core/sessions/session-store.ts"() {
@@ -25164,7 +25403,7 @@ var init_session_store = __esm({
25164
25403
  version: 1,
25165
25404
  sessions: Object.fromEntries(this.records)
25166
25405
  };
25167
- const dir = path46.dirname(this.filePath);
25406
+ const dir = path47.dirname(this.filePath);
25168
25407
  if (!fs41.existsSync(dir)) fs41.mkdirSync(dir, { recursive: true });
25169
25408
  const tmpPath = `${this.filePath}.tmp`;
25170
25409
  fs41.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
@@ -25933,7 +26172,7 @@ __export(agent_catalog_exports, {
25933
26172
  AgentCatalog: () => AgentCatalog
25934
26173
  });
25935
26174
  import * as fs42 from "fs";
25936
- import * as path47 from "path";
26175
+ import * as path48 from "path";
25937
26176
  function stripNpmVersion(pkg) {
25938
26177
  if (pkg.startsWith("@")) {
25939
26178
  const slashIdx = pkg.indexOf("/");
@@ -26000,7 +26239,7 @@ var init_agent_catalog = __esm({
26000
26239
  ttlHours: DEFAULT_TTL_HOURS,
26001
26240
  data
26002
26241
  };
26003
- fs42.mkdirSync(path47.dirname(this.cachePath), { recursive: true });
26242
+ fs42.mkdirSync(path48.dirname(this.cachePath), { recursive: true });
26004
26243
  fs42.writeFileSync(this.cachePath, JSON.stringify(cache, null, 2), { mode: 384 });
26005
26244
  this.enrichInstalledFromRegistry();
26006
26245
  log40.info({ count: this.registryAgents.length }, "Registry updated");
@@ -26242,9 +26481,9 @@ var init_agent_catalog = __esm({
26242
26481
  }
26243
26482
  try {
26244
26483
  const candidates = [
26245
- path47.join(import.meta.dirname, "data", "registry-snapshot.json"),
26246
- path47.join(import.meta.dirname, "..", "data", "registry-snapshot.json"),
26247
- path47.join(import.meta.dirname, "..", "..", "data", "registry-snapshot.json")
26484
+ path48.join(import.meta.dirname, "data", "registry-snapshot.json"),
26485
+ path48.join(import.meta.dirname, "..", "data", "registry-snapshot.json"),
26486
+ path48.join(import.meta.dirname, "..", "..", "data", "registry-snapshot.json")
26248
26487
  ];
26249
26488
  for (const candidate of candidates) {
26250
26489
  if (fs42.existsSync(candidate)) {
@@ -26269,7 +26508,7 @@ __export(agent_store_exports, {
26269
26508
  AgentStore: () => AgentStore
26270
26509
  });
26271
26510
  import * as fs43 from "fs";
26272
- import * as path48 from "path";
26511
+ import * as path49 from "path";
26273
26512
  import { z as z10 } from "zod";
26274
26513
  var log41, InstalledAgentSchema, AgentStoreSchema, AgentStore;
26275
26514
  var init_agent_store = __esm({
@@ -26346,7 +26585,7 @@ var init_agent_store = __esm({
26346
26585
  * may contain agent binary paths and environment variables.
26347
26586
  */
26348
26587
  save() {
26349
- fs43.mkdirSync(path48.dirname(this.filePath), { recursive: true });
26588
+ fs43.mkdirSync(path49.dirname(this.filePath), { recursive: true });
26350
26589
  const tmpPath = this.filePath + ".tmp";
26351
26590
  fs43.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2), { mode: 384 });
26352
26591
  fs43.renameSync(tmpPath, this.filePath);
@@ -26665,7 +26904,7 @@ var init_error_tracker = __esm({
26665
26904
 
26666
26905
  // src/core/plugin/plugin-storage.ts
26667
26906
  import fs44 from "fs";
26668
- import path49 from "path";
26907
+ import path50 from "path";
26669
26908
  var PluginStorageImpl;
26670
26909
  var init_plugin_storage = __esm({
26671
26910
  "src/core/plugin/plugin-storage.ts"() {
@@ -26676,8 +26915,8 @@ var init_plugin_storage = __esm({
26676
26915
  /** Serializes writes to prevent concurrent file corruption */
26677
26916
  writeChain = Promise.resolve();
26678
26917
  constructor(baseDir) {
26679
- this.dataDir = path49.join(baseDir, "data");
26680
- this.kvPath = path49.join(baseDir, "kv.json");
26918
+ this.dataDir = path50.join(baseDir, "data");
26919
+ this.kvPath = path50.join(baseDir, "kv.json");
26681
26920
  fs44.mkdirSync(baseDir, { recursive: true });
26682
26921
  }
26683
26922
  readKv() {
@@ -27802,7 +28041,7 @@ var init_core_items = __esm({
27802
28041
  });
27803
28042
 
27804
28043
  // src/core/core.ts
27805
- import path50 from "path";
28044
+ import path51 from "path";
27806
28045
  import { nanoid as nanoid6 } from "nanoid";
27807
28046
  var log45, OpenACPCore;
27808
28047
  var init_core = __esm({
@@ -27828,6 +28067,7 @@ var init_core = __esm({
27828
28067
  init_middleware_chain();
27829
28068
  init_error_tracker();
27830
28069
  init_log();
28070
+ init_native_stt();
27831
28071
  init_events();
27832
28072
  init_turn_context();
27833
28073
  log45 = createChildLogger({ module: "core" });
@@ -27972,21 +28212,7 @@ var init_core = __esm({
27972
28212
  const settingsMgr = this.settingsManager;
27973
28213
  if (settingsMgr) {
27974
28214
  const pluginCfg = await settingsMgr.loadSettings("@openacp/speech");
27975
- const groqApiKey = pluginCfg.groqApiKey;
27976
- const sttProviders = {};
27977
- if (groqApiKey) {
27978
- sttProviders.groq = { apiKey: groqApiKey };
27979
- }
27980
- const newSpeechConfig = {
27981
- stt: {
27982
- provider: groqApiKey ? "groq" : null,
27983
- providers: sttProviders
27984
- },
27985
- tts: {
27986
- provider: pluginCfg.ttsProvider ?? null,
27987
- providers: {}
27988
- }
27989
- };
28215
+ const newSpeechConfig = buildSpeechServiceConfig(pluginCfg);
27990
28216
  speechSvc.refreshProviders(newSpeechConfig);
27991
28217
  log45.info("Speech service config updated at runtime (from plugin settings)");
27992
28218
  }
@@ -27995,7 +28221,7 @@ var init_core = __esm({
27995
28221
  }
27996
28222
  );
27997
28223
  registerCoreMenuItems(this.menuRegistry);
27998
- this.assistantRegistry.setInstanceRoot(path50.dirname(ctx.root));
28224
+ this.assistantRegistry.setInstanceRoot(path51.dirname(ctx.root));
27999
28225
  this.assistantRegistry.register(createSessionsSection(this));
28000
28226
  this.assistantRegistry.register(createAgentsSection(this));
28001
28227
  this.assistantRegistry.register(createConfigSection(this));
@@ -28429,8 +28655,8 @@ ${text5}`;
28429
28655
  message: `Agent '${agentName}' not found`
28430
28656
  };
28431
28657
  }
28432
- const { existsSync: existsSync20 } = await import("fs");
28433
- if (!existsSync20(cwd)) {
28658
+ const { existsSync: existsSync21 } = await import("fs");
28659
+ if (!existsSync21(cwd)) {
28434
28660
  return {
28435
28661
  ok: false,
28436
28662
  error: "invalid_cwd",
@@ -30148,11 +30374,11 @@ __export(instance_copy_exports, {
30148
30374
  copyInstance: () => copyInstance
30149
30375
  });
30150
30376
  import fs45 from "fs";
30151
- import path51 from "path";
30377
+ import path52 from "path";
30152
30378
  async function copyInstance(src, dst, opts) {
30153
30379
  const { inheritableKeys = {}, onProgress } = opts;
30154
30380
  fs45.mkdirSync(dst, { recursive: true });
30155
- const configSrc = path51.join(src, "config.json");
30381
+ const configSrc = path52.join(src, "config.json");
30156
30382
  if (fs45.existsSync(configSrc)) {
30157
30383
  onProgress?.("Configuration", "start");
30158
30384
  const config = JSON.parse(fs45.readFileSync(configSrc, "utf-8"));
@@ -30176,44 +30402,44 @@ async function copyInstance(src, dst, opts) {
30176
30402
  }
30177
30403
  }
30178
30404
  }
30179
- fs45.writeFileSync(path51.join(dst, "config.json"), JSON.stringify(config, null, 2));
30405
+ fs45.writeFileSync(path52.join(dst, "config.json"), JSON.stringify(config, null, 2));
30180
30406
  onProgress?.("Configuration", "done");
30181
30407
  }
30182
- const pluginsSrc = path51.join(src, "plugins.json");
30408
+ const pluginsSrc = path52.join(src, "plugins.json");
30183
30409
  if (fs45.existsSync(pluginsSrc)) {
30184
30410
  onProgress?.("Plugin list", "start");
30185
- fs45.copyFileSync(pluginsSrc, path51.join(dst, "plugins.json"));
30411
+ fs45.copyFileSync(pluginsSrc, path52.join(dst, "plugins.json"));
30186
30412
  onProgress?.("Plugin list", "done");
30187
30413
  }
30188
- const pluginsDir = path51.join(src, "plugins");
30414
+ const pluginsDir = path52.join(src, "plugins");
30189
30415
  if (fs45.existsSync(pluginsDir)) {
30190
30416
  onProgress?.("Plugins", "start");
30191
- const dstPlugins = path51.join(dst, "plugins");
30417
+ const dstPlugins = path52.join(dst, "plugins");
30192
30418
  fs45.mkdirSync(dstPlugins, { recursive: true });
30193
- const pkgJson = path51.join(pluginsDir, "package.json");
30194
- if (fs45.existsSync(pkgJson)) fs45.copyFileSync(pkgJson, path51.join(dstPlugins, "package.json"));
30195
- const nodeModules = path51.join(pluginsDir, "node_modules");
30196
- if (fs45.existsSync(nodeModules)) fs45.cpSync(nodeModules, path51.join(dstPlugins, "node_modules"), { recursive: true });
30419
+ const pkgJson = path52.join(pluginsDir, "package.json");
30420
+ if (fs45.existsSync(pkgJson)) fs45.copyFileSync(pkgJson, path52.join(dstPlugins, "package.json"));
30421
+ const nodeModules = path52.join(pluginsDir, "node_modules");
30422
+ if (fs45.existsSync(nodeModules)) fs45.cpSync(nodeModules, path52.join(dstPlugins, "node_modules"), { recursive: true });
30197
30423
  onProgress?.("Plugins", "done");
30198
30424
  }
30199
- const agentsJson = path51.join(src, "agents.json");
30425
+ const agentsJson = path52.join(src, "agents.json");
30200
30426
  if (fs45.existsSync(agentsJson)) {
30201
30427
  onProgress?.("Agents", "start");
30202
- fs45.copyFileSync(agentsJson, path51.join(dst, "agents.json"));
30203
- const agentsDir = path51.join(src, "agents");
30204
- if (fs45.existsSync(agentsDir)) fs45.cpSync(agentsDir, path51.join(dst, "agents"), { recursive: true });
30428
+ fs45.copyFileSync(agentsJson, path52.join(dst, "agents.json"));
30429
+ const agentsDir = path52.join(src, "agents");
30430
+ if (fs45.existsSync(agentsDir)) fs45.cpSync(agentsDir, path52.join(dst, "agents"), { recursive: true });
30205
30431
  onProgress?.("Agents", "done");
30206
30432
  }
30207
- const binDir = path51.join(src, "bin");
30433
+ const binDir = path52.join(src, "bin");
30208
30434
  if (fs45.existsSync(binDir)) {
30209
30435
  onProgress?.("Tools", "start");
30210
- fs45.cpSync(binDir, path51.join(dst, "bin"), { recursive: true });
30436
+ fs45.cpSync(binDir, path52.join(dst, "bin"), { recursive: true });
30211
30437
  onProgress?.("Tools", "done");
30212
30438
  }
30213
- const pluginDataSrc = path51.join(src, "plugins", "data");
30439
+ const pluginDataSrc = path52.join(src, "plugins", "data");
30214
30440
  if (fs45.existsSync(pluginDataSrc)) {
30215
30441
  onProgress?.("Preferences", "start");
30216
- copyPluginSettings(pluginDataSrc, path51.join(dst, "plugins", "data"), inheritableKeys);
30442
+ copyPluginSettings(pluginDataSrc, path52.join(dst, "plugins", "data"), inheritableKeys);
30217
30443
  onProgress?.("Preferences", "done");
30218
30444
  }
30219
30445
  }
@@ -30228,10 +30454,10 @@ function copyPluginSettings(srcData, dstData, inheritableKeys) {
30228
30454
  if (key in settings) filtered[key] = settings[key];
30229
30455
  }
30230
30456
  if (Object.keys(filtered).length > 0) {
30231
- const relative = path51.relative(srcData, path51.dirname(settingsPath));
30232
- const dstDir = path51.join(dstData, relative);
30457
+ const relative = path52.relative(srcData, path52.dirname(settingsPath));
30458
+ const dstDir = path52.join(dstData, relative);
30233
30459
  fs45.mkdirSync(dstDir, { recursive: true });
30234
- fs45.writeFileSync(path51.join(dstDir, "settings.json"), JSON.stringify(filtered, null, 2));
30460
+ fs45.writeFileSync(path52.join(dstDir, "settings.json"), JSON.stringify(filtered, null, 2));
30235
30461
  }
30236
30462
  } catch {
30237
30463
  }
@@ -30242,15 +30468,15 @@ function walkPluginDirs(base, cb) {
30242
30468
  for (const entry of fs45.readdirSync(base, { withFileTypes: true })) {
30243
30469
  if (!entry.isDirectory()) continue;
30244
30470
  if (entry.name.startsWith("@")) {
30245
- const scopeDir = path51.join(base, entry.name);
30471
+ const scopeDir = path52.join(base, entry.name);
30246
30472
  for (const sub of fs45.readdirSync(scopeDir, { withFileTypes: true })) {
30247
30473
  if (!sub.isDirectory()) continue;
30248
30474
  const pluginName = `${entry.name}/${sub.name}`;
30249
- const settingsPath = path51.join(scopeDir, sub.name, "settings.json");
30475
+ const settingsPath = path52.join(scopeDir, sub.name, "settings.json");
30250
30476
  if (fs45.existsSync(settingsPath)) cb(pluginName, settingsPath);
30251
30477
  }
30252
30478
  } else {
30253
- const settingsPath = path51.join(base, entry.name, "settings.json");
30479
+ const settingsPath = path52.join(base, entry.name, "settings.json");
30254
30480
  if (fs45.existsSync(settingsPath)) cb(entry.name, settingsPath);
30255
30481
  }
30256
30482
  }
@@ -30263,14 +30489,14 @@ var init_instance_copy = __esm({
30263
30489
 
30264
30490
  // src/core/setup/git-protect.ts
30265
30491
  import fs46 from "fs";
30266
- import path52 from "path";
30492
+ import path53 from "path";
30267
30493
  function protectLocalInstance(projectDir) {
30268
30494
  ensureGitignore(projectDir);
30269
30495
  ensureClaudeMd(projectDir);
30270
30496
  printSecurityWarning();
30271
30497
  }
30272
30498
  function ensureGitignore(projectDir) {
30273
- const gitignorePath = path52.join(projectDir, ".gitignore");
30499
+ const gitignorePath = path53.join(projectDir, ".gitignore");
30274
30500
  const entry = ".openacp";
30275
30501
  if (fs46.existsSync(gitignorePath)) {
30276
30502
  const content = fs46.readFileSync(gitignorePath, "utf-8");
@@ -30290,7 +30516,7 @@ ${entry}
30290
30516
  }
30291
30517
  }
30292
30518
  function ensureClaudeMd(projectDir) {
30293
- const claudeMdPath = path52.join(projectDir, "CLAUDE.md");
30519
+ const claudeMdPath = path53.join(projectDir, "CLAUDE.md");
30294
30520
  const marker = "## Local OpenACP Workspace";
30295
30521
  if (fs46.existsSync(claudeMdPath)) {
30296
30522
  const content = fs46.readFileSync(claudeMdPath, "utf-8");
@@ -30333,7 +30559,7 @@ var init_git_protect = __esm({
30333
30559
  });
30334
30560
 
30335
30561
  // src/core/setup/wizard.ts
30336
- import * as path53 from "path";
30562
+ import * as path54 from "path";
30337
30563
  import * as fs47 from "fs";
30338
30564
  import * as os10 from "os";
30339
30565
  import * as clack7 from "@clack/prompts";
@@ -30381,7 +30607,7 @@ async function runSetup(configManager, opts) {
30381
30607
  const instanceRoot = opts?.instanceRoot;
30382
30608
  let instanceName = opts?.instanceName;
30383
30609
  if (!instanceName) {
30384
- const defaultName = path53.basename(path53.dirname(instanceRoot));
30610
+ const defaultName = path54.basename(path54.dirname(instanceRoot));
30385
30611
  const locationHint = instanceRoot.replace(/\/.openacp$/, "").replace(os10.homedir(), "~");
30386
30612
  const nameResult = await clack7.text({
30387
30613
  message: `Name for this workspace (${locationHint})`,
@@ -30392,13 +30618,13 @@ async function runSetup(configManager, opts) {
30392
30618
  instanceName = nameResult.trim();
30393
30619
  }
30394
30620
  const globalRoot = getGlobalRoot();
30395
- const registryPath = path53.join(globalRoot, "instances.json");
30621
+ const registryPath = path54.join(globalRoot, "instances.json");
30396
30622
  const instanceRegistry = new InstanceRegistry(registryPath);
30397
30623
  instanceRegistry.load();
30398
30624
  let didCopy = false;
30399
30625
  if (opts?.from) {
30400
- const fromRoot = path53.join(opts.from, ".openacp");
30401
- if (fs47.existsSync(path53.join(fromRoot, "config.json"))) {
30626
+ const fromRoot = path54.join(opts.from, ".openacp");
30627
+ if (fs47.existsSync(path54.join(fromRoot, "config.json"))) {
30402
30628
  const inheritableMap = buildInheritableKeysMap();
30403
30629
  await copyInstance(fromRoot, instanceRoot, { inheritableKeys: inheritableMap });
30404
30630
  didCopy = true;
@@ -30409,7 +30635,7 @@ async function runSetup(configManager, opts) {
30409
30635
  }
30410
30636
  if (!didCopy) {
30411
30637
  const existingInstances = instanceRegistry.list().filter(
30412
- (e) => fs47.existsSync(path53.join(e.root, "config.json")) && e.root !== instanceRoot
30638
+ (e) => fs47.existsSync(path54.join(e.root, "config.json")) && e.root !== instanceRoot
30413
30639
  );
30414
30640
  if (existingInstances.length > 0) {
30415
30641
  let singleLabel;
@@ -30417,7 +30643,7 @@ async function runSetup(configManager, opts) {
30417
30643
  const e = existingInstances[0];
30418
30644
  let name = e.id;
30419
30645
  try {
30420
- const cfg = JSON.parse(fs47.readFileSync(path53.join(e.root, "config.json"), "utf-8"));
30646
+ const cfg = JSON.parse(fs47.readFileSync(path54.join(e.root, "config.json"), "utf-8"));
30421
30647
  if (cfg.instanceName) name = cfg.instanceName;
30422
30648
  } catch {
30423
30649
  }
@@ -30440,7 +30666,7 @@ async function runSetup(configManager, opts) {
30440
30666
  options: existingInstances.map((e) => {
30441
30667
  let name = e.id;
30442
30668
  try {
30443
- const cfg = JSON.parse(fs47.readFileSync(path53.join(e.root, "config.json"), "utf-8"));
30669
+ const cfg = JSON.parse(fs47.readFileSync(path54.join(e.root, "config.json"), "utf-8"));
30444
30670
  if (cfg.instanceName) name = cfg.instanceName;
30445
30671
  } catch {
30446
30672
  }
@@ -30535,9 +30761,9 @@ async function runSetup(configManager, opts) {
30535
30761
  if (channelId.startsWith("official:")) {
30536
30762
  const npmPackage = channelId.slice("official:".length);
30537
30763
  const { execFileSync: execFileSync9 } = await import("child_process");
30538
- const pluginsDir = path53.join(instanceRoot, "plugins");
30539
- const nodeModulesDir = path53.join(pluginsDir, "node_modules");
30540
- const installedPath = path53.join(nodeModulesDir, npmPackage);
30764
+ const pluginsDir = path54.join(instanceRoot, "plugins");
30765
+ const nodeModulesDir = path54.join(pluginsDir, "node_modules");
30766
+ const installedPath = path54.join(nodeModulesDir, npmPackage);
30541
30767
  if (!fs47.existsSync(installedPath)) {
30542
30768
  try {
30543
30769
  clack7.log.step(`Installing ${npmPackage}...`);
@@ -30551,9 +30777,9 @@ async function runSetup(configManager, opts) {
30551
30777
  }
30552
30778
  }
30553
30779
  try {
30554
- const installedPkgPath = path53.join(nodeModulesDir, npmPackage, "package.json");
30780
+ const installedPkgPath = path54.join(nodeModulesDir, npmPackage, "package.json");
30555
30781
  const installedPkg = JSON.parse(fs47.readFileSync(installedPkgPath, "utf-8"));
30556
- const pluginModule = await import(path53.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
30782
+ const pluginModule = await import(path54.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
30557
30783
  const plugin2 = pluginModule.default;
30558
30784
  if (plugin2?.install) {
30559
30785
  const installCtx = createInstallContext2({
@@ -30583,8 +30809,8 @@ async function runSetup(configManager, opts) {
30583
30809
  if (channelId.startsWith("community:")) {
30584
30810
  const npmPackage = channelId.slice("community:".length);
30585
30811
  const { execFileSync: execFileSync9 } = await import("child_process");
30586
- const pluginsDir = path53.join(instanceRoot, "plugins");
30587
- const nodeModulesDir = path53.join(pluginsDir, "node_modules");
30812
+ const pluginsDir = path54.join(instanceRoot, "plugins");
30813
+ const nodeModulesDir = path54.join(pluginsDir, "node_modules");
30588
30814
  try {
30589
30815
  execFileSync9("npm", ["install", npmPackage, "--prefix", pluginsDir, "--save", "--ignore-scripts"], {
30590
30816
  stdio: "inherit",
@@ -30596,9 +30822,9 @@ async function runSetup(configManager, opts) {
30596
30822
  }
30597
30823
  try {
30598
30824
  const { readFileSync: readFileSync18 } = await import("fs");
30599
- const installedPkgPath = path53.join(nodeModulesDir, npmPackage, "package.json");
30825
+ const installedPkgPath = path54.join(nodeModulesDir, npmPackage, "package.json");
30600
30826
  const installedPkg = JSON.parse(readFileSync18(installedPkgPath, "utf-8"));
30601
- const pluginModule = await import(path53.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
30827
+ const pluginModule = await import(path54.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
30602
30828
  const plugin2 = pluginModule.default;
30603
30829
  if (plugin2?.install) {
30604
30830
  const installCtx = createInstallContext2({
@@ -30651,7 +30877,7 @@ async function runSetup(configManager, opts) {
30651
30877
  workspace: { allowExternalWorkspaces: true, security: { allowedPaths: [], envWhitelist: [] } },
30652
30878
  logging: {
30653
30879
  level: "info",
30654
- logDir: path53.join(instanceRoot, "logs"),
30880
+ logDir: path54.join(instanceRoot, "logs"),
30655
30881
  maxFileSize: "10m",
30656
30882
  maxFiles: 7,
30657
30883
  sessionLogRetentionDays: 30
@@ -30678,7 +30904,7 @@ async function runSetup(configManager, opts) {
30678
30904
  instanceRegistry.register(instanceId, instanceRoot);
30679
30905
  await instanceRegistry.save();
30680
30906
  }
30681
- const projectDir = path53.dirname(instanceRoot);
30907
+ const projectDir = path54.dirname(instanceRoot);
30682
30908
  protectLocalInstance(projectDir);
30683
30909
  clack7.outro(`Config saved to ${configManager.getConfigPath()}`);
30684
30910
  if (!opts?.skipRunMode) {
@@ -30757,7 +30983,7 @@ async function runReconfigure(configManager, settingsManager) {
30757
30983
  await configureChannels(config, settingsManager);
30758
30984
  }
30759
30985
  if (choice === "agents") {
30760
- const reconfigRoot = path53.dirname(configManager.getConfigPath());
30986
+ const reconfigRoot = path54.dirname(configManager.getConfigPath());
30761
30987
  const { defaultAgent } = await setupAgents(reconfigRoot);
30762
30988
  await configManager.save({ defaultAgent });
30763
30989
  config = configManager.get();
@@ -30962,7 +31188,7 @@ __export(dev_loader_exports, {
30962
31188
  });
30963
31189
  import fs48 from "fs";
30964
31190
  import os11 from "os";
30965
- import path54 from "path";
31191
+ import path55 from "path";
30966
31192
  var loadCounter, DevPluginLoader;
30967
31193
  var init_dev_loader = __esm({
30968
31194
  "src/core/plugin/dev-loader.ts"() {
@@ -30972,24 +31198,24 @@ var init_dev_loader = __esm({
30972
31198
  pluginPath;
30973
31199
  lastTempDir = null;
30974
31200
  constructor(pluginPath) {
30975
- this.pluginPath = path54.resolve(pluginPath);
31201
+ this.pluginPath = path55.resolve(pluginPath);
30976
31202
  }
30977
31203
  async load() {
30978
- const distPath = path54.join(this.pluginPath, "dist");
30979
- const distIndex = path54.join(distPath, "index.js");
30980
- const srcIndex = path54.join(this.pluginPath, "src", "index.ts");
31204
+ const distPath = path55.join(this.pluginPath, "dist");
31205
+ const distIndex = path55.join(distPath, "index.js");
31206
+ const srcIndex = path55.join(this.pluginPath, "src", "index.ts");
30981
31207
  if (!fs48.existsSync(distIndex) && !fs48.existsSync(srcIndex)) {
30982
31208
  throw new Error(`Plugin not found at ${this.pluginPath}. Expected dist/index.js or src/index.ts`);
30983
31209
  }
30984
31210
  if (!fs48.existsSync(distIndex)) {
30985
31211
  throw new Error(`Built plugin not found at ${distIndex}. Run 'npm run build' first.`);
30986
31212
  }
30987
- const tempDir = path54.join(os11.tmpdir(), `openacp-dev-plugin-${Date.now()}-${++loadCounter}`);
31213
+ const tempDir = path55.join(os11.tmpdir(), `openacp-dev-plugin-${Date.now()}-${++loadCounter}`);
30988
31214
  fs48.cpSync(distPath, tempDir, { recursive: true });
30989
31215
  const previousTempDir = this.lastTempDir;
30990
31216
  this.lastTempDir = tempDir;
30991
31217
  try {
30992
- const mod = await import(`file://${path54.join(tempDir, "index.js")}`);
31218
+ const mod = await import(`file://${path55.join(tempDir, "index.js")}`);
30993
31219
  const plugin2 = mod.default;
30994
31220
  if (!plugin2 || !plugin2.name || !plugin2.setup) {
30995
31221
  throw new Error(`Invalid plugin at ${distIndex}. Must export default OpenACPPlugin with name and setup().`);
@@ -31012,7 +31238,7 @@ var init_dev_loader = __esm({
31012
31238
  }
31013
31239
  /** Returns the path to the plugin's dist directory (the source of truth — NOT the temp copy). */
31014
31240
  getDistPath() {
31015
- return path54.join(this.pluginPath, "dist");
31241
+ return path55.join(this.pluginPath, "dist");
31016
31242
  }
31017
31243
  };
31018
31244
  }
@@ -31024,7 +31250,7 @@ __export(main_exports, {
31024
31250
  RESTART_EXIT_CODE: () => RESTART_EXIT_CODE,
31025
31251
  startServer: () => startServer
31026
31252
  });
31027
- import path55 from "path";
31253
+ import path56 from "path";
31028
31254
  import { randomUUID as randomUUID4 } from "crypto";
31029
31255
  import fs49 from "fs";
31030
31256
  async function startServer(opts) {
@@ -31049,7 +31275,7 @@ async function startServer(opts) {
31049
31275
  process.exit(1);
31050
31276
  }
31051
31277
  const globalRoot = getGlobalRoot();
31052
- const reg = new InstanceRegistry(path55.join(globalRoot, "instances.json"));
31278
+ const reg = new InstanceRegistry(path56.join(globalRoot, "instances.json"));
31053
31279
  reg.load();
31054
31280
  const entry = reg.getByRoot(root);
31055
31281
  opts = { ...opts, instanceContext: createInstanceContext({ id: entry?.id ?? randomUUID4(), root }) };
@@ -31137,22 +31363,22 @@ async function startServer(opts) {
31137
31363
  try {
31138
31364
  let modulePath;
31139
31365
  if (name.startsWith("/") || name.startsWith(".")) {
31140
- const resolved = path55.resolve(name);
31141
- const pkgPath = path55.join(resolved, "package.json");
31366
+ const resolved = path56.resolve(name);
31367
+ const pkgPath = path56.join(resolved, "package.json");
31142
31368
  const pkg = JSON.parse(await fs49.promises.readFile(pkgPath, "utf-8"));
31143
- modulePath = path55.join(resolved, pkg.main || "dist/index.js");
31369
+ modulePath = path56.join(resolved, pkg.main || "dist/index.js");
31144
31370
  } else {
31145
- const nodeModulesDir = path55.join(ctx.paths.plugins, "node_modules");
31146
- let pkgDir = path55.join(nodeModulesDir, name);
31147
- if (!fs49.existsSync(path55.join(pkgDir, "package.json"))) {
31371
+ const nodeModulesDir = path56.join(ctx.paths.plugins, "node_modules");
31372
+ let pkgDir = path56.join(nodeModulesDir, name);
31373
+ if (!fs49.existsSync(path56.join(pkgDir, "package.json"))) {
31148
31374
  let found = false;
31149
31375
  const scopes = fs49.existsSync(nodeModulesDir) ? fs49.readdirSync(nodeModulesDir).filter((d) => d.startsWith("@")) : [];
31150
31376
  for (const scope of scopes) {
31151
- const scopeDir = path55.join(nodeModulesDir, scope);
31377
+ const scopeDir = path56.join(nodeModulesDir, scope);
31152
31378
  const pkgs = fs49.readdirSync(scopeDir);
31153
31379
  for (const pkg2 of pkgs) {
31154
- const candidateDir = path55.join(scopeDir, pkg2);
31155
- const candidatePkgPath = path55.join(candidateDir, "package.json");
31380
+ const candidateDir = path56.join(scopeDir, pkg2);
31381
+ const candidatePkgPath = path56.join(candidateDir, "package.json");
31156
31382
  if (fs49.existsSync(candidatePkgPath)) {
31157
31383
  try {
31158
31384
  const candidatePkg = JSON.parse(fs49.readFileSync(candidatePkgPath, "utf-8"));
@@ -31169,9 +31395,9 @@ async function startServer(opts) {
31169
31395
  if (found) break;
31170
31396
  }
31171
31397
  }
31172
- const pkgJsonPath = path55.join(pkgDir, "package.json");
31398
+ const pkgJsonPath = path56.join(pkgDir, "package.json");
31173
31399
  const pkg = JSON.parse(await fs49.promises.readFile(pkgJsonPath, "utf-8"));
31174
- modulePath = path55.join(pkgDir, pkg.main || "dist/index.js");
31400
+ modulePath = path56.join(pkgDir, pkg.main || "dist/index.js");
31175
31401
  }
31176
31402
  log.debug({ plugin: name, modulePath }, "Loading community plugin");
31177
31403
  const mod = await import(modulePath);
@@ -31343,7 +31569,7 @@ async function startServer(opts) {
31343
31569
  await core.start();
31344
31570
  try {
31345
31571
  const globalRoot = getGlobalRoot();
31346
- const registryPath = path55.join(globalRoot, "instances.json");
31572
+ const registryPath = path56.join(globalRoot, "instances.json");
31347
31573
  const instanceReg = new InstanceRegistry(registryPath);
31348
31574
  await instanceReg.load();
31349
31575
  if (!instanceReg.getByRoot(ctx.root)) {
@@ -31515,7 +31741,7 @@ var restart_exports = {};
31515
31741
  __export(restart_exports, {
31516
31742
  cmdRestart: () => cmdRestart
31517
31743
  });
31518
- import path56 from "path";
31744
+ import path57 from "path";
31519
31745
  import { randomUUID as randomUUID5 } from "crypto";
31520
31746
  async function cmdRestart(args2 = [], instanceRoot) {
31521
31747
  const json = isJsonMode(args2);
@@ -31555,7 +31781,7 @@ Stops the running daemon (if any) and starts a new one.
31555
31781
  if (!json && stopResult.stopped) {
31556
31782
  console.log(`Stopped daemon (was PID ${stopResult.pid})`);
31557
31783
  }
31558
- const cm = new ConfigManager2(path56.join(root, "config.json"));
31784
+ const cm = new ConfigManager2(path57.join(root, "config.json"));
31559
31785
  if (!await cm.exists()) {
31560
31786
  if (json) jsonError(ErrorCodes.CONFIG_NOT_FOUND, 'No config found. Run "openacp" first to set up.');
31561
31787
  console.error('No config found. Run "openacp" first to set up.');
@@ -31576,7 +31802,7 @@ Stops the running daemon (if any) and starts a new one.
31576
31802
  printInstanceHint(root);
31577
31803
  console.log("Starting in foreground mode...");
31578
31804
  const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
31579
- const reg = new InstanceRegistry(path56.join(getGlobalRoot(), "instances.json"));
31805
+ const reg = new InstanceRegistry(path57.join(getGlobalRoot(), "instances.json"));
31580
31806
  reg.load();
31581
31807
  const existingEntry = reg.getByRoot(root);
31582
31808
  const ctx = createInstanceContext({
@@ -31625,7 +31851,7 @@ __export(status_exports, {
31625
31851
  readInstanceInfo: () => readInstanceInfo
31626
31852
  });
31627
31853
  import fs50 from "fs";
31628
- import path57 from "path";
31854
+ import path58 from "path";
31629
31855
  import os12 from "os";
31630
31856
  async function cmdStatus(args2 = [], instanceRoot) {
31631
31857
  const json = isJsonMode(args2);
@@ -31643,7 +31869,7 @@ async function cmdStatus(args2 = [], instanceRoot) {
31643
31869
  await showSingleInstance(root, json);
31644
31870
  }
31645
31871
  async function showAllInstances(json = false) {
31646
- const registryPath = path57.join(getGlobalRoot(), "instances.json");
31872
+ const registryPath = path58.join(getGlobalRoot(), "instances.json");
31647
31873
  const registry = new InstanceRegistry(registryPath);
31648
31874
  await registry.load();
31649
31875
  const instances = registry.list();
@@ -31686,7 +31912,7 @@ async function showAllInstances(json = false) {
31686
31912
  console.log("");
31687
31913
  }
31688
31914
  async function showInstanceById(id, json = false) {
31689
- const registryPath = path57.join(getGlobalRoot(), "instances.json");
31915
+ const registryPath = path58.join(getGlobalRoot(), "instances.json");
31690
31916
  const registry = new InstanceRegistry(registryPath);
31691
31917
  await registry.load();
31692
31918
  const entry = registry.get(id);
@@ -31701,7 +31927,7 @@ async function showSingleInstance(root, json = false) {
31701
31927
  const info = readInstanceInfo(root);
31702
31928
  if (json) {
31703
31929
  jsonSuccess({
31704
- id: path57.basename(root),
31930
+ id: path58.basename(root),
31705
31931
  name: info.name,
31706
31932
  status: info.pid ? "online" : "offline",
31707
31933
  pid: info.pid,
@@ -31732,13 +31958,13 @@ function readInstanceInfo(root) {
31732
31958
  channels: []
31733
31959
  };
31734
31960
  try {
31735
- const config = JSON.parse(fs50.readFileSync(path57.join(root, "config.json"), "utf-8"));
31961
+ const config = JSON.parse(fs50.readFileSync(path58.join(root, "config.json"), "utf-8"));
31736
31962
  result.name = config.instanceName ?? null;
31737
31963
  result.runMode = config.runMode ?? null;
31738
31964
  } catch {
31739
31965
  }
31740
31966
  try {
31741
- const pid = parseInt(fs50.readFileSync(path57.join(root, "openacp.pid"), "utf-8").trim());
31967
+ const pid = parseInt(fs50.readFileSync(path58.join(root, "openacp.pid"), "utf-8").trim());
31742
31968
  if (!isNaN(pid)) {
31743
31969
  process.kill(pid, 0);
31744
31970
  result.pid = pid;
@@ -31746,19 +31972,19 @@ function readInstanceInfo(root) {
31746
31972
  } catch {
31747
31973
  }
31748
31974
  try {
31749
- const port = parseInt(fs50.readFileSync(path57.join(root, "api.port"), "utf-8").trim());
31975
+ const port = parseInt(fs50.readFileSync(path58.join(root, "api.port"), "utf-8").trim());
31750
31976
  if (!isNaN(port)) result.apiPort = port;
31751
31977
  } catch {
31752
31978
  }
31753
31979
  try {
31754
- const tunnels = JSON.parse(fs50.readFileSync(path57.join(root, "tunnels.json"), "utf-8"));
31980
+ const tunnels = JSON.parse(fs50.readFileSync(path58.join(root, "tunnels.json"), "utf-8"));
31755
31981
  const entries = Object.values(tunnels);
31756
31982
  const systemEntry = entries.find((t) => t.type === "system");
31757
31983
  if (systemEntry?.port) result.tunnelPort = systemEntry.port;
31758
31984
  } catch {
31759
31985
  }
31760
31986
  try {
31761
- const plugins = JSON.parse(fs50.readFileSync(path57.join(root, "plugins.json"), "utf-8"));
31987
+ const plugins = JSON.parse(fs50.readFileSync(path58.join(root, "plugins.json"), "utf-8"));
31762
31988
  const adapterMap = [
31763
31989
  { pluginName: "@openacp/telegram", channelId: "telegram" },
31764
31990
  { pluginName: "@openacp/discord-adapter", channelId: "discord" },
@@ -31776,7 +32002,7 @@ function readInstanceInfo(root) {
31776
32002
  function formatInstanceStatus(root) {
31777
32003
  const info = readInstanceInfo(root);
31778
32004
  if (!info.pid) return null;
31779
- const workspaceDir = path57.dirname(root);
32005
+ const workspaceDir = path58.dirname(root);
31780
32006
  const displayPath = workspaceDir.replace(os12.homedir(), "~");
31781
32007
  const lines = [];
31782
32008
  lines.push(` PID: ${info.pid}`);
@@ -31845,7 +32071,7 @@ var config_editor_exports = {};
31845
32071
  __export(config_editor_exports, {
31846
32072
  runConfigEditor: () => runConfigEditor
31847
32073
  });
31848
- import * as path58 from "path";
32074
+ import * as path59 from "path";
31849
32075
  import * as clack8 from "@clack/prompts";
31850
32076
  async function select8(opts) {
31851
32077
  const result = await clack8.select({
@@ -32399,7 +32625,7 @@ async function runConfigEditor(configManager, mode = "file", apiPort, settingsMa
32399
32625
  await configManager.load();
32400
32626
  const config = configManager.get();
32401
32627
  const updates = {};
32402
- const instanceRoot = path58.dirname(configManager.getConfigPath());
32628
+ const instanceRoot = path59.dirname(configManager.getConfigPath());
32403
32629
  console.log(`
32404
32630
  ${c2.cyan}${c2.bold}OpenACP Config Editor${c2.reset}`);
32405
32631
  console.log(dim2(`Config: ${configManager.getConfigPath()}`));
@@ -32456,17 +32682,17 @@ ${c2.cyan}${c2.bold}OpenACP Config Editor${c2.reset}`);
32456
32682
  async function sendConfigViaApi(port, updates) {
32457
32683
  const { apiCall: call } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
32458
32684
  const paths = flattenToPaths(updates);
32459
- for (const { path: path71, value } of paths) {
32685
+ for (const { path: path72, value } of paths) {
32460
32686
  const res = await call(port, "/api/config", {
32461
32687
  method: "PATCH",
32462
32688
  headers: { "Content-Type": "application/json" },
32463
- body: JSON.stringify({ path: path71, value })
32689
+ body: JSON.stringify({ path: path72, value })
32464
32690
  });
32465
32691
  const data = await res.json();
32466
32692
  if (!res.ok) {
32467
- console.log(warn2(`Failed to update ${path71}: ${data.error}`));
32693
+ console.log(warn2(`Failed to update ${path72}: ${data.error}`));
32468
32694
  } else if (data.needsRestart) {
32469
- console.log(warn2(`${path71} updated \u2014 restart required`));
32695
+ console.log(warn2(`${path72} updated \u2014 restart required`));
32470
32696
  }
32471
32697
  }
32472
32698
  }
@@ -32576,24 +32802,24 @@ __export(migration_exports, {
32576
32802
  migrateGlobalInstance: () => migrateGlobalInstance
32577
32803
  });
32578
32804
  import fs55 from "fs";
32579
- import path68 from "path";
32805
+ import path69 from "path";
32580
32806
  import os15 from "os";
32581
32807
  import { randomUUID as randomUUID8 } from "crypto";
32582
32808
  async function migrateGlobalInstance() {
32583
32809
  const globalRoot = getGlobalRoot();
32584
- const globalConfig = path68.join(globalRoot, "config.json");
32810
+ const globalConfig = path69.join(globalRoot, "config.json");
32585
32811
  if (!fs55.existsSync(globalConfig)) return null;
32586
- let baseDir = path68.join(os15.homedir(), "openacp-workspace");
32812
+ let baseDir = path69.join(os15.homedir(), "openacp-workspace");
32587
32813
  try {
32588
32814
  const raw = JSON.parse(fs55.readFileSync(globalConfig, "utf-8"));
32589
32815
  if (raw.workspace?.baseDir) {
32590
32816
  const configured = raw.workspace.baseDir;
32591
- baseDir = configured.startsWith("~") ? path68.join(os15.homedir(), configured.slice(1)) : configured;
32817
+ baseDir = configured.startsWith("~") ? path69.join(os15.homedir(), configured.slice(1)) : configured;
32592
32818
  }
32593
32819
  } catch {
32594
32820
  }
32595
- const targetRoot = path68.join(baseDir, ".openacp");
32596
- if (path68.resolve(targetRoot) === path68.resolve(globalRoot)) {
32821
+ const targetRoot = path69.join(baseDir, ".openacp");
32822
+ if (path69.resolve(targetRoot) === path69.resolve(globalRoot)) {
32597
32823
  return null;
32598
32824
  }
32599
32825
  const instanceFiles = [
@@ -32607,34 +32833,34 @@ async function migrateGlobalInstance() {
32607
32833
  const instanceDirs = ["plugins", "logs", "history", "files"];
32608
32834
  fs55.mkdirSync(targetRoot, { recursive: true });
32609
32835
  for (const file of instanceFiles) {
32610
- const src = path68.join(globalRoot, file);
32611
- const dst = path68.join(targetRoot, file);
32836
+ const src = path69.join(globalRoot, file);
32837
+ const dst = path69.join(targetRoot, file);
32612
32838
  if (fs55.existsSync(src)) {
32613
32839
  fs55.cpSync(src, dst, { force: true });
32614
32840
  fs55.rmSync(src);
32615
32841
  }
32616
32842
  }
32617
32843
  for (const dir of instanceDirs) {
32618
- const src = path68.join(globalRoot, dir);
32619
- const dst = path68.join(targetRoot, dir);
32844
+ const src = path69.join(globalRoot, dir);
32845
+ const dst = path69.join(targetRoot, dir);
32620
32846
  if (fs55.existsSync(src)) {
32621
32847
  fs55.cpSync(src, dst, { recursive: true, force: true });
32622
32848
  fs55.rmSync(src, { recursive: true, force: true });
32623
32849
  }
32624
32850
  }
32625
- const srcCache = path68.join(globalRoot, "cache");
32626
- const dstCache = path68.join(targetRoot, "cache");
32851
+ const srcCache = path69.join(globalRoot, "cache");
32852
+ const dstCache = path69.join(targetRoot, "cache");
32627
32853
  if (fs55.existsSync(srcCache)) {
32628
32854
  fs55.mkdirSync(dstCache, { recursive: true });
32629
32855
  for (const entry of fs55.readdirSync(srcCache)) {
32630
32856
  if (entry === "registry-cache.json") continue;
32631
- const s = path68.join(srcCache, entry);
32632
- const d = path68.join(dstCache, entry);
32857
+ const s = path69.join(srcCache, entry);
32858
+ const d = path69.join(dstCache, entry);
32633
32859
  fs55.cpSync(s, d, { recursive: true, force: true });
32634
32860
  fs55.rmSync(s, { recursive: true, force: true });
32635
32861
  }
32636
32862
  }
32637
- const migratedConfigPath = path68.join(targetRoot, "config.json");
32863
+ const migratedConfigPath = path69.join(targetRoot, "config.json");
32638
32864
  try {
32639
32865
  const config = JSON.parse(fs55.readFileSync(migratedConfigPath, "utf-8"));
32640
32866
  if (config.workspace?.baseDir) {
@@ -32643,7 +32869,7 @@ async function migrateGlobalInstance() {
32643
32869
  fs55.writeFileSync(migratedConfigPath, JSON.stringify(config, null, 2));
32644
32870
  } catch {
32645
32871
  }
32646
- const registryPath = path68.join(globalRoot, "instances.json");
32872
+ const registryPath = path69.join(globalRoot, "instances.json");
32647
32873
  try {
32648
32874
  const registry = new InstanceRegistry(registryPath);
32649
32875
  registry.load();
@@ -32675,17 +32901,17 @@ __export(instance_prompt_exports, {
32675
32901
  promptForInstance: () => promptForInstance
32676
32902
  });
32677
32903
  import fs56 from "fs";
32678
- import path69 from "path";
32904
+ import path70 from "path";
32679
32905
  import os16 from "os";
32680
32906
  async function promptForInstance(opts) {
32681
32907
  const globalRoot = getGlobalRoot();
32682
- const globalConfigExists = fs56.existsSync(path69.join(globalRoot, "config.json"));
32908
+ const globalConfigExists = fs56.existsSync(path70.join(globalRoot, "config.json"));
32683
32909
  const cwd = process.cwd();
32684
- const isHomeDir = path69.resolve(cwd) === path69.resolve(os16.homedir());
32685
- const defaultWorkspace = path69.join(os16.homedir(), "openacp-workspace");
32686
- const createRoot = isHomeDir ? path69.join(defaultWorkspace, ".openacp") : path69.join(cwd, ".openacp");
32910
+ const isHomeDir = path70.resolve(cwd) === path70.resolve(os16.homedir());
32911
+ const defaultWorkspace = path70.join(os16.homedir(), "openacp-workspace");
32912
+ const createRoot = isHomeDir ? path70.join(defaultWorkspace, ".openacp") : path70.join(cwd, ".openacp");
32687
32913
  const detectedParent = findParentInstance(cwd, globalRoot);
32688
- const registryPath = path69.join(globalRoot, "instances.json");
32914
+ const registryPath = path70.join(globalRoot, "instances.json");
32689
32915
  const registry = new InstanceRegistry(registryPath);
32690
32916
  registry.load();
32691
32917
  const instances = registry.list().filter((e) => fs56.existsSync(e.root));
@@ -32717,24 +32943,24 @@ async function promptForInstance(opts) {
32717
32943
  const instanceOptions = instances.filter((e) => !detectedParent || e.root !== detectedParent).map((e) => {
32718
32944
  let name = e.id;
32719
32945
  try {
32720
- const raw = fs56.readFileSync(path69.join(e.root, "config.json"), "utf-8");
32946
+ const raw = fs56.readFileSync(path70.join(e.root, "config.json"), "utf-8");
32721
32947
  const parsed = JSON.parse(raw);
32722
32948
  if (parsed.instanceName) name = parsed.instanceName;
32723
32949
  } catch {
32724
32950
  }
32725
- const workspaceDir = path69.dirname(e.root);
32951
+ const workspaceDir = path70.dirname(e.root);
32726
32952
  const displayPath = workspaceDir.replace(os16.homedir(), "~");
32727
32953
  return { value: e.root, label: `${name} (${displayPath})` };
32728
32954
  });
32729
32955
  if (detectedParent) {
32730
- let name = path69.basename(path69.dirname(detectedParent));
32956
+ let name = path70.basename(path70.dirname(detectedParent));
32731
32957
  try {
32732
- const raw = fs56.readFileSync(path69.join(detectedParent, "config.json"), "utf-8");
32958
+ const raw = fs56.readFileSync(path70.join(detectedParent, "config.json"), "utf-8");
32733
32959
  const parsed = JSON.parse(raw);
32734
32960
  if (parsed.instanceName) name = parsed.instanceName;
32735
32961
  } catch {
32736
32962
  }
32737
- const workspaceDir = path69.dirname(detectedParent);
32963
+ const workspaceDir = path70.dirname(detectedParent);
32738
32964
  const displayPath = workspaceDir.replace(os16.homedir(), "~");
32739
32965
  instanceOptions.unshift({ value: detectedParent, label: `${name} (${displayPath})` });
32740
32966
  }
@@ -32773,11 +32999,11 @@ async function promptForInstance(opts) {
32773
32999
  return choice;
32774
33000
  }
32775
33001
  function findParentInstance(cwd, globalRoot) {
32776
- let dir = path69.dirname(cwd);
33002
+ let dir = path70.dirname(cwd);
32777
33003
  while (true) {
32778
- const candidate = path69.join(dir, ".openacp");
32779
- if (candidate !== globalRoot && fs56.existsSync(path69.join(candidate, "config.json"))) return candidate;
32780
- const parent = path69.dirname(dir);
33004
+ const candidate = path70.join(dir, ".openacp");
33005
+ if (candidate !== globalRoot && fs56.existsSync(path70.join(candidate, "config.json"))) return candidate;
33006
+ const parent = path70.dirname(dir);
32781
33007
  if (parent === dir) break;
32782
33008
  dir = parent;
32783
33009
  }
@@ -32793,7 +33019,7 @@ var init_instance_prompt = __esm({
32793
33019
 
32794
33020
  // src/cli.ts
32795
33021
  import { setDefaultAutoSelectFamily } from "net";
32796
- import path70 from "path";
33022
+ import path71 from "path";
32797
33023
 
32798
33024
  // src/cli/commands/help.ts
32799
33025
  function printHelp() {
@@ -32937,10 +33163,10 @@ Shows all plugins registered in the plugin registry.
32937
33163
  `);
32938
33164
  return;
32939
33165
  }
32940
- const path71 = await import("path");
33166
+ const path72 = await import("path");
32941
33167
  const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
32942
33168
  const root = instanceRoot;
32943
- const registryPath = path71.join(root, "plugins.json");
33169
+ const registryPath = path72.join(root, "plugins.json");
32944
33170
  const registry = new PluginRegistry2(registryPath);
32945
33171
  await registry.load();
32946
33172
  const plugins = registry.list();
@@ -33076,10 +33302,10 @@ async function cmdPlugin(args2 = [], instanceRoot) {
33076
33302
  }
33077
33303
  async function setPluginEnabled(name, enabled, instanceRoot, json = false) {
33078
33304
  if (json) await muteForJson();
33079
- const path71 = await import("path");
33305
+ const path72 = await import("path");
33080
33306
  const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
33081
33307
  const root = instanceRoot;
33082
- const registryPath = path71.join(root, "plugins.json");
33308
+ const registryPath = path72.join(root, "plugins.json");
33083
33309
  const registry = new PluginRegistry2(registryPath);
33084
33310
  await registry.load();
33085
33311
  const entry = registry.get(name);
@@ -33094,7 +33320,7 @@ async function setPluginEnabled(name, enabled, instanceRoot, json = false) {
33094
33320
  console.log(`Plugin ${name} ${enabled ? "enabled" : "disabled"}. Restart to apply.`);
33095
33321
  }
33096
33322
  async function configurePlugin(name, instanceRoot) {
33097
- const path71 = await import("path");
33323
+ const path72 = await import("path");
33098
33324
  const { corePlugins: corePlugins2 } = await Promise.resolve().then(() => (init_core_plugins(), core_plugins_exports));
33099
33325
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
33100
33326
  const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
@@ -33104,7 +33330,7 @@ async function configurePlugin(name, instanceRoot) {
33104
33330
  process.exit(1);
33105
33331
  }
33106
33332
  const root = instanceRoot;
33107
- const basePath = path71.join(root, "plugins", "data");
33333
+ const basePath = path72.join(root, "plugins", "data");
33108
33334
  const settingsManager = new SettingsManager2(basePath);
33109
33335
  const ctx = createInstallContext2({ pluginName: name, settingsManager, basePath });
33110
33336
  if (plugin2.configure) {
@@ -33117,7 +33343,7 @@ async function configurePlugin(name, instanceRoot) {
33117
33343
  }
33118
33344
  async function installPlugin(input2, instanceRoot, json = false) {
33119
33345
  if (json) await muteForJson();
33120
- const path71 = await import("path");
33346
+ const path72 = await import("path");
33121
33347
  const { execFileSync: execFileSync9 } = await import("child_process");
33122
33348
  const { getCurrentVersion: getCurrentVersion2 } = await Promise.resolve().then(() => (init_version(), version_exports));
33123
33349
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
@@ -33168,9 +33394,9 @@ async function installPlugin(input2, instanceRoot, json = false) {
33168
33394
  if (!json) console.log(`Installing ${installSpec}...`);
33169
33395
  const { corePlugins: corePlugins2 } = await Promise.resolve().then(() => (init_core_plugins(), core_plugins_exports));
33170
33396
  const builtinPlugin = corePlugins2.find((p2) => p2.name === pkgName);
33171
- const basePath = path71.join(root, "plugins", "data");
33397
+ const basePath = path72.join(root, "plugins", "data");
33172
33398
  const settingsManager = new SettingsManager2(basePath);
33173
- const registryPath = path71.join(root, "plugins.json");
33399
+ const registryPath = path72.join(root, "plugins.json");
33174
33400
  const pluginRegistry = new PluginRegistry2(registryPath);
33175
33401
  await pluginRegistry.load();
33176
33402
  if (builtinPlugin) {
@@ -33190,8 +33416,8 @@ async function installPlugin(input2, instanceRoot, json = false) {
33190
33416
  console.log(`\u2713 ${builtinPlugin.name} installed! Restart to activate.`);
33191
33417
  return;
33192
33418
  }
33193
- const pluginsDir = path71.join(root, "plugins");
33194
- const nodeModulesDir = path71.join(pluginsDir, "node_modules");
33419
+ const pluginsDir = path72.join(root, "plugins");
33420
+ const nodeModulesDir = path72.join(pluginsDir, "node_modules");
33195
33421
  try {
33196
33422
  execFileSync9("npm", ["install", installSpec, "--prefix", pluginsDir, "--save"], {
33197
33423
  stdio: json ? "pipe" : "inherit",
@@ -33205,8 +33431,8 @@ async function installPlugin(input2, instanceRoot, json = false) {
33205
33431
  const cliVersion = getCurrentVersion2();
33206
33432
  const isLocalPath = pkgName.startsWith("/") || pkgName.startsWith(".");
33207
33433
  try {
33208
- const pluginRoot = isLocalPath ? path71.resolve(pkgName) : path71.join(nodeModulesDir, pkgName);
33209
- const installedPkgPath = path71.join(pluginRoot, "package.json");
33434
+ const pluginRoot = isLocalPath ? path72.resolve(pkgName) : path72.join(nodeModulesDir, pkgName);
33435
+ const installedPkgPath = path72.join(pluginRoot, "package.json");
33210
33436
  const { readFileSync: readFileSync18 } = await import("fs");
33211
33437
  const installedPkg = JSON.parse(readFileSync18(installedPkgPath, "utf-8"));
33212
33438
  const minVersion = installedPkg.engines?.openacp?.replace(/[>=^~\s]/g, "");
@@ -33221,7 +33447,7 @@ async function installPlugin(input2, instanceRoot, json = false) {
33221
33447
  }
33222
33448
  }
33223
33449
  }
33224
- const pluginModule = await import(path71.join(pluginRoot, installedPkg.main ?? "dist/index.js"));
33450
+ const pluginModule = await import(path72.join(pluginRoot, installedPkg.main ?? "dist/index.js"));
33225
33451
  const plugin2 = pluginModule.default;
33226
33452
  if (plugin2?.install) {
33227
33453
  const ctx = createInstallContext2({ pluginName: plugin2.name ?? pkgName, settingsManager, basePath });
@@ -33251,11 +33477,11 @@ async function installPlugin(input2, instanceRoot, json = false) {
33251
33477
  }
33252
33478
  async function uninstallPlugin(name, purge, instanceRoot, json = false) {
33253
33479
  if (json) await muteForJson();
33254
- const path71 = await import("path");
33480
+ const path72 = await import("path");
33255
33481
  const fs57 = await import("fs");
33256
33482
  const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
33257
33483
  const root = instanceRoot;
33258
- const registryPath = path71.join(root, "plugins.json");
33484
+ const registryPath = path72.join(root, "plugins.json");
33259
33485
  const registry = new PluginRegistry2(registryPath);
33260
33486
  await registry.load();
33261
33487
  const entry = registry.get(name);
@@ -33275,7 +33501,7 @@ async function uninstallPlugin(name, purge, instanceRoot, json = false) {
33275
33501
  if (plugin2?.uninstall) {
33276
33502
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
33277
33503
  const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
33278
- const basePath = path71.join(root, "plugins", "data");
33504
+ const basePath = path72.join(root, "plugins", "data");
33279
33505
  const settingsManager = new SettingsManager2(basePath);
33280
33506
  const ctx = createInstallContext2({ pluginName: name, settingsManager, basePath });
33281
33507
  await plugin2.uninstall(ctx, { purge });
@@ -33283,7 +33509,7 @@ async function uninstallPlugin(name, purge, instanceRoot, json = false) {
33283
33509
  } catch {
33284
33510
  }
33285
33511
  if (purge) {
33286
- const pluginDir = path71.join(root, "plugins", name);
33512
+ const pluginDir = path72.join(root, "plugins", name);
33287
33513
  fs57.rmSync(pluginDir, { recursive: true, force: true });
33288
33514
  }
33289
33515
  registry.remove(name);
@@ -33324,12 +33550,12 @@ init_helpers();
33324
33550
  init_output();
33325
33551
  import { execSync as execSync2 } from "child_process";
33326
33552
  import * as fs32 from "fs";
33327
- import * as path35 from "path";
33553
+ import * as path36 from "path";
33328
33554
  async function cmdUninstall(args2, instanceRoot) {
33329
33555
  const json = isJsonMode(args2);
33330
33556
  if (json) await muteForJson();
33331
33557
  const root = instanceRoot;
33332
- const pluginsDir = path35.join(root, "plugins");
33558
+ const pluginsDir = path36.join(root, "plugins");
33333
33559
  if (!json && wantsHelp(args2)) {
33334
33560
  console.log(`
33335
33561
  \x1B[1mopenacp uninstall\x1B[0m \u2014 Remove a plugin adapter
@@ -33356,7 +33582,7 @@ async function cmdUninstall(args2, instanceRoot) {
33356
33582
  process.exit(1);
33357
33583
  }
33358
33584
  fs32.mkdirSync(pluginsDir, { recursive: true });
33359
- const pkgPath = path35.join(pluginsDir, "package.json");
33585
+ const pkgPath = path36.join(pluginsDir, "package.json");
33360
33586
  if (!fs32.existsSync(pkgPath)) {
33361
33587
  fs32.writeFileSync(pkgPath, JSON.stringify({ name: "openacp-plugins", private: true, dependencies: {} }, null, 2));
33362
33588
  }
@@ -34202,7 +34428,7 @@ init_helpers();
34202
34428
  init_output();
34203
34429
  init_instance_hint();
34204
34430
  init_resolve_instance_id();
34205
- import path41 from "path";
34431
+ import path42 from "path";
34206
34432
  async function cmdStart(args2 = [], instanceRoot) {
34207
34433
  const json = isJsonMode(args2);
34208
34434
  if (json) await muteForJson();
@@ -34232,7 +34458,7 @@ Requires an existing config \u2014 run 'openacp' first to set up.
34232
34458
  await checkAndPromptUpdate();
34233
34459
  const { startDaemon: startDaemon2, getPidPath: getPidPath2, isProcessRunning: isProcessRunning2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
34234
34460
  const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
34235
- const cm = new ConfigManager2(path41.join(root, "config.json"));
34461
+ const cm = new ConfigManager2(path42.join(root, "config.json"));
34236
34462
  if (await cm.exists()) {
34237
34463
  await cm.load();
34238
34464
  const config = cm.get();
@@ -34258,12 +34484,12 @@ Requires an existing config \u2014 run 'openacp' first to set up.
34258
34484
  }
34259
34485
  if (json) {
34260
34486
  const { waitForPortFile: waitForPortFile2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
34261
- const port = await waitForPortFile2(path41.join(root, "api.port")) ?? 21420;
34487
+ const port = await waitForPortFile2(path42.join(root, "api.port")) ?? 21420;
34262
34488
  jsonSuccess({
34263
34489
  pid: result.pid,
34264
34490
  instanceId,
34265
34491
  name: config.instanceName ?? null,
34266
- directory: path41.dirname(root),
34492
+ directory: path42.dirname(root),
34267
34493
  dir: root,
34268
34494
  port
34269
34495
  });
@@ -34433,7 +34659,7 @@ start fresh with the setup wizard. The daemon must be stopped first.
34433
34659
  `);
34434
34660
  return;
34435
34661
  }
34436
- const path71 = await import("path");
34662
+ const path72 = await import("path");
34437
34663
  const root = instanceRoot;
34438
34664
  const { getStatus: getStatus2, getPidPath: getPidPath2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
34439
34665
  const status = getStatus2(getPidPath2(root));
@@ -34595,14 +34821,14 @@ as a messaging thread. Requires a running daemon.
34595
34821
  // src/cli/commands/instances.ts
34596
34822
  init_instance_registry();
34597
34823
  init_instance_context();
34598
- import path60 from "path";
34824
+ import path61 from "path";
34599
34825
  import os13 from "os";
34600
34826
  import fs52 from "fs";
34601
34827
  import { randomUUID as randomUUID6 } from "crypto";
34602
34828
 
34603
34829
  // src/core/instance/instance-init.ts
34604
34830
  import fs51 from "fs";
34605
- import path59 from "path";
34831
+ import path60 from "path";
34606
34832
  function initInstanceFiles(instanceRoot, opts = {}) {
34607
34833
  fs51.mkdirSync(instanceRoot, { recursive: true });
34608
34834
  writeConfig(instanceRoot, opts);
@@ -34612,7 +34838,7 @@ function initInstanceFiles(instanceRoot, opts = {}) {
34612
34838
  writePluginsIfMissing(instanceRoot);
34613
34839
  }
34614
34840
  function writeConfig(instanceRoot, opts) {
34615
- const configPath = path59.join(instanceRoot, "config.json");
34841
+ const configPath = path60.join(instanceRoot, "config.json");
34616
34842
  let existing = {};
34617
34843
  if (opts.mergeExisting && fs51.existsSync(configPath)) {
34618
34844
  try {
@@ -34642,7 +34868,7 @@ function writeConfig(instanceRoot, opts) {
34642
34868
  fs51.writeFileSync(configPath, JSON.stringify(config, null, 2));
34643
34869
  }
34644
34870
  function writeAgentsIfMissing(instanceRoot, agents) {
34645
- const agentsPath = path59.join(instanceRoot, "agents.json");
34871
+ const agentsPath = path60.join(instanceRoot, "agents.json");
34646
34872
  if (fs51.existsSync(agentsPath)) return;
34647
34873
  const installed = {};
34648
34874
  for (const agentName of agents) {
@@ -34661,7 +34887,7 @@ function writeAgentsIfMissing(instanceRoot, agents) {
34661
34887
  fs51.writeFileSync(agentsPath, JSON.stringify({ version: 1, installed }, null, 2));
34662
34888
  }
34663
34889
  function writePluginsIfMissing(instanceRoot) {
34664
- const pluginsPath = path59.join(instanceRoot, "plugins.json");
34890
+ const pluginsPath = path60.join(instanceRoot, "plugins.json");
34665
34891
  if (!fs51.existsSync(pluginsPath)) {
34666
34892
  fs51.writeFileSync(pluginsPath, JSON.stringify({ version: 1, installed: {} }, null, 2));
34667
34893
  }
@@ -34672,7 +34898,7 @@ init_status();
34672
34898
  init_output();
34673
34899
  init_helpers();
34674
34900
  async function buildInstanceListEntries() {
34675
- const registryPath = path60.join(getGlobalRoot(), "instances.json");
34901
+ const registryPath = path61.join(getGlobalRoot(), "instances.json");
34676
34902
  const registry = new InstanceRegistry(registryPath);
34677
34903
  registry.load();
34678
34904
  const entries = registry.list();
@@ -34682,7 +34908,7 @@ async function buildInstanceListEntries() {
34682
34908
  return {
34683
34909
  id: entry.id,
34684
34910
  name: info.name,
34685
- directory: path60.dirname(entry.root),
34911
+ directory: path61.dirname(entry.root),
34686
34912
  root: entry.root,
34687
34913
  status,
34688
34914
  port: info.apiPort
@@ -34775,9 +35001,9 @@ async function cmdInstancesCreate(args2) {
34775
35001
  const agentIdx = args2.indexOf("--agent");
34776
35002
  const agent = agentIdx !== -1 ? args2[agentIdx + 1] : void 0;
34777
35003
  const noInteractive = args2.includes("--no-interactive");
34778
- const resolvedDir = path60.resolve(rawDir.replace(/^~/, os13.homedir()));
34779
- const instanceRoot = path60.join(resolvedDir, ".openacp");
34780
- const registryPath = path60.join(getGlobalRoot(), "instances.json");
35004
+ const resolvedDir = path61.resolve(rawDir.replace(/^~/, os13.homedir()));
35005
+ const instanceRoot = path61.join(resolvedDir, ".openacp");
35006
+ const registryPath = path61.join(getGlobalRoot(), "instances.json");
34781
35007
  const registry = new InstanceRegistry(registryPath);
34782
35008
  registry.load();
34783
35009
  if (fs52.existsSync(instanceRoot)) {
@@ -34802,8 +35028,8 @@ async function cmdInstancesCreate(args2) {
34802
35028
  const name = instanceName ?? `openacp-${registry.list().length + 1}`;
34803
35029
  const id = randomUUID6();
34804
35030
  if (rawFrom) {
34805
- const fromRoot = path60.join(path60.resolve(rawFrom.replace(/^~/, os13.homedir())), ".openacp");
34806
- if (!fs52.existsSync(path60.join(fromRoot, "config.json"))) {
35031
+ const fromRoot = path61.join(path61.resolve(rawFrom.replace(/^~/, os13.homedir())), ".openacp");
35032
+ if (!fs52.existsSync(path61.join(fromRoot, "config.json"))) {
34807
35033
  console.error(`Error: No OpenACP instance found at ${rawFrom}`);
34808
35034
  process.exit(1);
34809
35035
  }
@@ -34827,7 +35053,7 @@ async function outputInstance(json, { id, root }) {
34827
35053
  const entry = {
34828
35054
  id,
34829
35055
  name: info.name,
34830
- directory: path60.dirname(root),
35056
+ directory: path61.dirname(root),
34831
35057
  root,
34832
35058
  status: info.pid ? "running" : "stopped",
34833
35059
  port: info.apiPort
@@ -34836,7 +35062,7 @@ async function outputInstance(json, { id, root }) {
34836
35062
  jsonSuccess(entry);
34837
35063
  return;
34838
35064
  }
34839
- console.log(`Instance created: ${info.name ?? id} at ${path60.dirname(root)}`);
35065
+ console.log(`Instance created: ${info.name ?? id} at ${path61.dirname(root)}`);
34840
35066
  }
34841
35067
 
34842
35068
  // src/cli/commands/integrate.ts
@@ -35597,15 +35823,15 @@ Options:
35597
35823
  }
35598
35824
 
35599
35825
  // src/cli/commands/onboard.ts
35600
- import * as path61 from "path";
35826
+ import * as path62 from "path";
35601
35827
  async function cmdOnboard(instanceRoot) {
35602
35828
  const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
35603
35829
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
35604
35830
  const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
35605
35831
  const OPENACP_DIR = instanceRoot;
35606
- const PLUGINS_DATA_DIR = path61.join(OPENACP_DIR, "plugins", "data");
35607
- const REGISTRY_PATH = path61.join(OPENACP_DIR, "plugins.json");
35608
- const cm = new ConfigManager2(path61.join(OPENACP_DIR, "config.json"));
35832
+ const PLUGINS_DATA_DIR = path62.join(OPENACP_DIR, "plugins", "data");
35833
+ const REGISTRY_PATH = path62.join(OPENACP_DIR, "plugins.json");
35834
+ const cm = new ConfigManager2(path62.join(OPENACP_DIR, "config.json"));
35609
35835
  const settingsManager = new SettingsManager2(PLUGINS_DATA_DIR);
35610
35836
  const pluginRegistry = new PluginRegistry2(REGISTRY_PATH);
35611
35837
  await pluginRegistry.load();
@@ -35625,15 +35851,15 @@ init_instance_registry();
35625
35851
  init_instance_hint();
35626
35852
  init_output();
35627
35853
  init_resolve_instance_id();
35628
- import path62 from "path";
35854
+ import path63 from "path";
35629
35855
  import { randomUUID as randomUUID7 } from "crypto";
35630
35856
  async function cmdDefault(command2, instanceRoot) {
35631
35857
  const args2 = command2 ? [command2] : [];
35632
35858
  const json = isJsonMode(args2);
35633
35859
  if (json) await muteForJson();
35634
35860
  const root = instanceRoot;
35635
- const pluginsDataDir = path62.join(root, "plugins", "data");
35636
- const registryPath = path62.join(root, "plugins.json");
35861
+ const pluginsDataDir = path63.join(root, "plugins", "data");
35862
+ const registryPath = path63.join(root, "plugins.json");
35637
35863
  const forceForeground = command2 === "--foreground";
35638
35864
  if (command2 && !command2.startsWith("-")) {
35639
35865
  const { suggestMatch: suggestMatch2 } = await Promise.resolve().then(() => (init_suggest(), suggest_exports));
@@ -35665,7 +35891,7 @@ async function cmdDefault(command2, instanceRoot) {
35665
35891
  }
35666
35892
  await checkAndPromptUpdate();
35667
35893
  const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
35668
- const configPath = path62.join(root, "config.json");
35894
+ const configPath = path63.join(root, "config.json");
35669
35895
  const cm = new ConfigManager2(configPath);
35670
35896
  if (!await cm.exists()) {
35671
35897
  const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
@@ -35702,12 +35928,12 @@ async function cmdDefault(command2, instanceRoot) {
35702
35928
  }
35703
35929
  if (json) {
35704
35930
  const { waitForPortFile: waitForPortFile2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
35705
- const port = await waitForPortFile2(path62.join(root, "api.port")) ?? 21420;
35931
+ const port = await waitForPortFile2(path63.join(root, "api.port")) ?? 21420;
35706
35932
  jsonSuccess({
35707
35933
  pid: result.pid,
35708
35934
  instanceId: instanceId2,
35709
35935
  name: config.instanceName ?? null,
35710
- directory: path62.dirname(root),
35936
+ directory: path63.dirname(root),
35711
35937
  dir: root,
35712
35938
  port
35713
35939
  });
@@ -35720,7 +35946,7 @@ async function cmdDefault(command2, instanceRoot) {
35720
35946
  markRunning2(root);
35721
35947
  printInstanceHint(root);
35722
35948
  const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
35723
- const reg = new InstanceRegistry(path62.join(getGlobalRoot(), "instances.json"));
35949
+ const reg = new InstanceRegistry(path63.join(getGlobalRoot(), "instances.json"));
35724
35950
  reg.load();
35725
35951
  const existingEntry = reg.getByRoot(root);
35726
35952
  const instanceId = existingEntry?.id ?? randomUUID7();
@@ -35734,7 +35960,7 @@ async function cmdDefault(command2, instanceRoot) {
35734
35960
  pid: process.pid,
35735
35961
  instanceId,
35736
35962
  name: config.instanceName ?? null,
35737
- directory: path62.dirname(root),
35963
+ directory: path63.dirname(root),
35738
35964
  dir: root,
35739
35965
  port
35740
35966
  });
@@ -35803,7 +36029,7 @@ async function showAlreadyRunningMenu(root) {
35803
36029
  // src/cli/commands/dev.ts
35804
36030
  init_helpers();
35805
36031
  import fs53 from "fs";
35806
- import path63 from "path";
36032
+ import path64 from "path";
35807
36033
  async function cmdDev(args2 = []) {
35808
36034
  if (wantsHelp(args2)) {
35809
36035
  console.log(`
@@ -35830,12 +36056,12 @@ async function cmdDev(args2 = []) {
35830
36056
  console.error("Error: missing plugin path. Usage: openacp dev <plugin-path>");
35831
36057
  process.exit(1);
35832
36058
  }
35833
- const pluginPath = path63.resolve(pluginPathArg);
36059
+ const pluginPath = path64.resolve(pluginPathArg);
35834
36060
  if (!fs53.existsSync(pluginPath)) {
35835
36061
  console.error(`Error: plugin path does not exist: ${pluginPath}`);
35836
36062
  process.exit(1);
35837
36063
  }
35838
- const tsconfigPath = path63.join(pluginPath, "tsconfig.json");
36064
+ const tsconfigPath = path64.join(pluginPath, "tsconfig.json");
35839
36065
  const hasTsconfig = fs53.existsSync(tsconfigPath);
35840
36066
  if (hasTsconfig) {
35841
36067
  console.log("Compiling plugin TypeScript...");
@@ -35877,7 +36103,7 @@ async function cmdDev(args2 = []) {
35877
36103
 
35878
36104
  // src/cli/commands/attach.ts
35879
36105
  init_helpers();
35880
- import path64 from "path";
36106
+ import path65 from "path";
35881
36107
  async function cmdAttach(args2 = [], instanceRoot) {
35882
36108
  const root = instanceRoot;
35883
36109
  if (wantsHelp(args2)) {
@@ -35913,15 +36139,15 @@ Press Ctrl+C to detach.
35913
36139
  console.log("");
35914
36140
  const { spawn: spawn9 } = await import("child_process");
35915
36141
  const { expandHome: expandHome4 } = await Promise.resolve().then(() => (init_config2(), config_exports));
35916
- let logDir2 = path64.join(root, "logs");
36142
+ let logDir2 = path65.join(root, "logs");
35917
36143
  try {
35918
- const configPath = path64.join(root, "config.json");
36144
+ const configPath = path65.join(root, "config.json");
35919
36145
  const { readFileSync: readFileSync18 } = await import("fs");
35920
36146
  const config = JSON.parse(readFileSync18(configPath, "utf-8"));
35921
36147
  if (config.logging?.logDir) logDir2 = expandHome4(config.logging.logDir);
35922
36148
  } catch {
35923
36149
  }
35924
- const logFile = path64.join(logDir2, "openacp.log");
36150
+ const logFile = path65.join(logDir2, "openacp.log");
35925
36151
  const tail = spawn9("tail", ["-f", "-n", "50", logFile], { stdio: "inherit" });
35926
36152
  tail.on("error", (err) => {
35927
36153
  console.error(`Cannot tail log file: ${err.message}`);
@@ -35933,7 +36159,7 @@ Press Ctrl+C to detach.
35933
36159
  init_api_client();
35934
36160
  init_instance_registry();
35935
36161
  init_output();
35936
- import path65 from "path";
36162
+ import path66 from "path";
35937
36163
  import os14 from "os";
35938
36164
  import qrcode from "qrcode-terminal";
35939
36165
  async function cmdRemote(args2, instanceRoot) {
@@ -35949,7 +36175,7 @@ async function cmdRemote(args2, instanceRoot) {
35949
36175
  const scopes = scopesRaw ? scopesRaw.split(",").map((s) => s.trim()) : void 0;
35950
36176
  let resolvedInstanceRoot2 = instanceRoot;
35951
36177
  if (instanceId) {
35952
- const registryPath = path65.join(os14.homedir(), ".openacp", "instances.json");
36178
+ const registryPath = path66.join(os14.homedir(), ".openacp", "instances.json");
35953
36179
  const registry = new InstanceRegistry(registryPath);
35954
36180
  await registry.load();
35955
36181
  const entry = registry.get(instanceId);
@@ -36088,7 +36314,7 @@ function extractFlag(args2, flag) {
36088
36314
  init_output();
36089
36315
  init_instance_context();
36090
36316
  init_instance_registry();
36091
- import * as path66 from "path";
36317
+ import * as path67 from "path";
36092
36318
  import fs54 from "fs";
36093
36319
  function parseFlag(args2, flag) {
36094
36320
  const idx = args2.indexOf(flag);
@@ -36096,7 +36322,7 @@ function parseFlag(args2, flag) {
36096
36322
  }
36097
36323
  function readConfigField(instanceRoot, field) {
36098
36324
  try {
36099
- const raw = JSON.parse(fs54.readFileSync(path66.join(instanceRoot, "config.json"), "utf-8"));
36325
+ const raw = JSON.parse(fs54.readFileSync(path67.join(instanceRoot, "config.json"), "utf-8"));
36100
36326
  return typeof raw[field] === "string" ? raw[field] : null;
36101
36327
  } catch {
36102
36328
  return null;
@@ -36119,7 +36345,7 @@ async function cmdSetup(args2, instanceRoot) {
36119
36345
  }
36120
36346
  const runMode = rawRunMode;
36121
36347
  const agents = agentRaw.split(",").map((a) => a.trim());
36122
- const registryPath = path66.join(getGlobalRoot(), "instances.json");
36348
+ const registryPath = path67.join(getGlobalRoot(), "instances.json");
36123
36349
  const registry = new InstanceRegistry(registryPath);
36124
36350
  registry.load();
36125
36351
  const { id, registryUpdated } = registry.resolveId(instanceRoot);
@@ -36127,9 +36353,9 @@ async function cmdSetup(args2, instanceRoot) {
36127
36353
  if (registryUpdated) {
36128
36354
  registry.save();
36129
36355
  }
36130
- const name = readConfigField(instanceRoot, "instanceName") ?? path66.basename(path66.dirname(instanceRoot));
36356
+ const name = readConfigField(instanceRoot, "instanceName") ?? path67.basename(path67.dirname(instanceRoot));
36131
36357
  if (!readConfigField(instanceRoot, "instanceName")) {
36132
- const configPath = path66.join(instanceRoot, "config.json");
36358
+ const configPath = path67.join(instanceRoot, "config.json");
36133
36359
  try {
36134
36360
  const raw = JSON.parse(fs54.readFileSync(configPath, "utf-8"));
36135
36361
  raw.instanceName = name;
@@ -36138,17 +36364,17 @@ async function cmdSetup(args2, instanceRoot) {
36138
36364
  }
36139
36365
  }
36140
36366
  if (json) {
36141
- jsonSuccess({ id, name, directory: path66.dirname(instanceRoot), configPath: path66.join(instanceRoot, "config.json") });
36367
+ jsonSuccess({ id, name, directory: path67.dirname(instanceRoot), configPath: path67.join(instanceRoot, "config.json") });
36142
36368
  } else {
36143
36369
  console.log(`
36144
- \x1B[32m\u2713 Setup complete.\x1B[0m Config written to ${path66.join(instanceRoot, "config.json")}
36370
+ \x1B[32m\u2713 Setup complete.\x1B[0m Config written to ${path67.join(instanceRoot, "config.json")}
36145
36371
  `);
36146
36372
  }
36147
36373
  }
36148
36374
 
36149
36375
  // src/cli/commands/autostart.ts
36150
36376
  init_helpers();
36151
- import path67 from "path";
36377
+ import path68 from "path";
36152
36378
  async function cmdAutostart(args2 = [], instanceRoot) {
36153
36379
  const subcommand = args2[0];
36154
36380
  if (!subcommand || wantsHelp(args2)) {
@@ -36186,7 +36412,7 @@ async function cmdAutostart(args2 = [], instanceRoot) {
36186
36412
  let logDir2 = `${root}/logs`;
36187
36413
  try {
36188
36414
  const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
36189
- const cm = new ConfigManager2(path67.join(root, "config.json"));
36415
+ const cm = new ConfigManager2(path68.join(root, "config.json"));
36190
36416
  if (await cm.exists()) {
36191
36417
  await cm.load();
36192
36418
  logDir2 = cm.get().logging?.logDir ?? logDir2;
@@ -36374,7 +36600,7 @@ async function main() {
36374
36600
  if (envRoot) {
36375
36601
  const { createInstanceContext: createInstanceContext2, getGlobalRoot: getGlobal } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
36376
36602
  const { InstanceRegistry: InstanceRegistry2 } = await Promise.resolve().then(() => (init_instance_registry(), instance_registry_exports));
36377
- const registry = new InstanceRegistry2(path70.join(getGlobal(), "instances.json"));
36603
+ const registry = new InstanceRegistry2(path71.join(getGlobal(), "instances.json"));
36378
36604
  await registry.load();
36379
36605
  const entry = registry.getByRoot(envRoot);
36380
36606
  const { randomUUID: randomUUID9 } = await import("crypto");