episoda 0.2.74 → 0.2.76

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.
@@ -2741,7 +2741,7 @@ var require_package = __commonJS({
2741
2741
  "package.json"(exports2, module2) {
2742
2742
  module2.exports = {
2743
2743
  name: "episoda",
2744
- version: "0.2.74",
2744
+ version: "0.2.76",
2745
2745
  description: "CLI tool for Episoda local development workflow orchestration",
2746
2746
  main: "dist/index.js",
2747
2747
  types: "dist/index.d.ts",
@@ -4187,6 +4187,27 @@ async function clearTunnelUrl(moduleUid) {
4187
4187
  }
4188
4188
  }
4189
4189
 
4190
+ // src/daemon/mode-config.ts
4191
+ var CLOUD_CONFIG = {
4192
+ mode: "cloud",
4193
+ portAllocation: "fixed",
4194
+ fixedPort: 3e3,
4195
+ orphanTunnelCleanup: false,
4196
+ orphanWorktreeCleanup: false,
4197
+ maxConcurrentModules: 1
4198
+ };
4199
+ var LOCAL_CONFIG = {
4200
+ mode: "local",
4201
+ portAllocation: "dynamic",
4202
+ orphanTunnelCleanup: true,
4203
+ orphanWorktreeCleanup: true,
4204
+ maxConcurrentModules: Infinity
4205
+ };
4206
+ function getDaemonModeConfig() {
4207
+ const mode = process.env.EPISODA_MODE;
4208
+ return mode === "cloud" ? CLOUD_CONFIG : LOCAL_CONFIG;
4209
+ }
4210
+
4190
4211
  // src/tunnel/tunnel-manager.ts
4191
4212
  var TUNNEL_PID_DIR = path7.join(os2.homedir(), ".episoda", "tunnels");
4192
4213
  var TUNNEL_TIMEOUTS = {
@@ -4380,9 +4401,17 @@ var TunnelManager = class extends import_events.EventEmitter {
4380
4401
  * EP877: Cleanup orphaned cloudflared processes on startup
4381
4402
  * Kills any cloudflared processes that have PID files but aren't tracked in memory,
4382
4403
  * and any cloudflared processes that don't have corresponding PID files.
4404
+ *
4405
+ * EP1111: Skip cleanup in cloud mode - supervisord manages cloudflared there,
4406
+ * and we must not kill processes we didn't start.
4383
4407
  */
4384
4408
  async cleanupOrphanedProcesses() {
4385
4409
  const cleaned = [];
4410
+ const modeConfig = getDaemonModeConfig();
4411
+ if (!modeConfig.orphanTunnelCleanup) {
4412
+ console.log(`[Tunnel] EP1115: Skipping orphan cleanup (mode: ${modeConfig.mode}, orphanTunnelCleanup: false)`);
4413
+ return { cleaned: 0, pids: [] };
4414
+ }
4386
4415
  try {
4387
4416
  this.ensurePidDir();
4388
4417
  const pidFiles = fs6.readdirSync(TUNNEL_PID_DIR).filter((f) => f.endsWith(".pid"));
@@ -8096,6 +8125,15 @@ var Daemon = class _Daemon {
8096
8125
  this.startHealthCheckPolling();
8097
8126
  this.setupShutdownHandlers();
8098
8127
  console.log("[Daemon] Daemon started successfully");
8128
+ const modeConfig = getDaemonModeConfig();
8129
+ console.log("[Daemon] EP1115: Mode config:", {
8130
+ mode: modeConfig.mode,
8131
+ portAllocation: modeConfig.portAllocation,
8132
+ fixedPort: modeConfig.fixedPort,
8133
+ orphanTunnelCleanup: modeConfig.orphanTunnelCleanup,
8134
+ orphanWorktreeCleanup: modeConfig.orphanWorktreeCleanup,
8135
+ maxConcurrentModules: modeConfig.maxConcurrentModules
8136
+ });
8099
8137
  this.checkAndNotifyUpdates();
8100
8138
  }
8101
8139
  /**
@@ -8586,8 +8624,16 @@ var Daemon = class _Daemon {
8586
8624
  return;
8587
8625
  }
8588
8626
  console.log(`[Daemon] EP1024: Using worktree path ${worktree.path} for ${cmd.moduleUid}`);
8589
- const port = cmd.port || allocatePort(cmd.moduleUid);
8590
- console.log(`[Daemon] EP1038: Allocated port ${port} for ${cmd.moduleUid}`);
8627
+ const modeConfig = getDaemonModeConfig();
8628
+ let port;
8629
+ if (cmd.port) {
8630
+ port = cmd.port;
8631
+ } else if (modeConfig.portAllocation === "fixed" && modeConfig.fixedPort) {
8632
+ port = modeConfig.fixedPort;
8633
+ } else {
8634
+ port = allocatePort(cmd.moduleUid);
8635
+ }
8636
+ console.log(`[Daemon] EP1115: Using port ${port} for ${cmd.moduleUid} (mode: ${modeConfig.mode})`);
8591
8637
  const devConfig = await (0, import_core12.loadConfig)();
8592
8638
  const customCommand = devConfig?.project_settings?.worktree_dev_server_script;
8593
8639
  const startResult = await previewManager.startPreview({