episoda 0.2.11 → 0.2.12

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.
@@ -2068,11 +2068,11 @@ var require_auth = __commonJS({
2068
2068
  exports2.validateToken = validateToken;
2069
2069
  var fs6 = __importStar(require("fs"));
2070
2070
  var path7 = __importStar(require("path"));
2071
- var os4 = __importStar(require("os"));
2071
+ var os2 = __importStar(require("os"));
2072
2072
  var child_process_1 = require("child_process");
2073
2073
  var DEFAULT_CONFIG_FILE = "config.json";
2074
2074
  function getConfigDir5() {
2075
- return process.env.EPISODA_CONFIG_DIR || path7.join(os4.homedir(), ".episoda");
2075
+ return process.env.EPISODA_CONFIG_DIR || path7.join(os2.homedir(), ".episoda");
2076
2076
  }
2077
2077
  function getConfigPath(configPath) {
2078
2078
  if (configPath) {
@@ -2228,7 +2228,7 @@ var require_package = __commonJS({
2228
2228
  "package.json"(exports2, module2) {
2229
2229
  module2.exports = {
2230
2230
  name: "episoda",
2231
- version: "0.2.10",
2231
+ version: "0.2.11",
2232
2232
  description: "CLI tool for Episoda local development workflow orchestration",
2233
2233
  main: "dist/index.js",
2234
2234
  types: "dist/index.d.ts",
@@ -2283,19 +2283,29 @@ var require_package = __commonJS({
2283
2283
  });
2284
2284
 
2285
2285
  // src/daemon/machine-id.ts
2286
- var os = __toESM(require("os"));
2287
2286
  var fs = __toESM(require("fs"));
2288
2287
  var path = __toESM(require("path"));
2289
2288
  var crypto = __toESM(require("crypto"));
2290
2289
  var import_child_process = require("child_process");
2291
2290
  var import_core = __toESM(require_dist());
2291
+ function isValidUUID(str) {
2292
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2293
+ return uuidRegex.test(str);
2294
+ }
2292
2295
  async function getMachineId() {
2293
2296
  const machineIdPath = path.join((0, import_core.getConfigDir)(), "machine-id");
2294
2297
  try {
2295
2298
  if (fs.existsSync(machineIdPath)) {
2296
- const machineId2 = fs.readFileSync(machineIdPath, "utf-8").trim();
2297
- if (machineId2) {
2298
- return machineId2;
2299
+ const existingId = fs.readFileSync(machineIdPath, "utf-8").trim();
2300
+ if (existingId) {
2301
+ if (isValidUUID(existingId)) {
2302
+ return existingId;
2303
+ }
2304
+ console.log("[MachineId] Migrating legacy machine ID to UUID format...");
2305
+ const newUUID = generateMachineId();
2306
+ fs.writeFileSync(machineIdPath, newUUID, "utf-8");
2307
+ console.log(`[MachineId] Migrated: ${existingId} \u2192 ${newUUID}`);
2308
+ return newUUID;
2299
2309
  }
2300
2310
  }
2301
2311
  } catch (error) {
@@ -2354,10 +2364,21 @@ function getHardwareUUID() {
2354
2364
  return crypto.randomUUID();
2355
2365
  }
2356
2366
  function generateMachineId() {
2357
- const hostname4 = os.hostname();
2358
2367
  const hwUUID = getHardwareUUID();
2359
- const shortId = hwUUID.replace(/-/g, "").slice(0, 8).toLowerCase();
2360
- return `${hostname4}-${shortId}`;
2368
+ if (isValidUUID(hwUUID)) {
2369
+ return hwUUID.toLowerCase();
2370
+ }
2371
+ const hash = crypto.createHash("sha256").update(hwUUID).digest("hex");
2372
+ const uuid = [
2373
+ hash.slice(0, 8),
2374
+ hash.slice(8, 12),
2375
+ "4" + hash.slice(13, 16),
2376
+ // Version 4
2377
+ (parseInt(hash.slice(16, 17), 16) & 3 | 8).toString(16) + hash.slice(17, 20),
2378
+ // Variant
2379
+ hash.slice(20, 32)
2380
+ ].join("-");
2381
+ return uuid.toLowerCase();
2361
2382
  }
2362
2383
 
2363
2384
  // src/daemon/project-tracker.ts
@@ -2615,97 +2636,6 @@ function performBackgroundUpdate() {
2615
2636
  }
2616
2637
  }
2617
2638
 
2618
- // src/daemon/identity-server.ts
2619
- var http = __toESM(require("http"));
2620
- var os2 = __toESM(require("os"));
2621
- var IDENTITY_SERVER_PORT = 3002;
2622
- var IdentityServer = class {
2623
- constructor(machineId) {
2624
- this.server = null;
2625
- this.isConnected = false;
2626
- this.machineId = machineId;
2627
- }
2628
- /**
2629
- * Update connection status
2630
- * Called when WebSocket connection state changes
2631
- */
2632
- setConnected(connected) {
2633
- this.isConnected = connected;
2634
- }
2635
- /**
2636
- * Start the identity server on localhost:3002
2637
- */
2638
- async start() {
2639
- return new Promise((resolve2, reject) => {
2640
- this.server = http.createServer((req, res) => {
2641
- res.setHeader("Access-Control-Allow-Origin", "*");
2642
- res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
2643
- res.setHeader("Access-Control-Allow-Headers", "Content-Type");
2644
- res.setHeader("Access-Control-Allow-Private-Network", "true");
2645
- if (req.method === "OPTIONS") {
2646
- res.writeHead(204);
2647
- res.end();
2648
- return;
2649
- }
2650
- if (req.method !== "GET") {
2651
- res.writeHead(405, { "Content-Type": "application/json" });
2652
- res.end(JSON.stringify({ error: "Method not allowed" }));
2653
- return;
2654
- }
2655
- const url = new URL(req.url || "/", `http://${req.headers.host}`);
2656
- if (url.pathname === "/identity") {
2657
- const response = {
2658
- machineId: this.machineId,
2659
- hostname: os2.hostname(),
2660
- platform: os2.platform(),
2661
- arch: os2.arch(),
2662
- connected: this.isConnected
2663
- };
2664
- res.writeHead(200, { "Content-Type": "application/json" });
2665
- res.end(JSON.stringify(response));
2666
- return;
2667
- }
2668
- if (url.pathname === "/health") {
2669
- res.writeHead(200, { "Content-Type": "application/json" });
2670
- res.end(JSON.stringify({ status: "ok", machineId: this.machineId }));
2671
- return;
2672
- }
2673
- res.writeHead(404, { "Content-Type": "application/json" });
2674
- res.end(JSON.stringify({ error: "Not found" }));
2675
- });
2676
- this.server.listen(IDENTITY_SERVER_PORT, "127.0.0.1", () => {
2677
- console.log(`[IdentityServer] Started on http://127.0.0.1:${IDENTITY_SERVER_PORT}`);
2678
- resolve2();
2679
- });
2680
- this.server.on("error", (err) => {
2681
- if (err.code === "EADDRINUSE") {
2682
- console.warn(`[IdentityServer] Port ${IDENTITY_SERVER_PORT} already in use, skipping`);
2683
- resolve2();
2684
- } else {
2685
- console.error("[IdentityServer] Failed to start:", err.message);
2686
- reject(err);
2687
- }
2688
- });
2689
- });
2690
- }
2691
- /**
2692
- * Stop the identity server
2693
- */
2694
- async stop() {
2695
- return new Promise((resolve2) => {
2696
- if (this.server) {
2697
- this.server.close(() => {
2698
- console.log("[IdentityServer] Stopped");
2699
- this.server = null;
2700
- resolve2();
2701
- });
2702
- } else {
2703
- resolve2();
2704
- }
2705
- });
2706
- }
2707
- };
2708
-
2709
2639
  // src/daemon/handlers/file-handlers.ts
2710
2640
  var fs4 = __toESM(require("fs"));
2711
2641
  var path5 = __toESM(require("path"));
@@ -3172,7 +3102,7 @@ async function handleExec(command, projectPath) {
3172
3102
 
3173
3103
  // src/daemon/daemon-process.ts
3174
3104
  var fs5 = __toESM(require("fs"));
3175
- var os3 = __toESM(require("os"));
3105
+ var os = __toESM(require("os"));
3176
3106
  var path6 = __toESM(require("path"));
3177
3107
  var packageJson = require_package();
3178
3108
  var Daemon = class {
@@ -3183,8 +3113,7 @@ var Daemon = class {
3183
3113
  this.deviceName = null;
3184
3114
  // EP661: Cached device name from server
3185
3115
  this.flyMachineId = null;
3186
- this.identityServer = null;
3187
- // EP803: Local identity server for browser detection
3116
+ // EP812: Removed identityServer - browser identity now uses cookie-based pairing
3188
3117
  this.connections = /* @__PURE__ */ new Map();
3189
3118
  // projectPath -> connection
3190
3119
  // EP701: Track which connections are currently live (WebSocket open)
@@ -3208,8 +3137,6 @@ var Daemon = class {
3208
3137
  }
3209
3138
  await this.ipcServer.start();
3210
3139
  console.log("[Daemon] IPC server started");
3211
- this.identityServer = new IdentityServer(this.machineId);
3212
- await this.identityServer.start();
3213
3140
  this.registerIPCHandlers();
3214
3141
  await this.restoreConnections();
3215
3142
  this.setupShutdownHandlers();
@@ -3252,9 +3179,9 @@ var Daemon = class {
3252
3179
  machineId: this.machineId,
3253
3180
  deviceId: this.deviceId,
3254
3181
  // EP726: UUID for unified device identification
3255
- hostname: os3.hostname(),
3256
- platform: os3.platform(),
3257
- arch: os3.arch(),
3182
+ hostname: os.hostname(),
3183
+ platform: os.platform(),
3184
+ arch: os.arch(),
3258
3185
  projects
3259
3186
  };
3260
3187
  });
@@ -3468,9 +3395,6 @@ var Daemon = class {
3468
3395
  console.log(`[Daemon] Authenticated for project ${projectId}`);
3469
3396
  touchProject(projectPath);
3470
3397
  this.liveConnections.add(projectPath);
3471
- if (this.identityServer) {
3472
- this.identityServer.setConnected(true);
3473
- }
3474
3398
  const authMessage = message;
3475
3399
  if (authMessage.userId && authMessage.workspaceId) {
3476
3400
  await this.configureGitUser(projectPath, authMessage.userId, authMessage.workspaceId, this.machineId, projectId, authMessage.deviceId);
@@ -3497,9 +3421,6 @@ var Daemon = class {
3497
3421
  const disconnectEvent = event;
3498
3422
  console.log(`[Daemon] Connection closed for ${projectId}: code=${disconnectEvent.code}, willReconnect=${disconnectEvent.willReconnect}`);
3499
3423
  this.liveConnections.delete(projectPath);
3500
- if (this.identityServer && this.liveConnections.size === 0) {
3501
- this.identityServer.setConnected(false);
3502
- }
3503
3424
  if (!disconnectEvent.willReconnect) {
3504
3425
  this.connections.delete(projectPath);
3505
3426
  console.log(`[Daemon] Removed connection for ${projectPath} from map`);
@@ -3517,9 +3438,9 @@ var Daemon = class {
3517
3438
  console.warn(`[Daemon] Could not read daemon PID:`, pidError instanceof Error ? pidError.message : pidError);
3518
3439
  }
3519
3440
  await client.connect(wsUrl, config.access_token, this.machineId, {
3520
- hostname: os3.hostname(),
3521
- osPlatform: os3.platform(),
3522
- osArch: os3.arch(),
3441
+ hostname: os.hostname(),
3442
+ osPlatform: os.platform(),
3443
+ osArch: os.arch(),
3523
3444
  daemonPid
3524
3445
  });
3525
3446
  console.log(`[Daemon] Successfully connected to project ${projectId}`);
@@ -3678,10 +3599,6 @@ var Daemon = class {
3678
3599
  await connection.client.disconnect();
3679
3600
  }
3680
3601
  this.connections.clear();
3681
- if (this.identityServer) {
3682
- await this.identityServer.stop();
3683
- this.identityServer = null;
3684
- }
3685
3602
  await this.ipcServer.stop();
3686
3603
  console.log("[Daemon] Shutdown complete");
3687
3604
  }