episoda 0.2.56 → 0.2.57

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.
@@ -2726,7 +2726,7 @@ var require_package = __commonJS({
2726
2726
  "package.json"(exports2, module2) {
2727
2727
  module2.exports = {
2728
2728
  name: "episoda",
2729
- version: "0.2.56",
2729
+ version: "0.2.57",
2730
2730
  description: "CLI tool for Episoda local development workflow orchestration",
2731
2731
  main: "dist/index.js",
2732
2732
  types: "dist/index.d.ts",
@@ -8787,6 +8787,9 @@ var Daemon = class _Daemon {
8787
8787
  this.reconcileWorktrees(projectId, projectPath, client).catch((err) => {
8788
8788
  console.warn("[Daemon] EP1003: Reconciliation report failed:", err.message);
8789
8789
  });
8790
+ this.reconcilePendingCleanups(projectId, projectPath).catch((err) => {
8791
+ console.warn("[Daemon] EP1047: Cleanup queue reconciliation failed:", err.message);
8792
+ });
8790
8793
  });
8791
8794
  client.on("module_state_changed", async (message) => {
8792
8795
  if (message.type === "module_state_changed") {
@@ -9229,6 +9232,117 @@ var Daemon = class _Daemon {
9229
9232
  // EP1025: Removed cleanupModuleWorktree - was dead code (never called).
9230
9233
  // Worktree cleanup is handled by server's cleanupWorktreeAsync which sends
9231
9234
  // worktree_remove command via WebSocket, handled by GitExecutor.executeWorktreeRemove.
9235
+ /**
9236
+ * EP1047: Process pending cleanup queue entries for this machine
9237
+ *
9238
+ * On daemon startup/reconnect, fetch pending worktree cleanup tasks from the queue
9239
+ * and process them. This catches any cleanups missed while the daemon was offline.
9240
+ *
9241
+ * Flow:
9242
+ * 1. Query server for pending cleanup tasks for this machine
9243
+ * 2. For each task, attempt worktree removal
9244
+ * 3. Report success/failure back to server
9245
+ */
9246
+ async reconcilePendingCleanups(projectId, projectPath) {
9247
+ if (!this.deviceId) {
9248
+ console.log("[Daemon] EP1047: Cannot reconcile cleanups - deviceId not available yet");
9249
+ return;
9250
+ }
9251
+ console.log(`[Daemon] EP1047: Checking for pending cleanup tasks for machine ${this.deviceId}`);
9252
+ try {
9253
+ const config = await (0, import_core12.loadConfig)();
9254
+ if (!config) {
9255
+ console.log("[Daemon] EP1047: No config loaded, skipping cleanup reconciliation");
9256
+ return;
9257
+ }
9258
+ const apiUrl = config.api_url || "https://episoda.dev";
9259
+ const controller = new AbortController();
9260
+ const timeoutId = setTimeout(() => controller.abort(), 1e4);
9261
+ let response;
9262
+ try {
9263
+ response = await fetchWithAuth(
9264
+ `${apiUrl}/api/cli/cleanup-queue?machine_id=${this.deviceId}`,
9265
+ { signal: controller.signal }
9266
+ );
9267
+ } finally {
9268
+ clearTimeout(timeoutId);
9269
+ }
9270
+ if (!response.ok) {
9271
+ console.warn(`[Daemon] EP1047: Failed to fetch cleanup tasks: ${response.status}`);
9272
+ return;
9273
+ }
9274
+ const data = await response.json();
9275
+ const tasks = data.data?.tasks || [];
9276
+ if (tasks.length === 0) {
9277
+ console.log("[Daemon] EP1047: No pending cleanup tasks");
9278
+ return;
9279
+ }
9280
+ console.log(`[Daemon] EP1047: Processing ${tasks.length} pending cleanup task(s)`);
9281
+ const projectRoot = await findProjectRoot(projectPath);
9282
+ if (!projectRoot) {
9283
+ console.warn("[Daemon] EP1047: Could not find project root, skipping cleanup reconciliation");
9284
+ return;
9285
+ }
9286
+ const worktreeManager = new WorktreeManager(projectRoot);
9287
+ if (!await worktreeManager.initialize()) {
9288
+ console.warn("[Daemon] EP1047: Failed to initialize worktree manager");
9289
+ return;
9290
+ }
9291
+ for (const task of tasks) {
9292
+ const moduleUid = task.payload.module_uid || task.target_id;
9293
+ console.log(`[Daemon] EP1047: Processing cleanup for ${moduleUid} (task ${task.id})`);
9294
+ try {
9295
+ const result = await worktreeManager.removeWorktree(moduleUid, true);
9296
+ if (result.success) {
9297
+ console.log(`[Daemon] EP1047: Successfully cleaned up worktree for ${moduleUid}`);
9298
+ await this.reportCleanupResult(apiUrl, task.id, "complete");
9299
+ } else {
9300
+ if (result.error?.includes("not found") || result.error?.includes("No worktree found")) {
9301
+ console.log(`[Daemon] EP1047: Worktree ${moduleUid} already removed, marking complete`);
9302
+ await this.reportCleanupResult(apiUrl, task.id, "complete");
9303
+ } else {
9304
+ console.warn(`[Daemon] EP1047: Cleanup failed for ${moduleUid}: ${result.error}`);
9305
+ await this.reportCleanupResult(apiUrl, task.id, "retry", {
9306
+ code: "CLEANUP_ERROR",
9307
+ message: result.error || "Unknown error"
9308
+ });
9309
+ }
9310
+ }
9311
+ } catch (error) {
9312
+ console.error(`[Daemon] EP1047: Error processing cleanup for ${moduleUid}:`, error.message);
9313
+ await this.reportCleanupResult(apiUrl, task.id, "retry", {
9314
+ code: "CLEANUP_EXCEPTION",
9315
+ message: error.message
9316
+ });
9317
+ }
9318
+ }
9319
+ console.log("[Daemon] EP1047: Cleanup reconciliation complete");
9320
+ } catch (error) {
9321
+ console.error("[Daemon] EP1047: Cleanup reconciliation error:", error instanceof Error ? error.message : error);
9322
+ throw error;
9323
+ }
9324
+ }
9325
+ /**
9326
+ * EP1047: Report cleanup task result to server
9327
+ */
9328
+ async reportCleanupResult(apiUrl, taskId, action, error) {
9329
+ try {
9330
+ const response = await fetchWithAuth(`${apiUrl}/api/cli/cleanup-queue`, {
9331
+ method: "POST",
9332
+ headers: { "Content-Type": "application/json" },
9333
+ body: JSON.stringify({
9334
+ task_id: taskId,
9335
+ action,
9336
+ error
9337
+ })
9338
+ });
9339
+ if (!response.ok) {
9340
+ console.warn(`[Daemon] EP1047: Failed to report cleanup result: ${response.status}`);
9341
+ }
9342
+ } catch (err) {
9343
+ console.warn(`[Daemon] EP1047: Error reporting cleanup result: ${err.message}`);
9344
+ }
9345
+ }
9232
9346
  /**
9233
9347
  * EP1002: Handle worktree_setup command from server
9234
9348
  * This provides a unified setup flow for both local and cloud environments.