episoda 0.2.11 → 0.2.13
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 +52 -125
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +55 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1646,9 +1646,19 @@ var require_version = __commonJS({
|
|
|
1646
1646
|
exports2.VERSION = void 0;
|
|
1647
1647
|
var fs_1 = require("fs");
|
|
1648
1648
|
var path_1 = require("path");
|
|
1649
|
-
var
|
|
1650
|
-
|
|
1651
|
-
|
|
1649
|
+
var FALLBACK_VERSION = "0.1.11";
|
|
1650
|
+
function getVersion() {
|
|
1651
|
+
try {
|
|
1652
|
+
const packageJsonPath = (0, path_1.join)(__dirname, "..", "package.json");
|
|
1653
|
+
if ((0, fs_1.existsSync)(packageJsonPath)) {
|
|
1654
|
+
const packageJson2 = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, "utf-8"));
|
|
1655
|
+
return packageJson2.version;
|
|
1656
|
+
}
|
|
1657
|
+
} catch {
|
|
1658
|
+
}
|
|
1659
|
+
return FALLBACK_VERSION;
|
|
1660
|
+
}
|
|
1661
|
+
exports2.VERSION = getVersion();
|
|
1652
1662
|
}
|
|
1653
1663
|
});
|
|
1654
1664
|
|
|
@@ -2068,11 +2078,11 @@ var require_auth = __commonJS({
|
|
|
2068
2078
|
exports2.validateToken = validateToken;
|
|
2069
2079
|
var fs6 = __importStar(require("fs"));
|
|
2070
2080
|
var path7 = __importStar(require("path"));
|
|
2071
|
-
var
|
|
2081
|
+
var os2 = __importStar(require("os"));
|
|
2072
2082
|
var child_process_1 = require("child_process");
|
|
2073
2083
|
var DEFAULT_CONFIG_FILE = "config.json";
|
|
2074
2084
|
function getConfigDir5() {
|
|
2075
|
-
return process.env.EPISODA_CONFIG_DIR || path7.join(
|
|
2085
|
+
return process.env.EPISODA_CONFIG_DIR || path7.join(os2.homedir(), ".episoda");
|
|
2076
2086
|
}
|
|
2077
2087
|
function getConfigPath(configPath) {
|
|
2078
2088
|
if (configPath) {
|
|
@@ -2228,7 +2238,7 @@ var require_package = __commonJS({
|
|
|
2228
2238
|
"package.json"(exports2, module2) {
|
|
2229
2239
|
module2.exports = {
|
|
2230
2240
|
name: "episoda",
|
|
2231
|
-
version: "0.2.
|
|
2241
|
+
version: "0.2.12",
|
|
2232
2242
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2233
2243
|
main: "dist/index.js",
|
|
2234
2244
|
types: "dist/index.d.ts",
|
|
@@ -2283,19 +2293,29 @@ var require_package = __commonJS({
|
|
|
2283
2293
|
});
|
|
2284
2294
|
|
|
2285
2295
|
// src/daemon/machine-id.ts
|
|
2286
|
-
var os = __toESM(require("os"));
|
|
2287
2296
|
var fs = __toESM(require("fs"));
|
|
2288
2297
|
var path = __toESM(require("path"));
|
|
2289
2298
|
var crypto = __toESM(require("crypto"));
|
|
2290
2299
|
var import_child_process = require("child_process");
|
|
2291
2300
|
var import_core = __toESM(require_dist());
|
|
2301
|
+
function isValidUUID(str) {
|
|
2302
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2303
|
+
return uuidRegex.test(str);
|
|
2304
|
+
}
|
|
2292
2305
|
async function getMachineId() {
|
|
2293
2306
|
const machineIdPath = path.join((0, import_core.getConfigDir)(), "machine-id");
|
|
2294
2307
|
try {
|
|
2295
2308
|
if (fs.existsSync(machineIdPath)) {
|
|
2296
|
-
const
|
|
2297
|
-
if (
|
|
2298
|
-
|
|
2309
|
+
const existingId = fs.readFileSync(machineIdPath, "utf-8").trim();
|
|
2310
|
+
if (existingId) {
|
|
2311
|
+
if (isValidUUID(existingId)) {
|
|
2312
|
+
return existingId;
|
|
2313
|
+
}
|
|
2314
|
+
console.log("[MachineId] Migrating legacy machine ID to UUID format...");
|
|
2315
|
+
const newUUID = generateMachineId();
|
|
2316
|
+
fs.writeFileSync(machineIdPath, newUUID, "utf-8");
|
|
2317
|
+
console.log(`[MachineId] Migrated: ${existingId} \u2192 ${newUUID}`);
|
|
2318
|
+
return newUUID;
|
|
2299
2319
|
}
|
|
2300
2320
|
}
|
|
2301
2321
|
} catch (error) {
|
|
@@ -2354,10 +2374,21 @@ function getHardwareUUID() {
|
|
|
2354
2374
|
return crypto.randomUUID();
|
|
2355
2375
|
}
|
|
2356
2376
|
function generateMachineId() {
|
|
2357
|
-
const hostname4 = os.hostname();
|
|
2358
2377
|
const hwUUID = getHardwareUUID();
|
|
2359
|
-
|
|
2360
|
-
|
|
2378
|
+
if (isValidUUID(hwUUID)) {
|
|
2379
|
+
return hwUUID.toLowerCase();
|
|
2380
|
+
}
|
|
2381
|
+
const hash = crypto.createHash("sha256").update(hwUUID).digest("hex");
|
|
2382
|
+
const uuid = [
|
|
2383
|
+
hash.slice(0, 8),
|
|
2384
|
+
hash.slice(8, 12),
|
|
2385
|
+
"4" + hash.slice(13, 16),
|
|
2386
|
+
// Version 4
|
|
2387
|
+
(parseInt(hash.slice(16, 17), 16) & 3 | 8).toString(16) + hash.slice(17, 20),
|
|
2388
|
+
// Variant
|
|
2389
|
+
hash.slice(20, 32)
|
|
2390
|
+
].join("-");
|
|
2391
|
+
return uuid.toLowerCase();
|
|
2361
2392
|
}
|
|
2362
2393
|
|
|
2363
2394
|
// src/daemon/project-tracker.ts
|
|
@@ -2615,97 +2646,6 @@ function performBackgroundUpdate() {
|
|
|
2615
2646
|
}
|
|
2616
2647
|
}
|
|
2617
2648
|
|
|
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
2649
|
// src/daemon/handlers/file-handlers.ts
|
|
2710
2650
|
var fs4 = __toESM(require("fs"));
|
|
2711
2651
|
var path5 = __toESM(require("path"));
|
|
@@ -3172,7 +3112,7 @@ async function handleExec(command, projectPath) {
|
|
|
3172
3112
|
|
|
3173
3113
|
// src/daemon/daemon-process.ts
|
|
3174
3114
|
var fs5 = __toESM(require("fs"));
|
|
3175
|
-
var
|
|
3115
|
+
var os = __toESM(require("os"));
|
|
3176
3116
|
var path6 = __toESM(require("path"));
|
|
3177
3117
|
var packageJson = require_package();
|
|
3178
3118
|
var Daemon = class {
|
|
@@ -3183,8 +3123,7 @@ var Daemon = class {
|
|
|
3183
3123
|
this.deviceName = null;
|
|
3184
3124
|
// EP661: Cached device name from server
|
|
3185
3125
|
this.flyMachineId = null;
|
|
3186
|
-
|
|
3187
|
-
// EP803: Local identity server for browser detection
|
|
3126
|
+
// EP812: Removed identityServer - browser identity now uses cookie-based pairing
|
|
3188
3127
|
this.connections = /* @__PURE__ */ new Map();
|
|
3189
3128
|
// projectPath -> connection
|
|
3190
3129
|
// EP701: Track which connections are currently live (WebSocket open)
|
|
@@ -3208,8 +3147,6 @@ var Daemon = class {
|
|
|
3208
3147
|
}
|
|
3209
3148
|
await this.ipcServer.start();
|
|
3210
3149
|
console.log("[Daemon] IPC server started");
|
|
3211
|
-
this.identityServer = new IdentityServer(this.machineId);
|
|
3212
|
-
await this.identityServer.start();
|
|
3213
3150
|
this.registerIPCHandlers();
|
|
3214
3151
|
await this.restoreConnections();
|
|
3215
3152
|
this.setupShutdownHandlers();
|
|
@@ -3252,9 +3189,9 @@ var Daemon = class {
|
|
|
3252
3189
|
machineId: this.machineId,
|
|
3253
3190
|
deviceId: this.deviceId,
|
|
3254
3191
|
// EP726: UUID for unified device identification
|
|
3255
|
-
hostname:
|
|
3256
|
-
platform:
|
|
3257
|
-
arch:
|
|
3192
|
+
hostname: os.hostname(),
|
|
3193
|
+
platform: os.platform(),
|
|
3194
|
+
arch: os.arch(),
|
|
3258
3195
|
projects
|
|
3259
3196
|
};
|
|
3260
3197
|
});
|
|
@@ -3468,9 +3405,6 @@ var Daemon = class {
|
|
|
3468
3405
|
console.log(`[Daemon] Authenticated for project ${projectId}`);
|
|
3469
3406
|
touchProject(projectPath);
|
|
3470
3407
|
this.liveConnections.add(projectPath);
|
|
3471
|
-
if (this.identityServer) {
|
|
3472
|
-
this.identityServer.setConnected(true);
|
|
3473
|
-
}
|
|
3474
3408
|
const authMessage = message;
|
|
3475
3409
|
if (authMessage.userId && authMessage.workspaceId) {
|
|
3476
3410
|
await this.configureGitUser(projectPath, authMessage.userId, authMessage.workspaceId, this.machineId, projectId, authMessage.deviceId);
|
|
@@ -3497,9 +3431,6 @@ var Daemon = class {
|
|
|
3497
3431
|
const disconnectEvent = event;
|
|
3498
3432
|
console.log(`[Daemon] Connection closed for ${projectId}: code=${disconnectEvent.code}, willReconnect=${disconnectEvent.willReconnect}`);
|
|
3499
3433
|
this.liveConnections.delete(projectPath);
|
|
3500
|
-
if (this.identityServer && this.liveConnections.size === 0) {
|
|
3501
|
-
this.identityServer.setConnected(false);
|
|
3502
|
-
}
|
|
3503
3434
|
if (!disconnectEvent.willReconnect) {
|
|
3504
3435
|
this.connections.delete(projectPath);
|
|
3505
3436
|
console.log(`[Daemon] Removed connection for ${projectPath} from map`);
|
|
@@ -3517,9 +3448,9 @@ var Daemon = class {
|
|
|
3517
3448
|
console.warn(`[Daemon] Could not read daemon PID:`, pidError instanceof Error ? pidError.message : pidError);
|
|
3518
3449
|
}
|
|
3519
3450
|
await client.connect(wsUrl, config.access_token, this.machineId, {
|
|
3520
|
-
hostname:
|
|
3521
|
-
osPlatform:
|
|
3522
|
-
osArch:
|
|
3451
|
+
hostname: os.hostname(),
|
|
3452
|
+
osPlatform: os.platform(),
|
|
3453
|
+
osArch: os.arch(),
|
|
3523
3454
|
daemonPid
|
|
3524
3455
|
});
|
|
3525
3456
|
console.log(`[Daemon] Successfully connected to project ${projectId}`);
|
|
@@ -3678,10 +3609,6 @@ var Daemon = class {
|
|
|
3678
3609
|
await connection.client.disconnect();
|
|
3679
3610
|
}
|
|
3680
3611
|
this.connections.clear();
|
|
3681
|
-
if (this.identityServer) {
|
|
3682
|
-
await this.identityServer.stop();
|
|
3683
|
-
this.identityServer = null;
|
|
3684
|
-
}
|
|
3685
3612
|
await this.ipcServer.stop();
|
|
3686
3613
|
console.log("[Daemon] Shutdown complete");
|
|
3687
3614
|
}
|