episoda 0.2.75 → 0.2.77
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/daemon/daemon-process.js +80 -10
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -2116,6 +2116,7 @@ var require_websocket_client = __commonJS({
|
|
|
2116
2116
|
* @param token - OAuth access token
|
|
2117
2117
|
* @param machineId - Optional machine identifier for multi-machine support
|
|
2118
2118
|
* @param deviceInfo - Optional device information (hostname, OS, daemonPid)
|
|
2119
|
+
* EP1119: Added environment and containerId for cloud routing
|
|
2119
2120
|
*/
|
|
2120
2121
|
async connect(url, token, machineId, deviceInfo) {
|
|
2121
2122
|
this.url = url;
|
|
@@ -2125,6 +2126,8 @@ var require_websocket_client = __commonJS({
|
|
|
2125
2126
|
this.osPlatform = deviceInfo?.osPlatform;
|
|
2126
2127
|
this.osArch = deviceInfo?.osArch;
|
|
2127
2128
|
this.daemonPid = deviceInfo?.daemonPid;
|
|
2129
|
+
this.environment = deviceInfo?.environment;
|
|
2130
|
+
this.containerId = deviceInfo?.containerId;
|
|
2128
2131
|
this.isDisconnecting = false;
|
|
2129
2132
|
this.isGracefulShutdown = false;
|
|
2130
2133
|
this.isIntentionalDisconnect = false;
|
|
@@ -2162,7 +2165,9 @@ var require_websocket_client = __commonJS({
|
|
|
2162
2165
|
type: "auth",
|
|
2163
2166
|
token,
|
|
2164
2167
|
version: version_1.VERSION,
|
|
2168
|
+
environment: this.environment,
|
|
2165
2169
|
machineId,
|
|
2170
|
+
containerId: this.containerId,
|
|
2166
2171
|
hostname: this.hostname,
|
|
2167
2172
|
osPlatform: this.osPlatform,
|
|
2168
2173
|
osArch: this.osArch,
|
|
@@ -2463,7 +2468,9 @@ var require_websocket_client = __commonJS({
|
|
|
2463
2468
|
hostname: this.hostname,
|
|
2464
2469
|
osPlatform: this.osPlatform,
|
|
2465
2470
|
osArch: this.osArch,
|
|
2466
|
-
daemonPid: this.daemonPid
|
|
2471
|
+
daemonPid: this.daemonPid,
|
|
2472
|
+
environment: this.environment,
|
|
2473
|
+
containerId: this.containerId
|
|
2467
2474
|
}).then(() => {
|
|
2468
2475
|
console.log("[EpisodaClient] Reconnection successful");
|
|
2469
2476
|
this.reconnectAttempts = 0;
|
|
@@ -2741,7 +2748,7 @@ var require_package = __commonJS({
|
|
|
2741
2748
|
"package.json"(exports2, module2) {
|
|
2742
2749
|
module2.exports = {
|
|
2743
2750
|
name: "episoda",
|
|
2744
|
-
version: "0.2.
|
|
2751
|
+
version: "0.2.77",
|
|
2745
2752
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2746
2753
|
main: "dist/index.js",
|
|
2747
2754
|
types: "dist/index.d.ts",
|
|
@@ -4187,6 +4194,27 @@ async function clearTunnelUrl(moduleUid) {
|
|
|
4187
4194
|
}
|
|
4188
4195
|
}
|
|
4189
4196
|
|
|
4197
|
+
// src/daemon/mode-config.ts
|
|
4198
|
+
var CLOUD_CONFIG = {
|
|
4199
|
+
mode: "cloud",
|
|
4200
|
+
portAllocation: "fixed",
|
|
4201
|
+
fixedPort: 3e3,
|
|
4202
|
+
orphanTunnelCleanup: false,
|
|
4203
|
+
orphanWorktreeCleanup: false,
|
|
4204
|
+
maxConcurrentModules: 1
|
|
4205
|
+
};
|
|
4206
|
+
var LOCAL_CONFIG = {
|
|
4207
|
+
mode: "local",
|
|
4208
|
+
portAllocation: "dynamic",
|
|
4209
|
+
orphanTunnelCleanup: true,
|
|
4210
|
+
orphanWorktreeCleanup: true,
|
|
4211
|
+
maxConcurrentModules: Infinity
|
|
4212
|
+
};
|
|
4213
|
+
function getDaemonModeConfig() {
|
|
4214
|
+
const mode = process.env.EPISODA_MODE;
|
|
4215
|
+
return mode === "cloud" ? CLOUD_CONFIG : LOCAL_CONFIG;
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4190
4218
|
// src/tunnel/tunnel-manager.ts
|
|
4191
4219
|
var TUNNEL_PID_DIR = path7.join(os2.homedir(), ".episoda", "tunnels");
|
|
4192
4220
|
var TUNNEL_TIMEOUTS = {
|
|
@@ -4386,8 +4414,9 @@ var TunnelManager = class extends import_events.EventEmitter {
|
|
|
4386
4414
|
*/
|
|
4387
4415
|
async cleanupOrphanedProcesses() {
|
|
4388
4416
|
const cleaned = [];
|
|
4389
|
-
|
|
4390
|
-
|
|
4417
|
+
const modeConfig = getDaemonModeConfig();
|
|
4418
|
+
if (!modeConfig.orphanTunnelCleanup) {
|
|
4419
|
+
console.log(`[Tunnel] EP1115: Skipping orphan cleanup (mode: ${modeConfig.mode}, orphanTunnelCleanup: false)`);
|
|
4391
4420
|
return { cleaned: 0, pids: [] };
|
|
4392
4421
|
}
|
|
4393
4422
|
try {
|
|
@@ -6380,13 +6409,19 @@ var PreviewManager = class extends import_events3.EventEmitter {
|
|
|
6380
6409
|
*
|
|
6381
6410
|
* Must be called before starting any previews.
|
|
6382
6411
|
* Initializes the tunnel manager (ensures cloudflared, cleans orphans).
|
|
6412
|
+
* EP1119: Skips tunnel initialization in cloud mode - supervisord manages cloudflared there.
|
|
6383
6413
|
*/
|
|
6384
6414
|
async initialize() {
|
|
6385
6415
|
if (this.initialized) {
|
|
6386
6416
|
return;
|
|
6387
6417
|
}
|
|
6388
6418
|
console.log("[PreviewManager] Initializing...");
|
|
6389
|
-
|
|
6419
|
+
const modeConfig = getDaemonModeConfig();
|
|
6420
|
+
if (modeConfig.mode === "cloud") {
|
|
6421
|
+
console.log("[PreviewManager] EP1119: Skipping TunnelManager init in cloud mode");
|
|
6422
|
+
} else {
|
|
6423
|
+
await this.tunnel.initialize();
|
|
6424
|
+
}
|
|
6390
6425
|
this.initialized = true;
|
|
6391
6426
|
console.log("[PreviewManager] Initialized");
|
|
6392
6427
|
}
|
|
@@ -6403,7 +6438,7 @@ var PreviewManager = class extends import_events3.EventEmitter {
|
|
|
6403
6438
|
* @returns Result with success status and preview URL
|
|
6404
6439
|
*/
|
|
6405
6440
|
async startPreview(config) {
|
|
6406
|
-
const { moduleUid, worktreePath, port = DEFAULT_PORT, customCommand } = config;
|
|
6441
|
+
const { moduleUid, worktreePath, port = DEFAULT_PORT, customCommand, skipTunnel } = config;
|
|
6407
6442
|
if (!worktreePath) {
|
|
6408
6443
|
return { success: false, error: "Worktree path is required" };
|
|
6409
6444
|
}
|
|
@@ -6467,6 +6502,17 @@ var PreviewManager = class extends import_events3.EventEmitter {
|
|
|
6467
6502
|
state.state = "running";
|
|
6468
6503
|
this.emitStateChange(moduleUid, "running");
|
|
6469
6504
|
console.log(`[PreviewManager] Dev server running on port ${port}`);
|
|
6505
|
+
if (skipTunnel) {
|
|
6506
|
+
console.log(`[PreviewManager] EP1119: Skipping tunnel management for ${moduleUid} (cloud mode)`);
|
|
6507
|
+
state.state = "live";
|
|
6508
|
+
this.emitStateChange(moduleUid, "live");
|
|
6509
|
+
this.startingModules.delete(moduleUid);
|
|
6510
|
+
return {
|
|
6511
|
+
success: true,
|
|
6512
|
+
previewUrl: void 0
|
|
6513
|
+
// URL comes from Cloudflare Named Tunnel, not local
|
|
6514
|
+
};
|
|
6515
|
+
}
|
|
6470
6516
|
console.log(`[PreviewManager] Starting Named Tunnel for ${moduleUid}...`);
|
|
6471
6517
|
state.state = "tunneling";
|
|
6472
6518
|
this.emitStateChange(moduleUid, "tunneling");
|
|
@@ -8103,6 +8149,15 @@ var Daemon = class _Daemon {
|
|
|
8103
8149
|
this.startHealthCheckPolling();
|
|
8104
8150
|
this.setupShutdownHandlers();
|
|
8105
8151
|
console.log("[Daemon] Daemon started successfully");
|
|
8152
|
+
const modeConfig = getDaemonModeConfig();
|
|
8153
|
+
console.log("[Daemon] EP1115: Mode config:", {
|
|
8154
|
+
mode: modeConfig.mode,
|
|
8155
|
+
portAllocation: modeConfig.portAllocation,
|
|
8156
|
+
fixedPort: modeConfig.fixedPort,
|
|
8157
|
+
orphanTunnelCleanup: modeConfig.orphanTunnelCleanup,
|
|
8158
|
+
orphanWorktreeCleanup: modeConfig.orphanWorktreeCleanup,
|
|
8159
|
+
maxConcurrentModules: modeConfig.maxConcurrentModules
|
|
8160
|
+
});
|
|
8106
8161
|
this.checkAndNotifyUpdates();
|
|
8107
8162
|
}
|
|
8108
8163
|
/**
|
|
@@ -8593,15 +8648,25 @@ var Daemon = class _Daemon {
|
|
|
8593
8648
|
return;
|
|
8594
8649
|
}
|
|
8595
8650
|
console.log(`[Daemon] EP1024: Using worktree path ${worktree.path} for ${cmd.moduleUid}`);
|
|
8596
|
-
const
|
|
8597
|
-
|
|
8651
|
+
const modeConfig = getDaemonModeConfig();
|
|
8652
|
+
let port;
|
|
8653
|
+
if (cmd.port) {
|
|
8654
|
+
port = cmd.port;
|
|
8655
|
+
} else if (modeConfig.portAllocation === "fixed" && modeConfig.fixedPort) {
|
|
8656
|
+
port = modeConfig.fixedPort;
|
|
8657
|
+
} else {
|
|
8658
|
+
port = allocatePort(cmd.moduleUid);
|
|
8659
|
+
}
|
|
8660
|
+
console.log(`[Daemon] EP1115: Using port ${port} for ${cmd.moduleUid} (mode: ${modeConfig.mode})`);
|
|
8598
8661
|
const devConfig = await (0, import_core12.loadConfig)();
|
|
8599
8662
|
const customCommand = devConfig?.project_settings?.worktree_dev_server_script;
|
|
8600
8663
|
const startResult = await previewManager.startPreview({
|
|
8601
8664
|
moduleUid: cmd.moduleUid,
|
|
8602
8665
|
worktreePath: worktree.path,
|
|
8603
8666
|
port,
|
|
8604
|
-
customCommand
|
|
8667
|
+
customCommand,
|
|
8668
|
+
skipTunnel: modeConfig.mode === "cloud"
|
|
8669
|
+
// EP1119: Cloud mode - supervisord handles cloudflared
|
|
8605
8670
|
});
|
|
8606
8671
|
if (startResult.success) {
|
|
8607
8672
|
console.log(`[Daemon] EP1024: Preview started for ${cmd.moduleUid}: ${startResult.previewUrl}`);
|
|
@@ -8978,11 +9043,16 @@ var Daemon = class _Daemon {
|
|
|
8978
9043
|
};
|
|
8979
9044
|
client.once("auth_error", errorHandler);
|
|
8980
9045
|
});
|
|
9046
|
+
const modeConfig = getDaemonModeConfig();
|
|
9047
|
+
const environment = modeConfig.mode;
|
|
9048
|
+
const containerId = process.env.EPISODA_CONTAINER_ID;
|
|
8981
9049
|
await client.connect(wsUrl, config.access_token, this.machineId, {
|
|
8982
9050
|
hostname: os8.hostname(),
|
|
8983
9051
|
osPlatform: os8.platform(),
|
|
8984
9052
|
osArch: os8.arch(),
|
|
8985
|
-
daemonPid
|
|
9053
|
+
daemonPid,
|
|
9054
|
+
environment,
|
|
9055
|
+
containerId
|
|
8986
9056
|
});
|
|
8987
9057
|
console.log(`[Daemon] Successfully connected to project ${projectId}`);
|
|
8988
9058
|
await authSuccessPromise;
|