@vibedeckx/linux-x64 0.3.38 → 0.3.39

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.
Files changed (2) hide show
  1. package/dist/bin.js +198 -129
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -66967,7 +66967,7 @@ var require_sonic_boom = __commonJS({
66967
66967
  if (!(this instanceof SonicBoom)) {
66968
66968
  return new SonicBoom(opts);
66969
66969
  }
66970
- let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir7, retryEAGAIN, fsync, contentMode, mode } = opts || {};
66970
+ let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir6, retryEAGAIN, fsync, contentMode, mode } = opts || {};
66971
66971
  fd = fd || dest;
66972
66972
  this._len = 0;
66973
66973
  this.fd = -1;
@@ -66992,7 +66992,7 @@ var require_sonic_boom = __commonJS({
66992
66992
  this.append = append || false;
66993
66993
  this.mode = mode;
66994
66994
  this.retryEAGAIN = retryEAGAIN || (() => true);
66995
- this.mkdir = mkdir7 || false;
66995
+ this.mkdir = mkdir6 || false;
66996
66996
  let fsWriteSync;
66997
66997
  let fsWrite;
66998
66998
  if (contentMode === kContentModeBuffer) {
@@ -100215,7 +100215,7 @@ var require_commonjs6 = __commonJS({
100215
100215
  var node_url_1 = __require("node:url");
100216
100216
  var fs_1 = __require("fs");
100217
100217
  var actualFS = __importStar(__require("node:fs"));
100218
- var realpathSync = fs_1.realpathSync.native;
100218
+ var realpathSync2 = fs_1.realpathSync.native;
100219
100219
  var promises_1 = __require("node:fs/promises");
100220
100220
  var minipass_1 = require_commonjs5();
100221
100221
  var defaultFS = {
@@ -100223,7 +100223,7 @@ var require_commonjs6 = __commonJS({
100223
100223
  readdir: fs_1.readdir,
100224
100224
  readdirSync: fs_1.readdirSync,
100225
100225
  readlinkSync: fs_1.readlinkSync,
100226
- realpathSync,
100226
+ realpathSync: realpathSync2,
100227
100227
  promises: {
100228
100228
  lstat: promises_1.lstat,
100229
100229
  readdir: promises_1.readdir,
@@ -115594,7 +115594,7 @@ var require_token_io = __commonJS({
115594
115594
  });
115595
115595
  module.exports = __toCommonJS2(token_io_exports);
115596
115596
  var import_path16 = __toESM3(__require("path"));
115597
- var import_fs10 = __toESM3(__require("fs"));
115597
+ var import_fs11 = __toESM3(__require("fs"));
115598
115598
  var import_os4 = __toESM3(__require("os"));
115599
115599
  var import_token_error = require_token_error();
115600
115600
  function findRootDir() {
@@ -115602,7 +115602,7 @@ var require_token_io = __commonJS({
115602
115602
  let dir = process.cwd();
115603
115603
  while (dir !== import_path16.default.dirname(dir)) {
115604
115604
  const pkgPath = import_path16.default.join(dir, ".vercel");
115605
- if (import_fs10.default.existsSync(pkgPath)) {
115605
+ if (import_fs11.default.existsSync(pkgPath)) {
115606
115606
  return dir;
115607
115607
  }
115608
115608
  dir = import_path16.default.dirname(dir);
@@ -128873,7 +128873,7 @@ var require_snapshot_utils = __commonJS({
128873
128873
  var require_snapshot_recorder = __commonJS({
128874
128874
  "../../node_modules/.pnpm/undici@7.22.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
128875
128875
  "use strict";
128876
- var { writeFile: writeFile2, readFile: readFile2, mkdir: mkdir7 } = __require("node:fs/promises");
128876
+ var { writeFile: writeFile2, readFile: readFile2, mkdir: mkdir6 } = __require("node:fs/promises");
128877
128877
  var { dirname, resolve: resolve3 } = __require("node:path");
128878
128878
  var { setTimeout: setTimeout3, clearTimeout: clearTimeout2 } = __require("node:timers");
128879
128879
  var { InvalidArgumentError: InvalidArgumentError4, UndiciError } = require_errors7();
@@ -129105,7 +129105,7 @@ var require_snapshot_recorder = __commonJS({
129105
129105
  throw new InvalidArgumentError4("Snapshot path is required");
129106
129106
  }
129107
129107
  const resolvedPath = resolve3(path26);
129108
- await mkdir7(dirname(resolvedPath), { recursive: true });
129108
+ await mkdir6(dirname(resolvedPath), { recursive: true });
129109
129109
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
129110
129110
  hash: hash2,
129111
129111
  snapshot
@@ -208665,6 +208665,7 @@ function parseRows(rows, sessionIdForLog) {
208665
208665
  import path7 from "path";
208666
208666
  import { createHash } from "crypto";
208667
208667
  import { execSync, execFileSync as execFileSync2 } from "child_process";
208668
+ import { mkdirSync as mkdirSync2, realpathSync } from "fs";
208668
208669
  var WORKTREE_BASE_DIR = "/var/tmp/vibedeckx/worktrees";
208669
208670
  var WORKTREE_LIST_TTL_MS = 1e4;
208670
208671
  var worktreeListCache = /* @__PURE__ */ new Map();
@@ -208677,35 +208678,41 @@ function isSubpath(basePath33, targetPath) {
208677
208678
  const relative = path7.relative(basePath33, targetPath);
208678
208679
  return relative === "" || !relative.startsWith("..") && !path7.isAbsolute(relative);
208679
208680
  }
208681
+ function canonicalPath(target) {
208682
+ try {
208683
+ return realpathSync(target);
208684
+ } catch {
208685
+ return path7.resolve(target);
208686
+ }
208687
+ }
208680
208688
  function isTrustedWorktreePath(projectPath, worktreePath) {
208681
- const normalizedWorktreePath = path7.resolve(worktreePath);
208682
- if (normalizedWorktreePath === path7.resolve(projectPath)) return true;
208683
- const managedBase = path7.resolve(getWorktreeBaseForProject(projectPath));
208689
+ const normalizedWorktreePath = canonicalPath(worktreePath);
208690
+ if (normalizedWorktreePath === canonicalPath(projectPath)) return true;
208691
+ const managedBase = canonicalPath(getWorktreeBaseForProject(projectPath));
208684
208692
  return isSubpath(managedBase, normalizedWorktreePath);
208685
208693
  }
208686
- function readWorktreeListFromGit(projectPath) {
208694
+ function readWorktreeRecords(projectPath) {
208687
208695
  const output = execSync("git worktree list --porcelain", {
208688
208696
  cwd: projectPath,
208689
208697
  encoding: "utf-8",
208690
208698
  stdio: ["pipe", "pipe", "pipe"]
208691
208699
  });
208692
- const entries = [];
208693
- const blocks = output.trim().split("\n\n");
208694
- for (const block of blocks) {
208695
- const lines = block.split("\n");
208700
+ const records = [];
208701
+ for (const block of output.trim().split("\n\n")) {
208696
208702
  let worktreePath = "";
208697
208703
  let branch = null;
208698
- let isPrunable = false;
208699
- for (const line of lines) {
208704
+ let prunable = false;
208705
+ for (const line of block.split("\n")) {
208700
208706
  if (line.startsWith("worktree ")) worktreePath = line.slice(9);
208701
208707
  else if (line.startsWith("branch refs/heads/")) branch = line.slice(18);
208702
- else if (line === "prunable" || line.startsWith("prunable ")) isPrunable = true;
208703
- }
208704
- if (worktreePath && !isPrunable && isTrustedWorktreePath(projectPath, worktreePath)) {
208705
- entries.push({ path: worktreePath, branch });
208708
+ else if (line === "prunable" || line.startsWith("prunable ")) prunable = true;
208706
208709
  }
208710
+ if (worktreePath) records.push({ path: worktreePath, branch, prunable });
208707
208711
  }
208708
- return entries;
208712
+ return records;
208713
+ }
208714
+ function readWorktreeListFromGit(projectPath) {
208715
+ return readWorktreeRecords(projectPath).filter((record2) => !record2.prunable && isTrustedWorktreePath(projectPath, record2.path)).map(({ path: worktreePath, branch }) => ({ path: worktreePath, branch }));
208709
208716
  }
208710
208717
  function parseGitWorktreeList(projectPath) {
208711
208718
  const now3 = Date.now();
@@ -208739,6 +208746,76 @@ function pruneWorktrees(projectPath) {
208739
208746
  function invalidateWorktreeListCache(projectPath) {
208740
208747
  worktreeListCache.delete(projectPath);
208741
208748
  }
208749
+ function branchExists(projectPath, branch) {
208750
+ try {
208751
+ execFileSync2("git", ["rev-parse", "--verify", `refs/heads/${branch}`], {
208752
+ cwd: projectPath,
208753
+ encoding: "utf-8",
208754
+ stdio: ["pipe", "pipe", "pipe"]
208755
+ });
208756
+ return true;
208757
+ } catch {
208758
+ return false;
208759
+ }
208760
+ }
208761
+ function planWorktreeAdd(projectPath, branch, startPoint) {
208762
+ const exists2 = branchExists(projectPath, branch);
208763
+ if (exists2) {
208764
+ pruneWorktrees(projectPath);
208765
+ const existing = parseGitWorktreeList(projectPath).find((e) => e.branch === branch);
208766
+ if (existing) {
208767
+ if (canonicalPath(existing.path) === canonicalPath(projectPath)) {
208768
+ throw Object.assign(
208769
+ new Error(`Branch '${branch}' is checked out in the main workspace`),
208770
+ { statusCode: 409 }
208771
+ );
208772
+ }
208773
+ return { worktreePath: existing.path, adopted: true, addArgs: null };
208774
+ }
208775
+ }
208776
+ const worktreePath = resolveWorktreePath(projectPath, branch);
208777
+ return {
208778
+ worktreePath,
208779
+ adopted: exists2,
208780
+ addArgs: exists2 ? ["worktree", "add", worktreePath, branch] : ["worktree", "add", "-b", branch, worktreePath, startPoint]
208781
+ };
208782
+ }
208783
+ function liveWorktreeRecord(projectPath, worktreePath) {
208784
+ const target = canonicalPath(worktreePath);
208785
+ const match2 = readWorktreeRecords(projectPath).find((record2) => !record2.prunable && canonicalPath(record2.path) === target);
208786
+ return match2 ? { path: match2.path, branch: match2.branch } : null;
208787
+ }
208788
+ function worktreeRecordExists(projectPath, worktreePath) {
208789
+ try {
208790
+ return liveWorktreeRecord(projectPath, worktreePath) !== null;
208791
+ } catch {
208792
+ return null;
208793
+ }
208794
+ }
208795
+ function deleteBranchAfterRemoval(projectPath, branch) {
208796
+ if (!branchExists(projectPath, branch)) return null;
208797
+ try {
208798
+ execFileSync2("git", ["branch", "-d", branch], {
208799
+ cwd: projectPath,
208800
+ encoding: "utf-8",
208801
+ stdio: ["pipe", "pipe", "pipe"]
208802
+ });
208803
+ return null;
208804
+ } catch (error48) {
208805
+ const stderr = String(error48?.stderr ?? "");
208806
+ return { branch, unmerged: /not fully merged/i.test(stderr) };
208807
+ }
208808
+ }
208809
+ function applyWorktreeAdd(projectPath, plan) {
208810
+ if (!plan.addArgs) return;
208811
+ mkdirSync2(getWorktreeBaseForProject(projectPath), { recursive: true });
208812
+ execFileSync2("git", plan.addArgs, {
208813
+ cwd: projectPath,
208814
+ encoding: "utf-8",
208815
+ stdio: ["pipe", "pipe", "pipe"]
208816
+ });
208817
+ invalidateWorktreeListCache(projectPath);
208818
+ }
208742
208819
  function resolveWorktreePath(projectPath, branch) {
208743
208820
  if (!branch) return projectPath;
208744
208821
  try {
@@ -247391,7 +247468,6 @@ var process_routes_default = (0, import_fastify_plugin8.default)(routes7, { name
247391
247468
 
247392
247469
  // src/routes/worktree-routes.ts
247393
247470
  var import_fastify_plugin9 = __toESM(require_plugin2(), 1);
247394
- import { mkdir as mkdir4 } from "fs/promises";
247395
247471
 
247396
247472
  // src/utils/path-project.ts
247397
247473
  async function ensurePathProjectId(fastify2, projectPath) {
@@ -247413,7 +247489,8 @@ async function getAllRemoteConfigs(fastify2, project) {
247413
247489
  const remotes = await fastify2.storage.projectRemotes.getByProject(project.id);
247414
247490
  return remotes.map((r) => ({
247415
247491
  serverId: r.remote_server_id,
247416
- remotePath: r.remote_path
247492
+ remotePath: r.remote_path,
247493
+ serverName: r.server_name
247417
247494
  }));
247418
247495
  }
247419
247496
  async function getRemoteConfig(fastify2, project) {
@@ -247436,6 +247513,30 @@ async function ensurePathProject(fastify2, projectPath) {
247436
247513
  if (!project) throw new Error(`Path project '${projectId}' was not persisted`);
247437
247514
  return project;
247438
247515
  }
247516
+ function removeWorktreeIfPresent(execFileSync8, projectPath, worktreePath) {
247517
+ try {
247518
+ execFileSync8("git", ["worktree", "remove", worktreePath], {
247519
+ cwd: projectPath,
247520
+ encoding: "utf-8",
247521
+ stdio: ["pipe", "pipe", "pipe"]
247522
+ });
247523
+ } catch (error48) {
247524
+ if (worktreeRecordExists(projectPath, worktreePath) !== false) throw error48;
247525
+ pruneWorktrees(projectPath);
247526
+ }
247527
+ }
247528
+ async function assertPathIsFree(fastify2, opts) {
247529
+ const registered = await fastify2.storage.workspaceRegistry.listByProject(opts.projectId, opts.targetId);
247530
+ const target = canonicalPath(opts.worktreePath);
247531
+ const owner = registered.find((row) => row.workspace.branch !== opts.branch && canonicalPath(row.checkout.worktree_path) === target);
247532
+ if (!owner) return;
247533
+ throw Object.assign(
247534
+ new Error(
247535
+ `That worktree already belongs to workspace '${owner.workspace.branch || "main"}'`
247536
+ ),
247537
+ { statusCode: 409 }
247538
+ );
247539
+ }
247439
247540
  async function syncRemoteWorktreeList(fastify2, projectId, remote, data) {
247440
247541
  const worktrees = data?.worktrees;
247441
247542
  if (!Array.isArray(worktrees)) return;
@@ -247535,37 +247636,27 @@ var routes8 = async (fastify2) => {
247535
247636
  console.log(`[worktree] ${requestId} Creating: branch=${trimmedBranch}, base=${startPoint}, path=${projectPath}`);
247536
247637
  let pendingCheckoutId = null;
247537
247638
  try {
247538
- const { execFileSync: execFileSync8 } = await import("child_process");
247539
- try {
247540
- execFileSync8("git", ["rev-parse", "--verify", `refs/heads/${trimmedBranch}`], {
247541
- cwd: projectPath,
247542
- encoding: "utf-8",
247543
- stdio: ["pipe", "pipe", "pipe"]
247544
- });
247545
- return reply.code(409).send({ error: `Branch '${trimmedBranch}' already exists` });
247546
- } catch {
247547
- }
247548
- const worktreeAbsolutePath = resolveWorktreePath(projectPath, trimmedBranch);
247639
+ const plan = planWorktreeAdd(projectPath, trimmedBranch, startPoint);
247549
247640
  const project = await ensurePathProject(fastify2, projectPath);
247641
+ await assertPathIsFree(fastify2, {
247642
+ projectId: project.id,
247643
+ branch: trimmedBranch,
247644
+ targetId: "local",
247645
+ worktreePath: plan.worktreePath
247646
+ });
247550
247647
  const pending = await fastify2.storage.workspaceRegistry.beginCheckout({
247551
247648
  projectId: project.id,
247552
247649
  branch: trimmedBranch,
247553
247650
  targetId: "local",
247554
- worktreePath: worktreeAbsolutePath,
247651
+ worktreePath: plan.worktreePath,
247555
247652
  expectedBranch: trimmedBranch
247556
247653
  });
247557
247654
  pendingCheckoutId = pending.checkout.id;
247558
- await mkdir4(getWorktreeBaseForProject(projectPath), { recursive: true });
247559
- execFileSync8("git", ["worktree", "add", "-b", trimmedBranch, worktreeAbsolutePath, startPoint], {
247560
- cwd: projectPath,
247561
- encoding: "utf-8",
247562
- stdio: ["pipe", "pipe", "pipe"]
247563
- });
247564
- invalidateWorktreeListCache(projectPath);
247655
+ applyWorktreeAdd(projectPath, plan);
247565
247656
  await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.checkout.id, "ready");
247566
- console.log(`[worktree] ${requestId} Created: branch=${trimmedBranch}`);
247657
+ console.log(`[worktree] ${requestId} ${plan.adopted ? "Adopted" : "Created"}: branch=${trimmedBranch}`);
247567
247658
  return reply.code(201).send({
247568
- worktree: { branch: trimmedBranch, worktreePath: worktreeAbsolutePath }
247659
+ worktree: { branch: trimmedBranch, worktreePath: plan.worktreePath, adopted: plan.adopted }
247569
247660
  });
247570
247661
  } catch (error48) {
247571
247662
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
@@ -247574,6 +247665,8 @@ var routes8 = async (fastify2) => {
247574
247665
  }
247575
247666
  const stderr = error48?.stderr || "";
247576
247667
  console.error(`[worktree] ${requestId} Failed: ${errorMessage}${stderr ? `, stderr: ${stderr}` : ""}`);
247668
+ const statusCode = error48?.statusCode;
247669
+ if (statusCode) return reply.code(statusCode).send({ error: errorMessage });
247577
247670
  return reply.code(500).send({ error: `Failed to create worktree: ${errorMessage}` });
247578
247671
  }
247579
247672
  });
@@ -247615,34 +247708,19 @@ var routes8 = async (fastify2) => {
247615
247708
  branch,
247616
247709
  worktreePath: worktreeAbsPath
247617
247710
  });
247618
- let branchToDelete = null;
247711
+ let branchToDelete = branch;
247619
247712
  try {
247620
- const entries = parseGitWorktreeList(projectPath);
247621
- const match2 = entries.find((e) => e.path === worktreeAbsPath);
247622
- if (match2) branchToDelete = match2.branch;
247713
+ branchToDelete = liveWorktreeRecord(projectPath, worktreeAbsPath)?.branch ?? branch;
247623
247714
  } catch {
247624
247715
  }
247625
- execFileSync8("git", ["worktree", "remove", worktreeAbsPath], {
247626
- cwd: projectPath,
247627
- encoding: "utf-8",
247628
- stdio: ["pipe", "pipe", "pipe"]
247629
- });
247716
+ removeWorktreeIfPresent(execFileSync8, projectPath, worktreeAbsPath);
247630
247717
  worktreeRemoved = true;
247631
247718
  invalidateWorktreeListCache(projectPath);
247632
- if (branchToDelete) {
247633
- try {
247634
- execFileSync8("git", ["branch", "-d", branchToDelete], {
247635
- cwd: projectPath,
247636
- encoding: "utf-8",
247637
- stdio: ["pipe", "pipe", "pipe"]
247638
- });
247639
- } catch {
247640
- }
247641
- }
247719
+ const branchRetained = branchToDelete ? deleteBranchAfterRemoval(projectPath, branchToDelete) : null;
247642
247720
  if (registered) {
247643
247721
  await fastify2.storage.workspaceRegistry.markCheckoutDeleted(registered.checkout.id);
247644
247722
  }
247645
- return reply.code(200).send({ success: true });
247723
+ return reply.code(200).send({ success: true, branchRetained });
247646
247724
  } catch (error48) {
247647
247725
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
247648
247726
  const busy = error48 instanceof WorktreeBusyError;
@@ -247757,7 +247835,11 @@ var routes8 = async (fastify2) => {
247757
247835
  } else {
247758
247836
  const targetRemote = await fastify2.storage.projectRemotes.getByProjectAndServer(project.id, requestedTarget);
247759
247837
  if (!targetRemote) return reply.code(400).send({ error: "Unknown remote target" });
247760
- remoteConfig = { serverId: targetRemote.remote_server_id, remotePath: targetRemote.remote_path };
247838
+ remoteConfig = {
247839
+ serverId: targetRemote.remote_server_id,
247840
+ remotePath: targetRemote.remote_path,
247841
+ serverName: targetRemote.server_name
247842
+ };
247761
247843
  }
247762
247844
  if (remoteConfig) {
247763
247845
  const result = await proxyToRemoteAuto(
@@ -247807,7 +247889,11 @@ var routes8 = async (fastify2) => {
247807
247889
  } else {
247808
247890
  const targetRemote = await fastify2.storage.projectRemotes.getByProjectAndServer(project.id, requestedTarget);
247809
247891
  if (!targetRemote) return reply.code(400).send({ error: "Unknown remote target" });
247810
- remoteConfig = { serverId: targetRemote.remote_server_id, remotePath: targetRemote.remote_path };
247892
+ remoteConfig = {
247893
+ serverId: targetRemote.remote_server_id,
247894
+ remotePath: targetRemote.remote_path,
247895
+ serverName: targetRemote.server_name
247896
+ };
247811
247897
  }
247812
247898
  if (remoteConfig) {
247813
247899
  const result = await proxyToRemoteAuto(
@@ -247951,17 +248037,19 @@ var routes8 = async (fastify2) => {
247951
248037
  await Promise.allSettled(
247952
248038
  remoteConfigs.map(async (rc) => {
247953
248039
  const key2 = rc.serverId;
248040
+ const label = rc.serverName;
247954
248041
  try {
247955
248042
  const result = await deleteOnRemote(rc);
247956
248043
  if (result.ok) {
247957
- results2[key2] = { success: true };
248044
+ const data = result.data;
248045
+ results2[key2] = { success: true, label, branchRetained: data?.branchRetained };
247958
248046
  } else {
247959
248047
  const data = result.data;
247960
- results2[key2] = { success: false, error: data.error || "Remote deletion failed" };
248048
+ results2[key2] = { success: false, label, error: data.error || "Remote deletion failed" };
247961
248049
  }
247962
248050
  } catch (error48) {
247963
248051
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
247964
- results2[key2] = { success: false, error: errorMessage };
248052
+ results2[key2] = { success: false, label, error: errorMessage };
247965
248053
  }
247966
248054
  })
247967
248055
  );
@@ -248000,33 +248088,19 @@ var routes8 = async (fastify2) => {
248000
248088
  branch,
248001
248089
  worktreePath: worktreeAbsPath
248002
248090
  });
248003
- let branchToDelete = null;
248091
+ let branchToDelete = branch;
248004
248092
  try {
248005
- const entries = parseGitWorktreeList(project.path);
248006
- const match2 = entries.find((e) => e.path === worktreeAbsPath);
248007
- if (match2) branchToDelete = match2.branch;
248093
+ branchToDelete = liveWorktreeRecord(project.path, worktreeAbsPath)?.branch ?? branch;
248008
248094
  } catch {
248009
248095
  }
248010
- execFileSync8("git", ["worktree", "remove", worktreeAbsPath], {
248011
- cwd: project.path,
248012
- encoding: "utf-8",
248013
- stdio: ["pipe", "pipe", "pipe"]
248014
- });
248096
+ removeWorktreeIfPresent(execFileSync8, project.path, worktreeAbsPath);
248015
248097
  worktreeRemoved = true;
248016
248098
  invalidateWorktreeListCache(project.path);
248017
- if (branchToDelete) {
248018
- try {
248019
- execFileSync8("git", ["branch", "-d", branchToDelete], {
248020
- cwd: project.path,
248021
- encoding: "utf-8",
248022
- stdio: ["pipe", "pipe", "pipe"]
248023
- });
248024
- } catch {
248025
- }
248026
- }
248099
+ const branchRetained = branchToDelete ? deleteBranchAfterRemoval(project.path, branchToDelete) : null;
248027
248100
  if (registered) {
248028
248101
  await fastify2.storage.workspaceRegistry.markCheckoutDeleted(registered.checkout.id);
248029
248102
  }
248103
+ return branchRetained;
248030
248104
  } catch (error48) {
248031
248105
  if (registered && !worktreeRemoved) {
248032
248106
  const message = error48 instanceof Error ? error48.message : "Local deletion failed";
@@ -248038,8 +248112,8 @@ var routes8 = async (fastify2) => {
248038
248112
  };
248039
248113
  if (!hasRemote) {
248040
248114
  try {
248041
- await deleteLocal();
248042
- return reply.code(200).send({ success: true });
248115
+ const branchRetained = await deleteLocal();
248116
+ return reply.code(200).send({ success: true, branchRetained });
248043
248117
  } catch (error48) {
248044
248118
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248045
248119
  if (errorMessage.includes("uncommitted changes") || error48 instanceof WorktreeBusyError) {
@@ -248050,8 +248124,7 @@ var routes8 = async (fastify2) => {
248050
248124
  }
248051
248125
  const results = {};
248052
248126
  try {
248053
- await deleteLocal();
248054
- results.local = { success: true };
248127
+ results.local = { success: true, label: "local", branchRetained: await deleteLocal() };
248055
248128
  } catch (error48) {
248056
248129
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248057
248130
  return reply.code(500).send({ error: `Failed to delete local worktree: ${errorMessage}` });
@@ -248059,17 +248132,19 @@ var routes8 = async (fastify2) => {
248059
248132
  await Promise.allSettled(
248060
248133
  remoteConfigs.map(async (rc) => {
248061
248134
  const key2 = remoteConfigs.length === 1 ? "remote" : rc.serverId;
248135
+ const label = rc.serverName;
248062
248136
  try {
248063
248137
  const remoteResult = await deleteOnRemote(rc);
248064
248138
  if (remoteResult.ok) {
248065
- results[key2] = { success: true };
248139
+ const remoteData = remoteResult.data;
248140
+ results[key2] = { success: true, label, branchRetained: remoteData?.branchRetained };
248066
248141
  } else {
248067
248142
  const remoteData = remoteResult.data;
248068
- results[key2] = { success: false, error: remoteData.error || "Remote deletion failed" };
248143
+ results[key2] = { success: false, label, error: remoteData.error || "Remote deletion failed" };
248069
248144
  }
248070
248145
  } catch (error48) {
248071
248146
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248072
- results[key2] = { success: false, error: errorMessage };
248147
+ results[key2] = { success: false, label, error: errorMessage };
248073
248148
  }
248074
248149
  })
248075
248150
  );
@@ -248183,20 +248258,21 @@ var routes8 = async (fastify2) => {
248183
248258
  const settled = await Promise.allSettled(
248184
248259
  remoteConfigs.map(async (rc) => {
248185
248260
  const key2 = rc.serverId;
248261
+ const label = rc.serverName;
248186
248262
  console.log(`[worktree] Creating remote worktree: project=${req.params.id}, branch=${trimmedBranch}, serverId=${rc.serverId}`);
248187
248263
  try {
248188
248264
  const result = await createOnRemote(rc);
248189
248265
  if (result.ok) {
248190
248266
  const data = result.data;
248191
- results2[key2] = { success: true, worktree: data.worktree };
248267
+ results2[key2] = { success: true, label, worktree: data.worktree, adopted: data.worktree?.adopted };
248192
248268
  } else {
248193
248269
  const data = result.data;
248194
248270
  console.error(`[worktree] Remote failed: serverId=${rc.serverId}, requestId=${result.requestId}, error=${JSON.stringify(result.data)}`);
248195
- results2[key2] = { success: false, error: data.error || "Remote creation failed", errorCode: result.errorCode, requestId: result.requestId };
248271
+ results2[key2] = { success: false, label, error: data.error || "Remote creation failed", errorCode: result.errorCode, requestId: result.requestId };
248196
248272
  }
248197
248273
  } catch (error48) {
248198
248274
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248199
- results2[key2] = { success: false, error: errorMessage };
248275
+ results2[key2] = { success: false, label, error: errorMessage };
248200
248276
  }
248201
248277
  })
248202
248278
  );
@@ -248211,35 +248287,24 @@ var routes8 = async (fastify2) => {
248211
248287
  return reply.code(201).send({ worktree: { branch: trimmedBranch }, results: results2 });
248212
248288
  }
248213
248289
  const createLocal = async () => {
248214
- const { execFileSync: execFileSync8 } = await import("child_process");
248215
- try {
248216
- execFileSync8("git", ["rev-parse", "--verify", `refs/heads/${trimmedBranch}`], {
248217
- cwd: project.path,
248218
- encoding: "utf-8",
248219
- stdio: ["pipe", "pipe", "pipe"]
248220
- });
248221
- throw new Error(`Branch '${trimmedBranch}' already exists`);
248222
- } catch (err) {
248223
- if (err instanceof Error && err.message.includes("already exists")) throw err;
248224
- }
248225
- const worktreeAbsolutePath = resolveWorktreePath(project.path, trimmedBranch);
248290
+ const plan = planWorktreeAdd(project.path, trimmedBranch, localStartPoint);
248291
+ await assertPathIsFree(fastify2, {
248292
+ projectId: project.id,
248293
+ branch: trimmedBranch,
248294
+ targetId: "local",
248295
+ worktreePath: plan.worktreePath
248296
+ });
248226
248297
  const pending = await fastify2.storage.workspaceRegistry.beginCheckout({
248227
248298
  projectId: project.id,
248228
248299
  branch: trimmedBranch,
248229
248300
  targetId: "local",
248230
- worktreePath: worktreeAbsolutePath,
248301
+ worktreePath: plan.worktreePath,
248231
248302
  expectedBranch: trimmedBranch
248232
248303
  });
248233
248304
  try {
248234
- await mkdir4(getWorktreeBaseForProject(project.path), { recursive: true });
248235
- execFileSync8("git", ["worktree", "add", "-b", trimmedBranch, worktreeAbsolutePath, localStartPoint], {
248236
- cwd: project.path,
248237
- encoding: "utf-8",
248238
- stdio: ["pipe", "pipe", "pipe"]
248239
- });
248240
- invalidateWorktreeListCache(project.path);
248305
+ applyWorktreeAdd(project.path, plan);
248241
248306
  await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.checkout.id, "ready");
248242
- return { branch: trimmedBranch };
248307
+ return { branch: trimmedBranch, adopted: plan.adopted };
248243
248308
  } catch (error48) {
248244
248309
  const message = error48 instanceof Error ? error48.message : "Local creation failed";
248245
248310
  await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.checkout.id, "error", message).catch((registryError) => console.error("[worktree] Failed to record local checkout error:", registryError));
@@ -248252,6 +248317,8 @@ var routes8 = async (fastify2) => {
248252
248317
  return reply.code(201).send({ worktree });
248253
248318
  } catch (error48) {
248254
248319
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248320
+ const statusCode = error48?.statusCode;
248321
+ if (statusCode) return reply.code(statusCode).send({ error: errorMessage });
248255
248322
  if (errorMessage.includes("already exists")) {
248256
248323
  return reply.code(409).send({ error: errorMessage });
248257
248324
  }
@@ -248262,7 +248329,7 @@ var routes8 = async (fastify2) => {
248262
248329
  let localWorktree;
248263
248330
  try {
248264
248331
  localWorktree = await createLocal();
248265
- results.local = { success: true, worktree: localWorktree };
248332
+ results.local = { success: true, label: "local", worktree: localWorktree, adopted: localWorktree.adopted };
248266
248333
  } catch (error48) {
248267
248334
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248268
248335
  return reply.code(500).send({ error: `Failed to create local worktree: ${errorMessage}` });
@@ -248270,17 +248337,19 @@ var routes8 = async (fastify2) => {
248270
248337
  await Promise.allSettled(
248271
248338
  remoteConfigs.map(async (rc) => {
248272
248339
  const key2 = remoteConfigs.length === 1 ? "remote" : rc.serverId;
248340
+ const label = rc.serverName;
248273
248341
  console.log(`[worktree] Creating remote worktree: project=${req.params.id}, branch=${trimmedBranch}, serverId=${rc.serverId}`);
248274
248342
  try {
248275
248343
  const remoteResult = await createOnRemote(rc);
248276
248344
  if (remoteResult.ok) {
248277
248345
  const remoteData = remoteResult.data;
248278
- results[key2] = { success: true, worktree: remoteData.worktree };
248346
+ results[key2] = { success: true, label, worktree: remoteData.worktree, adopted: remoteData.worktree?.adopted };
248279
248347
  } else {
248280
248348
  const remoteData = remoteResult.data;
248281
248349
  console.error(`[worktree] Remote failed: serverId=${rc.serverId}, requestId=${remoteResult.requestId}, errorCode=${remoteResult.errorCode}, status=${remoteResult.status}, duration=${remoteResult.durationMs}ms, error=${JSON.stringify(remoteResult.data)}`);
248282
248350
  results[key2] = {
248283
248351
  success: false,
248352
+ label,
248284
248353
  error: remoteData.error || "Remote creation failed",
248285
248354
  errorCode: remoteResult.errorCode,
248286
248355
  requestId: remoteResult.requestId
@@ -248288,7 +248357,7 @@ var routes8 = async (fastify2) => {
248288
248357
  }
248289
248358
  } catch (error48) {
248290
248359
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
248291
- results[key2] = { success: false, error: errorMessage };
248360
+ results[key2] = { success: false, label, error: errorMessage };
248292
248361
  }
248293
248362
  })
248294
248363
  );
@@ -249600,7 +249669,7 @@ var file_routes_default = (0, import_fastify_plugin11.default)(routes10, { name:
249600
249669
  var import_fastify_plugin12 = __toESM(require_plugin2(), 1);
249601
249670
 
249602
249671
  // src/utils/paste-file.ts
249603
- import { chmod, mkdir as mkdir5, open as open2 } from "node:fs/promises";
249672
+ import { chmod, mkdir as mkdir4, open as open2 } from "node:fs/promises";
249604
249673
  import { constants as fsConstants2 } from "node:fs";
249605
249674
  import path15 from "node:path";
249606
249675
  import { randomUUID as randomUUID15 } from "node:crypto";
@@ -249646,7 +249715,7 @@ var DIR_MODE = 448;
249646
249715
  var FILE_MODE = 384;
249647
249716
  var FILE_FLAGS = fsConstants2.O_WRONLY | fsConstants2.O_CREAT | fsConstants2.O_EXCL | fsConstants2.O_NOFOLLOW;
249648
249717
  async function writePasteToTempFile(content) {
249649
- await mkdir5(PASTE_DIR, { recursive: true, mode: DIR_MODE });
249718
+ await mkdir4(PASTE_DIR, { recursive: true, mode: DIR_MODE });
249650
249719
  await chmod(PASTE_DIR, DIR_MODE);
249651
249720
  const filePath = path15.join(PASTE_DIR, `${randomUUID15()}.txt`);
249652
249721
  const handle = await open2(filePath, FILE_FLAGS, FILE_MODE);
@@ -249660,7 +249729,7 @@ async function writePasteToTempFile(content) {
249660
249729
  }
249661
249730
 
249662
249731
  // src/utils/attachment-file.ts
249663
- import { chmod as chmod2, mkdir as mkdir6, open as open3 } from "node:fs/promises";
249732
+ import { chmod as chmod2, mkdir as mkdir5, open as open3 } from "node:fs/promises";
249664
249733
  import { constants as fsConstants3 } from "node:fs";
249665
249734
  import path16 from "node:path";
249666
249735
  import { randomUUID as randomUUID16 } from "node:crypto";
@@ -249683,10 +249752,10 @@ function sanitizeAttachmentName(raw) {
249683
249752
  }
249684
249753
  async function writeAttachmentToTempFile(rawName, data) {
249685
249754
  const name25 = sanitizeAttachmentName(rawName);
249686
- await mkdir6(ATTACHMENT_DIR, { recursive: true, mode: DIR_MODE2 });
249755
+ await mkdir5(ATTACHMENT_DIR, { recursive: true, mode: DIR_MODE2 });
249687
249756
  await chmod2(ATTACHMENT_DIR, DIR_MODE2);
249688
249757
  const dir = path16.join(ATTACHMENT_DIR, randomUUID16());
249689
- await mkdir6(dir, { mode: DIR_MODE2 });
249758
+ await mkdir5(dir, { mode: DIR_MODE2 });
249690
249759
  const filePath = path16.join(dir, name25);
249691
249760
  const handle = await open3(filePath, FILE_FLAGS2, FILE_MODE2);
249692
249761
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibedeckx/linux-x64",
3
- "version": "0.3.38",
3
+ "version": "0.3.39",
4
4
  "description": "Vibedeckx platform binaries for Linux x64",
5
5
  "os": [
6
6
  "linux"