episoda 0.2.22 → 0.2.24

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.
@@ -537,6 +537,24 @@ var require_git_executor = __commonJS({
537
537
  * Execute status command
538
538
  */
539
539
  async executeStatus(cwd, options) {
540
+ try {
541
+ const isBareResult = await execAsync2("git rev-parse --is-bare-repository", { cwd, timeout: 5e3 });
542
+ if (isBareResult.stdout.trim() === "true") {
543
+ const headResult = await execAsync2("git symbolic-ref --short HEAD", { cwd, timeout: 5e3 });
544
+ const branchName = headResult.stdout.trim();
545
+ return {
546
+ success: true,
547
+ output: `## ${branchName}`,
548
+ details: {
549
+ uncommittedFiles: [],
550
+ // No working tree in bare repo
551
+ branchName,
552
+ currentBranch: branchName
553
+ }
554
+ };
555
+ }
556
+ } catch {
557
+ }
540
558
  const result = await this.runGitCommand(["status", "--porcelain", "-b"], cwd, options);
541
559
  if (result.success && result.output) {
542
560
  const statusInfo = (0, git_parser_1.parseGitStatus)(result.output);
@@ -1868,7 +1886,6 @@ var require_git_executor = __commonJS({
1868
1886
  const fs14 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
1869
1887
  const path15 = await Promise.resolve().then(() => __importStar(require("path")));
1870
1888
  let currentPath = cwd;
1871
- let worktreeMode = false;
1872
1889
  let projectPath = cwd;
1873
1890
  let bareRepoPath;
1874
1891
  for (let i = 0; i < 10; i++) {
@@ -1877,7 +1894,6 @@ var require_git_executor = __commonJS({
1877
1894
  try {
1878
1895
  await fs14.access(bareDir);
1879
1896
  await fs14.access(episodaDir);
1880
- worktreeMode = true;
1881
1897
  projectPath = currentPath;
1882
1898
  bareRepoPath = bareDir;
1883
1899
  break;
@@ -1891,9 +1907,8 @@ var require_git_executor = __commonJS({
1891
1907
  }
1892
1908
  return {
1893
1909
  success: true,
1894
- output: worktreeMode ? "Worktree mode project" : "Standard git project",
1910
+ output: bareRepoPath ? "Episoda project" : "Git repository",
1895
1911
  details: {
1896
- worktreeMode,
1897
1912
  projectPath,
1898
1913
  bareRepoPath
1899
1914
  }
@@ -2681,7 +2696,7 @@ var require_package = __commonJS({
2681
2696
  "package.json"(exports2, module2) {
2682
2697
  module2.exports = {
2683
2698
  name: "episoda",
2684
- version: "0.2.21",
2699
+ version: "0.2.23",
2685
2700
  description: "CLI tool for Episoda local development workflow orchestration",
2686
2701
  main: "dist/index.js",
2687
2702
  types: "dist/index.d.ts",
@@ -2883,9 +2898,6 @@ function addProject(projectId, projectPath, options) {
2883
2898
  if (existingByPath) {
2884
2899
  existingByPath.id = projectId;
2885
2900
  existingByPath.last_active = now;
2886
- if (options?.worktreeMode !== void 0) {
2887
- existingByPath.worktreeMode = options.worktreeMode;
2888
- }
2889
2901
  if (options?.bareRepoPath) {
2890
2902
  existingByPath.bareRepoPath = options.bareRepoPath;
2891
2903
  }
@@ -2905,8 +2917,7 @@ function addProject(projectId, projectPath, options) {
2905
2917
  name: projectName,
2906
2918
  added_at: now,
2907
2919
  last_active: now,
2908
- // EP944: Worktree mode fields
2909
- worktreeMode: options?.worktreeMode,
2920
+ // EP971: Bare repo path for worktree architecture
2910
2921
  bareRepoPath: options?.bareRepoPath
2911
2922
  };
2912
2923
  data.projects.push(newProject);
@@ -5447,7 +5458,8 @@ var WorktreeManager = class _WorktreeManager {
5447
5458
  }
5448
5459
  /**
5449
5460
  * Initialize worktree manager from existing project root
5450
- * @returns true if valid worktree project, false otherwise
5461
+ * EP971: All projects use worktree architecture
5462
+ * @returns true if valid project, false otherwise
5451
5463
  */
5452
5464
  async initialize() {
5453
5465
  if (!fs11.existsSync(this.bareRepoPath)) {
@@ -5458,7 +5470,7 @@ var WorktreeManager = class _WorktreeManager {
5458
5470
  }
5459
5471
  try {
5460
5472
  const config = this.readConfig();
5461
- return config?.worktreeMode === true;
5473
+ return config !== null;
5462
5474
  } catch {
5463
5475
  return false;
5464
5476
  }
@@ -5483,7 +5495,6 @@ var WorktreeManager = class _WorktreeManager {
5483
5495
  workspaceSlug,
5484
5496
  projectSlug,
5485
5497
  bareRepoPath: manager.bareRepoPath,
5486
- worktreeMode: true,
5487
5498
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5488
5499
  worktrees: []
5489
5500
  };
@@ -6163,6 +6174,28 @@ async function fetchWithAuth(url, options = {}, retryOnUnauthorized = true) {
6163
6174
  }
6164
6175
  return response;
6165
6176
  }
6177
+ async function fetchEnvVars() {
6178
+ try {
6179
+ const config = await (0, import_core10.loadConfig)();
6180
+ if (!config?.project_id) {
6181
+ console.warn("[Daemon] EP973: No project_id in config, cannot fetch env vars");
6182
+ return {};
6183
+ }
6184
+ const apiUrl = config.api_url || "https://episoda.dev";
6185
+ const response = await fetchWithAuth(`${apiUrl}/api/cli/env-vars`);
6186
+ if (!response.ok) {
6187
+ console.warn(`[Daemon] EP973: Failed to fetch env vars: ${response.status}`);
6188
+ return {};
6189
+ }
6190
+ const data = await response.json();
6191
+ const envVars = data.env_vars || {};
6192
+ console.log(`[Daemon] EP973: Fetched ${Object.keys(envVars).length} env vars from server`);
6193
+ return envVars;
6194
+ } catch (error) {
6195
+ console.warn("[Daemon] EP973: Error fetching env vars:", error instanceof Error ? error.message : error);
6196
+ return {};
6197
+ }
6198
+ }
6166
6199
  var Daemon = class _Daemon {
6167
6200
  // 60 seconds
6168
6201
  constructor() {
@@ -6569,9 +6602,12 @@ var Daemon = class _Daemon {
6569
6602
  client.updateActivity();
6570
6603
  try {
6571
6604
  const gitCmd = message.command;
6572
- const cwd = gitCmd.worktreePath || projectPath;
6605
+ const bareRepoPath = path14.join(projectPath, ".bare");
6606
+ const cwd = gitCmd.worktreePath || bareRepoPath;
6573
6607
  if (gitCmd.worktreePath) {
6574
- console.log(`[Daemon] EP944: Routing command to worktree: ${gitCmd.worktreePath}`);
6608
+ console.log(`[Daemon] Routing command to worktree: ${gitCmd.worktreePath}`);
6609
+ } else {
6610
+ console.log(`[Daemon] Running git command in bare repo: ${bareRepoPath}`);
6575
6611
  }
6576
6612
  const result = await gitExecutor.execute(gitCmd, {
6577
6613
  cwd
@@ -6674,7 +6710,27 @@ var Daemon = class _Daemon {
6674
6710
  const tunnelManager = getTunnelManager();
6675
6711
  let result;
6676
6712
  if (cmd.action === "start") {
6677
- const port = cmd.port || detectDevPort(projectPath);
6713
+ const worktree = await getWorktreeInfoForModule(cmd.moduleUid);
6714
+ if (!worktree) {
6715
+ console.error(`[Daemon] EP973: Cannot resolve worktree path for ${cmd.moduleUid}`);
6716
+ await client.send({
6717
+ type: "tunnel_result",
6718
+ commandId: message.id,
6719
+ result: { success: false, error: "Cannot resolve worktree path - missing config slugs" }
6720
+ });
6721
+ return;
6722
+ }
6723
+ if (!worktree.exists) {
6724
+ console.error(`[Daemon] EP973: Worktree not found at ${worktree.path}`);
6725
+ await client.send({
6726
+ type: "tunnel_result",
6727
+ commandId: message.id,
6728
+ result: { success: false, error: `Worktree not found at ${worktree.path}` }
6729
+ });
6730
+ return;
6731
+ }
6732
+ console.log(`[Daemon] EP973: Using worktree path ${worktree.path} for ${cmd.moduleUid}`);
6733
+ const port = cmd.port || detectDevPort(worktree.path);
6678
6734
  const previewUrl = `https://${cmd.moduleUid.toLowerCase()}-${cmd.projectUid.toLowerCase()}.episoda.site`;
6679
6735
  const reportTunnelStatus = async (data) => {
6680
6736
  const config2 = await (0, import_core10.loadConfig)();
@@ -6709,8 +6765,10 @@ var Daemon = class _Daemon {
6709
6765
  });
6710
6766
  try {
6711
6767
  await tunnelManager.initialize();
6712
- console.log(`[Daemon] Ensuring dev server is running on port ${port}...`);
6713
- const devServerResult = await ensureDevServer(projectPath, port, cmd.moduleUid);
6768
+ const devConfig = await (0, import_core10.loadConfig)();
6769
+ const devServerScript = devConfig?.project_settings?.worktree_dev_server_script;
6770
+ console.log(`[Daemon] EP973: Ensuring dev server is running in ${worktree.path} on port ${port}...`);
6771
+ const devServerResult = await ensureDevServer(worktree.path, port, cmd.moduleUid, devServerScript);
6714
6772
  if (!devServerResult.success) {
6715
6773
  const errorMsg2 = `Dev server failed to start: ${devServerResult.error}`;
6716
6774
  console.error(`[Daemon] ${errorMsg2}`);
@@ -7041,17 +7099,18 @@ var Daemon = class _Daemon {
7041
7099
  }
7042
7100
  const worktreeConfig = await (0, import_core10.loadConfig)();
7043
7101
  const setupConfig = worktreeConfig?.project_settings;
7044
- const hasEnvVars = setupConfig?.worktree_env_vars && Object.keys(setupConfig.worktree_env_vars).length > 0;
7102
+ const envVars = await fetchEnvVars();
7103
+ const hasEnvVars = Object.keys(envVars).length > 0;
7045
7104
  if (setupConfig?.worktree_copy_files?.length || setupConfig?.worktree_setup_script || hasEnvVars) {
7046
7105
  console.log(`[Daemon] EP959: Starting async worktree setup for ${moduleUid}`);
7047
7106
  await worktreeManager.updateWorktreeStatus(moduleUid, "pending");
7048
7107
  this.runWorktreeSetupAsync(
7049
7108
  moduleUid,
7050
7109
  worktreeManager,
7051
- setupConfig.worktree_copy_files || [],
7052
- setupConfig.worktree_setup_script,
7110
+ setupConfig?.worktree_copy_files || [],
7111
+ setupConfig?.worktree_setup_script,
7053
7112
  worktree.path,
7054
- setupConfig.worktree_env_vars || {}
7113
+ envVars
7055
7114
  ).then(() => {
7056
7115
  console.log(`[Daemon] EP959: Setup complete for ${moduleUid}, starting tunnel`);
7057
7116
  this.startTunnelForModule(moduleUid, worktree.path);
@@ -7345,22 +7404,31 @@ var Daemon = class _Daemon {
7345
7404
  const data = await response.json();
7346
7405
  const serverSettings = data.settings;
7347
7406
  if (serverSettings) {
7348
- const envVars = serverSettings.worktree_env_vars || {};
7407
+ const projectSlug = data.project_slug || config.project_slug;
7408
+ const workspaceSlug = data.workspace_slug || config.workspace_slug;
7409
+ if (data.project_slug && !config.project_slug) {
7410
+ console.log(`[Daemon] EP973: Synced project_slug: ${data.project_slug}`);
7411
+ }
7412
+ if (data.workspace_slug && !config.workspace_slug) {
7413
+ console.log(`[Daemon] EP973: Synced workspace_slug: ${data.workspace_slug}`);
7414
+ }
7349
7415
  const updatedConfig = {
7350
7416
  ...config,
7417
+ // EP973: Include synced slugs
7418
+ project_slug: projectSlug,
7419
+ workspace_slug: workspaceSlug,
7351
7420
  project_settings: {
7352
7421
  ...config.project_settings,
7353
7422
  worktree_setup_script: serverSettings.worktree_setup_script,
7354
7423
  worktree_cleanup_script: serverSettings.worktree_cleanup_script,
7355
7424
  worktree_dev_server_script: serverSettings.worktree_dev_server_script,
7356
- worktree_env_vars: envVars,
7357
7425
  // Keep deprecated field for backward compatibility
7358
7426
  worktree_copy_files: serverSettings.worktree_copy_files,
7359
7427
  cached_at: Date.now()
7360
7428
  }
7361
7429
  };
7362
7430
  await (0, import_core10.saveConfig)(updatedConfig);
7363
- console.log(`[Daemon] EP964: Project settings synced (env_vars: ${Object.keys(envVars).length} keys)`);
7431
+ console.log(`[Daemon] EP973: Project settings synced (slugs: ${projectSlug}/${workspaceSlug})`);
7364
7432
  }
7365
7433
  } catch (error) {
7366
7434
  console.warn("[Daemon] EP964: Failed to sync project settings:", error instanceof Error ? error.message : error);
@@ -7937,14 +8005,13 @@ var Daemon = class _Daemon {
7937
8005
  } catch (e) {
7938
8006
  console.warn(`[Daemon] EP833: Failed to fetch module details for project lookup`);
7939
8007
  }
7940
- const trackedProjects = getAllProjects();
7941
- let project = projectId ? trackedProjects.find((p) => p.id === projectId) : trackedProjects[0];
7942
- if (!project && trackedProjects.length > 0) {
7943
- project = trackedProjects[0];
7944
- console.warn(`[Daemon] EP833: Could not find project ${projectId}, using fallback`);
8008
+ const worktree = await getWorktreeInfoForModule(moduleUid);
8009
+ if (!worktree) {
8010
+ console.error(`[Daemon] EP973: Cannot resolve worktree path for ${moduleUid} - missing config slugs`);
8011
+ return;
7945
8012
  }
7946
- if (!project) {
7947
- console.error(`[Daemon] EP833: No project found for tunnel restart`);
8013
+ if (!worktree.exists) {
8014
+ console.error(`[Daemon] EP973: Worktree not found at ${worktree.path}`);
7948
8015
  return;
7949
8016
  }
7950
8017
  const { isPortInUse: isPortInUse2 } = await Promise.resolve().then(() => (init_port_check(), port_check_exports));
@@ -7956,7 +8023,8 @@ var Daemon = class _Daemon {
7956
8023
  await killProcessOnPort(port);
7957
8024
  }
7958
8025
  }
7959
- const startResult2 = await ensureDevServer(project.path, port, moduleUid);
8026
+ const devServerScript = config.project_settings?.worktree_dev_server_script;
8027
+ const startResult2 = await ensureDevServer(worktree.path, port, moduleUid, devServerScript);
7960
8028
  if (!startResult2.success) {
7961
8029
  console.error(`[Daemon] EP932: Failed to start dev server: ${startResult2.error}`);
7962
8030
  return;