@episoda/cli 0.2.159 → 0.2.161

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.
@@ -2909,7 +2909,7 @@ var require_package = __commonJS({
2909
2909
  "package.json"(exports2, module2) {
2910
2910
  module2.exports = {
2911
2911
  name: "@episoda/cli",
2912
- version: "0.2.159",
2912
+ version: "0.2.161",
2913
2913
  description: "CLI tool for Episoda local development workflow orchestration",
2914
2914
  main: "dist/index.js",
2915
2915
  types: "dist/index.d.ts",
@@ -6410,6 +6410,24 @@ var path10 = __toESM(require("path"));
6410
6410
  var fs9 = __toESM(require("fs"));
6411
6411
  var os4 = __toESM(require("os"));
6412
6412
  var import_core8 = __toESM(require_dist());
6413
+
6414
+ // src/utils/github-token.ts
6415
+ var INVALID_GITHUB_TOKEN_LITERALS = /* @__PURE__ */ new Set([
6416
+ "${GITHUB_PERSONAL_ACCESS_TOKEN}",
6417
+ "undefined",
6418
+ "null",
6419
+ '""',
6420
+ "''"
6421
+ ]);
6422
+ function sanitizeGithubToken(token) {
6423
+ if (token === void 0) return "";
6424
+ const trimmed = token.trim();
6425
+ if (!trimmed) return "";
6426
+ if (INVALID_GITHUB_TOKEN_LITERALS.has(trimmed)) return "";
6427
+ return trimmed;
6428
+ }
6429
+
6430
+ // src/agent/mcp-server-configurator.ts
6413
6431
  var McpServerConfigurator = class {
6414
6432
  // ---------------------------------------------------------------------------
6415
6433
  // MCP Auth Resolution
@@ -6479,10 +6497,10 @@ var McpServerConfigurator = class {
6479
6497
  }
6480
6498
  servers.push({
6481
6499
  name: "github",
6482
- command: "npx -y @modelcontextprotocol/server-github"
6500
+ command: "bash scripts/github-mcp-server.sh"
6483
6501
  });
6484
- if (!session.credentials.githubToken) {
6485
- console.warn("[McpServerConfigurator] EP1296: GitHub MCP registered without token (githubToken missing)");
6502
+ if (!sanitizeGithubToken(session.credentials.githubToken)) {
6503
+ console.warn('[McpServerConfigurator] EP1377: GitHub MCP registered without token \u2014 GitHub tools may fail with "Requires authentication"');
6486
6504
  } else {
6487
6505
  console.log("[McpServerConfigurator] EP1251: GitHub MCP server registered");
6488
6506
  }
@@ -7369,9 +7387,10 @@ ${message}`;
7369
7387
  if (sessionToken) {
7370
7388
  episodaMcpEnv.EPISODA_SESSION_TOKEN = sessionToken;
7371
7389
  }
7390
+ const githubToken = sanitizeGithubToken(session.credentials.githubToken);
7372
7391
  const githubMcpEnv = {
7373
7392
  ...baseEnv,
7374
- GITHUB_PERSONAL_ACCESS_TOKEN: session.credentials.githubToken || ""
7393
+ GITHUB_PERSONAL_ACCESS_TOKEN: githubToken
7375
7394
  };
7376
7395
  for (const mcpServer of mcpServersToRegister) {
7377
7396
  const parts = mcpServer.command.split(" ");
@@ -7506,10 +7525,7 @@ ${message}`;
7506
7525
  const args2 = parts.slice(1);
7507
7526
  let env;
7508
7527
  if (server.name === "github") {
7509
- env = {
7510
- ...baseEnv,
7511
- GITHUB_PERSONAL_ACCESS_TOKEN: session.credentials.githubToken || ""
7512
- };
7528
+ env = { ...baseEnv };
7513
7529
  } else {
7514
7530
  env = {
7515
7531
  ...baseEnv,
@@ -7629,9 +7645,10 @@ ${message}`;
7629
7645
  console.warn("[AgentManager] EP1287: No session token available for MCP servers");
7630
7646
  }
7631
7647
  }
7632
- if (session.credentials.githubToken) {
7633
- envVars.GITHUB_PERSONAL_ACCESS_TOKEN = session.credentials.githubToken;
7634
- console.log("[AgentManager] EP1251: Set GITHUB_PERSONAL_ACCESS_TOKEN for GitHub MCP");
7648
+ const processGithubToken = sanitizeGithubToken(session.credentials.githubToken);
7649
+ if (processGithubToken) {
7650
+ envVars.GITHUB_PERSONAL_ACCESS_TOKEN = processGithubToken;
7651
+ console.log("[AgentManager] EP1377: Set GITHUB_PERSONAL_ACCESS_TOKEN for GitHub MCP");
7635
7652
  }
7636
7653
  if (useApiKey && session.credentials.apiKey) {
7637
7654
  if (provider === "codex") {
@@ -11497,45 +11514,6 @@ function getPreviewManager() {
11497
11514
  var import_core13 = __toESM(require_dist());
11498
11515
 
11499
11516
  // src/api/worktree-api.ts
11500
- async function updateWorktree(config, request2) {
11501
- const machineUuid = config.machine_uuid || config.device_id;
11502
- if (!machineUuid || !config.access_token) {
11503
- console.debug("[WorktreeAPI] updateWorktree: no machineUuid or access_token");
11504
- return false;
11505
- }
11506
- const serverUrl = config.api_url || "https://episoda.dev";
11507
- const url = `${serverUrl}/api/dev/worktrees`;
11508
- try {
11509
- const response = await fetch(url, {
11510
- method: "POST",
11511
- headers: {
11512
- "Authorization": `Bearer ${config.access_token}`,
11513
- "Content-Type": "application/json"
11514
- },
11515
- body: JSON.stringify({
11516
- module_id: request2.moduleId,
11517
- // EP1143: For cloud containers, use container_id; for local, use machine_id
11518
- local_machine_id: process.env.EPISODA_MODE === "cloud" ? void 0 : machineUuid,
11519
- cloud_container_id: process.env.EPISODA_MODE === "cloud" ? process.env.EPISODA_CONTAINER_ID : void 0,
11520
- worktree_path: request2.worktreePath,
11521
- branch_name: request2.branchName,
11522
- status: request2.status,
11523
- port: request2.port,
11524
- preview_url: request2.previewUrl,
11525
- error: request2.error
11526
- })
11527
- });
11528
- if (!response.ok) {
11529
- const text = await response.text();
11530
- console.debug(`[WorktreeAPI] updateWorktree failed: ${response.status} ${text}`);
11531
- return false;
11532
- }
11533
- return true;
11534
- } catch (error) {
11535
- console.debug(`[WorktreeAPI] updateWorktree network error:`, error);
11536
- return false;
11537
- }
11538
- }
11539
11517
  async function deleteWorktree(config, moduleUid) {
11540
11518
  const machineUuid = config.machine_uuid || config.device_id;
11541
11519
  if (!machineUuid || !config.access_token) {
@@ -11826,7 +11804,7 @@ async function handleWorktreeCreate(request2) {
11826
11804
  console.log(`[Worktree] K1273: Clone successful`);
11827
11805
  await execAsync2(`git -C "${bareRepoPath}" config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"`, { env: gitEnv });
11828
11806
  const configPath = path23.join(episodaDir, "config.json");
11829
- const config2 = {
11807
+ const config = {
11830
11808
  projectId,
11831
11809
  workspaceSlug,
11832
11810
  projectSlug,
@@ -11834,7 +11812,7 @@ async function handleWorktreeCreate(request2) {
11834
11812
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
11835
11813
  worktrees: []
11836
11814
  };
11837
- fs22.writeFileSync(configPath, JSON.stringify(config2, null, 2), "utf-8");
11815
+ fs22.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
11838
11816
  console.log(`[Worktree] K1273: Project initialized at ${projectPath}`);
11839
11817
  } catch (cloneError) {
11840
11818
  console.error(`[Worktree] K1273: Git clone failed: ${cloneError.message}`);
@@ -11865,18 +11843,8 @@ async function handleWorktreeCreate(request2) {
11865
11843
  const worktreePath = result.worktreePath;
11866
11844
  console.log(`[Worktree] EP1373: worktree_add phase=worktree_add durationMs=${Date.now() - worktreeAddStartMs} moduleUid=${moduleUid} correlationId=${correlationId || "none"}`);
11867
11845
  console.log(`[Worktree] EP1143: Worktree created at ${worktreePath}`);
11868
- const config = await getConfigForApi();
11869
11846
  let finalStatus = "ready";
11870
11847
  let finalError;
11871
- if (config?.access_token) {
11872
- await updateWorktree(config, {
11873
- moduleId,
11874
- worktreePath,
11875
- branchName,
11876
- status: "pending"
11877
- }).catch(() => {
11878
- });
11879
- }
11880
11848
  if (envVars && Object.keys(envVars).length > 0) {
11881
11849
  const envContent = Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n");
11882
11850
  const envPath = path23.join(worktreePath, ".env");
@@ -11897,15 +11865,6 @@ ${buildCmd}` : buildCmd;
11897
11865
  if (effectiveSetupScript) {
11898
11866
  const setupStartMs = Date.now();
11899
11867
  await manager.updateWorktreeStatus(moduleUid, "setup");
11900
- if (config?.access_token) {
11901
- await updateWorktree(config, {
11902
- moduleId,
11903
- worktreePath,
11904
- branchName,
11905
- status: "setup"
11906
- }).catch(() => {
11907
- });
11908
- }
11909
11868
  console.log(`[Worktree] EP1143: Running setup script...`);
11910
11869
  const scriptResult = await manager.runSetupScript(moduleUid, effectiveSetupScript);
11911
11870
  console.log(`[Worktree] EP1373: setup_script phase=worktree_setup durationMs=${Date.now() - setupStartMs} moduleUid=${moduleUid} correlationId=${correlationId || "none"} success=${scriptResult.success}`);
@@ -11948,33 +11907,15 @@ ${buildCmd}` : buildCmd;
11948
11907
  } else if (finalStatus === "ready" && isCloud) {
11949
11908
  console.log(`[Worktree] EP1262: Skipping preview start in cloud mode (server orchestrates)`);
11950
11909
  }
11951
- if (config?.access_token) {
11952
- try {
11953
- const updated = await updateWorktree(config, {
11954
- moduleId,
11955
- worktreePath,
11956
- branchName,
11957
- status: finalStatus,
11958
- port,
11959
- previewUrl,
11960
- error: finalError
11961
- });
11962
- if (updated) {
11963
- console.log(`[Worktree] EP1143: Updated worktrees table with status '${finalStatus}'`);
11964
- } else {
11965
- console.warn(`[Worktree] EP1143: Failed to update worktrees table`);
11966
- }
11967
- } catch (apiError) {
11968
- console.error(`[Worktree] EP1143: Failed to update worktrees table: ${apiError.message}`);
11969
- }
11970
- }
11971
11910
  console.log(`[Worktree] EP1373: worktree_create_total phase=worktree_create_total durationMs=${Date.now() - worktreeStartMs} moduleUid=${moduleUid} correlationId=${correlationId || "none"} status=${finalStatus}`);
11972
11911
  console.log(`[Worktree] EP1143: Worktree ready for ${moduleUid}`);
11973
11912
  return {
11974
11913
  success: true,
11975
11914
  worktreePath,
11976
11915
  previewUrl,
11977
- port
11916
+ port,
11917
+ status: finalStatus,
11918
+ error: finalError
11978
11919
  };
11979
11920
  } catch (error) {
11980
11921
  console.error(`[Worktree] EP1143: Create failed: ${error.message}`);
@@ -14349,9 +14290,9 @@ var Daemon = class _Daemon {
14349
14290
  });
14350
14291
  if (!process.env.EPISODA_CONTAINER_ID) {
14351
14292
  if (process.env.GITHUB_PERSONAL_ACCESS_TOKEN) {
14352
- console.log("[Daemon] EP1365: GITHUB_PERSONAL_ACCESS_TOKEN is set in environment");
14293
+ console.log("[Daemon] EP1377: GITHUB_PERSONAL_ACCESS_TOKEN is set in environment");
14353
14294
  } else {
14354
- console.warn("[Daemon] EP1365: GITHUB_PERSONAL_ACCESS_TOKEN not set - GitHub MCP tools in local dev may fail");
14295
+ console.log("[Daemon] EP1377: GITHUB_PERSONAL_ACCESS_TOKEN not set in daemon env (OK - daemon sessions inject token via credentials, local CLI uses scripts/github-mcp-server.sh)");
14355
14296
  }
14356
14297
  }
14357
14298
  this.updateManager.checkOnStartup();