@episoda/cli 0.2.184 → 0.2.189

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.
@@ -1937,7 +1937,7 @@ var require_git_executor = __commonJS({
1937
1937
  async executeCloneBare(command, options) {
1938
1938
  try {
1939
1939
  const fs35 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
1940
- const path35 = await Promise.resolve().then(() => __importStar(require("path")));
1940
+ const path37 = await Promise.resolve().then(() => __importStar(require("path")));
1941
1941
  try {
1942
1942
  await fs35.access(command.path);
1943
1943
  return {
@@ -1948,7 +1948,7 @@ var require_git_executor = __commonJS({
1948
1948
  };
1949
1949
  } catch {
1950
1950
  }
1951
- const parentDir = path35.dirname(command.path);
1951
+ const parentDir = path37.dirname(command.path);
1952
1952
  try {
1953
1953
  await fs35.mkdir(parentDir, { recursive: true });
1954
1954
  } catch {
@@ -1999,13 +1999,13 @@ var require_git_executor = __commonJS({
1999
1999
  async executeProjectInfo(cwd, options) {
2000
2000
  try {
2001
2001
  const fs35 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
2002
- const path35 = await Promise.resolve().then(() => __importStar(require("path")));
2002
+ const path37 = await Promise.resolve().then(() => __importStar(require("path")));
2003
2003
  let currentPath = cwd;
2004
2004
  let projectPath = cwd;
2005
2005
  let bareRepoPath;
2006
2006
  for (let i = 0; i < 10; i++) {
2007
- const bareDir = path35.join(currentPath, ".bare");
2008
- const episodaDir = path35.join(currentPath, ".episoda");
2007
+ const bareDir = path37.join(currentPath, ".bare");
2008
+ const episodaDir = path37.join(currentPath, ".episoda");
2009
2009
  try {
2010
2010
  await fs35.access(bareDir);
2011
2011
  await fs35.access(episodaDir);
@@ -2013,7 +2013,7 @@ var require_git_executor = __commonJS({
2013
2013
  bareRepoPath = bareDir;
2014
2014
  break;
2015
2015
  } catch {
2016
- const parentPath = path35.dirname(currentPath);
2016
+ const parentPath = path37.dirname(currentPath);
2017
2017
  if (parentPath === currentPath) {
2018
2018
  break;
2019
2019
  }
@@ -2236,7 +2236,7 @@ var require_websocket_client = __commonJS({
2236
2236
  clearTimeout(this.reconnectTimeout);
2237
2237
  this.reconnectTimeout = void 0;
2238
2238
  }
2239
- return new Promise((resolve7, reject) => {
2239
+ return new Promise((resolve8, reject) => {
2240
2240
  const connectionTimeout = setTimeout(() => {
2241
2241
  if (this.ws) {
2242
2242
  this.ws.terminate();
@@ -2267,7 +2267,7 @@ var require_websocket_client = __commonJS({
2267
2267
  daemonPid: this.daemonPid
2268
2268
  });
2269
2269
  this.startHeartbeat();
2270
- resolve7();
2270
+ resolve8();
2271
2271
  });
2272
2272
  this.ws.on("pong", () => {
2273
2273
  if (this.heartbeatTimeoutTimer) {
@@ -2411,13 +2411,13 @@ var require_websocket_client = __commonJS({
2411
2411
  console.warn("[EpisodaClient] Cannot send - WebSocket not connected");
2412
2412
  return false;
2413
2413
  }
2414
- return new Promise((resolve7) => {
2414
+ return new Promise((resolve8) => {
2415
2415
  this.ws.send(JSON.stringify(message), (error) => {
2416
2416
  if (error) {
2417
2417
  console.error("[EpisodaClient] Failed to send message:", error);
2418
- resolve7(false);
2418
+ resolve8(false);
2419
2419
  } else {
2420
- resolve7(true);
2420
+ resolve8(true);
2421
2421
  }
2422
2422
  });
2423
2423
  });
@@ -2725,29 +2725,29 @@ var require_auth = __commonJS({
2725
2725
  exports2.saveConfig = saveConfig4;
2726
2726
  exports2.validateToken = validateToken;
2727
2727
  var fs35 = __importStar(require("fs"));
2728
- var path35 = __importStar(require("path"));
2728
+ var path37 = __importStar(require("path"));
2729
2729
  var os16 = __importStar(require("os"));
2730
2730
  var child_process_1 = require("child_process");
2731
2731
  var DEFAULT_CONFIG_FILE = "config.json";
2732
2732
  var hasWarnedMissingProjectId = false;
2733
2733
  var hasWarnedMissingRequiredFields = false;
2734
2734
  function getConfigDir10() {
2735
- return process.env.EPISODA_CONFIG_DIR || path35.join(os16.homedir(), ".episoda");
2735
+ return process.env.EPISODA_CONFIG_DIR || path37.join(os16.homedir(), ".episoda");
2736
2736
  }
2737
2737
  function getConfigPath(configPath) {
2738
2738
  if (configPath) {
2739
2739
  return configPath;
2740
2740
  }
2741
- return path35.join(getConfigDir10(), DEFAULT_CONFIG_FILE);
2741
+ return path37.join(getConfigDir10(), DEFAULT_CONFIG_FILE);
2742
2742
  }
2743
2743
  function ensureConfigDir(configPath) {
2744
- const dir = path35.dirname(configPath);
2744
+ const dir = path37.dirname(configPath);
2745
2745
  const isNew = !fs35.existsSync(dir);
2746
2746
  if (isNew) {
2747
2747
  fs35.mkdirSync(dir, { recursive: true, mode: 448 });
2748
2748
  }
2749
2749
  if (process.platform === "darwin") {
2750
- const nosyncPath = path35.join(dir, ".nosync");
2750
+ const nosyncPath = path37.join(dir, ".nosync");
2751
2751
  if (isNew || !fs35.existsSync(nosyncPath)) {
2752
2752
  try {
2753
2753
  fs35.writeFileSync(nosyncPath, "", { mode: 384 });
@@ -3046,7 +3046,7 @@ var require_package = __commonJS({
3046
3046
  "package.json"(exports2, module2) {
3047
3047
  module2.exports = {
3048
3048
  name: "@episoda/cli",
3049
- version: "0.2.184",
3049
+ version: "0.2.189",
3050
3050
  description: "CLI tool for Episoda local development workflow orchestration",
3051
3051
  main: "dist/index.js",
3052
3052
  types: "dist/index.d.ts",
@@ -3362,10 +3362,10 @@ var IPCServer = class {
3362
3362
  this.server = net.createServer((socket) => {
3363
3363
  this.handleConnection(socket);
3364
3364
  });
3365
- return new Promise((resolve7, reject) => {
3365
+ return new Promise((resolve8, reject) => {
3366
3366
  this.server.listen(socketPath, () => {
3367
3367
  fs3.chmodSync(socketPath, 384);
3368
- resolve7();
3368
+ resolve8();
3369
3369
  });
3370
3370
  this.server.on("error", reject);
3371
3371
  });
@@ -3376,12 +3376,12 @@ var IPCServer = class {
3376
3376
  async stop() {
3377
3377
  if (!this.server) return;
3378
3378
  const socketPath = getSocketPath();
3379
- return new Promise((resolve7) => {
3379
+ return new Promise((resolve8) => {
3380
3380
  this.server.close(() => {
3381
3381
  if (fs3.existsSync(socketPath)) {
3382
3382
  fs3.unlinkSync(socketPath);
3383
3383
  }
3384
- resolve7();
3384
+ resolve8();
3385
3385
  });
3386
3386
  });
3387
3387
  }
@@ -3626,7 +3626,7 @@ function getDownloadUrl() {
3626
3626
  return platformUrls[arch4] || null;
3627
3627
  }
3628
3628
  async function downloadFile(url, destPath) {
3629
- return new Promise((resolve7, reject) => {
3629
+ return new Promise((resolve8, reject) => {
3630
3630
  const followRedirect = (currentUrl, redirectCount = 0) => {
3631
3631
  if (redirectCount > 5) {
3632
3632
  reject(new Error("Too many redirects"));
@@ -3656,7 +3656,7 @@ async function downloadFile(url, destPath) {
3656
3656
  response.pipe(file);
3657
3657
  file.on("finish", () => {
3658
3658
  file.close();
3659
- resolve7();
3659
+ resolve8();
3660
3660
  });
3661
3661
  file.on("error", (err) => {
3662
3662
  fs4.unlinkSync(destPath);
@@ -4070,10 +4070,10 @@ var TunnelManager = class extends import_events.EventEmitter {
4070
4070
  const isTracked = Array.from(this.tunnelStates.values()).some((s) => s.info.pid === pid);
4071
4071
  console.log(`[Tunnel] EP904: Found cloudflared PID ${pid} on port ${port} (tracked: ${isTracked})`);
4072
4072
  this.killByPid(pid, "SIGTERM");
4073
- await new Promise((resolve7) => setTimeout(resolve7, 500));
4073
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
4074
4074
  if (this.isProcessRunning(pid)) {
4075
4075
  this.killByPid(pid, "SIGKILL");
4076
- await new Promise((resolve7) => setTimeout(resolve7, 200));
4076
+ await new Promise((resolve8) => setTimeout(resolve8, 200));
4077
4077
  }
4078
4078
  killed.push(pid);
4079
4079
  }
@@ -4107,7 +4107,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4107
4107
  if (!this.tunnelStates.has(moduleUid)) {
4108
4108
  console.log(`[Tunnel] EP877: Found orphaned process PID ${pid} for ${moduleUid}, killing...`);
4109
4109
  this.killByPid(pid, "SIGTERM");
4110
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
4110
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
4111
4111
  if (this.isProcessRunning(pid)) {
4112
4112
  this.killByPid(pid, "SIGKILL");
4113
4113
  }
@@ -4122,7 +4122,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4122
4122
  if (!trackedPids.includes(pid) && !cleaned.includes(pid)) {
4123
4123
  console.log(`[Tunnel] EP877: Found untracked cloudflared process PID ${pid}, killing...`);
4124
4124
  this.killByPid(pid, "SIGTERM");
4125
- await new Promise((resolve7) => setTimeout(resolve7, 500));
4125
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
4126
4126
  if (this.isProcessRunning(pid)) {
4127
4127
  this.killByPid(pid, "SIGKILL");
4128
4128
  }
@@ -4212,7 +4212,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4212
4212
  return { success: false, error: `Failed to get cloudflared: ${errorMessage}` };
4213
4213
  }
4214
4214
  }
4215
- return new Promise((resolve7) => {
4215
+ return new Promise((resolve8) => {
4216
4216
  const tunnelInfo = {
4217
4217
  moduleUid,
4218
4218
  url: previewUrl || "",
@@ -4278,7 +4278,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4278
4278
  moduleUid,
4279
4279
  url: tunnelInfo.url
4280
4280
  });
4281
- resolve7({ success: true, url: tunnelInfo.url });
4281
+ resolve8({ success: true, url: tunnelInfo.url });
4282
4282
  }
4283
4283
  };
4284
4284
  process2.stderr?.on("data", (data) => {
@@ -4305,7 +4305,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4305
4305
  onStatusChange?.("error", errorMsg);
4306
4306
  this.emitEvent({ type: "error", moduleUid, error: errorMsg });
4307
4307
  }
4308
- resolve7({ success: false, error: errorMsg });
4308
+ resolve8({ success: false, error: errorMsg });
4309
4309
  } else if (wasConnected) {
4310
4310
  if (currentState && !currentState.intentionallyStopped) {
4311
4311
  console.log(`[Tunnel] EP948: Named tunnel ${moduleUid} crashed unexpectedly, attempting reconnect...`);
@@ -4336,7 +4336,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4336
4336
  this.emitEvent({ type: "error", moduleUid, error: error.message });
4337
4337
  }
4338
4338
  if (!connected) {
4339
- resolve7({ success: false, error: error.message });
4339
+ resolve8({ success: false, error: error.message });
4340
4340
  }
4341
4341
  });
4342
4342
  setTimeout(() => {
@@ -4359,7 +4359,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4359
4359
  onStatusChange?.("error", errorMsg);
4360
4360
  this.emitEvent({ type: "error", moduleUid, error: errorMsg });
4361
4361
  }
4362
- resolve7({ success: false, error: errorMsg });
4362
+ resolve8({ success: false, error: errorMsg });
4363
4363
  }
4364
4364
  }, TUNNEL_TIMEOUTS.NAMED_TUNNEL_CONNECT);
4365
4365
  });
@@ -4420,7 +4420,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4420
4420
  if (orphanPid && this.isProcessRunning(orphanPid)) {
4421
4421
  console.log(`[Tunnel] EP877: Killing orphaned process ${orphanPid} for ${moduleUid} before starting new tunnel`);
4422
4422
  this.killByPid(orphanPid, "SIGTERM");
4423
- await new Promise((resolve7) => setTimeout(resolve7, 500));
4423
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
4424
4424
  if (this.isProcessRunning(orphanPid)) {
4425
4425
  this.killByPid(orphanPid, "SIGKILL");
4426
4426
  }
@@ -4429,7 +4429,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4429
4429
  const killedOnPort = await this.killCloudflaredOnPort(port);
4430
4430
  if (killedOnPort.length > 0) {
4431
4431
  console.log(`[Tunnel] EP904: Pre-start port cleanup killed ${killedOnPort.length} process(es) on port ${port}`);
4432
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
4432
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
4433
4433
  }
4434
4434
  const cleanup = await this.cleanupOrphanedProcesses();
4435
4435
  if (cleanup.cleaned > 0) {
@@ -4469,7 +4469,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4469
4469
  if (orphanPid && this.isProcessRunning(orphanPid)) {
4470
4470
  console.log(`[Tunnel] EP877: Stopping orphaned process ${orphanPid} for ${moduleUid} via PID file`);
4471
4471
  this.killByPid(orphanPid, "SIGTERM");
4472
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
4472
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
4473
4473
  if (this.isProcessRunning(orphanPid)) {
4474
4474
  this.killByPid(orphanPid, "SIGKILL");
4475
4475
  }
@@ -4485,16 +4485,16 @@ var TunnelManager = class extends import_events.EventEmitter {
4485
4485
  const tunnel = state.info;
4486
4486
  if (tunnel.process && !tunnel.process.killed) {
4487
4487
  tunnel.process.kill("SIGTERM");
4488
- await new Promise((resolve7) => {
4488
+ await new Promise((resolve8) => {
4489
4489
  const timeout = setTimeout(() => {
4490
4490
  if (tunnel.process && !tunnel.process.killed) {
4491
4491
  tunnel.process.kill("SIGKILL");
4492
4492
  }
4493
- resolve7();
4493
+ resolve8();
4494
4494
  }, 3e3);
4495
4495
  tunnel.process.once("exit", () => {
4496
4496
  clearTimeout(timeout);
4497
- resolve7();
4497
+ resolve8();
4498
4498
  });
4499
4499
  });
4500
4500
  }
@@ -4781,15 +4781,15 @@ async function writeToStdinWithBackpressure(process2, data, drainTimeoutMs, labe
4781
4781
  if (!stdin || stdin.destroyed) {
4782
4782
  throw new Error(`[${label}] stdin not available. session=${sessionId}`);
4783
4783
  }
4784
- await new Promise((resolve7, reject) => {
4784
+ await new Promise((resolve8, reject) => {
4785
4785
  const ok = stdin.write(data);
4786
4786
  if (ok) {
4787
- resolve7();
4787
+ resolve8();
4788
4788
  return;
4789
4789
  }
4790
4790
  const onDrain = () => {
4791
4791
  cleanup();
4792
- resolve7();
4792
+ resolve8();
4793
4793
  };
4794
4794
  const onError = (err) => {
4795
4795
  cleanup();
@@ -4810,18 +4810,18 @@ async function writeToStdinWithBackpressure(process2, data, drainTimeoutMs, labe
4810
4810
  });
4811
4811
  }
4812
4812
  function waitForProcessExit(process2, alive, timeoutMs) {
4813
- return new Promise((resolve7) => {
4813
+ return new Promise((resolve8) => {
4814
4814
  if (!process2 || !alive) {
4815
- resolve7(true);
4815
+ resolve8(true);
4816
4816
  return;
4817
4817
  }
4818
4818
  const onExit = () => {
4819
4819
  clearTimeout(timer);
4820
- resolve7(true);
4820
+ resolve8(true);
4821
4821
  };
4822
4822
  const timer = setTimeout(() => {
4823
4823
  process2.removeListener("exit", onExit);
4824
- resolve7(false);
4824
+ resolve8(false);
4825
4825
  }, timeoutMs);
4826
4826
  process2.once("exit", onExit);
4827
4827
  });
@@ -5817,10 +5817,10 @@ var CodexPersistentRuntime = class {
5817
5817
  }
5818
5818
  waitForThreadId(timeoutMs) {
5819
5819
  if (this._agentSessionId) return Promise.resolve(this._agentSessionId);
5820
- return new Promise((resolve7, reject) => {
5820
+ return new Promise((resolve8, reject) => {
5821
5821
  const onId = (id) => {
5822
5822
  clearTimeout(timer);
5823
- resolve7(id);
5823
+ resolve8(id);
5824
5824
  };
5825
5825
  const timer = setTimeout(() => {
5826
5826
  this.threadIdWaiters = this.threadIdWaiters.filter((w) => w !== onId);
@@ -5851,12 +5851,12 @@ var CodexPersistentRuntime = class {
5851
5851
  sendRequest(method, params, timeoutMs = INIT_TIMEOUT_MS) {
5852
5852
  const id = this.nextId++;
5853
5853
  const msg = { jsonrpc: "2.0", id, method, params };
5854
- return new Promise(async (resolve7, reject) => {
5854
+ return new Promise(async (resolve8, reject) => {
5855
5855
  const timeout = setTimeout(() => {
5856
5856
  this.pending.delete(id);
5857
5857
  reject(new Error(`JSON-RPC timeout: ${method}`));
5858
5858
  }, timeoutMs);
5859
- this.pending.set(id, { resolve: resolve7, reject, timeout });
5859
+ this.pending.set(id, { resolve: resolve8, reject, timeout });
5860
5860
  try {
5861
5861
  await this.writeToStdin(JSON.stringify(msg) + "\n");
5862
5862
  } catch (err) {
@@ -6006,11 +6006,11 @@ var UnifiedAgentRuntime = class {
6006
6006
  if (!this.currentTurn && this.impl.turnState === "idle") {
6007
6007
  return this.dispatchTurn(message, callbacks);
6008
6008
  }
6009
- return new Promise((resolve7, reject) => {
6009
+ return new Promise((resolve8, reject) => {
6010
6010
  this.queuedTurns.push({
6011
6011
  message,
6012
6012
  callbacks,
6013
- resolve: resolve7,
6013
+ resolve: resolve8,
6014
6014
  reject
6015
6015
  });
6016
6016
  });
@@ -7523,13 +7523,13 @@ async function getChildProcessRssMb(pid) {
7523
7523
  if (!pid || pid <= 0) return null;
7524
7524
  try {
7525
7525
  if (typeof import_child_process9.execFile !== "function") return null;
7526
- const stdout = await new Promise((resolve7, reject) => {
7526
+ const stdout = await new Promise((resolve8, reject) => {
7527
7527
  (0, import_child_process9.execFile)("ps", ["-o", "rss=", "-p", String(pid)], { timeout: 1e3 }, (err, out) => {
7528
7528
  if (err) {
7529
7529
  reject(err);
7530
7530
  return;
7531
7531
  }
7532
- resolve7(String(out));
7532
+ resolve8(String(out));
7533
7533
  });
7534
7534
  });
7535
7535
  const kb = Number(String(stdout).trim());
@@ -7632,8 +7632,8 @@ var AgentControlPlane = class {
7632
7632
  async withConfigLock(fn) {
7633
7633
  const previousLock = this.configWriteLock;
7634
7634
  let releaseLock;
7635
- this.configWriteLock = new Promise((resolve7) => {
7636
- releaseLock = resolve7;
7635
+ this.configWriteLock = new Promise((resolve8) => {
7636
+ releaseLock = resolve8;
7637
7637
  });
7638
7638
  try {
7639
7639
  await previousLock;
@@ -8862,7 +8862,7 @@ var WorktreeManager = class _WorktreeManager {
8862
8862
  const lockContent = fs14.readFileSync(lockPath, "utf-8").trim();
8863
8863
  const lockPid = parseInt(lockContent, 10);
8864
8864
  if (!isNaN(lockPid) && this.isProcessRunning(lockPid)) {
8865
- await new Promise((resolve7) => setTimeout(resolve7, retryInterval));
8865
+ await new Promise((resolve8) => setTimeout(resolve8, retryInterval));
8866
8866
  continue;
8867
8867
  }
8868
8868
  } catch {
@@ -8876,7 +8876,7 @@ var WorktreeManager = class _WorktreeManager {
8876
8876
  } catch {
8877
8877
  continue;
8878
8878
  }
8879
- await new Promise((resolve7) => setTimeout(resolve7, retryInterval));
8879
+ await new Promise((resolve8) => setTimeout(resolve8, retryInterval));
8880
8880
  continue;
8881
8881
  }
8882
8882
  throw err;
@@ -9666,6 +9666,7 @@ function getInstallCommand(cwd) {
9666
9666
  var fs34 = __toESM(require("fs"));
9667
9667
  var http2 = __toESM(require("http"));
9668
9668
  var os15 = __toESM(require("os"));
9669
+ var path36 = __toESM(require("path"));
9669
9670
  var import_child_process19 = require("child_process");
9670
9671
 
9671
9672
  // src/daemon/ipc-router.ts
@@ -10400,7 +10401,7 @@ async function handleExec(command, projectPath) {
10400
10401
  env = {}
10401
10402
  } = command;
10402
10403
  const effectiveTimeout = Math.min(Math.max(timeout, 1e3), MAX_TIMEOUT);
10403
- return new Promise((resolve7) => {
10404
+ return new Promise((resolve8) => {
10404
10405
  let stdout = "";
10405
10406
  let stderr = "";
10406
10407
  let timedOut = false;
@@ -10408,7 +10409,7 @@ async function handleExec(command, projectPath) {
10408
10409
  const done = (result) => {
10409
10410
  if (resolved) return;
10410
10411
  resolved = true;
10411
- resolve7(result);
10412
+ resolve8(result);
10412
10413
  };
10413
10414
  try {
10414
10415
  const proc = (0, import_child_process11.spawn)(cmd, {
@@ -10512,18 +10513,18 @@ var import_core12 = __toESM(require_dist());
10512
10513
  // src/utils/port-check.ts
10513
10514
  var net2 = __toESM(require("net"));
10514
10515
  async function isPortInUse(port) {
10515
- return new Promise((resolve7) => {
10516
+ return new Promise((resolve8) => {
10516
10517
  const server = net2.createServer();
10517
10518
  server.once("error", (err) => {
10518
10519
  if (err.code === "EADDRINUSE") {
10519
- resolve7(true);
10520
+ resolve8(true);
10520
10521
  } else {
10521
- resolve7(false);
10522
+ resolve8(false);
10522
10523
  }
10523
10524
  });
10524
10525
  server.once("listening", () => {
10525
10526
  server.close();
10526
- resolve7(false);
10527
+ resolve8(false);
10527
10528
  });
10528
10529
  server.listen(port);
10529
10530
  });
@@ -10926,7 +10927,7 @@ var DevServerRegistry = class {
10926
10927
  return killed;
10927
10928
  }
10928
10929
  wait(ms) {
10929
- return new Promise((resolve7) => setTimeout(resolve7, ms));
10930
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
10930
10931
  }
10931
10932
  killWsServerOnPort(wsPort, worktreePath) {
10932
10933
  const killed = [];
@@ -11500,7 +11501,7 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11500
11501
  return Math.min(delay, DEV_SERVER_CONSTANTS.MAX_RESTART_DELAY_MS);
11501
11502
  }
11502
11503
  async checkHealth(port) {
11503
- return new Promise((resolve7) => {
11504
+ return new Promise((resolve8) => {
11504
11505
  const req = http.request(
11505
11506
  {
11506
11507
  hostname: "localhost",
@@ -11509,18 +11510,18 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11509
11510
  method: "HEAD",
11510
11511
  timeout: DEV_SERVER_CONSTANTS.HEALTH_CHECK_TIMEOUT_MS
11511
11512
  },
11512
- () => resolve7(true)
11513
+ () => resolve8(true)
11513
11514
  );
11514
- req.on("error", () => resolve7(false));
11515
+ req.on("error", () => resolve8(false));
11515
11516
  req.on("timeout", () => {
11516
11517
  req.destroy();
11517
- resolve7(false);
11518
+ resolve8(false);
11518
11519
  });
11519
11520
  req.end();
11520
11521
  });
11521
11522
  }
11522
11523
  async checkWsHealth(wsPort) {
11523
- return new Promise((resolve7) => {
11524
+ return new Promise((resolve8) => {
11524
11525
  const req = http.request(
11525
11526
  {
11526
11527
  hostname: "127.0.0.1",
@@ -11530,14 +11531,14 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11530
11531
  timeout: DEV_SERVER_CONSTANTS.HEALTH_CHECK_TIMEOUT_MS
11531
11532
  },
11532
11533
  (res) => {
11533
- resolve7(res.statusCode === 200);
11534
+ resolve8(res.statusCode === 200);
11534
11535
  res.resume();
11535
11536
  }
11536
11537
  );
11537
- req.on("error", () => resolve7(false));
11538
+ req.on("error", () => resolve8(false));
11538
11539
  req.on("timeout", () => {
11539
11540
  req.destroy();
11540
- resolve7(false);
11541
+ resolve8(false);
11541
11542
  });
11542
11543
  req.end();
11543
11544
  });
@@ -11565,7 +11566,7 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11565
11566
  return false;
11566
11567
  }
11567
11568
  wait(ms) {
11568
- return new Promise((resolve7) => setTimeout(resolve7, ms));
11569
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
11569
11570
  }
11570
11571
  getLogsDir() {
11571
11572
  const logsDir = path25.join((0, import_core12.getConfigDir)(), "logs");
@@ -11764,7 +11765,7 @@ var PreviewManager = class extends import_events3.EventEmitter {
11764
11765
  for (let attempt = 1; attempt <= MAX_TUNNEL_RETRIES; attempt++) {
11765
11766
  if (attempt > 1) {
11766
11767
  console.log(`[PreviewManager] Retrying tunnel for ${moduleUid} (attempt ${attempt}/${MAX_TUNNEL_RETRIES})...`);
11767
- await new Promise((resolve7) => setTimeout(resolve7, 2e3));
11768
+ await new Promise((resolve8) => setTimeout(resolve8, 2e3));
11768
11769
  }
11769
11770
  tunnelResult = await this.tunnel.startTunnel({
11770
11771
  moduleUid,
@@ -11896,7 +11897,7 @@ var PreviewManager = class extends import_events3.EventEmitter {
11896
11897
  }
11897
11898
  console.log(`[PreviewManager] Restarting preview for ${moduleUid}`);
11898
11899
  await this.stopPreview(moduleUid);
11899
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
11900
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
11900
11901
  return this.startPreview({
11901
11902
  moduleUid,
11902
11903
  worktreePath: state.worktreePath,
@@ -12875,7 +12876,7 @@ var pty = __toESM(require("@lydell/node-pty"));
12875
12876
  var INACTIVITY_TIMEOUT_MS3 = 30 * 60 * 1e3;
12876
12877
  var sessions = /* @__PURE__ */ new Map();
12877
12878
  async function handlePtySpawn(payload, client) {
12878
- const { moduleUid, agent_run_id, command, args, env, cwd, cols = 220, rows = 50 } = payload;
12879
+ const { moduleUid, agent_run_id, command, args, stdin, env, cwd, cols = 220, rows = 50 } = payload;
12879
12880
  if (sessions.has(agent_run_id)) {
12880
12881
  console.warn(`[PTY] Session already exists for agent_run_id ${agent_run_id}, ignoring spawn`);
12881
12882
  return;
@@ -12933,6 +12934,9 @@ async function handlePtySpawn(payload, client) {
12933
12934
  console.error(`[PTY] Failed to send pty_data for ${agent_run_id}:`, err.message);
12934
12935
  });
12935
12936
  });
12937
+ if (typeof stdin === "string" && stdin.trim().length > 0) {
12938
+ proc.write(`${stdin.replace(/\n/g, "\r")}\r`);
12939
+ }
12936
12940
  proc.onExit(({ exitCode }) => {
12937
12941
  const durationMs = Date.now() - session.startedAt;
12938
12942
  if (session.watchdogTimer) clearTimeout(session.watchdogTimer);
@@ -13041,7 +13045,7 @@ async function killProcessOnPort(port) {
13041
13045
  } catch {
13042
13046
  }
13043
13047
  }
13044
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
13048
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
13045
13049
  for (const pid of pids) {
13046
13050
  try {
13047
13051
  (0, import_child_process15.execSync)(`kill -0 ${pid} 2>/dev/null`, { encoding: "utf8" });
@@ -13050,7 +13054,7 @@ async function killProcessOnPort(port) {
13050
13054
  } catch {
13051
13055
  }
13052
13056
  }
13053
- await new Promise((resolve7) => setTimeout(resolve7, 500));
13057
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
13054
13058
  const stillInUse = await isPortInUse(port);
13055
13059
  if (stillInUse) {
13056
13060
  console.error(`[DevServer] EP929: Port ${port} still in use after kill attempts`);
@@ -13070,7 +13074,7 @@ async function waitForPort(port, timeoutMs = 3e4) {
13070
13074
  if (await isPortInUse(port)) {
13071
13075
  return true;
13072
13076
  }
13073
- await new Promise((resolve7) => setTimeout(resolve7, checkInterval));
13077
+ await new Promise((resolve8) => setTimeout(resolve8, checkInterval));
13074
13078
  }
13075
13079
  return false;
13076
13080
  }
@@ -13142,7 +13146,7 @@ async function handleProcessExit(moduleUid, code, signal) {
13142
13146
  const delay = calculateRestartDelay(serverInfo.restartCount);
13143
13147
  console.log(`[DevServer] EP932: Restarting ${moduleUid} in ${delay}ms (attempt ${serverInfo.restartCount + 1}/${MAX_RESTART_ATTEMPTS})`);
13144
13148
  writeToLog(serverInfo.logFile || "", `Scheduling restart in ${delay}ms (attempt ${serverInfo.restartCount + 1})`, false);
13145
- await new Promise((resolve7) => setTimeout(resolve7, delay));
13149
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
13146
13150
  if (!activeServers.has(moduleUid)) {
13147
13151
  console.log(`[DevServer] EP932: Server ${moduleUid} was removed during restart delay, aborting restart`);
13148
13152
  return;
@@ -13267,7 +13271,7 @@ async function stopDevServer(moduleUid) {
13267
13271
  writeToLog(serverInfo.logFile, `Stopping server (manual stop)`, false);
13268
13272
  }
13269
13273
  serverInfo.process.kill("SIGTERM");
13270
- await new Promise((resolve7) => setTimeout(resolve7, 2e3));
13274
+ await new Promise((resolve8) => setTimeout(resolve8, 2e3));
13271
13275
  if (!serverInfo.process.killed) {
13272
13276
  serverInfo.process.kill("SIGKILL");
13273
13277
  }
@@ -13285,7 +13289,7 @@ async function restartDevServer(moduleUid) {
13285
13289
  writeToLog(logFile, `Manual restart requested`, false);
13286
13290
  }
13287
13291
  await stopDevServer(moduleUid);
13288
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
13292
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
13289
13293
  if (await isPortInUse(port)) {
13290
13294
  await killProcessOnPort(port);
13291
13295
  }
@@ -13367,7 +13371,7 @@ var IPCRouter = class {
13367
13371
  if (attempt < MAX_RETRIES) {
13368
13372
  const delay = INITIAL_DELAY * Math.pow(2, attempt - 1);
13369
13373
  console.log(`[Daemon] Retrying in ${delay / 1e3}s...`);
13370
- await new Promise((resolve7) => setTimeout(resolve7, delay));
13374
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
13371
13375
  await this.host.disconnectProject(projectPath);
13372
13376
  }
13373
13377
  }
@@ -14643,7 +14647,7 @@ var ConnectionManager = class {
14643
14647
  * handlers are removed deterministically on every exit path.
14644
14648
  */
14645
14649
  async waitForAuthentication(client, timeoutMs = 3e4) {
14646
- await new Promise((resolve7, reject) => {
14650
+ await new Promise((resolve8, reject) => {
14647
14651
  let settled = false;
14648
14652
  const cleanup = () => {
14649
14653
  clearTimeout(timeout);
@@ -14662,7 +14666,7 @@ var ConnectionManager = class {
14662
14666
  if (settled) return;
14663
14667
  settled = true;
14664
14668
  cleanup();
14665
- resolve7();
14669
+ resolve8();
14666
14670
  };
14667
14671
  const authErrorHandler = (message) => {
14668
14672
  if (settled) return;
@@ -15012,9 +15016,19 @@ var ProjectMessageRouter = class {
15012
15016
  client.on("pty_spawn", async (message) => {
15013
15017
  if (message.type === "pty_spawn") {
15014
15018
  const payload = message.payload;
15019
+ let resolvedPayload = payload;
15020
+ if (!payload.cwd && payload.moduleUid) {
15021
+ const worktreeInfo = await getWorktreeInfoForModule(payload.moduleUid);
15022
+ if (worktreeInfo?.path) {
15023
+ resolvedPayload = {
15024
+ ...payload,
15025
+ cwd: worktreeInfo.path
15026
+ };
15027
+ }
15028
+ }
15015
15029
  console.log(`[Daemon] EP1441: Received pty_spawn for ${projectId}: ${payload.agent_run_id}`);
15016
15030
  client.updateActivity();
15017
- await handlePtySpawn(payload, client);
15031
+ await handlePtySpawn(resolvedPayload, client);
15018
15032
  }
15019
15033
  });
15020
15034
  client.on("pty_resize", (message) => {
@@ -15269,6 +15283,36 @@ async function cacheMachineUuid(machineUuid, machineId) {
15269
15283
  }
15270
15284
  }
15271
15285
 
15286
+ // src/daemon/reconciliation-utils.ts
15287
+ var path35 = __toESM(require("path"));
15288
+ function isPathUnderRoot(candidatePath, projectRoot) {
15289
+ const relative4 = path35.relative(projectRoot, candidatePath);
15290
+ return relative4 !== "" && !relative4.startsWith("..") && !path35.isAbsolute(relative4);
15291
+ }
15292
+ function collectUnexpectedWorktrees(params) {
15293
+ const projectRootResolved = path35.resolve(params.projectRoot);
15294
+ const bareRepoPathResolved = path35.resolve(params.bareRepoPath);
15295
+ const unexpectedWorktrees = [];
15296
+ for (const worktree of params.worktrees) {
15297
+ const worktreePathResolved = path35.resolve(worktree.path);
15298
+ if (worktreePathResolved === bareRepoPathResolved) continue;
15299
+ if (worktree.prunable || worktree.locked) continue;
15300
+ if (!isPathUnderRoot(worktreePathResolved, projectRootResolved)) continue;
15301
+ const moduleUid = path35.basename(worktreePathResolved);
15302
+ if (!validateModuleUid(moduleUid)) continue;
15303
+ if (!/^EP\d+$/.test(moduleUid)) continue;
15304
+ if (params.expectedModuleUids.has(moduleUid)) continue;
15305
+ const branch = worktree.branch || "unknown";
15306
+ if (branch === "HEAD (detached)") continue;
15307
+ unexpectedWorktrees.push({
15308
+ moduleUid,
15309
+ path: worktreePathResolved,
15310
+ branch
15311
+ });
15312
+ }
15313
+ return unexpectedWorktrees;
15314
+ }
15315
+
15272
15316
  // src/daemon/daemon-process.ts
15273
15317
  var packageJson = require_package();
15274
15318
  var Daemon = class _Daemon {
@@ -15471,9 +15515,9 @@ var Daemon = class _Daemon {
15471
15515
  this.healthServer = http2.createServer((req, res) => {
15472
15516
  if (req.url === "/health" || req.url === "/") {
15473
15517
  const isConnected = this.connectionManager.liveConnectionCount() > 0;
15474
- const projects = Array.from(this.connectionManager.entries()).map(([path35, conn]) => ({
15475
- path: path35,
15476
- connected: this.connectionManager.hasLiveConnection(path35)
15518
+ const projects = Array.from(this.connectionManager.entries()).map(([path37, conn]) => ({
15519
+ path: path37,
15520
+ connected: this.connectionManager.hasLiveConnection(path37)
15477
15521
  }));
15478
15522
  const status = {
15479
15523
  status: isConnected ? "healthy" : "degraded",
@@ -15610,8 +15654,8 @@ var Daemon = class _Daemon {
15610
15654
  }
15611
15655
  }
15612
15656
  let releaseLock;
15613
- const lockPromise = new Promise((resolve7) => {
15614
- releaseLock = resolve7;
15657
+ const lockPromise = new Promise((resolve8) => {
15658
+ releaseLock = resolve8;
15615
15659
  });
15616
15660
  this.tunnelOperationLocks.set(moduleUid, lockPromise);
15617
15661
  try {
@@ -15657,7 +15701,7 @@ var Daemon = class _Daemon {
15657
15701
  const maxWait = 35e3;
15658
15702
  const startTime = Date.now();
15659
15703
  while (this.connectionManager.hasPendingConnection(projectPath) && Date.now() - startTime < maxWait) {
15660
- await new Promise((resolve7) => setTimeout(resolve7, 500));
15704
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
15661
15705
  }
15662
15706
  if (this.connectionManager.hasLiveConnection(projectPath)) {
15663
15707
  console.log(`[Daemon] Pending connection succeeded for ${projectPath}`);
@@ -16476,6 +16520,7 @@ var Daemon = class _Daemon {
16476
16520
  await tunnelManager.initialize();
16477
16521
  const moduleStatuses = [];
16478
16522
  const expectedModuleUids = new Set(modules.map((m) => m.uid));
16523
+ const bareRepoPath = path36.join(projectPath, ".bare");
16479
16524
  for (const mod of modules) {
16480
16525
  const moduleUid = mod.uid;
16481
16526
  const worktree = await getWorktreeInfoForModule(moduleUid);
@@ -16506,11 +16551,36 @@ var Daemon = class _Daemon {
16506
16551
  if (orphanTunnels.length > 0) {
16507
16552
  console.log(`[Daemon] EP1003: Reporting ${orphanTunnels.length} orphan tunnel(s) for server cleanup`);
16508
16553
  }
16554
+ let unexpectedWorktrees;
16555
+ try {
16556
+ const listResult = await new import_core22.GitExecutor().execute(
16557
+ { action: "worktree_list" },
16558
+ { cwd: bareRepoPath }
16559
+ );
16560
+ if (listResult.success) {
16561
+ const localWorktrees = listResult.details?.worktrees || [];
16562
+ const discoveredUnexpectedWorktrees = collectUnexpectedWorktrees({
16563
+ worktrees: localWorktrees,
16564
+ expectedModuleUids,
16565
+ projectRoot: projectPath,
16566
+ bareRepoPath
16567
+ });
16568
+ if (discoveredUnexpectedWorktrees.length > 0) {
16569
+ unexpectedWorktrees = discoveredUnexpectedWorktrees;
16570
+ console.log(`[Daemon] EP1446: Reporting ${discoveredUnexpectedWorktrees.length} unexpected worktree(s) for recovery`);
16571
+ }
16572
+ } else {
16573
+ console.warn("[Daemon] EP1446: Failed to list local worktrees for reconciliation");
16574
+ }
16575
+ } catch (error) {
16576
+ console.warn("[Daemon] EP1446: Error while scanning local worktrees:", error instanceof Error ? error.message : error);
16577
+ }
16509
16578
  const report = {
16510
16579
  projectId,
16511
16580
  machineId: this.machineUuid,
16512
16581
  modules: moduleStatuses,
16513
- orphanTunnels: orphanTunnels.length > 0 ? orphanTunnels : void 0
16582
+ orphanTunnels: orphanTunnels.length > 0 ? orphanTunnels : void 0,
16583
+ unexpectedWorktrees
16514
16584
  };
16515
16585
  console.log(`[Daemon] EP1003: Sending reconciliation report with ${moduleStatuses.length} module(s)`);
16516
16586
  await client.send({
@@ -16757,7 +16827,7 @@ var Daemon = class _Daemon {
16757
16827
  console.log(`[Daemon] EP1002: Worktree setup complete for ${moduleUid}`);
16758
16828
  }
16759
16829
  async runForegroundCommand(command, args, cwd, env, timeoutMs) {
16760
- await new Promise((resolve7, reject) => {
16830
+ await new Promise((resolve8, reject) => {
16761
16831
  const commandLabel = `${command} ${args.join(" ")}`.trim();
16762
16832
  const child = (0, import_child_process19.spawn)(command, args, {
16763
16833
  cwd,
@@ -16780,7 +16850,7 @@ var Daemon = class _Daemon {
16780
16850
  reject(error);
16781
16851
  return;
16782
16852
  }
16783
- resolve7();
16853
+ resolve8();
16784
16854
  };
16785
16855
  termTimer = setTimeout(() => {
16786
16856
  timedOut = true;