episoda 0.2.101 → 0.2.102

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/index.js CHANGED
@@ -3977,40 +3977,54 @@ async function daemonCommand(options = {}) {
3977
3977
  await new Promise((resolve5) => setTimeout(resolve5, 2e3));
3978
3978
  }
3979
3979
  }
3980
- let projectPath;
3981
- const serverPath = await fetchProjectPath(config, config.project_id);
3982
- if (serverPath && fs4.existsSync(serverPath)) {
3983
- projectPath = serverPath;
3984
- status.debug(`Using server-synced project path: ${projectPath}`);
3980
+ let projectPath = null;
3981
+ if (!isCloudMode) {
3982
+ const serverPath = await fetchProjectPath(config, config.project_id);
3983
+ if (serverPath && fs4.existsSync(serverPath)) {
3984
+ projectPath = serverPath;
3985
+ status.debug(`Using server-synced project path: ${projectPath}`);
3986
+ } else {
3987
+ const detectedRoot = findGitRoot(options.cwd || process.cwd());
3988
+ projectPath = detectedRoot || path5.resolve(options.cwd || process.cwd());
3989
+ if (detectedRoot) {
3990
+ status.debug(`Detected project root: ${projectPath}`);
3991
+ } else {
3992
+ status.warning(`Could not detect git root, using: ${projectPath}`);
3993
+ }
3994
+ syncProjectPath(config, config.project_id, projectPath).catch(() => {
3995
+ });
3996
+ }
3997
+ const episodaProjectRoot = await findProjectRoot(projectPath);
3998
+ if (!episodaProjectRoot) {
3999
+ status.error("Not an Episoda project.");
4000
+ status.info("");
4001
+ status.info("Use `episoda clone {workspace}/{project}` to set up a project.");
4002
+ status.info("");
4003
+ process.exit(1);
4004
+ }
4005
+ projectPath = episodaProjectRoot;
4006
+ const isWorktree = await isWorktreeProject(projectPath);
4007
+ if (!isWorktree) {
4008
+ status.error("Invalid Episoda project configuration.");
4009
+ process.exit(1);
4010
+ }
4011
+ const bareRepoPath = path5.join(projectPath, ".bare");
4012
+ const scriptsExtracted = await extractBootstrapScripts(bareRepoPath, projectPath);
4013
+ if (scriptsExtracted) {
4014
+ status.success("Bootstrap scripts extracted");
4015
+ }
3985
4016
  } else {
3986
4017
  const detectedRoot = findGitRoot(options.cwd || process.cwd());
3987
- projectPath = detectedRoot || path5.resolve(options.cwd || process.cwd());
3988
4018
  if (detectedRoot) {
3989
- status.debug(`Detected project root: ${projectPath}`);
3990
- } else {
3991
- status.warning(`Could not detect git root, using: ${projectPath}`);
4019
+ const episodaProjectRoot = await findProjectRoot(detectedRoot);
4020
+ if (episodaProjectRoot) {
4021
+ projectPath = episodaProjectRoot;
4022
+ status.debug(`Cloud mode: Found project at ${projectPath}`);
4023
+ }
4024
+ }
4025
+ if (!projectPath) {
4026
+ status.info("Cloud mode: No project detected. Daemon will wait for worktree creation.");
3992
4027
  }
3993
- syncProjectPath(config, config.project_id, projectPath).catch(() => {
3994
- });
3995
- }
3996
- const episodaProjectRoot = await findProjectRoot(projectPath);
3997
- if (!episodaProjectRoot) {
3998
- status.error("Not an Episoda project.");
3999
- status.info("");
4000
- status.info("Use `episoda clone {workspace}/{project}` to set up a project.");
4001
- status.info("");
4002
- process.exit(1);
4003
- }
4004
- projectPath = episodaProjectRoot;
4005
- const isWorktree = await isWorktreeProject(projectPath);
4006
- if (!isWorktree) {
4007
- status.error("Invalid Episoda project configuration.");
4008
- process.exit(1);
4009
- }
4010
- const bareRepoPath = path5.join(projectPath, ".bare");
4011
- const scriptsExtracted = await extractBootstrapScripts(bareRepoPath, projectPath);
4012
- if (scriptsExtracted) {
4013
- status.success("Bootstrap scripts extracted");
4014
4028
  }
4015
4029
  let daemonPid = isDaemonRunning();
4016
4030
  if (!daemonPid) {
@@ -4030,34 +4044,42 @@ async function daemonCommand(options = {}) {
4030
4044
  status.error("Daemon is running but not responding. Try: episoda stop && episoda dev");
4031
4045
  process.exit(1);
4032
4046
  }
4033
- status.info("Connecting project to Episoda...");
4034
- let connected = false;
4035
- let lastError;
4036
- for (let retry = 0; retry < CONNECTION_MAX_RETRIES && !connected; retry++) {
4037
- if (retry > 0) {
4038
- status.info(`Retrying connection (attempt ${retry + 1}/${CONNECTION_MAX_RETRIES})...`);
4039
- await new Promise((resolve5) => setTimeout(resolve5, 1e3));
4040
- }
4041
- try {
4042
- const result = await addProject(config.project_id, projectPath);
4043
- if (result.connected) {
4044
- connected = true;
4045
- } else {
4046
- lastError = result.error || "Connection failed";
4047
+ if (projectPath && config.project_id) {
4048
+ status.info("Connecting project to Episoda...");
4049
+ let connected = false;
4050
+ let lastError;
4051
+ for (let retry = 0; retry < CONNECTION_MAX_RETRIES && !connected; retry++) {
4052
+ if (retry > 0) {
4053
+ status.info(`Retrying connection (attempt ${retry + 1}/${CONNECTION_MAX_RETRIES})...`);
4054
+ await new Promise((resolve5) => setTimeout(resolve5, 1e3));
4055
+ }
4056
+ try {
4057
+ const result = await addProject(config.project_id, projectPath);
4058
+ if (result.connected) {
4059
+ connected = true;
4060
+ } else {
4061
+ lastError = result.error || "Connection failed";
4062
+ }
4063
+ } catch (error) {
4064
+ lastError = error instanceof Error ? error.message : String(error);
4047
4065
  }
4048
- } catch (error) {
4049
- lastError = error instanceof Error ? error.message : String(error);
4050
4066
  }
4067
+ if (!connected) {
4068
+ status.error(`Failed to connect: ${lastError}`);
4069
+ status.info("Check server status at https://episoda.dev/api/system/health");
4070
+ process.exit(1);
4071
+ }
4072
+ status.success("Connected to Episoda");
4073
+ } else if (isCloudMode) {
4074
+ status.success("Daemon started in cloud mode (awaiting project)");
4051
4075
  }
4052
- if (!connected) {
4053
- status.error(`Failed to connect: ${lastError}`);
4054
- status.info("Check server status at https://episoda.dev/api/system/health");
4055
- process.exit(1);
4056
- }
4057
- status.success("Connected to Episoda");
4058
4076
  if (options.foreground) {
4059
4077
  status.info("");
4060
- status.info("Daemon connected! Dev servers start automatically when you begin work on a module.");
4078
+ if (isCloudMode && !projectPath) {
4079
+ status.info("Daemon running in cloud mode. Waiting for worktree creation commands.");
4080
+ } else {
4081
+ status.info("Daemon connected! Dev servers start automatically when you begin work on a module.");
4082
+ }
4061
4083
  status.info("Press Ctrl+C to disconnect (daemon continues in background).");
4062
4084
  status.info("");
4063
4085
  const shutdownHandler = (signal) => {
@@ -4074,7 +4096,11 @@ Received ${signal}. Daemon continues running in background.`);
4074
4096
  });
4075
4097
  } else {
4076
4098
  status.info("");
4077
- status.info("Daemon running in background. Use `episoda status` to check connection.");
4099
+ if (isCloudMode && !projectPath) {
4100
+ status.info("Daemon running in cloud mode. Waiting for worktree creation commands.");
4101
+ } else {
4102
+ status.info("Daemon running in background. Use `episoda status` to check connection.");
4103
+ }
4078
4104
  process.exit(0);
4079
4105
  }
4080
4106
  } catch (error) {