@episoda/cli 0.2.158 → 0.2.160
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 +198 -76
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +217 -85
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1653,10 +1653,6 @@ var require_git_executor = __commonJS({
|
|
|
1653
1653
|
};
|
|
1654
1654
|
} catch {
|
|
1655
1655
|
}
|
|
1656
|
-
try {
|
|
1657
|
-
await this.runGitCommand(["fetch", "--all", "--prune"], cwd, options);
|
|
1658
|
-
} catch {
|
|
1659
|
-
}
|
|
1660
1656
|
const args = ["worktree", "add"];
|
|
1661
1657
|
if (command.detach) {
|
|
1662
1658
|
args.push("--detach", command.path);
|
|
@@ -3203,13 +3199,14 @@ async function getDevServerStatus() {
|
|
|
3203
3199
|
}
|
|
3204
3200
|
|
|
3205
3201
|
// src/commands/daemon.ts
|
|
3206
|
-
var
|
|
3202
|
+
var import_child_process5 = require("child_process");
|
|
3207
3203
|
var path6 = __toESM(require("path"));
|
|
3208
3204
|
var fs5 = __toESM(require("fs"));
|
|
3209
3205
|
|
|
3210
3206
|
// src/daemon/worktree-manager.ts
|
|
3211
3207
|
var fs2 = __toESM(require("fs"));
|
|
3212
3208
|
var path3 = __toESM(require("path"));
|
|
3209
|
+
var import_child_process2 = require("child_process");
|
|
3213
3210
|
var import_core3 = __toESM(require_dist());
|
|
3214
3211
|
function validateModuleUid(moduleUid) {
|
|
3215
3212
|
if (!moduleUid || typeof moduleUid !== "string" || !moduleUid.trim()) {
|
|
@@ -3226,6 +3223,38 @@ function validateModuleUid(moduleUid) {
|
|
|
3226
3223
|
}
|
|
3227
3224
|
return true;
|
|
3228
3225
|
}
|
|
3226
|
+
function isValidDefaultBranchName(name) {
|
|
3227
|
+
if (!name || typeof name !== "string") return false;
|
|
3228
|
+
const trimmed = name.trim();
|
|
3229
|
+
if (trimmed !== name) return false;
|
|
3230
|
+
if (name.length > 255) return false;
|
|
3231
|
+
if (name.startsWith("-")) return false;
|
|
3232
|
+
if (name.startsWith("/")) return false;
|
|
3233
|
+
if (name.endsWith("/")) return false;
|
|
3234
|
+
if (name.endsWith(".")) return false;
|
|
3235
|
+
if (name.endsWith(".lock")) return false;
|
|
3236
|
+
if (name.includes("..")) return false;
|
|
3237
|
+
if (name.includes("@{")) return false;
|
|
3238
|
+
if (name.includes("//")) return false;
|
|
3239
|
+
if (name.includes("\\")) return false;
|
|
3240
|
+
if (/[ ~^:?*\[\]\s]/.test(name)) return false;
|
|
3241
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(name)) return false;
|
|
3242
|
+
return true;
|
|
3243
|
+
}
|
|
3244
|
+
function runGit(args, cwd, timeoutMs) {
|
|
3245
|
+
const res = (0, import_child_process2.spawnSync)("git", args, {
|
|
3246
|
+
cwd,
|
|
3247
|
+
encoding: "utf-8",
|
|
3248
|
+
timeout: timeoutMs,
|
|
3249
|
+
windowsHide: true,
|
|
3250
|
+
shell: false
|
|
3251
|
+
});
|
|
3252
|
+
return {
|
|
3253
|
+
success: res.status === 0,
|
|
3254
|
+
stdout: (res.stdout || "").toString(),
|
|
3255
|
+
stderr: (res.stderr || "").toString()
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3229
3258
|
var WorktreeManager = class _WorktreeManager {
|
|
3230
3259
|
constructor(projectRoot) {
|
|
3231
3260
|
// ============================================================
|
|
@@ -3283,22 +3312,24 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3283
3312
|
*/
|
|
3284
3313
|
async ensureFetchRefspecConfigured() {
|
|
3285
3314
|
try {
|
|
3286
|
-
const { execSync: execSync10 } = require("child_process");
|
|
3287
3315
|
let fetchRefspec = null;
|
|
3288
3316
|
try {
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
}).trim();
|
|
3317
|
+
const res = runGit(["config", "--get", "remote.origin.fetch"], this.bareRepoPath, 5e3);
|
|
3318
|
+
if (res.success) {
|
|
3319
|
+
fetchRefspec = res.stdout.trim();
|
|
3320
|
+
}
|
|
3294
3321
|
} catch {
|
|
3295
3322
|
}
|
|
3296
3323
|
if (!fetchRefspec) {
|
|
3297
3324
|
console.log("[WorktreeManager] EP1014: Configuring missing fetch refspec for bare repo");
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3325
|
+
const setRes = runGit(
|
|
3326
|
+
["config", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"],
|
|
3327
|
+
this.bareRepoPath,
|
|
3328
|
+
5e3
|
|
3329
|
+
);
|
|
3330
|
+
if (!setRes.success) {
|
|
3331
|
+
throw new Error(setRes.stderr || "Failed to configure fetch refspec");
|
|
3332
|
+
}
|
|
3302
3333
|
console.log("[WorktreeManager] EP1014: Fetch refspec configured successfully");
|
|
3303
3334
|
}
|
|
3304
3335
|
} catch (error) {
|
|
@@ -3331,11 +3362,44 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3331
3362
|
manager.writeConfig(config);
|
|
3332
3363
|
return manager;
|
|
3333
3364
|
}
|
|
3365
|
+
/**
|
|
3366
|
+
* EP1373: Resolve the default branch name using a 3-level fallback:
|
|
3367
|
+
* 1. Explicit defaultBranch parameter (from project GitHub config)
|
|
3368
|
+
* 2. Git-derived: refs/remotes/origin/HEAD symbolic-ref target
|
|
3369
|
+
* 3. Final fallback: 'main' (with warning)
|
|
3370
|
+
*/
|
|
3371
|
+
async resolveDefaultBranch(explicitDefault) {
|
|
3372
|
+
if (explicitDefault) {
|
|
3373
|
+
if (isValidDefaultBranchName(explicitDefault)) {
|
|
3374
|
+
return explicitDefault;
|
|
3375
|
+
}
|
|
3376
|
+
console.warn(`[WorktreeManager] EP1373: Invalid defaultBranch provided ("${explicitDefault}"), ignoring`);
|
|
3377
|
+
}
|
|
3378
|
+
try {
|
|
3379
|
+
const res = runGit(["symbolic-ref", "refs/remotes/origin/HEAD"], this.bareRepoPath, 5e3);
|
|
3380
|
+
if (!res.success) {
|
|
3381
|
+
throw new Error(res.stderr || "symbolic-ref failed");
|
|
3382
|
+
}
|
|
3383
|
+
const symref = res.stdout.trim();
|
|
3384
|
+
const match = symref.match(/^refs\/remotes\/origin\/(.+)$/);
|
|
3385
|
+
if (match && match[1]) {
|
|
3386
|
+
const derived = match[1];
|
|
3387
|
+
if (isValidDefaultBranchName(derived)) {
|
|
3388
|
+
return derived;
|
|
3389
|
+
}
|
|
3390
|
+
console.warn(`[WorktreeManager] EP1373: Derived default branch from origin/HEAD is invalid ("${derived}"), ignoring`);
|
|
3391
|
+
}
|
|
3392
|
+
} catch {
|
|
3393
|
+
}
|
|
3394
|
+
console.warn('[WorktreeManager] EP1373: Could not resolve default branch, falling back to "main"');
|
|
3395
|
+
return "main";
|
|
3396
|
+
}
|
|
3334
3397
|
/**
|
|
3335
3398
|
* Create a worktree for a module
|
|
3336
3399
|
* The entire operation is locked to prevent race conditions
|
|
3400
|
+
* EP1373: Added defaultBranch parameter for explicit default branch resolution
|
|
3337
3401
|
*/
|
|
3338
|
-
async createWorktree(moduleUid, branchName, createBranch = false) {
|
|
3402
|
+
async createWorktree(moduleUid, branchName, createBranch = false, defaultBranch, correlationId) {
|
|
3339
3403
|
if (!validateModuleUid(moduleUid)) {
|
|
3340
3404
|
return {
|
|
3341
3405
|
success: false,
|
|
@@ -3401,25 +3465,63 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3401
3465
|
console.warn("[WorktreeManager] EP1265: Failed to prune worktrees (continuing):", pruneResult.output);
|
|
3402
3466
|
}
|
|
3403
3467
|
}
|
|
3404
|
-
const
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
};
|
|
3468
|
+
const resolvedDefault = await this.resolveDefaultBranch(defaultBranch);
|
|
3469
|
+
let shouldCreateBranch = createBranch;
|
|
3470
|
+
let startPoint;
|
|
3471
|
+
if (createBranch) {
|
|
3472
|
+
const managerFetchStartMs = Date.now();
|
|
3473
|
+
const fetchResult = await this.gitExecutor.execute({
|
|
3474
|
+
action: "fetch",
|
|
3475
|
+
remote: "origin",
|
|
3476
|
+
branch: `+refs/heads/${resolvedDefault}:refs/remotes/origin/${resolvedDefault}`
|
|
3477
|
+
}, { cwd: this.bareRepoPath });
|
|
3478
|
+
console.log(`[WorktreeManager] EP1373: manager_fetch phase=manager_fetch durationMs=${Date.now() - managerFetchStartMs} moduleUid=${moduleUid} correlationId=${correlationId || "none"} defaultBranch=${resolvedDefault} success=${fetchResult.success}`);
|
|
3479
|
+
if (!fetchResult.success) {
|
|
3480
|
+
console.error("[worktree-manager] Failed to fetch from origin:", fetchResult.output);
|
|
3481
|
+
return {
|
|
3482
|
+
success: false,
|
|
3483
|
+
error: "Failed to fetch latest refs from origin. Cannot create worktree with stale refs."
|
|
3484
|
+
};
|
|
3485
|
+
}
|
|
3486
|
+
startPoint = `origin/${resolvedDefault}`;
|
|
3487
|
+
} else {
|
|
3488
|
+
const existingBranchFetchStartMs = Date.now();
|
|
3489
|
+
const branchFetchResult = await this.gitExecutor.execute({
|
|
3490
|
+
action: "fetch",
|
|
3491
|
+
remote: "origin",
|
|
3492
|
+
branch: `+refs/heads/${branchName}:refs/remotes/origin/${branchName}`
|
|
3493
|
+
}, { cwd: this.bareRepoPath });
|
|
3494
|
+
console.log(`[WorktreeManager] EP1373: existing_branch_fetch phase=existing_branch_fetch durationMs=${Date.now() - existingBranchFetchStartMs} moduleUid=${moduleUid} correlationId=${correlationId || "none"} branch=${branchName} success=${branchFetchResult.success}`);
|
|
3495
|
+
const localBranchExists = runGit(
|
|
3496
|
+
["show-ref", "--verify", `refs/heads/${branchName}`],
|
|
3497
|
+
this.bareRepoPath,
|
|
3498
|
+
5e3
|
|
3499
|
+
).success;
|
|
3500
|
+
const remoteBranchExists = runGit(
|
|
3501
|
+
["show-ref", "--verify", `refs/remotes/origin/${branchName}`],
|
|
3502
|
+
this.bareRepoPath,
|
|
3503
|
+
5e3
|
|
3504
|
+
).success;
|
|
3505
|
+
if (!localBranchExists && remoteBranchExists) {
|
|
3506
|
+
shouldCreateBranch = true;
|
|
3507
|
+
startPoint = `origin/${branchName}`;
|
|
3508
|
+
console.log(`[WorktreeManager] EP1373: remote_only_branch phase=remote_only_branch moduleUid=${moduleUid} correlationId=${correlationId || "none"} branch=${branchName}`);
|
|
3509
|
+
} else if (!localBranchExists && !remoteBranchExists) {
|
|
3510
|
+
return {
|
|
3511
|
+
success: false,
|
|
3512
|
+
error: `Branch "${branchName}" not found locally or on origin`
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3415
3515
|
}
|
|
3516
|
+
const gitWorktreeAddStartMs = Date.now();
|
|
3416
3517
|
const result = await this.gitExecutor.execute({
|
|
3417
3518
|
action: "worktree_add",
|
|
3418
3519
|
path: worktreePath,
|
|
3419
3520
|
branch: branchName,
|
|
3420
|
-
create:
|
|
3421
|
-
startPoint
|
|
3521
|
+
create: shouldCreateBranch,
|
|
3522
|
+
startPoint
|
|
3422
3523
|
}, { cwd: this.bareRepoPath });
|
|
3524
|
+
console.log(`[WorktreeManager] EP1373: git_worktree_add phase=git_worktree_add durationMs=${Date.now() - gitWorktreeAddStartMs} moduleUid=${moduleUid} correlationId=${correlationId || "none"} success=${result.success}`);
|
|
3423
3525
|
if (!result.success) {
|
|
3424
3526
|
return {
|
|
3425
3527
|
success: false,
|
|
@@ -3915,8 +4017,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3915
4017
|
console.log(`[WorktreeManager] EP959: Timeout: ${TIMEOUT_MINUTES} minutes`);
|
|
3916
4018
|
console.log(`[WorktreeManager] EP959: Script: ${scriptPreview}`);
|
|
3917
4019
|
try {
|
|
3918
|
-
const { execSync:
|
|
3919
|
-
|
|
4020
|
+
const { execSync: execSync11 } = require("child_process");
|
|
4021
|
+
execSync11(script, {
|
|
3920
4022
|
cwd: worktree.worktreePath,
|
|
3921
4023
|
stdio: "inherit",
|
|
3922
4024
|
timeout: TIMEOUT_MINUTES * 60 * 1e3,
|
|
@@ -3950,8 +4052,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3950
4052
|
console.log(`[WorktreeManager] EP959: Timeout: ${TIMEOUT_MINUTES} minutes`);
|
|
3951
4053
|
console.log(`[WorktreeManager] EP959: Script: ${scriptPreview}`);
|
|
3952
4054
|
try {
|
|
3953
|
-
const { execSync:
|
|
3954
|
-
|
|
4055
|
+
const { execSync: execSync11 } = require("child_process");
|
|
4056
|
+
execSync11(script, {
|
|
3955
4057
|
cwd: worktree.worktreePath,
|
|
3956
4058
|
stdio: "inherit",
|
|
3957
4059
|
timeout: TIMEOUT_MINUTES * 60 * 1e3,
|
|
@@ -4090,7 +4192,7 @@ async function syncProjectPath(config, projectId, path18) {
|
|
|
4090
4192
|
// src/utils/bootstrap.ts
|
|
4091
4193
|
var fs3 = __toESM(require("fs"));
|
|
4092
4194
|
var path4 = __toESM(require("path"));
|
|
4093
|
-
var
|
|
4195
|
+
var import_child_process3 = require("child_process");
|
|
4094
4196
|
async function extractBootstrapScripts(bareRepoPath, projectPath) {
|
|
4095
4197
|
const scriptsDir = path4.join(projectPath, ".episoda", "scripts");
|
|
4096
4198
|
const scriptPath = path4.join(scriptsDir, "api-helper.sh");
|
|
@@ -4106,7 +4208,7 @@ async function extractBootstrapScripts(bareRepoPath, projectPath) {
|
|
|
4106
4208
|
];
|
|
4107
4209
|
for (const srcPath of scriptPaths) {
|
|
4108
4210
|
try {
|
|
4109
|
-
const scriptContent = (0,
|
|
4211
|
+
const scriptContent = (0, import_child_process3.execSync)(
|
|
4110
4212
|
`git --git-dir="${bareRepoPath}" show main:${srcPath}`,
|
|
4111
4213
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4112
4214
|
);
|
|
@@ -4124,7 +4226,7 @@ async function extractBootstrapScripts(bareRepoPath, projectPath) {
|
|
|
4124
4226
|
var fs4 = __toESM(require("fs"));
|
|
4125
4227
|
var os = __toESM(require("os"));
|
|
4126
4228
|
var path5 = __toESM(require("path"));
|
|
4127
|
-
var
|
|
4229
|
+
var import_child_process4 = require("child_process");
|
|
4128
4230
|
var PROTOCOL_SCHEME = "episoda";
|
|
4129
4231
|
var APP_NAME = "Episoda";
|
|
4130
4232
|
function parseProtocolUrl(rawUrl) {
|
|
@@ -4151,11 +4253,11 @@ function getLinuxDesktopPath() {
|
|
|
4151
4253
|
function resolveBinaryFromPath(name) {
|
|
4152
4254
|
try {
|
|
4153
4255
|
if (process.platform === "win32") {
|
|
4154
|
-
const output2 = (0,
|
|
4256
|
+
const output2 = (0, import_child_process4.execSync)(`where ${name}`, { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
4155
4257
|
const first = output2.split(/\r?\n/)[0];
|
|
4156
4258
|
return first || null;
|
|
4157
4259
|
}
|
|
4158
|
-
const output = (0,
|
|
4260
|
+
const output = (0, import_child_process4.execSync)(`command -v ${name}`, { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
4159
4261
|
return output || null;
|
|
4160
4262
|
} catch {
|
|
4161
4263
|
return null;
|
|
@@ -4264,7 +4366,7 @@ exit 0
|
|
|
4264
4366
|
fs4.writeFileSync(handlerPath, handlerScript, { mode: 493 });
|
|
4265
4367
|
fs4.writeFileSync(infoPlistPath, infoPlist);
|
|
4266
4368
|
const lsregister = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
|
|
4267
|
-
(0,
|
|
4369
|
+
(0, import_child_process4.execSync)(`"${lsregister}" -f "${appPath}"`);
|
|
4268
4370
|
return { success: true, message: "Protocol handler registered for macOS." };
|
|
4269
4371
|
}
|
|
4270
4372
|
if (process.platform === "linux") {
|
|
@@ -4286,7 +4388,7 @@ Terminal=false
|
|
|
4286
4388
|
MimeType=x-scheme-handler/${PROTOCOL_SCHEME};
|
|
4287
4389
|
`;
|
|
4288
4390
|
fs4.writeFileSync(desktopPath, desktopEntry);
|
|
4289
|
-
(0,
|
|
4391
|
+
(0, import_child_process4.execSync)(`xdg-mime default ${path5.basename(desktopPath)} x-scheme-handler/${PROTOCOL_SCHEME}`);
|
|
4290
4392
|
return { success: true, message: "Protocol handler registered for Linux." };
|
|
4291
4393
|
}
|
|
4292
4394
|
if (process.platform === "win32") {
|
|
@@ -4301,9 +4403,9 @@ shell.Run cmd, 0, False
|
|
|
4301
4403
|
`;
|
|
4302
4404
|
fs4.writeFileSync(vbsPath, vbsScript);
|
|
4303
4405
|
const handlerCommand = `wscript.exe "${vbsPath}" "%1"`;
|
|
4304
|
-
(0,
|
|
4305
|
-
(0,
|
|
4306
|
-
(0,
|
|
4406
|
+
(0, import_child_process4.execSync)(`reg add HKCU\\Software\\Classes\\${PROTOCOL_SCHEME} /ve /d "URL:Episoda Protocol" /f`);
|
|
4407
|
+
(0, import_child_process4.execSync)(`reg add HKCU\\Software\\Classes\\${PROTOCOL_SCHEME} /v "URL Protocol" /d "" /f`);
|
|
4408
|
+
(0, import_child_process4.execSync)(`reg add HKCU\\Software\\Classes\\${PROTOCOL_SCHEME}\\shell\\open\\command /ve /d "${handlerCommand}" /f`);
|
|
4307
4409
|
fs4.writeFileSync(marker, JSON.stringify({ registeredAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
4308
4410
|
return { success: true, message: "Protocol handler registered for Windows." };
|
|
4309
4411
|
}
|
|
@@ -4355,7 +4457,7 @@ async function maybeRegisterProtocolHandler() {
|
|
|
4355
4457
|
}
|
|
4356
4458
|
function findGitRoot(startDir) {
|
|
4357
4459
|
try {
|
|
4358
|
-
const result = (0,
|
|
4460
|
+
const result = (0, import_child_process5.execSync)("git rev-parse --show-toplevel", {
|
|
4359
4461
|
cwd: startDir,
|
|
4360
4462
|
encoding: "utf-8",
|
|
4361
4463
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4559,14 +4661,14 @@ Received ${signal}. Daemon continues running in background.`);
|
|
|
4559
4661
|
var os2 = __toESM(require("os"));
|
|
4560
4662
|
var fs7 = __toESM(require("fs"));
|
|
4561
4663
|
var path8 = __toESM(require("path"));
|
|
4562
|
-
var
|
|
4664
|
+
var import_child_process7 = require("child_process");
|
|
4563
4665
|
var import_core6 = __toESM(require_dist());
|
|
4564
4666
|
|
|
4565
4667
|
// src/daemon/machine-id.ts
|
|
4566
4668
|
var fs6 = __toESM(require("fs"));
|
|
4567
4669
|
var path7 = __toESM(require("path"));
|
|
4568
4670
|
var crypto2 = __toESM(require("crypto"));
|
|
4569
|
-
var
|
|
4671
|
+
var import_child_process6 = require("child_process");
|
|
4570
4672
|
var import_core5 = __toESM(require_dist());
|
|
4571
4673
|
function isValidUUID(str) {
|
|
4572
4674
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -4609,7 +4711,7 @@ async function getMachineId() {
|
|
|
4609
4711
|
function getHardwareUUID() {
|
|
4610
4712
|
try {
|
|
4611
4713
|
if (process.platform === "darwin") {
|
|
4612
|
-
const output = (0,
|
|
4714
|
+
const output = (0, import_child_process6.execSync)(
|
|
4613
4715
|
`ioreg -d2 -c IOPlatformExpertDevice | awk -F\\" '/IOPlatformUUID/{print $(NF-1)}'`,
|
|
4614
4716
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4615
4717
|
).trim();
|
|
@@ -4630,7 +4732,7 @@ function getHardwareUUID() {
|
|
|
4630
4732
|
}
|
|
4631
4733
|
}
|
|
4632
4734
|
} else if (process.platform === "win32") {
|
|
4633
|
-
const output = (0,
|
|
4735
|
+
const output = (0, import_child_process6.execSync)("wmic csproduct get uuid", {
|
|
4634
4736
|
encoding: "utf-8",
|
|
4635
4737
|
timeout: 5e3
|
|
4636
4738
|
});
|
|
@@ -5069,7 +5171,7 @@ async function monitorAuthorization(apiUrl, deviceCode, expiresIn) {
|
|
|
5069
5171
|
resolve5(false);
|
|
5070
5172
|
}, expiresIn * 1e3);
|
|
5071
5173
|
const url = `${apiUrl}/api/oauth/authorize-stream?device_code=${deviceCode}`;
|
|
5072
|
-
const curlProcess = (0,
|
|
5174
|
+
const curlProcess = (0, import_child_process7.spawn)("curl", ["-N", url]);
|
|
5073
5175
|
let buffer = "";
|
|
5074
5176
|
curlProcess.stdout.on("data", (chunk) => {
|
|
5075
5177
|
buffer += chunk.toString();
|
|
@@ -5173,7 +5275,7 @@ function openBrowser(url) {
|
|
|
5173
5275
|
break;
|
|
5174
5276
|
}
|
|
5175
5277
|
try {
|
|
5176
|
-
(0,
|
|
5278
|
+
(0, import_child_process7.spawn)(command, args, {
|
|
5177
5279
|
detached: true,
|
|
5178
5280
|
stdio: "ignore"
|
|
5179
5281
|
}).unref();
|
|
@@ -5194,7 +5296,7 @@ async function installGitCredentialHelper(apiUrl) {
|
|
|
5194
5296
|
} catch {
|
|
5195
5297
|
}
|
|
5196
5298
|
try {
|
|
5197
|
-
const allHelpers = (0,
|
|
5299
|
+
const allHelpers = (0, import_child_process7.execSync)("git config --global --get-all credential.helper", {
|
|
5198
5300
|
encoding: "utf8",
|
|
5199
5301
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5200
5302
|
}).trim().split("\n");
|
|
@@ -5203,7 +5305,7 @@ async function installGitCredentialHelper(apiUrl) {
|
|
|
5203
5305
|
}
|
|
5204
5306
|
} catch {
|
|
5205
5307
|
}
|
|
5206
|
-
(0,
|
|
5308
|
+
(0, import_child_process7.execSync)(`git config --global --add credential.helper "${helperPath}"`, {
|
|
5207
5309
|
encoding: "utf8",
|
|
5208
5310
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5209
5311
|
});
|
|
@@ -5247,7 +5349,7 @@ ${exportLine}
|
|
|
5247
5349
|
var os3 = __toESM(require("os"));
|
|
5248
5350
|
var fs8 = __toESM(require("fs"));
|
|
5249
5351
|
var path9 = __toESM(require("path"));
|
|
5250
|
-
var
|
|
5352
|
+
var import_child_process8 = require("child_process");
|
|
5251
5353
|
var import_core7 = __toESM(require_dist());
|
|
5252
5354
|
async function connectCommand(options) {
|
|
5253
5355
|
const { code } = options;
|
|
@@ -5327,7 +5429,7 @@ async function installGitCredentialHelper2(apiUrl) {
|
|
|
5327
5429
|
const scriptContent = generateCredentialHelperScript(apiUrl);
|
|
5328
5430
|
fs8.writeFileSync(helperPath, scriptContent, { mode: 493 });
|
|
5329
5431
|
try {
|
|
5330
|
-
const allHelpers = (0,
|
|
5432
|
+
const allHelpers = (0, import_child_process8.execSync)("git config --global --get-all credential.helper", {
|
|
5331
5433
|
encoding: "utf8",
|
|
5332
5434
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5333
5435
|
}).trim().split("\n");
|
|
@@ -5336,7 +5438,7 @@ async function installGitCredentialHelper2(apiUrl) {
|
|
|
5336
5438
|
}
|
|
5337
5439
|
} catch {
|
|
5338
5440
|
}
|
|
5339
|
-
(0,
|
|
5441
|
+
(0, import_child_process8.execSync)(`git config --global --add credential.helper "${helperPath}"`, {
|
|
5340
5442
|
encoding: "utf8",
|
|
5341
5443
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5342
5444
|
});
|
|
@@ -5377,16 +5479,17 @@ ${exportLine}
|
|
|
5377
5479
|
}
|
|
5378
5480
|
|
|
5379
5481
|
// src/commands/status.ts
|
|
5482
|
+
var import_child_process10 = require("child_process");
|
|
5380
5483
|
var import_core8 = __toESM(require_dist());
|
|
5381
5484
|
|
|
5382
5485
|
// src/utils/update-checker.ts
|
|
5383
|
-
var
|
|
5486
|
+
var import_child_process9 = require("child_process");
|
|
5384
5487
|
var semver = __toESM(require("semver"));
|
|
5385
5488
|
var PACKAGE_NAME = "@episoda/cli";
|
|
5386
5489
|
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
5387
5490
|
function isFileLinkedInstall() {
|
|
5388
5491
|
try {
|
|
5389
|
-
const output = (0,
|
|
5492
|
+
const output = (0, import_child_process9.execSync)(`npm list -g ${PACKAGE_NAME} --json`, {
|
|
5390
5493
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5391
5494
|
timeout: 1e4
|
|
5392
5495
|
}).toString();
|
|
@@ -5430,7 +5533,7 @@ async function checkForUpdates(currentVersion) {
|
|
|
5430
5533
|
}
|
|
5431
5534
|
function performSyncUpdate(targetVersion) {
|
|
5432
5535
|
try {
|
|
5433
|
-
(0,
|
|
5536
|
+
(0, import_child_process9.execSync)(`npm install -g ${PACKAGE_NAME}@${targetVersion}`, {
|
|
5434
5537
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5435
5538
|
timeout: 12e4
|
|
5436
5539
|
// 2 minute timeout
|
|
@@ -5445,12 +5548,12 @@ function performSyncUpdate(targetVersion) {
|
|
|
5445
5548
|
}
|
|
5446
5549
|
async function restartDaemon() {
|
|
5447
5550
|
try {
|
|
5448
|
-
(0,
|
|
5551
|
+
(0, import_child_process9.execSync)("episoda stop", {
|
|
5449
5552
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5450
5553
|
timeout: 1e4
|
|
5451
5554
|
});
|
|
5452
5555
|
await new Promise((resolve5) => setTimeout(resolve5, 1e3));
|
|
5453
|
-
const child = (0,
|
|
5556
|
+
const child = (0, import_child_process9.spawn)("episoda", ["dev"], {
|
|
5454
5557
|
detached: true,
|
|
5455
5558
|
stdio: "ignore",
|
|
5456
5559
|
shell: true
|
|
@@ -5506,7 +5609,7 @@ async function updateAndRestartDaemon(targetVersion) {
|
|
|
5506
5609
|
}
|
|
5507
5610
|
function getInstalledVersion() {
|
|
5508
5611
|
try {
|
|
5509
|
-
const output = (0,
|
|
5612
|
+
const output = (0, import_child_process9.execSync)(`npm list -g ${PACKAGE_NAME} --json`, {
|
|
5510
5613
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5511
5614
|
timeout: 1e4
|
|
5512
5615
|
}).toString();
|
|
@@ -5517,6 +5620,22 @@ function getInstalledVersion() {
|
|
|
5517
5620
|
}
|
|
5518
5621
|
}
|
|
5519
5622
|
|
|
5623
|
+
// src/utils/github-token.ts
|
|
5624
|
+
var INVALID_GITHUB_TOKEN_LITERALS = /* @__PURE__ */ new Set([
|
|
5625
|
+
"${GITHUB_PERSONAL_ACCESS_TOKEN}",
|
|
5626
|
+
"undefined",
|
|
5627
|
+
"null",
|
|
5628
|
+
'""',
|
|
5629
|
+
"''"
|
|
5630
|
+
]);
|
|
5631
|
+
function sanitizeGithubToken(token) {
|
|
5632
|
+
if (token === void 0) return "";
|
|
5633
|
+
const trimmed = token.trim();
|
|
5634
|
+
if (!trimmed) return "";
|
|
5635
|
+
if (INVALID_GITHUB_TOKEN_LITERALS.has(trimmed)) return "";
|
|
5636
|
+
return trimmed;
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5520
5639
|
// src/commands/status.ts
|
|
5521
5640
|
async function statusCommand(options = {}) {
|
|
5522
5641
|
status.info("Checking CLI status...");
|
|
@@ -5648,12 +5767,25 @@ async function statusCommand(options = {}) {
|
|
|
5648
5767
|
}
|
|
5649
5768
|
status.info("");
|
|
5650
5769
|
status.info("MCP Configuration:");
|
|
5651
|
-
|
|
5770
|
+
const envGithubToken = sanitizeGithubToken(process.env.GITHUB_PERSONAL_ACCESS_TOKEN);
|
|
5771
|
+
if (envGithubToken) {
|
|
5652
5772
|
status.success(" \u2713 GitHub MCP token available (GITHUB_PERSONAL_ACCESS_TOKEN is set)");
|
|
5653
5773
|
} else {
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5774
|
+
let ghAuthAvailable = false;
|
|
5775
|
+
try {
|
|
5776
|
+
const ghToken = (0, import_child_process10.execSync)("gh auth token", { encoding: "utf8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
5777
|
+
ghAuthAvailable = ghToken.length > 0;
|
|
5778
|
+
} catch {
|
|
5779
|
+
}
|
|
5780
|
+
if (ghAuthAvailable) {
|
|
5781
|
+
status.success(" \u2713 GitHub MCP token available (via gh auth)");
|
|
5782
|
+
status.info(' The portable launcher (scripts/github-mcp-server.sh) will use "gh auth token" automatically.');
|
|
5783
|
+
} else {
|
|
5784
|
+
status.warning(" \u26A0 GitHub MCP token missing");
|
|
5785
|
+
status.info(' GitHub MCP tools will fail with "Requires authentication".');
|
|
5786
|
+
status.info(" Fix: gh auth login # Authenticate GitHub CLI (recommended)");
|
|
5787
|
+
status.info(" Alt: export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...");
|
|
5788
|
+
}
|
|
5657
5789
|
}
|
|
5658
5790
|
if (options.verify) {
|
|
5659
5791
|
status.info("");
|
|
@@ -6524,7 +6656,7 @@ async function listWorktrees(options) {
|
|
|
6524
6656
|
}
|
|
6525
6657
|
|
|
6526
6658
|
// src/commands/update.ts
|
|
6527
|
-
var
|
|
6659
|
+
var import_child_process11 = require("child_process");
|
|
6528
6660
|
var import_core14 = __toESM(require_dist());
|
|
6529
6661
|
async function isDaemonRunning2() {
|
|
6530
6662
|
try {
|
|
@@ -6536,7 +6668,7 @@ async function isDaemonRunning2() {
|
|
|
6536
6668
|
}
|
|
6537
6669
|
function stopDaemon2() {
|
|
6538
6670
|
try {
|
|
6539
|
-
(0,
|
|
6671
|
+
(0, import_child_process11.execSync)("episoda stop", { stdio: "pipe" });
|
|
6540
6672
|
return true;
|
|
6541
6673
|
} catch {
|
|
6542
6674
|
return false;
|
|
@@ -6544,7 +6676,7 @@ function stopDaemon2() {
|
|
|
6544
6676
|
}
|
|
6545
6677
|
function startDaemon2() {
|
|
6546
6678
|
try {
|
|
6547
|
-
const child = (0,
|
|
6679
|
+
const child = (0, import_child_process11.spawn)("episoda", ["dev"], {
|
|
6548
6680
|
detached: true,
|
|
6549
6681
|
stdio: "ignore",
|
|
6550
6682
|
shell: process.platform === "win32"
|
|
@@ -6557,7 +6689,7 @@ function startDaemon2() {
|
|
|
6557
6689
|
}
|
|
6558
6690
|
function performUpdate(targetVersion) {
|
|
6559
6691
|
try {
|
|
6560
|
-
(0,
|
|
6692
|
+
(0, import_child_process11.execSync)(`npm install -g ${PACKAGE_NAME}@${targetVersion}`, {
|
|
6561
6693
|
stdio: "pipe",
|
|
6562
6694
|
timeout: 12e4
|
|
6563
6695
|
// 2 minute timeout
|
|
@@ -6685,7 +6817,7 @@ async function setupCommand(options = {}) {
|
|
|
6685
6817
|
}
|
|
6686
6818
|
|
|
6687
6819
|
// src/commands/run.ts
|
|
6688
|
-
var
|
|
6820
|
+
var import_child_process12 = require("child_process");
|
|
6689
6821
|
var import_core15 = __toESM(require_dist());
|
|
6690
6822
|
|
|
6691
6823
|
// src/utils/env-cache.ts
|
|
@@ -6843,7 +6975,7 @@ async function runCommand(args, options = {}) {
|
|
|
6843
6975
|
status.info(`Running: ${command} ${commandArgs.join(" ")}`);
|
|
6844
6976
|
status.info("");
|
|
6845
6977
|
}
|
|
6846
|
-
const child = (0,
|
|
6978
|
+
const child = (0, import_child_process12.spawn)(command, commandArgs, {
|
|
6847
6979
|
stdio: "inherit",
|
|
6848
6980
|
env: mergedEnv,
|
|
6849
6981
|
shell: process.platform === "win32"
|
|
@@ -6894,7 +7026,7 @@ function signalToNumber(signal) {
|
|
|
6894
7026
|
}
|
|
6895
7027
|
|
|
6896
7028
|
// src/commands/shell.ts
|
|
6897
|
-
var
|
|
7029
|
+
var import_child_process13 = require("child_process");
|
|
6898
7030
|
var import_core16 = __toESM(require_dist());
|
|
6899
7031
|
async function shellCommand(shell, options = {}) {
|
|
6900
7032
|
const config = await (0, import_core16.loadConfig)();
|
|
@@ -6938,7 +7070,7 @@ async function shellCommand(shell, options = {}) {
|
|
|
6938
7070
|
// Set a marker so users know they're in an episoda shell
|
|
6939
7071
|
EPISODA_SHELL: "1"
|
|
6940
7072
|
};
|
|
6941
|
-
const child = (0,
|
|
7073
|
+
const child = (0, import_child_process13.spawn)(targetShell, [], {
|
|
6942
7074
|
stdio: "inherit",
|
|
6943
7075
|
env: mergedEnv
|
|
6944
7076
|
});
|
|
@@ -7211,19 +7343,19 @@ async function promptForValue(key) {
|
|
|
7211
7343
|
}
|
|
7212
7344
|
|
|
7213
7345
|
// src/commands/migrations.ts
|
|
7214
|
-
var
|
|
7346
|
+
var import_child_process14 = require("child_process");
|
|
7215
7347
|
var import_util = require("util");
|
|
7216
7348
|
var import_path = __toESM(require("path"));
|
|
7217
|
-
var exec = (0, import_util.promisify)(
|
|
7349
|
+
var exec = (0, import_util.promisify)(import_child_process14.exec);
|
|
7218
7350
|
function getDefaultMigrationDir() {
|
|
7219
7351
|
return process.env.EPISODA_MIGRATION_DIR || "supabase/migrations";
|
|
7220
7352
|
}
|
|
7221
|
-
async function
|
|
7353
|
+
async function runGit2(command, cwd) {
|
|
7222
7354
|
const { stdout } = await exec(command, { cwd, maxBuffer: 1024 * 1024 * 10 });
|
|
7223
7355
|
return stdout.trim();
|
|
7224
7356
|
}
|
|
7225
7357
|
async function getRepoRoot() {
|
|
7226
|
-
return
|
|
7358
|
+
return runGit2("git rev-parse --show-toplevel", process.cwd());
|
|
7227
7359
|
}
|
|
7228
7360
|
function parseBaseRef(baseRef) {
|
|
7229
7361
|
const parts = baseRef.split("/");
|
|
@@ -7261,17 +7393,17 @@ async function getMigrationConflicts(options) {
|
|
|
7261
7393
|
if (options.fetch) {
|
|
7262
7394
|
const { remote, ref } = parseBaseRef(options.baseRef);
|
|
7263
7395
|
if (remote && ref) {
|
|
7264
|
-
await
|
|
7396
|
+
await runGit2(`git fetch ${remote} ${ref}`, repoRoot);
|
|
7265
7397
|
} else if (ref) {
|
|
7266
|
-
await
|
|
7398
|
+
await runGit2(`git fetch origin ${ref}`, repoRoot);
|
|
7267
7399
|
}
|
|
7268
7400
|
}
|
|
7269
|
-
const mainFilesOutput = await
|
|
7401
|
+
const mainFilesOutput = await runGit2(
|
|
7270
7402
|
`git ls-tree -r --name-only ${options.baseRef} ${options.migrationDir}`,
|
|
7271
7403
|
repoRoot
|
|
7272
7404
|
);
|
|
7273
7405
|
const mainFiles = mainFilesOutput.split("\n").filter(Boolean);
|
|
7274
|
-
const diffOutput = await
|
|
7406
|
+
const diffOutput = await runGit2(
|
|
7275
7407
|
`git diff --name-status ${options.baseRef}...HEAD -- ${options.migrationDir}`,
|
|
7276
7408
|
repoRoot
|
|
7277
7409
|
);
|
|
@@ -7409,15 +7541,15 @@ async function migrationsFixCommand(options) {
|
|
|
7409
7541
|
return;
|
|
7410
7542
|
}
|
|
7411
7543
|
for (const entry of renamePlan) {
|
|
7412
|
-
await
|
|
7544
|
+
await runGit2(`git mv "${entry.from}" "${entry.to}"`, repoRoot);
|
|
7413
7545
|
}
|
|
7414
7546
|
if (options.commit || options.push) {
|
|
7415
7547
|
const message = options.message || "Fix migration ordering conflicts";
|
|
7416
|
-
await
|
|
7417
|
-
await
|
|
7548
|
+
await runGit2("git add --all", repoRoot);
|
|
7549
|
+
await runGit2(`git commit -m "${message}"`, repoRoot);
|
|
7418
7550
|
}
|
|
7419
7551
|
if (options.push) {
|
|
7420
|
-
await
|
|
7552
|
+
await runGit2("git push", repoRoot);
|
|
7421
7553
|
}
|
|
7422
7554
|
status.success("Migration conflicts fixed.");
|
|
7423
7555
|
}
|