@vibedeckx/linux-x64 0.3.11 → 0.3.13

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 +582 -342
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -13356,12 +13356,12 @@ var require_semver = __commonJS({
13356
13356
  }
13357
13357
  function replaceHyphen(comp, options) {
13358
13358
  const r = HYPHENRANGE_REGEXP;
13359
- return comp.replace(r, (_3, from, fM, fm, fp36, fpr, fb, to, tM, tm, tp, tpr) => {
13359
+ return comp.replace(r, (_3, from, fM, fm, fp35, fpr, fb, to, tM, tm, tp, tpr) => {
13360
13360
  if (isX(fM)) {
13361
13361
  from = "";
13362
13362
  } else if (isX(fm)) {
13363
13363
  from = `>=${fM}.0.0${options?.includePrerelease ? "-0" : ""}`;
13364
- } else if (isX(fp36)) {
13364
+ } else if (isX(fp35)) {
13365
13365
  from = `>=${fM}.${fm}.0${options?.includePrerelease ? "-0" : ""}`;
13366
13366
  } else if (fpr) {
13367
13367
  from = `>=${from}`;
@@ -87525,12 +87525,12 @@ var require_range = __commonJS({
87525
87525
  debug("replaceGTE0", comp, options);
87526
87526
  return comp.trim().replace(re2[options.includePrerelease ? t.GTE0PRE : t.GTE0], "");
87527
87527
  };
87528
- var hyphenReplace = (incPr) => ($0, from, fM, fm, fp36, fpr, fb, to, tM, tm, tp, tpr) => {
87528
+ var hyphenReplace = (incPr) => ($0, from, fM, fm, fp35, fpr, fb, to, tM, tm, tp, tpr) => {
87529
87529
  if (isX(fM)) {
87530
87530
  from = "";
87531
87531
  } else if (isX(fm)) {
87532
87532
  from = `>=${fM}.0.0${incPr ? "-0" : ""}`;
87533
- } else if (isX(fp36)) {
87533
+ } else if (isX(fp35)) {
87534
87534
  from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`;
87535
87535
  } else if (fpr) {
87536
87536
  from = `>=${from}`;
@@ -90111,8 +90111,8 @@ var require_pretty_print = __commonJS({
90111
90111
  serializedRoute += serializeMetaData(route.metaData);
90112
90112
  return serializedRoute;
90113
90113
  }
90114
- function mergeSimilarRoutes(routes35) {
90115
- return routes35.reduce((mergedRoutes, route) => {
90114
+ function mergeSimilarRoutes(routes34) {
90115
+ return routes34.reduce((mergedRoutes, route) => {
90116
90116
  for (const nodeRoute of mergedRoutes) {
90117
90117
  if (deepEqual(route.opts.constraints, nodeRoute.opts.constraints) && deepEqual(route.metaData, nodeRoute.metaData)) {
90118
90118
  nodeRoute.method += ", " + route.method;
@@ -90124,18 +90124,18 @@ var require_pretty_print = __commonJS({
90124
90124
  }, []);
90125
90125
  }
90126
90126
  function serializeNode(node, prefix, options) {
90127
- let routes35 = node.routes;
90127
+ let routes34 = node.routes;
90128
90128
  if (options.method === void 0) {
90129
- routes35 = routes35.map(normalizeRoute);
90129
+ routes34 = routes34.map(normalizeRoute);
90130
90130
  }
90131
- routes35 = routes35.map((route) => {
90131
+ routes34 = routes34.map((route) => {
90132
90132
  route.metaData = getRouteMetaData(route, options);
90133
90133
  return route;
90134
90134
  });
90135
90135
  if (options.method === void 0) {
90136
- routes35 = mergeSimilarRoutes(routes35);
90136
+ routes34 = mergeSimilarRoutes(routes34);
90137
90137
  }
90138
- return routes35.map(serializeRoute).join(`
90138
+ return routes34.map(serializeRoute).join(`
90139
90139
  ${prefix}`);
90140
90140
  }
90141
90141
  function buildObjectTree(node, tree, prefix, options) {
@@ -91402,9 +91402,9 @@ var require_find_my_way = __commonJS({
91402
91402
  pathIndex = paramEndIndex;
91403
91403
  }
91404
91404
  };
91405
- Router.prototype._rebuild = function(routes35) {
91405
+ Router.prototype._rebuild = function(routes34) {
91406
91406
  this.reset();
91407
- for (const route of routes35) {
91407
+ for (const route of routes34) {
91408
91408
  const { method, path: path22, opts, handler, store } = route;
91409
91409
  this._on(method, path22, opts, handler, store);
91410
91410
  }
@@ -93805,7 +93805,7 @@ var require_parse_url = __commonJS({
93805
93805
  var require_form_data = __commonJS({
93806
93806
  "../../node_modules/.pnpm/light-my-request@6.6.0/node_modules/light-my-request/lib/form-data.js"(exports, module) {
93807
93807
  "use strict";
93808
- var { randomUUID: randomUUID24 } = __require("node:crypto");
93808
+ var { randomUUID: randomUUID23 } = __require("node:crypto");
93809
93809
  var { Readable: Readable4 } = __require("node:stream");
93810
93810
  var textEncoder;
93811
93811
  function isFormDataLike(payload) {
@@ -93813,7 +93813,7 @@ var require_form_data = __commonJS({
93813
93813
  }
93814
93814
  function formDataToStream(formdata) {
93815
93815
  textEncoder = textEncoder ?? new TextEncoder();
93816
- const boundary = `----formdata-${randomUUID24()}`;
93816
+ const boundary = `----formdata-${randomUUID23()}`;
93817
93817
  const prefix = `--${boundary}\r
93818
93818
  Content-Disposition: form-data`;
93819
93819
  const escape2 = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
@@ -100612,8 +100612,8 @@ var require_commonjs6 = __commonJS({
100612
100612
  return this.#fullpath = this.name;
100613
100613
  }
100614
100614
  const pv = p2.fullpath();
100615
- const fp36 = pv + (!p2.parent ? "" : this.sep) + name25;
100616
- return this.#fullpath = fp36;
100615
+ const fp35 = pv + (!p2.parent ? "" : this.sep) + name25;
100616
+ return this.#fullpath = fp35;
100617
100617
  }
100618
100618
  /**
100619
100619
  * On platforms other than windows, this is identical to fullpath.
@@ -105329,7 +105329,7 @@ var require_static = __commonJS({
105329
105329
  var { fileURLToPath: fileURLToPath4 } = __require("node:url");
105330
105330
  var { statSync: statSync2 } = __require("node:fs");
105331
105331
  var { glob } = require_commonjs7();
105332
- var fp36 = require_plugin2();
105332
+ var fp35 = require_plugin2();
105333
105333
  var send = require_send2();
105334
105334
  var encodingNegotiator = require_accept_negotiator();
105335
105335
  var contentDisposition = require_content_disposition();
@@ -105433,7 +105433,7 @@ var require_static = __commonJS({
105433
105433
  } else {
105434
105434
  const indexes = new Set(opts.index === void 0 ? ["index.html"] : [].concat(opts.index));
105435
105435
  const indexDirs = /* @__PURE__ */ new Map();
105436
- const routes35 = /* @__PURE__ */ new Set();
105436
+ const routes34 = /* @__PURE__ */ new Set();
105437
105437
  const roots = Array.isArray(sendOptions.root) ? sendOptions.root : [sendOptions.root];
105438
105438
  for (let rootPath of roots) {
105439
105439
  rootPath = rootPath.split(path22.win32.sep).join(path22.posix.sep);
@@ -105449,10 +105449,10 @@ var require_static = __commonJS({
105449
105449
  for (let file2 of files) {
105450
105450
  file2 = file2.split(path22.win32.sep).join(path22.posix.sep);
105451
105451
  const route = prefix + file2;
105452
- if (routes35.has(route)) {
105452
+ if (routes34.has(route)) {
105453
105453
  continue;
105454
105454
  }
105455
- routes35.add(route);
105455
+ routes34.add(route);
105456
105456
  setUpHeadAndGet(routeOpts, route, `/${file2}`, rootPath);
105457
105457
  const key2 = path22.posix.basename(route);
105458
105458
  if (indexes.has(key2) && !indexDirs.has(key2)) {
@@ -105747,7 +105747,7 @@ var require_static = __commonJS({
105747
105747
  throw err;
105748
105748
  }
105749
105749
  }
105750
- module.exports = fp36(fastifyStatic2, {
105750
+ module.exports = fp35(fastifyStatic2, {
105751
105751
  fastify: "5.x",
105752
105752
  name: "@fastify/static"
105753
105753
  });
@@ -112390,7 +112390,7 @@ var require_websocket2 = __commonJS({
112390
112390
  var { ServerResponse } = __require("node:http");
112391
112391
  var { PassThrough } = __require("node:stream");
112392
112392
  var { randomBytes: randomBytes3 } = __require("node:crypto");
112393
- var fp36 = require_plugin2();
112393
+ var fp35 = require_plugin2();
112394
112394
  var WebSocket2 = require_ws();
112395
112395
  var Duplexify = require_duplexify();
112396
112396
  var kWs = /* @__PURE__ */ Symbol("ws-socket");
@@ -112576,7 +112576,7 @@ var require_websocket2 = __commonJS({
112576
112576
  }
112577
112577
  next();
112578
112578
  }
112579
- module.exports = fp36(fastifyWebsocket2, {
112579
+ module.exports = fp35(fastifyWebsocket2, {
112580
112580
  fastify: "5.x",
112581
112581
  name: "@fastify/websocket"
112582
112582
  });
@@ -115020,7 +115020,7 @@ var require_multipart2 = __commonJS({
115020
115020
  "use strict";
115021
115021
  var Busboy = require_main();
115022
115022
  var os2 = __require("node:os");
115023
- var fp36 = require_plugin2();
115023
+ var fp35 = require_plugin2();
115024
115024
  var { createWriteStream: createWriteStream2 } = __require("node:fs");
115025
115025
  var { unlink: unlink2 } = __require("node:fs/promises");
115026
115026
  var path22 = __require("node:path");
@@ -115469,7 +115469,7 @@ var require_multipart2 = __commonJS({
115469
115469
  }
115470
115470
  });
115471
115471
  }
115472
- module.exports = fp36(fastifyMultipart2, {
115472
+ module.exports = fp35(fastifyMultipart2, {
115473
115473
  fastify: "5.x",
115474
115474
  name: "@fastify/multipart"
115475
115475
  });
@@ -169021,11 +169021,11 @@ function buildCommand(builderArgs) {
169021
169021
  }
169022
169022
  };
169023
169023
  }
169024
- function* generateRouteMapHelpLines(routes35, docs, args) {
169024
+ function* generateRouteMapHelpLines(routes34, docs, args) {
169025
169025
  const { brief, fullDescription, hideRoute } = docs;
169026
169026
  const { headers } = args.text;
169027
169027
  yield args.ansiColor ? `\x1B[1m${headers.usage}\x1B[22m` : headers.usage;
169028
- for (const [name25, route] of Object.entries(routes35)) {
169028
+ for (const [name25, route] of Object.entries(routes34)) {
169029
169029
  if (!hideRoute || !hideRoute[name25] || args.includeHidden) {
169030
169030
  const externalRouteName = args.config.caseStyle === "convert-camel-to-kebab" ? convertCamelCaseToKebabCase(name25) : name25;
169031
169031
  yield ` ${route.formatUsageLine({
@@ -169055,7 +169055,7 @@ function* generateRouteMapHelpLines(routes35, docs, args) {
169055
169055
  }
169056
169056
  yield "";
169057
169057
  yield args.ansiColor ? `\x1B[1m${headers.commands}\x1B[22m` : headers.commands;
169058
- const visibleRoutes = Object.entries(routes35).filter(
169058
+ const visibleRoutes = Object.entries(routes34).filter(
169059
169059
  ([name25]) => !hideRoute || !hideRoute[name25] || args.includeHidden
169060
169060
  );
169061
169061
  const rows = visibleRoutes.map(([internalRouteName, route]) => {
@@ -169083,24 +169083,24 @@ function* generateRouteMapHelpLines(routes35, docs, args) {
169083
169083
  }
169084
169084
  }
169085
169085
  function buildRouteMap({
169086
- routes: routes35,
169086
+ routes: routes34,
169087
169087
  defaultCommand: defaultCommandRoute,
169088
169088
  docs,
169089
169089
  aliases
169090
169090
  }) {
169091
- if (Object.entries(routes35).length === 0) {
169091
+ if (Object.entries(routes34).length === 0) {
169092
169092
  throw new InternalError("Route map must contain at least one route");
169093
169093
  }
169094
169094
  const activeAliases = aliases ?? {};
169095
169095
  const aliasesByRoute = /* @__PURE__ */ new Map();
169096
169096
  for (const [alias, routeName] of Object.entries(activeAliases)) {
169097
- if (alias in routes35) {
169097
+ if (alias in routes34) {
169098
169098
  throw new InternalError(`Cannot use "${alias}" as an alias when a route with that name already exists`);
169099
169099
  }
169100
169100
  const routeAliases = aliasesByRoute.get(routeName) ?? [];
169101
169101
  aliasesByRoute.set(routeName, [...routeAliases, alias]);
169102
169102
  }
169103
- const defaultCommand = defaultCommandRoute ? routes35[defaultCommandRoute] : void 0;
169103
+ const defaultCommand = defaultCommandRoute ? routes34[defaultCommandRoute] : void 0;
169104
169104
  if (defaultCommand && defaultCommand.kind === RouteMapSymbol) {
169105
169105
  throw new InternalError(
169106
169106
  `Cannot use "${defaultCommandRoute}" as the default command because it is not a Command`
@@ -169109,7 +169109,7 @@ function buildRouteMap({
169109
169109
  const resolveRouteName = (input) => {
169110
169110
  if (input in activeAliases) {
169111
169111
  return activeAliases[input];
169112
- } else if (input in routes35) {
169112
+ } else if (input in routes34) {
169113
169113
  return input;
169114
169114
  }
169115
169115
  };
@@ -169127,7 +169127,7 @@ function buildRouteMap({
169127
169127
  return `${args.prefix.join(" ")} ${routeNames.join("|")} ...`;
169128
169128
  },
169129
169129
  formatHelp: (config2) => {
169130
- const lines = [...generateRouteMapHelpLines(routes35, docs, config2)];
169130
+ const lines = [...generateRouteMapHelpLines(routes34, docs, config2)];
169131
169131
  const text2 = lines.join("\n");
169132
169132
  return text2 + "\n";
169133
169133
  },
@@ -169170,11 +169170,11 @@ function buildRouteMap({
169170
169170
  },
169171
169171
  getRoutingTargetForInput: (input) => {
169172
169172
  const routeName = input in activeAliases ? activeAliases[input] : input;
169173
- return routes35[routeName];
169173
+ return routes34[routeName];
169174
169174
  },
169175
169175
  getAllEntries() {
169176
169176
  const hiddenRoutes = docs.hideRoute;
169177
- return Object.entries(routes35).map(([originalRouteName, target]) => {
169177
+ return Object.entries(routes34).map(([originalRouteName, target]) => {
169178
169178
  return {
169179
169179
  name: {
169180
169180
  original: originalRouteName,
@@ -186340,10 +186340,6 @@ var createRemoteServerRepos = (kdb, _h) => ({
186340
186340
  // src/storage/repositories/executors.ts
186341
186341
  var mapExecutor = (row) => ({
186342
186342
  ...row,
186343
- // The DB column is nullable (legacy DDL), but every real caller supplies a
186344
- // group_id (routes/executor-routes.ts requires it; scheduler.ts/
186345
- // process-routes.ts pass ""), so this never actually surfaces null.
186346
- group_id: row.group_id ?? "",
186347
186343
  executor_type: row.executor_type || "command",
186348
186344
  prompt_provider: row.prompt_provider ?? null,
186349
186345
  pty: fromDbBool(row.pty),
@@ -186367,49 +186363,19 @@ var mapRemoteExecutorProcess = (row) => ({
186367
186363
  machine_id: row.machine_id
186368
186364
  });
186369
186365
  var createExecutorRepos = (kdb, h) => ({
186370
- executorGroups: {
186371
- create: async ({ id, project_id, name: name25, branch }) => {
186372
- await kdb.insertInto("executor_groups").values({ id, project_id, name: name25, branch }).execute();
186373
- const row = await kdb.selectFrom("executor_groups").selectAll().where("id", "=", id).executeTakeFirstOrThrow();
186374
- return row;
186375
- },
186376
- getByProjectId: async (projectId) => {
186377
- return kdb.selectFrom("executor_groups").selectAll().where("project_id", "=", projectId).orderBy("created_at", "asc").execute();
186378
- },
186379
- getById: async (id) => {
186380
- return kdb.selectFrom("executor_groups").selectAll().where("id", "=", id).executeTakeFirst();
186381
- },
186382
- getByBranch: async (projectId, branch) => {
186383
- return kdb.selectFrom("executor_groups").selectAll().where("project_id", "=", projectId).where("branch", "=", branch).executeTakeFirst();
186384
- },
186385
- createIfBranchFree: async ({ id, project_id, name: name25, branch }) => {
186386
- const result = await kdb.insertInto("executor_groups").values({ id, project_id, name: name25, branch }).onConflict((oc) => oc.columns(["project_id", "branch"]).doNothing()).executeTakeFirst();
186387
- const group2 = await kdb.selectFrom("executor_groups").selectAll().where("project_id", "=", project_id).where("branch", "=", branch).executeTakeFirstOrThrow();
186388
- return { created: (result?.numInsertedOrUpdatedRows ?? 0n) > 0n, group: group2 };
186389
- },
186390
- update: async (id, opts) => {
186391
- if (opts.name !== void 0) {
186392
- await kdb.updateTable("executor_groups").set({ name: opts.name }).where("id", "=", id).execute();
186393
- }
186394
- return kdb.selectFrom("executor_groups").selectAll().where("id", "=", id).executeTakeFirst();
186395
- },
186396
- delete: async (id) => {
186397
- await kdb.deleteFrom("executor_groups").where("id", "=", id).execute();
186398
- }
186399
- },
186400
186366
  executors: {
186401
- create: async ({ id, project_id, group_id, name: name25, command, executor_type, prompt_provider, cwd, pty: pty2 }) => {
186367
+ create: async ({ id, project_id, workspace_id, name: name25, command, executor_type, prompt_provider, cwd, pty: pty2 }) => {
186402
186368
  await kdb.insertInto("executors").values((eb) => ({
186403
186369
  id,
186404
186370
  project_id,
186405
- group_id,
186371
+ workspace_id,
186406
186372
  name: name25,
186407
186373
  command,
186408
186374
  executor_type: executor_type ?? "command",
186409
186375
  prompt_provider: prompt_provider ?? null,
186410
186376
  cwd: cwd ?? null,
186411
186377
  pty: h.toDbBool(pty2 !== false),
186412
- position: eb.selectFrom("executors").select(sql`coalesce(max(position), -1) + 1`.as("next_position")).where("group_id", "=", group_id)
186378
+ position: eb.selectFrom("executors").select(sql`coalesce(max(position), -1) + 1`.as("next_position")).where("workspace_id", "=", workspace_id)
186413
186379
  })).execute();
186414
186380
  const row = await kdb.selectFrom("executors").selectAll().where("id", "=", id).executeTakeFirstOrThrow();
186415
186381
  return mapExecutor(row);
@@ -186418,8 +186384,8 @@ var createExecutorRepos = (kdb, h) => ({
186418
186384
  const rows = await kdb.selectFrom("executors").selectAll().where("project_id", "=", projectId).orderBy("position", "asc").execute();
186419
186385
  return rows.map(mapExecutor);
186420
186386
  },
186421
- getByGroupId: async (groupId) => {
186422
- const rows = await kdb.selectFrom("executors").selectAll().where("group_id", "=", groupId).orderBy("position", "asc").execute();
186387
+ getByWorkspaceId: async (workspaceId) => {
186388
+ const rows = await kdb.selectFrom("executors").selectAll().where("workspace_id", "=", workspaceId).orderBy("position", "asc").execute();
186423
186389
  return rows.map(mapExecutor);
186424
186390
  },
186425
186391
  getById: async (id) => {
@@ -186456,10 +186422,10 @@ var createExecutorRepos = (kdb, h) => ({
186456
186422
  delete: async (id) => {
186457
186423
  await kdb.deleteFrom("executors").where("id", "=", id).execute();
186458
186424
  },
186459
- reorder: async (groupId, orderedIds) => {
186425
+ reorder: async (workspaceId, orderedIds) => {
186460
186426
  await kdb.transaction().execute(async (trx) => {
186461
186427
  for (let i = 0; i < orderedIds.length; i++) {
186462
- await trx.updateTable("executors").set({ position: i }).where("id", "=", orderedIds[i]).where("group_id", "=", groupId).execute();
186428
+ await trx.updateTable("executors").set({ position: i }).where("id", "=", orderedIds[i]).where("workspace_id", "=", workspaceId).execute();
186463
186429
  }
186464
186430
  });
186465
186431
  }
@@ -203469,6 +203435,14 @@ var createWorkspaceRegistryRepo = (kdb, h) => ({
203469
203435
  }
203470
203436
  };
203471
203437
  },
203438
+ getWorkspaceById: async (workspaceId) => {
203439
+ const row = await kdb.selectFrom("workspaces").selectAll().where("id", "=", workspaceId).executeTakeFirst();
203440
+ return row ? mapWorkspace(row) : void 0;
203441
+ },
203442
+ getWorkspaceByProjectBranch: async (projectId, branch) => {
203443
+ const row = await kdb.selectFrom("workspaces").selectAll().where("project_id", "=", projectId).where("branch", "=", branch).executeTakeFirst();
203444
+ return row ? mapWorkspace(row) : void 0;
203445
+ },
203472
203446
  markCheckoutDeleted: async (checkoutId) => {
203473
203447
  await kdb.transaction().execute(async (trx) => {
203474
203448
  const checkout = await trx.selectFrom("workspace_checkouts").select(["workspace_id", "deleted_at"]).where("id", "=", checkoutId).executeTakeFirst();
@@ -203730,20 +203704,10 @@ var createDatabase = (dbPath) => {
203730
203704
  CREATE INDEX IF NOT EXISTS idx_project_chat_operations_thread_status_created_id
203731
203705
  ON project_chat_operations(thread_id, status, created_at, id);
203732
203706
 
203733
- CREATE TABLE IF NOT EXISTS executor_groups (
203734
- id TEXT PRIMARY KEY,
203735
- project_id TEXT NOT NULL,
203736
- name TEXT NOT NULL,
203737
- branch TEXT NOT NULL DEFAULT '',
203738
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
203739
- UNIQUE(project_id, branch),
203740
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
203741
- );
203742
-
203743
203707
  CREATE TABLE IF NOT EXISTS executors (
203744
203708
  id TEXT PRIMARY KEY,
203745
203709
  project_id TEXT NOT NULL,
203746
- group_id TEXT,
203710
+ workspace_id TEXT NOT NULL,
203747
203711
  name TEXT NOT NULL,
203748
203712
  command TEXT NOT NULL,
203749
203713
  executor_type TEXT DEFAULT 'command',
@@ -203754,7 +203718,7 @@ var createDatabase = (dbPath) => {
203754
203718
  disabled_targets TEXT DEFAULT '[]',
203755
203719
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
203756
203720
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
203757
- FOREIGN KEY (group_id) REFERENCES executor_groups(id) ON DELETE CASCADE
203721
+ FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
203758
203722
  );
203759
203723
 
203760
203724
  CREATE TABLE IF NOT EXISTS executor_processes (
@@ -204265,31 +204229,6 @@ var createDatabase = (dbPath) => {
204265
204229
  db.exec("CREATE INDEX IF NOT EXISTS idx_projects_user_id ON projects(user_id)");
204266
204230
  }
204267
204231
  db.exec("UPDATE projects SET user_id = 'local' WHERE user_id = ''");
204268
- const hasGroupIdColumn = tableInfo.some((col) => col.name === "group_id");
204269
- if (!hasGroupIdColumn) {
204270
- db.exec(`
204271
- CREATE TABLE IF NOT EXISTS executor_groups (
204272
- id TEXT PRIMARY KEY,
204273
- project_id TEXT NOT NULL,
204274
- name TEXT NOT NULL,
204275
- branch TEXT NOT NULL DEFAULT '',
204276
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
204277
- UNIQUE(project_id, branch),
204278
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
204279
- )
204280
- `);
204281
- db.exec("ALTER TABLE executors ADD COLUMN group_id TEXT REFERENCES executor_groups(id) ON DELETE CASCADE");
204282
- const projects = db.prepare("SELECT DISTINCT project_id FROM executors").all();
204283
- for (const { project_id } of projects) {
204284
- const groupId = `default-${project_id}`;
204285
- db.prepare(
204286
- "INSERT OR IGNORE INTO executor_groups (id, project_id, name, branch) VALUES (@id, @project_id, 'Default', '')"
204287
- ).run({ id: groupId, project_id });
204288
- db.prepare(
204289
- "UPDATE executors SET group_id = @group_id WHERE project_id = @project_id AND group_id IS NULL"
204290
- ).run({ group_id: groupId, project_id });
204291
- }
204292
- }
204293
204232
  const taskTableInfo = db.prepare("PRAGMA table_info(tasks)").all();
204294
204233
  const hasAssignedBranchColumn = taskTableInfo.some((col) => col.name === "assigned_branch");
204295
204234
  if (!hasAssignedBranchColumn) {
@@ -205115,6 +205054,79 @@ var createDatabase = (dbPath) => {
205115
205054
  db.prepare(`DELETE FROM global_settings WHERE key IN (${placeholders})`).run(...USER_LEVEL_KEYS);
205116
205055
  });
205117
205056
  migrateUserSettings();
205057
+ const executorColsForWorkspace = db.prepare("PRAGMA table_info(executors)").all();
205058
+ if (executorColsForWorkspace.some((col) => col.name === "group_id")) {
205059
+ db.transaction(() => {
205060
+ const ensureWorkspace = db.prepare(
205061
+ `INSERT INTO workspaces (id, project_id, branch, status, error)
205062
+ VALUES (@id, @project_id, @branch, 'archived', NULL)
205063
+ ON CONFLICT(project_id, branch) DO NOTHING`
205064
+ );
205065
+ const groups = db.prepare(`
205066
+ SELECT DISTINCT g.project_id AS project_id, g.branch AS branch
205067
+ FROM executor_groups g
205068
+ JOIN executors e ON e.group_id = g.id
205069
+ JOIN projects p ON p.id = g.project_id
205070
+ `).all();
205071
+ for (const group2 of groups) {
205072
+ ensureWorkspace.run({ id: crypto5.randomUUID(), project_id: group2.project_id, branch: group2.branch });
205073
+ }
205074
+ const orphanProjects = db.prepare(`
205075
+ SELECT DISTINCT e.project_id AS project_id
205076
+ FROM executors e
205077
+ JOIN projects p ON p.id = e.project_id
205078
+ WHERE e.group_id IS NULL
205079
+ OR NOT EXISTS (SELECT 1 FROM executor_groups g WHERE g.id = e.group_id)
205080
+ `).all();
205081
+ for (const { project_id } of orphanProjects) {
205082
+ ensureWorkspace.run({ id: crypto5.randomUUID(), project_id, branch: "" });
205083
+ }
205084
+ db.exec(`
205085
+ CREATE TABLE executors_workspace_new (
205086
+ id TEXT PRIMARY KEY,
205087
+ project_id TEXT NOT NULL,
205088
+ workspace_id TEXT NOT NULL,
205089
+ name TEXT NOT NULL,
205090
+ command TEXT NOT NULL,
205091
+ executor_type TEXT DEFAULT 'command',
205092
+ prompt_provider TEXT,
205093
+ cwd TEXT,
205094
+ pty INTEGER DEFAULT 1,
205095
+ position INTEGER DEFAULT 0,
205096
+ disabled_targets TEXT DEFAULT '[]',
205097
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
205098
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
205099
+ FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
205100
+ );
205101
+
205102
+ INSERT INTO executors_workspace_new
205103
+ (id, project_id, workspace_id, name, command, executor_type,
205104
+ prompt_provider, cwd, pty, position, disabled_targets, created_at)
205105
+ SELECT e.id, e.project_id, w.id, e.name, e.command, e.executor_type,
205106
+ e.prompt_provider, e.cwd, e.pty,
205107
+ ROW_NUMBER() OVER (
205108
+ PARTITION BY w.id ORDER BY e.position, e.created_at, e.id
205109
+ ) - 1,
205110
+ e.disabled_targets, e.created_at
205111
+ FROM executors e
205112
+ LEFT JOIN executor_groups g ON g.id = e.group_id
205113
+ JOIN workspaces w
205114
+ ON w.project_id = e.project_id AND w.branch = COALESCE(g.branch, '');
205115
+ `);
205116
+ const dropped = db.prepare(
205117
+ "SELECT COUNT(*) AS n FROM executors WHERE id NOT IN (SELECT id FROM executors_workspace_new)"
205118
+ ).get().n;
205119
+ if (dropped > 0) {
205120
+ console.warn(`[storage] executor\u2192workspace migration skipped ${dropped} executor(s) with no surviving project`);
205121
+ }
205122
+ db.exec(`
205123
+ DROP TABLE executors;
205124
+ ALTER TABLE executors_workspace_new RENAME TO executors;
205125
+ DROP TABLE IF EXISTS executor_groups;
205126
+ `);
205127
+ })();
205128
+ }
205129
+ db.exec("CREATE INDEX IF NOT EXISTS idx_executors_workspace ON executors(workspace_id, position)");
205118
205130
  db.pragma("foreign_keys = ON");
205119
205131
  return db;
205120
205132
  };
@@ -206342,6 +206354,92 @@ ${GREEN}Done${info}${RESET}
206342
206354
  }
206343
206355
  return terminals;
206344
206356
  }
206357
+ /**
206358
+ * Running processes — executor runs and interactive terminals alike — whose
206359
+ * working directory is `root` or below it. Used to clear a worktree before
206360
+ * it is deleted out from under them.
206361
+ *
206362
+ * Matching is by cwd rather than by branch on purpose: only terminals carry
206363
+ * a `branch`, executor runs are always recorded with `branch: null`, and on
206364
+ * a reverse-connect worker they are path-based with no executor row to join
206365
+ * through. The cwd is the one identity every spawn path records.
206366
+ */
206367
+ getRunningProcessIdsUnderPath(root) {
206368
+ const resolvedRoot = path5.resolve(root);
206369
+ const ids = [];
206370
+ for (const [id, proc] of this.processes) {
206371
+ const relative = path5.relative(resolvedRoot, path5.resolve(proc.projectPath));
206372
+ const outside = relative === ".." || relative.startsWith(`..${path5.sep}`) || path5.isAbsolute(relative);
206373
+ if (relative !== "" && outside) continue;
206374
+ if (this.isRunning(id)) ids.push(id);
206375
+ }
206376
+ return ids;
206377
+ }
206378
+ /**
206379
+ * True once the tracked process has genuinely exited (or is no longer
206380
+ * tracked at all).
206381
+ *
206382
+ * Deliberately not `!isRunning()`: that helper treats `ChildProcess.killed`
206383
+ * as exited, and Node sets `killed` the moment a signal is *delivered*, so
206384
+ * it would report success while the process is still winding down. Real
206385
+ * exit is only observable through `exitCode`/`signalCode` for a child, or
206386
+ * the "finished" log the PTY exit handler appends.
206387
+ */
206388
+ hasExited(processId) {
206389
+ const runningProcess = this.processes.get(processId);
206390
+ if (!runningProcess) return true;
206391
+ if (runningProcess.isPty) {
206392
+ return runningProcess.logs[runningProcess.logs.length - 1]?.type === "finished";
206393
+ }
206394
+ const childProcess2 = runningProcess.process;
206395
+ return childProcess2.exitCode !== null || childProcess2.signalCode !== null;
206396
+ }
206397
+ async waitForExit(processId, timeoutMs) {
206398
+ const deadline = Date.now() + timeoutMs;
206399
+ while (!this.hasExited(processId)) {
206400
+ if (Date.now() >= deadline) return false;
206401
+ await new Promise((resolve3) => setTimeout(resolve3, 25));
206402
+ }
206403
+ return true;
206404
+ }
206405
+ signalProcessGroup(processId, signal) {
206406
+ const runningProcess = this.processes.get(processId);
206407
+ if (!runningProcess) return;
206408
+ const pid = runningProcess.isPty ? runningProcess.process.pid : runningProcess.process.pid;
206409
+ if (!pid) return;
206410
+ try {
206411
+ process.kill(-pid, signal);
206412
+ } catch {
206413
+ try {
206414
+ process.kill(pid, signal);
206415
+ } catch {
206416
+ }
206417
+ }
206418
+ }
206419
+ /**
206420
+ * Stop a process and confirm it actually exited, escalating to SIGKILL when
206421
+ * SIGTERM is ignored. Returns false if it is still alive after that.
206422
+ *
206423
+ * `stop()` alone is not enough for a caller that needs the working directory
206424
+ * to be free — deleting a worktree — because it reports only that a signal
206425
+ * was delivered. SIGTERM is asynchronous and can be trapped or ignored, so
206426
+ * the process may still be writing into the tree when `stop()` resolves.
206427
+ *
206428
+ * What this confirms is the exit of the tracked process, and with it
206429
+ * whatever else shared its process group. A grandchild that detached into
206430
+ * its own group or session is not observable here and is not covered.
206431
+ */
206432
+ async stopAndWait(processId, opts) {
206433
+ await this.stop(processId);
206434
+ if (await this.waitForExit(processId, opts?.termGraceMs ?? 3e3)) return true;
206435
+ console.warn(`[ProcessManager] Process ${processId} ignored SIGTERM, escalating to SIGKILL`);
206436
+ this.signalProcessGroup(processId, "SIGKILL");
206437
+ const exited = await this.waitForExit(processId, opts?.killGraceMs ?? 2e3);
206438
+ if (!exited) {
206439
+ console.error(`[ProcessManager] Process ${processId} survived SIGKILL \u2014 cannot confirm exit`);
206440
+ }
206441
+ return exited;
206442
+ }
206345
206443
  /**
206346
206444
  * Get all processes for a given executor ID with their status and logs
206347
206445
  */
@@ -207414,8 +207512,12 @@ function reconcileWorktreeBranches(projectPath, entries, sessionBranches = [], r
207414
207512
  }
207415
207513
  const rootEntry = entries[0];
207416
207514
  const rootAnchor = rootEntry ? registryByPath.get(path6.resolve(rootEntry.path)) : void 0;
207417
- const rootDrifted = Boolean(rootAnchor) && rootEntry?.branch != null && rootEntry.branch !== rootAnchor.expectedBranch;
207418
- const worktrees = [rootDrifted ? { branch: null, currentBranch: rootEntry?.branch ?? null } : { branch: null }];
207515
+ const rootExpectedBranch = rootAnchor?.expectedBranch || void 0;
207516
+ const rootDrifted = rootExpectedBranch !== void 0 && rootEntry?.branch != null && rootEntry.branch !== rootExpectedBranch;
207517
+ const root = { branch: null };
207518
+ if (rootExpectedBranch) root.expectedBranch = rootExpectedBranch;
207519
+ if (rootDrifted) root.currentBranch = rootEntry?.branch ?? null;
207520
+ const worktrees = [root];
207419
207521
  for (let i = 1; i < entries.length; i++) {
207420
207522
  const entry = entries[i];
207421
207523
  const anchor = registryByPath.get(path6.resolve(entry.path));
@@ -207462,6 +207564,15 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
207462
207564
  if (existing.checkout.status === "creating" || existing.checkout.status === "error") {
207463
207565
  await storage.workspaceRegistry.setCheckoutStatus(existing.checkout.id, "ready");
207464
207566
  }
207567
+ if (index === 0 && existing.checkout.expected_branch === "" && entry.branch) {
207568
+ await storage.workspaceRegistry.registerReadyCheckout({
207569
+ projectId,
207570
+ branch: existing.workspace.branch,
207571
+ targetId: "local",
207572
+ worktreePath: entry.path,
207573
+ expectedBranch: entry.branch
207574
+ });
207575
+ }
207465
207576
  continue;
207466
207577
  }
207467
207578
  if (registeredPaths.has(resolvedPath) || entry.branch === null && index > 0) continue;
@@ -207483,6 +207594,22 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
207483
207594
  }));
207484
207595
  return reconcileWorktreeBranches(projectPath, entries, sessionBranches, anchors);
207485
207596
  }
207597
+ async function anchorRootWorkspaceBranch(storage, projectId, projectPath, observedBranch) {
207598
+ invalidateWorktreeListCache(projectPath);
207599
+ const rootEntry = readWorktreeListTolerant(projectPath)[0];
207600
+ if (!rootEntry || rootEntry.branch !== observedBranch) {
207601
+ return { anchored: false, currentBranch: rootEntry?.branch ?? null };
207602
+ }
207603
+ await storage.workspaceRegistry.registerReadyCheckout({
207604
+ projectId,
207605
+ branch: "",
207606
+ // The main-workspace identity sentinel; never the branch name.
207607
+ targetId: "local",
207608
+ worktreePath: rootEntry.path,
207609
+ expectedBranch: rootEntry.branch
207610
+ });
207611
+ return { anchored: true, expectedBranch: rootEntry.branch };
207612
+ }
207486
207613
 
207487
207614
  // ../../node_modules/.pnpm/@ai-sdk+provider@3.0.8/node_modules/@ai-sdk/provider/dist/index.mjs
207488
207615
  var marker = "vercel.ai.error";
@@ -230148,6 +230275,16 @@ var AgentSessionManager = class {
230148
230275
  }
230149
230276
  return results;
230150
230277
  }
230278
+ /**
230279
+ * Ids of the sessions in one workspace that still own a live child process,
230280
+ * whatever their turn status. Deliberately broader than
230281
+ * `getRunningResidentProcesses`, which also demands `status === "running"`:
230282
+ * a resident process idling between turns is exactly the one that would be
230283
+ * orphaned when its worktree is deleted.
230284
+ */
230285
+ getLiveSessionIdsForBranch(projectId, branch) {
230286
+ return [...this.sessions.values()].filter((session) => session.projectId === projectId && session.branch === branch && this.isProcessAlive(session)).map((session) => session.id);
230287
+ }
230151
230288
  /**
230152
230289
  * Check if a session is running
230153
230290
  */
@@ -230160,8 +230297,11 @@ var AgentSessionManager = class {
230160
230297
  * (like pressing ESC in Claude Code). The session becomes dormant so the
230161
230298
  * next user message will spawn a fresh process with full context replay.
230162
230299
  * The WebSocket stays alive so the UI remains connected.
230300
+ *
230301
+ * `opts.note` overrides the system entry written into the conversation, for
230302
+ * stops the user did not press Stop for (e.g. the worktree being deleted).
230163
230303
  */
230164
- async stopSession(sessionId) {
230304
+ async stopSession(sessionId, opts) {
230165
230305
  const session = this.sessions.get(sessionId);
230166
230306
  if (!session) {
230167
230307
  return false;
@@ -230180,7 +230320,7 @@ var AgentSessionManager = class {
230180
230320
  session.store.currentAssistantIndex = null;
230181
230321
  await this.pushEntry(sessionId, {
230182
230322
  type: "system",
230183
- content: "Session stopped by user.",
230323
+ content: opts?.note ?? "Session stopped by user.",
230184
230324
  timestamp: Date.now()
230185
230325
  });
230186
230326
  await this.endActiveTurn(session, "stopped");
@@ -230204,6 +230344,41 @@ var AgentSessionManager = class {
230204
230344
  return false;
230205
230345
  }
230206
230346
  }
230347
+ /**
230348
+ * Stop a session and confirm its agent process actually exited, escalating
230349
+ * to SIGKILL when SIGTERM is ignored. Returns false if the process is still
230350
+ * alive after that.
230351
+ *
230352
+ * `stopSession` returns as soon as the signal has been sent, which is fine
230353
+ * for the Stop button but not for a caller that is about to delete the
230354
+ * session's working directory: an agent that traps SIGTERM to flush state
230355
+ * would keep writing into a tree that no longer exists.
230356
+ *
230357
+ * Confirms the tracked agent process, and with it whatever else shared its
230358
+ * process group. A grandchild that detached into its own group or session
230359
+ * (an MCP server started with `setsid`, say) is not observable here.
230360
+ */
230361
+ async stopSessionAndWait(sessionId, opts) {
230362
+ const proc = this.sessions.get(sessionId)?.process ?? null;
230363
+ const stopped = await this.stopSession(sessionId, { note: opts?.note });
230364
+ if (!stopped || !proc) return stopped;
230365
+ if (await this.waitForProcessExit(proc, opts?.termGraceMs ?? 3e3)) return true;
230366
+ console.warn(`[AgentSession] Session ${sessionId} ignored SIGTERM, escalating to SIGKILL`);
230367
+ this.killProcess(proc, "SIGKILL");
230368
+ const exited = await this.waitForProcessExit(proc, opts?.killGraceMs ?? 2e3);
230369
+ if (!exited) {
230370
+ console.error(`[AgentSession] Session ${sessionId} survived SIGKILL \u2014 cannot confirm exit`);
230371
+ }
230372
+ return exited;
230373
+ }
230374
+ async waitForProcessExit(proc, timeoutMs) {
230375
+ const deadline = Date.now() + timeoutMs;
230376
+ while (proc.exitCode === null && proc.signalCode === null) {
230377
+ if (Date.now() >= deadline) return false;
230378
+ await new Promise((resolve3) => setTimeout(resolve3, 25));
230379
+ }
230380
+ return true;
230381
+ }
230207
230382
  async hibernateSession(sessionId) {
230208
230383
  const session = this.sessions.get(sessionId);
230209
230384
  if (!session) return false;
@@ -232739,12 +232914,12 @@ var ChatSessionManager = class {
232739
232914
  console.log(`[ChatSession] handleExecutorFinished: executor not found`);
232740
232915
  return;
232741
232916
  }
232742
- const group2 = await this.storage.executorGroups.getById(executor.group_id);
232743
- if (!group2) {
232744
- console.log(`[ChatSession] handleExecutorFinished: group not found for executor.group_id=${executor.group_id}`);
232917
+ const workspace = await this.storage.workspaceRegistry.getWorkspaceById(executor.workspace_id);
232918
+ if (!workspace) {
232919
+ console.log(`[ChatSession] handleExecutorFinished: workspace not found for executor.workspace_id=${executor.workspace_id}`);
232745
232920
  return;
232746
232921
  }
232747
- const branch = group2.branch || null;
232922
+ const branch = workspace.branch || null;
232748
232923
  const key2 = `${event.projectId}:${branch ?? ""}`;
232749
232924
  const sessionId = this.sessionIndex.get(key2);
232750
232925
  if (!sessionId) {
@@ -233771,11 +233946,11 @@ var ChatSessionManager = class {
233771
233946
  tailLines: external_exports.number().min(1).max(100).default(20).describe("Number of recent output lines to include per executor")
233772
233947
  }),
233773
233948
  execute: async ({ tailLines }) => {
233774
- const group2 = await storage.executorGroups.getByBranch(projectId, branch ?? "");
233775
- if (!group2) {
233776
- return { executors: [], message: "No executor group found for this workspace." };
233949
+ const workspace = await storage.workspaceRegistry.getWorkspaceByProjectBranch(projectId, branch ?? "");
233950
+ if (!workspace) {
233951
+ return { executors: [], message: "No workspace found for this branch." };
233777
233952
  }
233778
- const executors = await storage.executors.getByGroupId(group2.id);
233953
+ const executors = await storage.executors.getByWorkspaceId(workspace.id);
233779
233954
  const now3 = Date.now();
233780
233955
  const results = await Promise.all(executors.map(async (executor) => {
233781
233956
  const lastRow = await storage.executorProcesses.getLastByExecutorId(executor.id);
@@ -233817,11 +233992,11 @@ var ChatSessionManager = class {
233817
233992
  remote: external_exports.string().optional().describe("Remote server name or ID to run the executor on. If omitted, uses project executor_mode or runs locally.")
233818
233993
  }),
233819
233994
  execute: async ({ executorName, remote }) => {
233820
- const group2 = await storage.executorGroups.getByBranch(projectId, branch ?? "");
233821
- if (!group2) {
233822
- return { success: false, message: "No executor group found for this workspace." };
233995
+ const workspace = await storage.workspaceRegistry.getWorkspaceByProjectBranch(projectId, branch ?? "");
233996
+ if (!workspace) {
233997
+ return { success: false, message: "No workspace found for this branch." };
233823
233998
  }
233824
- const executors = await storage.executors.getByGroupId(group2.id);
233999
+ const executors = await storage.executors.getByWorkspaceId(workspace.id);
233825
234000
  const executor = executors.find(
233826
234001
  (e) => e.name.toLowerCase() === executorName.toLowerCase()
233827
234002
  );
@@ -233957,11 +234132,11 @@ var ChatSessionManager = class {
233957
234132
  remote: external_exports.string().optional().describe("Remote server name or ID where the executor is running. If omitted, auto-detects.")
233958
234133
  }),
233959
234134
  execute: async ({ executorName, remote }) => {
233960
- const group2 = await storage.executorGroups.getByBranch(projectId, branch ?? "");
233961
- if (!group2) {
233962
- return { success: false, message: "No executor group found for this workspace." };
234135
+ const workspace = await storage.workspaceRegistry.getWorkspaceByProjectBranch(projectId, branch ?? "");
234136
+ if (!workspace) {
234137
+ return { success: false, message: "No workspace found for this branch." };
233963
234138
  }
233964
- const executors = await storage.executors.getByGroupId(group2.id);
234139
+ const executors = await storage.executors.getByWorkspaceId(workspace.id);
233965
234140
  const executor = executors.find(
233966
234141
  (e) => e.name.toLowerCase() === executorName.toLowerCase()
233967
234142
  );
@@ -239679,7 +239854,7 @@ var SchedulerService = class {
239679
239854
  const executor = {
239680
239855
  id: `schedule-${task.id}`,
239681
239856
  project_id: task.project_id,
239682
- group_id: "",
239857
+ workspace_id: "",
239683
239858
  name: task.name,
239684
239859
  command: buildRunContent(task),
239685
239860
  executor_type: task.run_type,
@@ -241459,91 +241634,15 @@ var routes5 = async (fastify2) => {
241459
241634
  };
241460
241635
  var project_remote_routes_default = (0, import_fastify_plugin6.default)(routes5, { name: "project-remote-routes" });
241461
241636
 
241462
- // src/routes/executor-group-routes.ts
241637
+ // src/routes/executor-routes.ts
241463
241638
  var import_fastify_plugin7 = __toESM(require_plugin2(), 1);
241464
241639
  import { randomUUID as randomUUID11 } from "crypto";
241465
- var routes6 = async (fastify2) => {
241466
- fastify2.get(
241467
- "/api/projects/:projectId/executor-groups",
241468
- async (req, reply) => {
241469
- const userId = requireUserFacingUserId(req, reply);
241470
- if (userId === null) return;
241471
- const project = await fastify2.storage.projects.getById(req.params.projectId, userId);
241472
- if (!project) {
241473
- return reply.code(404).send({ error: "Project not found" });
241474
- }
241475
- const groups = await fastify2.storage.executorGroups.getByProjectId(req.params.projectId);
241476
- return reply.code(200).send({ groups });
241477
- }
241478
- );
241479
- fastify2.get(
241480
- "/api/projects/:projectId/executor-groups/by-branch",
241481
- async (req, reply) => {
241482
- const userId = requireUserFacingUserId(req, reply);
241483
- if (userId === null) return;
241484
- const project = await fastify2.storage.projects.getById(req.params.projectId, userId);
241485
- if (!project) {
241486
- return reply.code(404).send({ error: "Project not found" });
241487
- }
241488
- const branch = req.query.branch ?? "";
241489
- const group2 = await fastify2.storage.executorGroups.getByBranch(req.params.projectId, branch);
241490
- if (!group2) {
241491
- return reply.code(404).send({ error: "Executor group not found for this branch" });
241492
- }
241493
- return reply.code(200).send({ group: group2 });
241494
- }
241495
- );
241496
- fastify2.post("/api/projects/:projectId/executor-groups", async (req, reply) => {
241497
- const userId = requireUserFacingUserId(req, reply);
241498
- if (userId === null) return;
241499
- const project = await fastify2.storage.projects.getById(req.params.projectId, userId);
241500
- if (!project) {
241501
- return reply.code(404).send({ error: "Project not found" });
241502
- }
241503
- const { name: name25, branch } = req.body;
241504
- const id = randomUUID11();
241505
- const result = await fastify2.storage.executorGroups.createIfBranchFree({
241506
- id,
241507
- project_id: req.params.projectId,
241508
- name: name25,
241509
- branch
241510
- });
241511
- if (!result.created) {
241512
- return reply.code(409).send({ error: "An executor group already exists for this branch" });
241513
- }
241514
- return reply.code(201).send({ group: result.group });
241515
- });
241516
- fastify2.put("/api/executor-groups/:id", async (req, reply) => {
241517
- const existing = await fastify2.storage.executorGroups.getById(req.params.id);
241518
- if (!existing) {
241519
- return reply.code(404).send({ error: "Executor group not found" });
241520
- }
241521
- const group2 = await fastify2.storage.executorGroups.update(req.params.id, req.body);
241522
- return reply.code(200).send({ group: group2 });
241523
- });
241524
- fastify2.delete(
241525
- "/api/executor-groups/:id",
241526
- async (req, reply) => {
241527
- const existing = await fastify2.storage.executorGroups.getById(req.params.id);
241528
- if (!existing) {
241529
- return reply.code(404).send({ error: "Executor group not found" });
241530
- }
241531
- await fastify2.storage.executorGroups.delete(req.params.id);
241532
- return reply.code(200).send({ success: true });
241533
- }
241534
- );
241535
- };
241536
- var executor_group_routes_default = (0, import_fastify_plugin7.default)(routes6, { name: "executor-group-routes" });
241537
-
241538
- // src/routes/executor-routes.ts
241539
- var import_fastify_plugin8 = __toESM(require_plugin2(), 1);
241540
- import { randomUUID as randomUUID12 } from "crypto";
241541
241640
  function normalizeSqlTimestamp(value) {
241542
241641
  if (!value) return null;
241543
241642
  if (value.includes("T") && /(Z|[+-]\d{2}:?\d{2})$/.test(value)) return value;
241544
241643
  return value.replace(" ", "T") + "Z";
241545
241644
  }
241546
- var routes7 = async (fastify2) => {
241645
+ var routes6 = async (fastify2) => {
241547
241646
  fastify2.get(
241548
241647
  "/api/projects/:projectId/executors",
241549
241648
  async (req, reply) => {
@@ -241553,7 +241652,16 @@ var routes7 = async (fastify2) => {
241553
241652
  if (!project) {
241554
241653
  return reply.code(404).send({ error: "Project not found" });
241555
241654
  }
241556
- const executors = req.query.groupId ? await fastify2.storage.executors.getByGroupId(req.query.groupId) : await fastify2.storage.executors.getByProjectId(req.params.projectId);
241655
+ let executors;
241656
+ if (req.query.branch === void 0) {
241657
+ executors = await fastify2.storage.executors.getByProjectId(req.params.projectId);
241658
+ } else {
241659
+ const workspace = await fastify2.storage.workspaceRegistry.getWorkspaceByProjectBranch(
241660
+ req.params.projectId,
241661
+ req.query.branch
241662
+ );
241663
+ executors = workspace ? await fastify2.storage.executors.getByWorkspaceId(workspace.id) : [];
241664
+ }
241557
241665
  const executorIds = executors.map((e) => e.id);
241558
241666
  const hasLocal = !!project.path;
241559
241667
  const hasRemotes = (await fastify2.storage.projectRemotes.getByProject(req.params.projectId)).length > 0;
@@ -241595,17 +241703,24 @@ var routes7 = async (fastify2) => {
241595
241703
  if (!project) {
241596
241704
  return reply.code(404).send({ error: "Project not found" });
241597
241705
  }
241598
- const { name: name25, command, executor_type, prompt_provider, cwd, pty: pty2, group_id } = req.body;
241599
- if (!group_id) {
241600
- return reply.code(400).send({ error: "group_id is required" });
241706
+ const { name: name25, command, executor_type, prompt_provider, cwd, pty: pty2, branch } = req.body;
241707
+ if (branch === void 0) {
241708
+ return reply.code(400).send({ error: "branch is required" });
241709
+ }
241710
+ const workspace = await fastify2.storage.workspaceRegistry.getWorkspaceByProjectBranch(
241711
+ req.params.projectId,
241712
+ branch
241713
+ );
241714
+ if (!workspace) {
241715
+ return reply.code(400).send({ error: "No workspace for this branch" });
241601
241716
  }
241602
241717
  const parsedType2 = executor_type === "prompt" ? "prompt" : "command";
241603
241718
  const parsedProvider = prompt_provider === "codex" ? "codex" : "claude";
241604
- const id = randomUUID12();
241719
+ const id = randomUUID11();
241605
241720
  const executor = await fastify2.storage.executors.create({
241606
241721
  id,
241607
241722
  project_id: req.params.projectId,
241608
- group_id,
241723
+ workspace_id: workspace.id,
241609
241724
  name: name25,
241610
241725
  command,
241611
241726
  executor_type: parsedType2,
@@ -241664,31 +241779,38 @@ var routes7 = async (fastify2) => {
241664
241779
  if (!project) {
241665
241780
  return reply.code(404).send({ error: "Project not found" });
241666
241781
  }
241667
- const { orderedIds, groupId } = req.body;
241782
+ const { orderedIds, branch } = req.body;
241668
241783
  if (!Array.isArray(orderedIds)) {
241669
241784
  return reply.code(400).send({ error: "orderedIds must be an array" });
241670
241785
  }
241671
- if (!groupId) {
241672
- return reply.code(400).send({ error: "groupId is required" });
241786
+ if (branch === void 0) {
241787
+ return reply.code(400).send({ error: "branch is required" });
241673
241788
  }
241674
- const existingExecutors = await fastify2.storage.executors.getByGroupId(groupId);
241789
+ const workspace = await fastify2.storage.workspaceRegistry.getWorkspaceByProjectBranch(
241790
+ req.params.projectId,
241791
+ branch
241792
+ );
241793
+ if (!workspace) {
241794
+ return reply.code(400).send({ error: "No workspace for this branch" });
241795
+ }
241796
+ const existingExecutors = await fastify2.storage.executors.getByWorkspaceId(workspace.id);
241675
241797
  const existingIds = new Set(existingExecutors.map((e) => e.id));
241676
241798
  for (const id of orderedIds) {
241677
241799
  if (!existingIds.has(id)) {
241678
- return reply.code(400).send({ error: `Executor ${id} not found in group` });
241800
+ return reply.code(400).send({ error: `Executor ${id} not found in workspace` });
241679
241801
  }
241680
241802
  }
241681
- await fastify2.storage.executors.reorder(groupId, orderedIds);
241803
+ await fastify2.storage.executors.reorder(workspace.id, orderedIds);
241682
241804
  return reply.code(200).send({ success: true });
241683
241805
  });
241684
241806
  };
241685
- var executor_routes_default = (0, import_fastify_plugin8.default)(routes7, { name: "executor-routes" });
241807
+ var executor_routes_default = (0, import_fastify_plugin7.default)(routes6, { name: "executor-routes" });
241686
241808
 
241687
241809
  // src/routes/process-routes.ts
241688
- var import_fastify_plugin9 = __toESM(require_plugin2(), 1);
241810
+ var import_fastify_plugin8 = __toESM(require_plugin2(), 1);
241689
241811
  import path9 from "path";
241690
- import { randomUUID as randomUUID13 } from "crypto";
241691
- var routes8 = async (fastify2) => {
241812
+ import { randomUUID as randomUUID12 } from "crypto";
241813
+ var routes7 = async (fastify2) => {
241692
241814
  fastify2.post("/api/path/execute", async (req, reply) => {
241693
241815
  const userId = requireAuth(req, reply);
241694
241816
  if (userId === null) return;
@@ -241705,9 +241827,9 @@ var routes8 = async (fastify2) => {
241705
241827
  const resolvedBase = resolveWorktreePath(projectPath, branch ?? null);
241706
241828
  const resolvedCwd = cwd ? path9.join(resolvedBase, cwd) : null;
241707
241829
  const tempExecutor = {
241708
- id: randomUUID13(),
241830
+ id: randomUUID12(),
241709
241831
  project_id: project.id,
241710
- group_id: "",
241832
+ workspace_id: "",
241711
241833
  name: "remote-command",
241712
241834
  command,
241713
241835
  executor_type: executor_type === "prompt" ? "prompt" : "command",
@@ -241737,7 +241859,11 @@ var routes8 = async (fastify2) => {
241737
241859
  if (!project) {
241738
241860
  return reply.code(404).send({ error: "Project not found" });
241739
241861
  }
241740
- const branch = req.body?.branch;
241862
+ const workspace = await fastify2.storage.workspaceRegistry.getWorkspaceById(executor.workspace_id);
241863
+ if (!workspace) {
241864
+ return reply.code(400).send({ error: "Executor's workspace no longer exists" });
241865
+ }
241866
+ const branch = workspace.branch || null;
241741
241867
  let executorMode = req.body?.target || project.executor_mode;
241742
241868
  let useRemoteExecutor = executorMode !== "local";
241743
241869
  if (useRemoteExecutor && executorMode === "remote") {
@@ -241900,10 +242026,10 @@ var routes8 = async (fastify2) => {
241900
242026
  return reply.code(200).send({ processes });
241901
242027
  });
241902
242028
  };
241903
- var process_routes_default = (0, import_fastify_plugin9.default)(routes8, { name: "process-routes" });
242029
+ var process_routes_default = (0, import_fastify_plugin8.default)(routes7, { name: "process-routes" });
241904
242030
 
241905
242031
  // src/routes/worktree-routes.ts
241906
- var import_fastify_plugin10 = __toESM(require_plugin2(), 1);
242032
+ var import_fastify_plugin9 = __toESM(require_plugin2(), 1);
241907
242033
  import { mkdir as mkdir3 } from "fs/promises";
241908
242034
 
241909
242035
  // src/utils/path-project.ts
@@ -241949,7 +242075,37 @@ async function syncRemoteWorktreeList(fastify2, projectId, remote, data) {
241949
242075
  worktrees
241950
242076
  });
241951
242077
  }
241952
- var routes9 = async (fastify2) => {
242078
+ var WorktreeBusyError = class extends Error {
242079
+ };
242080
+ async function stopWorkspaceActivity(fastify2, opts) {
242081
+ const sessionIds = [...new Set(
242082
+ opts.projectIds.filter((id) => Boolean(id)).flatMap((id) => fastify2.agentSessionManager.getLiveSessionIdsForBranch(id, opts.branch))
242083
+ )];
242084
+ const processIds = fastify2.processManager.getRunningProcessIdsUnderPath(opts.worktreePath);
242085
+ if (sessionIds.length === 0 && processIds.length === 0) return;
242086
+ const survivors = [];
242087
+ const confirm = async (label, stop) => {
242088
+ try {
242089
+ if (!await stop()) survivors.push(label);
242090
+ } catch (error48) {
242091
+ console.error(`[worktree] Failed to stop ${label} before delete:`, error48);
242092
+ survivors.push(label);
242093
+ }
242094
+ };
242095
+ await Promise.all(sessionIds.map((sessionId) => confirm(`session ${sessionId}`, () => fastify2.agentSessionManager.stopSessionAndWait(sessionId, {
242096
+ note: "Session stopped: its worktree is being deleted."
242097
+ }))));
242098
+ await Promise.all(processIds.map((processId) => confirm(`process ${processId}`, () => fastify2.processManager.stopAndWait(processId))));
242099
+ if (survivors.length > 0) {
242100
+ throw new WorktreeBusyError(
242101
+ `Worktree still has running work that could not be stopped (${survivors.join(", ")}). Nothing was deleted; retry in a moment.`
242102
+ );
242103
+ }
242104
+ console.log(
242105
+ `[worktree] Stopped ${sessionIds.length} session(s) and ${processIds.length} process(es) in ${opts.worktreePath}`
242106
+ );
242107
+ }
242108
+ var routes8 = async (fastify2) => {
241953
242109
  fastify2.get("/api/path/branches", async (req, reply) => {
241954
242110
  const projectPath = req.query.path;
241955
242111
  if (!projectPath) {
@@ -242083,6 +242239,11 @@ var routes9 = async (fastify2) => {
242083
242239
  }
242084
242240
  } catch {
242085
242241
  }
242242
+ await stopWorkspaceActivity(fastify2, {
242243
+ projectIds: [pathProject?.id, `path:${projectPath}`],
242244
+ branch,
242245
+ worktreePath: worktreeAbsPath
242246
+ });
242086
242247
  let branchToDelete = null;
242087
242248
  try {
242088
242249
  const entries = parseGitWorktreeList(projectPath);
@@ -242113,12 +242274,34 @@ var routes9 = async (fastify2) => {
242113
242274
  return reply.code(200).send({ success: true });
242114
242275
  } catch (error48) {
242115
242276
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
242277
+ const busy = error48 instanceof WorktreeBusyError;
242116
242278
  if (registered && !worktreeRemoved) {
242117
- await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.checkout.id, "error", errorMessage).catch((registryError) => console.error("[worktree] Failed to record delete error:", registryError));
242279
+ await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.checkout.id, busy ? "ready" : "error", busy ? null : errorMessage).catch((registryError) => console.error("[worktree] Failed to record delete error:", registryError));
242118
242280
  }
242281
+ if (busy) return reply.code(409).send({ error: errorMessage });
242119
242282
  return reply.code(500).send({ error: `Failed to delete worktree: ${errorMessage}` });
242120
242283
  }
242121
242284
  });
242285
+ fastify2.post("/api/path/worktrees/anchor", async (req, reply) => {
242286
+ const { path: projectPath, branch } = req.body ?? {};
242287
+ if (!projectPath || !branch) {
242288
+ return reply.code(400).send({ error: "Path and branch are required" });
242289
+ }
242290
+ try {
242291
+ const project = await ensurePathProject(fastify2, projectPath);
242292
+ const result = await anchorRootWorkspaceBranch(fastify2.storage, project.id, projectPath, branch);
242293
+ if (!result.anchored) {
242294
+ return reply.code(409).send({
242295
+ error: `The main workspace is on '${result.currentBranch ?? "detached HEAD"}', not '${branch}'`,
242296
+ currentBranch: result.currentBranch
242297
+ });
242298
+ }
242299
+ return reply.code(200).send({ expectedBranch: result.expectedBranch });
242300
+ } catch (error48) {
242301
+ const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
242302
+ return reply.code(500).send({ error: `Failed to anchor workspace: ${errorMessage}` });
242303
+ }
242304
+ });
242122
242305
  fastify2.get("/api/projects/:id/worktrees", async (req, reply) => {
242123
242306
  const userId = requireUserFacingUserId(req, reply);
242124
242307
  if (userId === null) return;
@@ -242169,6 +242352,56 @@ var routes9 = async (fastify2) => {
242169
242352
  return reply.code(500).send({ error: `Failed to list worktrees: ${errorMessage}` });
242170
242353
  }
242171
242354
  });
242355
+ fastify2.post("/api/projects/:id/worktrees/anchor", async (req, reply) => {
242356
+ const userId = requireUserFacingUserId(req, reply);
242357
+ if (userId === null) return;
242358
+ const project = await fastify2.storage.projects.getById(req.params.id, userId);
242359
+ if (!project) {
242360
+ return reply.code(404).send({ error: "Project not found" });
242361
+ }
242362
+ const branch = req.body?.branch;
242363
+ if (!branch) return reply.code(400).send({ error: "Branch is required" });
242364
+ const requestedTarget = req.body.target ?? "local";
242365
+ let remoteConfig;
242366
+ if (requestedTarget === "local") {
242367
+ remoteConfig = project.path ? null : await getRemoteConfig(fastify2, project);
242368
+ } else {
242369
+ const targetRemote = await fastify2.storage.projectRemotes.getByProjectAndServer(project.id, requestedTarget);
242370
+ if (!targetRemote) return reply.code(400).send({ error: "Unknown remote target" });
242371
+ remoteConfig = { serverId: targetRemote.remote_server_id, remotePath: targetRemote.remote_path };
242372
+ }
242373
+ if (remoteConfig) {
242374
+ const result = await proxyToRemoteAuto(
242375
+ remoteConfig.serverId,
242376
+ "POST",
242377
+ "/api/path/worktrees/anchor",
242378
+ { path: remoteConfig.remotePath, branch },
242379
+ { reverseConnectManager: fastify2.reverseConnectManager }
242380
+ );
242381
+ if (result.status === 404) {
242382
+ return reply.code(501).send({
242383
+ error: "This remote worker is too old to anchor a workspace. Update it and try again."
242384
+ });
242385
+ }
242386
+ return reply.code(proxyStatus(result)).send(result.data);
242387
+ }
242388
+ if (!project.path) {
242389
+ return reply.code(400).send({ error: "Project has no local path" });
242390
+ }
242391
+ try {
242392
+ const result = await anchorRootWorkspaceBranch(fastify2.storage, project.id, project.path, branch);
242393
+ if (!result.anchored) {
242394
+ return reply.code(409).send({
242395
+ error: `The main workspace is on '${result.currentBranch ?? "detached HEAD"}', not '${branch}'`,
242396
+ currentBranch: result.currentBranch
242397
+ });
242398
+ }
242399
+ return reply.code(200).send({ expectedBranch: result.expectedBranch });
242400
+ } catch (error48) {
242401
+ const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
242402
+ return reply.code(500).send({ error: `Failed to anchor workspace: ${errorMessage}` });
242403
+ }
242404
+ });
242172
242405
  fastify2.get("/api/projects/:id/branches", async (req, reply) => {
242173
242406
  const userId = requireUserFacingUserId(req, reply);
242174
242407
  if (userId === null) return;
@@ -242325,6 +242558,11 @@ var routes9 = async (fastify2) => {
242325
242558
  } catch (err) {
242326
242559
  if (err instanceof Error && err.message.includes("uncommitted changes")) throw err;
242327
242560
  }
242561
+ await stopWorkspaceActivity(fastify2, {
242562
+ projectIds: [project.id],
242563
+ branch,
242564
+ worktreePath: worktreeAbsPath
242565
+ });
242328
242566
  let branchToDelete = null;
242329
242567
  try {
242330
242568
  const entries = parseGitWorktreeList(project.path);
@@ -242355,7 +242593,7 @@ var routes9 = async (fastify2) => {
242355
242593
  } catch (error48) {
242356
242594
  if (registered && !worktreeRemoved) {
242357
242595
  const message = error48 instanceof Error ? error48.message : "Local deletion failed";
242358
- const status = message.includes("uncommitted changes") ? "ready" : "error";
242596
+ const status = message.includes("uncommitted changes") || error48 instanceof WorktreeBusyError ? "ready" : "error";
242359
242597
  await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.checkout.id, status, status === "error" ? message : null).catch((registryError) => console.error("[worktree] Failed to record local delete error:", registryError));
242360
242598
  }
242361
242599
  throw error48;
@@ -242367,7 +242605,7 @@ var routes9 = async (fastify2) => {
242367
242605
  return reply.code(200).send({ success: true });
242368
242606
  } catch (error48) {
242369
242607
  const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
242370
- if (errorMessage.includes("uncommitted changes")) {
242608
+ if (errorMessage.includes("uncommitted changes") || error48 instanceof WorktreeBusyError) {
242371
242609
  return reply.code(409).send({ error: errorMessage });
242372
242610
  }
242373
242611
  return reply.code(500).send({ error: `Failed to delete worktree: ${errorMessage}` });
@@ -242630,10 +242868,10 @@ var routes9 = async (fastify2) => {
242630
242868
  });
242631
242869
  });
242632
242870
  };
242633
- var worktree_routes_default = (0, import_fastify_plugin10.default)(routes9, { name: "worktree-routes" });
242871
+ var worktree_routes_default = (0, import_fastify_plugin9.default)(routes8, { name: "worktree-routes" });
242634
242872
 
242635
242873
  // src/routes/diff-routes.ts
242636
- var import_fastify_plugin11 = __toESM(require_plugin2(), 1);
242874
+ var import_fastify_plugin10 = __toESM(require_plugin2(), 1);
242637
242875
  import path10 from "path";
242638
242876
  import { readFileSync as readFileSync4 } from "fs";
242639
242877
  import { execFileSync as execFileSync5 } from "child_process";
@@ -242941,7 +243179,7 @@ async function getUntrackedFiles(cwd) {
242941
243179
  }
242942
243180
  return files;
242943
243181
  }
242944
- var routes10 = async (fastify2) => {
243182
+ var routes9 = async (fastify2) => {
242945
243183
  fastify2.get("/api/path/diff", async (req, reply) => {
242946
243184
  const projectPath = req.query.path;
242947
243185
  if (!projectPath) {
@@ -243132,10 +243370,10 @@ var routes10 = async (fastify2) => {
243132
243370
  }
243133
243371
  });
243134
243372
  };
243135
- var diff_routes_default = (0, import_fastify_plugin11.default)(routes10, { name: "diff-routes" });
243373
+ var diff_routes_default = (0, import_fastify_plugin10.default)(routes9, { name: "diff-routes" });
243136
243374
 
243137
243375
  // src/routes/file-routes.ts
243138
- var import_fastify_plugin12 = __toESM(require_plugin2(), 1);
243376
+ var import_fastify_plugin11 = __toESM(require_plugin2(), 1);
243139
243377
  import path11 from "path";
243140
243378
  import fs2 from "fs/promises";
243141
243379
  import { createReadStream, constants as fsConstants } from "fs";
@@ -243358,7 +243596,7 @@ async function searchSymbol(basePath33, symbol26) {
243358
243596
  }
243359
243597
  return { hits, truncated };
243360
243598
  }
243361
- var routes11 = async (fastify2) => {
243599
+ var routes10 = async (fastify2) => {
243362
243600
  fastify2.get("/api/path/browse", async (req, reply) => {
243363
243601
  const projectPath = req.query.path;
243364
243602
  if (!projectPath) {
@@ -243919,17 +244157,17 @@ var routes11 = async (fastify2) => {
243919
244157
  }
243920
244158
  });
243921
244159
  };
243922
- var file_routes_default = (0, import_fastify_plugin12.default)(routes11, { name: "file-routes" });
244160
+ var file_routes_default = (0, import_fastify_plugin11.default)(routes10, { name: "file-routes" });
243923
244161
 
243924
244162
  // src/routes/agent-session-routes.ts
243925
- var import_fastify_plugin13 = __toESM(require_plugin2(), 1);
244163
+ var import_fastify_plugin12 = __toESM(require_plugin2(), 1);
243926
244164
 
243927
244165
  // src/utils/paste-file.ts
243928
244166
  import { chmod, mkdir as mkdir4, open } from "node:fs/promises";
243929
244167
  import { constants as fsConstants2 } from "node:fs";
243930
244168
  import { tmpdir as tmpdir2 } from "node:os";
243931
244169
  import path12 from "node:path";
243932
- import { randomUUID as randomUUID14 } from "node:crypto";
244170
+ import { randomUUID as randomUUID13 } from "node:crypto";
243933
244171
  var PASTE_DIR = path12.join(tmpdir2(), "vibedeckx-pastes");
243934
244172
  var DIR_MODE = 448;
243935
244173
  var FILE_MODE = 384;
@@ -243937,7 +244175,7 @@ var FILE_FLAGS = fsConstants2.O_WRONLY | fsConstants2.O_CREAT | fsConstants2.O_E
243937
244175
  async function writePasteToTempFile(content) {
243938
244176
  await mkdir4(PASTE_DIR, { recursive: true, mode: DIR_MODE });
243939
244177
  await chmod(PASTE_DIR, DIR_MODE);
243940
- const filePath = path12.join(PASTE_DIR, `${randomUUID14()}.txt`);
244178
+ const filePath = path12.join(PASTE_DIR, `${randomUUID13()}.txt`);
243941
244179
  const handle = await open(filePath, FILE_FLAGS, FILE_MODE);
243942
244180
  try {
243943
244181
  await handle.writeFile(content, "utf8");
@@ -244295,7 +244533,7 @@ async function distillConversation(storage, userId, messages, conversation, main
244295
244533
  }
244296
244534
 
244297
244535
  // src/routes/agent-session-routes.ts
244298
- import { createHash as createHash6, randomUUID as randomUUID15 } from "crypto";
244536
+ import { createHash as createHash6, randomUUID as randomUUID14 } from "crypto";
244299
244537
 
244300
244538
  // src/protocol/model-suggestions.ts
244301
244539
  var MODEL_SUGGESTIONS = {
@@ -244320,8 +244558,8 @@ function messageTextLength(content) {
244320
244558
  }
244321
244559
  return n;
244322
244560
  }
244323
- var routes12 = async (fastify2) => {
244324
- const instructionReceiverToken = randomUUID15();
244561
+ var routes11 = async (fastify2) => {
244562
+ const instructionReceiverToken = randomUUID14();
244325
244563
  const instructionDeliveryLocks = /* @__PURE__ */ new Map();
244326
244564
  async function serializeInstructionDelivery(key2, effect) {
244327
244565
  const previous = instructionDeliveryLocks.get(key2) ?? Promise.resolve();
@@ -244976,7 +245214,7 @@ var routes12 = async (fastify2) => {
244976
245214
  return reply.code(400).send({ error: "Project has no local path" });
244977
245215
  }
244978
245216
  try {
244979
- const preSessionId = randomUUID15();
245217
+ const preSessionId = randomUUID14();
244980
245218
  const crossRemoteMcp = await mintCrossRemoteMcpConfig(
244981
245219
  { storage: fastify2.storage },
244982
245220
  { userId, sessionId: preSessionId, sourceRemoteServerId: null }
@@ -245532,7 +245770,7 @@ var routes12 = async (fastify2) => {
245532
245770
  messages
245533
245771
  });
245534
245772
  }
245535
- const preSessionId = randomUUID15();
245773
+ const preSessionId = randomUUID14();
245536
245774
  const crossRemoteMcp = await mintCrossRemoteMcpConfig(
245537
245775
  { storage: fastify2.storage },
245538
245776
  { userId, sessionId: preSessionId, sourceRemoteServerId: null }
@@ -245792,10 +246030,10 @@ var routes12 = async (fastify2) => {
245792
246030
  return reply.code(200).send({ success: true, favorited });
245793
246031
  });
245794
246032
  };
245795
- var agent_session_routes_default = (0, import_fastify_plugin13.default)(routes12, { name: "agent-session-routes" });
246033
+ var agent_session_routes_default = (0, import_fastify_plugin12.default)(routes11, { name: "agent-session-routes" });
245796
246034
 
245797
246035
  // src/routes/branch-activity-routes.ts
245798
- var import_fastify_plugin14 = __toESM(require_plugin2(), 1);
246036
+ var import_fastify_plugin13 = __toESM(require_plugin2(), 1);
245799
246037
  function toResponse(map2) {
245800
246038
  return {
245801
246039
  branches: Array.from(map2.entries()).map(([branch, state]) => ({
@@ -245810,7 +246048,7 @@ function fromResponse(resp) {
245810
246048
  resp.branches.map((b2) => [b2.branch ?? "", { activity: b2.activity, since: b2.since }])
245811
246049
  );
245812
246050
  }
245813
- var routes13 = async (fastify2) => {
246051
+ var routes12 = async (fastify2) => {
245814
246052
  function proxyAuto(remoteServerId, method, apiPath, body) {
245815
246053
  return proxyToRemoteAuto(remoteServerId, method, apiPath, body, {
245816
246054
  reverseConnectManager: fastify2.reverseConnectManager
@@ -245875,10 +246113,10 @@ var routes13 = async (fastify2) => {
245875
246113
  }
245876
246114
  );
245877
246115
  };
245878
- var branch_activity_routes_default = (0, import_fastify_plugin14.default)(routes13, { name: "branch-activity-routes" });
246116
+ var branch_activity_routes_default = (0, import_fastify_plugin13.default)(routes12, { name: "branch-activity-routes" });
245879
246117
 
245880
246118
  // src/routes/merge-status-routes.ts
245881
- var import_fastify_plugin15 = __toESM(require_plugin2(), 1);
246119
+ var import_fastify_plugin14 = __toESM(require_plugin2(), 1);
245882
246120
  function resolveTargets(comparisons, storedTargets) {
245883
246121
  const sources = [];
245884
246122
  const effective = comparisons.map((comparison) => {
@@ -245992,7 +246230,7 @@ function sendComputed(reply, repoPath, comparisons, repository) {
245992
246230
  return reply.code(statusCode).send({ error: message });
245993
246231
  }
245994
246232
  }
245995
- var routes14 = async (fastify2) => {
246233
+ var routes13 = async (fastify2) => {
245996
246234
  fastify2.post(
245997
246235
  "/api/path/branches/merge-status",
245998
246236
  async (req, reply) => {
@@ -246114,11 +246352,11 @@ var routes14 = async (fastify2) => {
246114
246352
  }
246115
246353
  );
246116
246354
  };
246117
- var merge_status_routes_default = (0, import_fastify_plugin15.default)(routes14, { name: "merge-status-routes" });
246355
+ var merge_status_routes_default = (0, import_fastify_plugin14.default)(routes13, { name: "merge-status-routes" });
246118
246356
 
246119
246357
  // src/routes/chat-session-routes.ts
246120
- var import_fastify_plugin16 = __toESM(require_plugin2(), 1);
246121
- var routes15 = async (fastify2) => {
246358
+ var import_fastify_plugin15 = __toESM(require_plugin2(), 1);
246359
+ var routes14 = async (fastify2) => {
246122
246360
  const getAuthorizedSession = (req, reply, sessionId) => {
246123
246361
  const authResult = requireUserFacingUserId(req, reply);
246124
246362
  if (authResult === null) return null;
@@ -246223,11 +246461,11 @@ var routes15 = async (fastify2) => {
246223
246461
  return reply.send({ ok: true });
246224
246462
  });
246225
246463
  };
246226
- var chat_session_routes_default = (0, import_fastify_plugin16.default)(routes15, { name: "chat-session-routes" });
246464
+ var chat_session_routes_default = (0, import_fastify_plugin15.default)(routes14, { name: "chat-session-routes" });
246227
246465
 
246228
246466
  // src/routes/project-chat-routes.ts
246229
- var import_fastify_plugin17 = __toESM(require_plugin2(), 1);
246230
- import { createHash as createHash7, randomUUID as randomUUID16 } from "crypto";
246467
+ var import_fastify_plugin16 = __toESM(require_plugin2(), 1);
246468
+ import { createHash as createHash7, randomUUID as randomUUID15 } from "crypto";
246231
246469
  var MAX_TITLE_LENGTH = 200;
246232
246470
  var MAX_MESSAGE_LENGTH = 1e5;
246233
246471
  var THREAD_PAGE_LIMIT = 50;
@@ -246339,7 +246577,7 @@ function parseWorkspaceSelectionBody(body) {
246339
246577
  if (!requestId || requestId.length > MAX_TOOL_SELECTOR_ID || !workspaceId || workspaceId.length > MAX_TOOL_SELECTOR_ID) return null;
246340
246578
  return { requestId, workspaceId };
246341
246579
  }
246342
- var routes16 = async (fastify2) => {
246580
+ var routes15 = async (fastify2) => {
246343
246581
  const getOwnedThread = async (req, reply, threadId) => {
246344
246582
  const authResult = requireAuth(req, reply);
246345
246583
  if (authResult === null) return null;
@@ -246395,20 +246633,20 @@ var routes16 = async (fastify2) => {
246395
246633
  if (!project) return reply.code(404).send({ error: "Project not found" });
246396
246634
  const body = parseCreateBody(req.body);
246397
246635
  if (!body) return reply.code(400).send({ error: "Body must contain only an optional non-empty message" });
246398
- const createRequestId = body.createRequestId ?? randomUUID16();
246636
+ const createRequestId = body.createRequestId ?? randomUUID15();
246399
246637
  const createPayloadHash = createHash7("sha256").update(JSON.stringify({ message: body.message ?? null })).digest("hex");
246400
246638
  let accepted;
246401
246639
  try {
246402
246640
  accepted = await fastify2.storage.projectChatThreads.createIdempotent({
246403
- id: randomUUID16(),
246641
+ id: randomUUID15(),
246404
246642
  project_id: projectId,
246405
246643
  user_id: userId,
246406
246644
  title: null,
246407
246645
  create_request_id: createRequestId,
246408
246646
  create_payload_hash: createPayloadHash,
246409
246647
  ...body.message !== void 0 ? { initialTurn: {
246410
- messageId: randomUUID16(),
246411
- workItemId: randomUUID16(),
246648
+ messageId: randomUUID15(),
246649
+ workItemId: randomUUID15(),
246412
246650
  content: body.message
246413
246651
  } } : {}
246414
246652
  });
@@ -246558,10 +246796,10 @@ var routes16 = async (fastify2) => {
246558
246796
  }
246559
246797
  });
246560
246798
  };
246561
- var project_chat_routes_default = (0, import_fastify_plugin17.default)(routes16, { name: "project-chat-routes" });
246799
+ var project_chat_routes_default = (0, import_fastify_plugin16.default)(routes15, { name: "project-chat-routes" });
246562
246800
 
246563
246801
  // src/routes/project-activity-routes.ts
246564
- var import_fastify_plugin18 = __toESM(require_plugin2(), 1);
246802
+ var import_fastify_plugin17 = __toESM(require_plugin2(), 1);
246565
246803
 
246566
246804
  // src/project-activity.ts
246567
246805
  var RECENT_THREAD_LIMIT = 5;
@@ -246653,7 +246891,7 @@ async function getProjectActivity(storage, projectId, userId) {
246653
246891
  }
246654
246892
 
246655
246893
  // src/routes/project-activity-routes.ts
246656
- var routes17 = async (fastify2) => {
246894
+ var routes16 = async (fastify2) => {
246657
246895
  fastify2.get(
246658
246896
  "/api/projects/:projectId/activity",
246659
246897
  async (req, reply) => {
@@ -246669,12 +246907,12 @@ var routes17 = async (fastify2) => {
246669
246907
  }
246670
246908
  );
246671
246909
  };
246672
- var project_activity_routes_default = (0, import_fastify_plugin18.default)(routes17);
246910
+ var project_activity_routes_default = (0, import_fastify_plugin17.default)(routes16);
246673
246911
 
246674
246912
  // src/routes/task-routes.ts
246675
- var import_fastify_plugin19 = __toESM(require_plugin2(), 1);
246676
- import { randomUUID as randomUUID17 } from "crypto";
246677
- var routes18 = async (fastify2) => {
246913
+ var import_fastify_plugin18 = __toESM(require_plugin2(), 1);
246914
+ import { randomUUID as randomUUID16 } from "crypto";
246915
+ var routes17 = async (fastify2) => {
246678
246916
  fastify2.get(
246679
246917
  "/api/projects/:projectId/tasks",
246680
246918
  async (req, reply) => {
@@ -246737,7 +246975,7 @@ Description: ${description}`,
246737
246975
  title = description.length > 50 ? description.slice(0, 50) + "..." : description;
246738
246976
  }
246739
246977
  }
246740
- const id = randomUUID17();
246978
+ const id = randomUUID16();
246741
246979
  const task = await fastify2.storage.tasks.create({
246742
246980
  id,
246743
246981
  project_id: req.params.projectId,
@@ -246834,12 +247072,12 @@ Description: ${description}`,
246834
247072
  return reply.code(200).send({ success: true });
246835
247073
  });
246836
247074
  };
246837
- var task_routes_default = (0, import_fastify_plugin19.default)(routes18, { name: "task-routes" });
247075
+ var task_routes_default = (0, import_fastify_plugin18.default)(routes17, { name: "task-routes" });
246838
247076
 
246839
247077
  // src/routes/rule-routes.ts
246840
- var import_fastify_plugin20 = __toESM(require_plugin2(), 1);
246841
- import { randomUUID as randomUUID18 } from "crypto";
246842
- var routes19 = async (fastify2) => {
247078
+ var import_fastify_plugin19 = __toESM(require_plugin2(), 1);
247079
+ import { randomUUID as randomUUID17 } from "crypto";
247080
+ var routes18 = async (fastify2) => {
246843
247081
  fastify2.get(
246844
247082
  "/api/projects/:projectId/rules",
246845
247083
  async (req, reply) => {
@@ -246865,7 +247103,7 @@ var routes19 = async (fastify2) => {
246865
247103
  if (!name25 || !content) {
246866
247104
  return reply.code(400).send({ error: "name and content are required" });
246867
247105
  }
246868
- const id = randomUUID18();
247106
+ const id = randomUUID17();
246869
247107
  const rule = await fastify2.storage.rules.create({
246870
247108
  id,
246871
247109
  project_id: req.params.projectId,
@@ -246925,12 +247163,12 @@ var routes19 = async (fastify2) => {
246925
247163
  return reply.code(200).send({ success: true });
246926
247164
  });
246927
247165
  };
246928
- var rule_routes_default = (0, import_fastify_plugin20.default)(routes19, { name: "rule-routes" });
247166
+ var rule_routes_default = (0, import_fastify_plugin19.default)(routes18, { name: "rule-routes" });
246929
247167
 
246930
247168
  // src/routes/command-routes.ts
246931
- var import_fastify_plugin21 = __toESM(require_plugin2(), 1);
246932
- import { randomUUID as randomUUID19 } from "crypto";
246933
- var routes20 = async (fastify2) => {
247169
+ var import_fastify_plugin20 = __toESM(require_plugin2(), 1);
247170
+ import { randomUUID as randomUUID18 } from "crypto";
247171
+ var routes19 = async (fastify2) => {
246934
247172
  fastify2.get(
246935
247173
  "/api/projects/:projectId/commands",
246936
247174
  async (req, reply) => {
@@ -246956,7 +247194,7 @@ var routes20 = async (fastify2) => {
246956
247194
  if (!name25 || !content) {
246957
247195
  return reply.code(400).send({ error: "name and content are required" });
246958
247196
  }
246959
- const id = randomUUID19();
247197
+ const id = randomUUID18();
246960
247198
  const command = await fastify2.storage.commands.create({
246961
247199
  id,
246962
247200
  project_id: req.params.projectId,
@@ -246999,10 +247237,10 @@ var routes20 = async (fastify2) => {
246999
247237
  return reply.code(200).send({ success: true });
247000
247238
  });
247001
247239
  };
247002
- var command_routes_default = (0, import_fastify_plugin21.default)(routes20, { name: "command-routes" });
247240
+ var command_routes_default = (0, import_fastify_plugin20.default)(routes19, { name: "command-routes" });
247003
247241
 
247004
247242
  // src/routes/workflow-run-routes.ts
247005
- var import_fastify_plugin22 = __toESM(require_plugin2(), 1);
247243
+ var import_fastify_plugin21 = __toESM(require_plugin2(), 1);
247006
247244
  function parseReviewerAgentType(raw) {
247007
247245
  if (raw === void 0) return void 0;
247008
247246
  return typeof raw === "string" && REVIEWER_AGENT_TYPES.has(raw) ? raw : null;
@@ -247036,7 +247274,7 @@ function errStatus(err) {
247036
247274
  return 500;
247037
247275
  }
247038
247276
  }
247039
- async function routes21(fastify2) {
247277
+ async function routes20(fastify2) {
247040
247278
  const durableReviewFlights = /* @__PURE__ */ new Map();
247041
247279
  const projectLocalSession = async (session) => {
247042
247280
  const reader = fastify2.storage.agentSessions.getActivityById;
@@ -247603,10 +247841,10 @@ async function routes21(fastify2) {
247603
247841
  return reply.send({ runs });
247604
247842
  });
247605
247843
  }
247606
- var workflow_run_routes_default = (0, import_fastify_plugin22.default)(routes21, { name: "workflow-run-routes" });
247844
+ var workflow_run_routes_default = (0, import_fastify_plugin21.default)(routes20, { name: "workflow-run-routes" });
247607
247845
 
247608
247846
  // src/routes/settings-routes.ts
247609
- var import_fastify_plugin23 = __toESM(require_plugin2(), 1);
247847
+ var import_fastify_plugin22 = __toESM(require_plugin2(), 1);
247610
247848
  var SettingsValidationError = class extends Error {
247611
247849
  };
247612
247850
  var DEFAULT_PROXY_CONFIG = { type: "none", host: "", port: 0 };
@@ -247670,7 +247908,7 @@ function requireSettingsUser(req, reply) {
247670
247908
  if (auth === null) return null;
247671
247909
  return resolveUserId(auth);
247672
247910
  }
247673
- var routes22 = async (fastify2) => {
247911
+ var routes21 = async (fastify2) => {
247674
247912
  fastify2.get("/api/settings/agent-processes", async (req, reply) => {
247675
247913
  if (requireAuth(req, reply) === null) return;
247676
247914
  const saved = await fastify2.storage.settings.get("agentProcesses");
@@ -247944,11 +248182,11 @@ var routes22 = async (fastify2) => {
247944
248182
  return reply.code(200).send(updated);
247945
248183
  });
247946
248184
  };
247947
- var settings_routes_default = (0, import_fastify_plugin23.default)(routes22, { name: "settings-routes" });
248185
+ var settings_routes_default = (0, import_fastify_plugin22.default)(routes21, { name: "settings-routes" });
247948
248186
 
247949
248187
  // src/routes/translate-routes.ts
247950
- var import_fastify_plugin24 = __toESM(require_plugin2(), 1);
247951
- var routes23 = async (fastify2) => {
248188
+ var import_fastify_plugin23 = __toESM(require_plugin2(), 1);
248189
+ var routes22 = async (fastify2) => {
247952
248190
  fastify2.post(
247953
248191
  "/api/translate",
247954
248192
  async (req, reply) => {
@@ -247989,13 +248227,13 @@ ${text2}`,
247989
248227
  }
247990
248228
  );
247991
248229
  };
247992
- var translate_routes_default = (0, import_fastify_plugin24.default)(routes23, { name: "translate-routes" });
248230
+ var translate_routes_default = (0, import_fastify_plugin23.default)(routes22, { name: "translate-routes" });
247993
248231
 
247994
248232
  // src/routes/websocket-routes.ts
247995
- var import_fastify_plugin25 = __toESM(require_plugin2(), 1);
248233
+ var import_fastify_plugin24 = __toESM(require_plugin2(), 1);
247996
248234
 
247997
248235
  // src/routes/executor-stream-handlers.ts
247998
- import { randomUUID as randomUUID20 } from "crypto";
248236
+ import { randomUUID as randomUUID19 } from "crypto";
247999
248237
  function attachLocalProcessStream(fastify2, processId, send, onTerminal) {
248000
248238
  const noop4 = { cleanup: () => {
248001
248239
  }, handleInput: () => {
@@ -248071,7 +248309,7 @@ function attachRemoteProcessStream(fastify2, processId, send, onTerminal) {
248071
248309
  return;
248072
248310
  }
248073
248311
  console.log(`[diag:remote-stop] ${(/* @__PURE__ */ new Date()).toISOString()} attach processId=${processId} executorId=${info.executorId} server=${info.remoteServerId} transport=reverse-connect remoteProcessId=${info.remoteProcessId}`);
248074
- const channelId = randomUUID20();
248312
+ const channelId = randomUUID19();
248075
248313
  const wsPath = `/api/executor-processes/${info.remoteProcessId}/logs`;
248076
248314
  const adapter = new VirtualWsAdapter(
248077
248315
  (data) => fastify2.reverseConnectManager.sendChannelData(info.remoteServerId, channelId, data),
@@ -248303,7 +248541,7 @@ function attachWsHeartbeat(socket, { label, intervalMs = DEFAULT_INTERVAL_MS, ke
248303
248541
  }
248304
248542
 
248305
248543
  // src/routes/websocket-routes.ts
248306
- var routes24 = async (fastify2) => {
248544
+ var routes23 = async (fastify2) => {
248307
248545
  fastify2.reverseConnectManager.setStatusChangeHandler((remoteServerId, status) => {
248308
248546
  if (status !== "online") return;
248309
248547
  const cache2 = fastify2.remotePatchCache;
@@ -248736,10 +248974,10 @@ var routes24 = async (fastify2) => {
248736
248974
  );
248737
248975
  });
248738
248976
  };
248739
- var websocket_routes_default = (0, import_fastify_plugin25.default)(routes24, { name: "websocket-routes" });
248977
+ var websocket_routes_default = (0, import_fastify_plugin24.default)(routes23, { name: "websocket-routes" });
248740
248978
 
248741
248979
  // src/routes/reverse-connect-routes.ts
248742
- var import_fastify_plugin26 = __toESM(require_plugin2(), 1);
248980
+ var import_fastify_plugin25 = __toESM(require_plugin2(), 1);
248743
248981
  import { randomBytes as randomBytes2, createHash as createHash8, verify as cryptoVerify } from "crypto";
248744
248982
 
248745
248983
  // src/utils/rate-limited-warn.ts
@@ -248784,7 +249022,7 @@ function extractReportedVersion(frame) {
248784
249022
  var MACHINE_HANDSHAKE_TIMEOUT_MS = 5e3;
248785
249023
  var REJECT_LOG_WINDOW_MS = 3e4;
248786
249024
  var REJECT_LOG_MAX_KEYS = 500;
248787
- var routes25 = async (fastify2) => {
249025
+ var routes24 = async (fastify2) => {
248788
249026
  const logRejectedUpgrade = createRateLimitedWarn(REJECT_LOG_WINDOW_MS, REJECT_LOG_MAX_KEYS);
248789
249027
  fastify2.get("/api/reverse-connect/identity", async (req, reply) => {
248790
249028
  const token = req.headers["x-vibedeckx-connect-token"];
@@ -248918,10 +249156,10 @@ var routes25 = async (fastify2) => {
248918
249156
  );
248919
249157
  });
248920
249158
  };
248921
- var reverse_connect_routes_default = (0, import_fastify_plugin26.default)(routes25, { name: "reverse-connect-routes" });
249159
+ var reverse_connect_routes_default = (0, import_fastify_plugin25.default)(routes24, { name: "reverse-connect-routes" });
248922
249160
 
248923
249161
  // src/routes/event-routes.ts
248924
- var import_fastify_plugin27 = __toESM(require_plugin2(), 1);
249162
+ var import_fastify_plugin26 = __toESM(require_plugin2(), 1);
248925
249163
  function toWireEvent(event) {
248926
249164
  if (event.type === "executor:stopped" && (event.tailOutput !== void 0 || event.finalResult !== void 0)) {
248927
249165
  const { tailOutput: _tailOutput, finalResult: _finalResult, ...rest } = event;
@@ -248929,7 +249167,7 @@ function toWireEvent(event) {
248929
249167
  }
248930
249168
  return event;
248931
249169
  }
248932
- var routes26 = async (fastify2) => {
249170
+ var routes25 = async (fastify2) => {
248933
249171
  fastify2.get("/api/events", async (req, reply) => {
248934
249172
  let userId = null;
248935
249173
  if (fastify2.authEnabled) {
@@ -248984,10 +249222,10 @@ var routes26 = async (fastify2) => {
248984
249222
  await reply;
248985
249223
  });
248986
249224
  };
248987
- var event_routes_default = (0, import_fastify_plugin27.default)(routes26, { name: "event-routes" });
249225
+ var event_routes_default = (0, import_fastify_plugin26.default)(routes25, { name: "event-routes" });
248988
249226
 
248989
249227
  // src/routes/terminal-routes.ts
248990
- var import_fastify_plugin28 = __toESM(require_plugin2(), 1);
249228
+ var import_fastify_plugin27 = __toESM(require_plugin2(), 1);
248991
249229
  import path13 from "path";
248992
249230
  async function getRemoteConfig5(fastify2, project, remoteServerId) {
248993
249231
  const remotes = await fastify2.storage.projectRemotes.getByProject(project.id);
@@ -248998,7 +249236,7 @@ async function getRemoteConfig5(fastify2, project, remoteServerId) {
248998
249236
  remotePath: target.remote_path
248999
249237
  };
249000
249238
  }
249001
- var routes27 = async (fastify2) => {
249239
+ var routes26 = async (fastify2) => {
249002
249240
  fastify2.post("/api/path/terminals", async (req, reply) => {
249003
249241
  const { path: projectPath, branch } = req.body;
249004
249242
  if (!projectPath) {
@@ -249174,11 +249412,11 @@ var routes27 = async (fastify2) => {
249174
249412
  }
249175
249413
  );
249176
249414
  };
249177
- var terminal_routes_default = (0, import_fastify_plugin28.default)(routes27, { name: "terminal-routes" });
249415
+ var terminal_routes_default = (0, import_fastify_plugin27.default)(routes26, { name: "terminal-routes" });
249178
249416
 
249179
249417
  // src/routes/browser-routes.ts
249180
- var import_fastify_plugin29 = __toESM(require_plugin2(), 1);
249181
- var routes28 = async (fastify2) => {
249418
+ var import_fastify_plugin28 = __toESM(require_plugin2(), 1);
249419
+ var routes27 = async (fastify2) => {
249182
249420
  const ensureProjectAccess = async (req, reply) => {
249183
249421
  const userId = requireUserFacingUserId(req, reply);
249184
249422
  if (userId === null) return null;
@@ -249249,11 +249487,11 @@ var routes28 = async (fastify2) => {
249249
249487
  return reply.code(200).send({ ok: true });
249250
249488
  });
249251
249489
  };
249252
- var browser_routes_default = (0, import_fastify_plugin29.default)(routes28, { name: "browser-routes" });
249490
+ var browser_routes_default = (0, import_fastify_plugin28.default)(routes27, { name: "browser-routes" });
249253
249491
 
249254
249492
  // src/routes/browser-proxy-routes.ts
249255
- var import_fastify_plugin30 = __toESM(require_plugin2(), 1);
249256
- import { randomUUID as randomUUID21 } from "crypto";
249493
+ var import_fastify_plugin29 = __toESM(require_plugin2(), 1);
249494
+ import { randomUUID as randomUUID20 } from "crypto";
249257
249495
 
249258
249496
  // src/utils/ssrf-guard.ts
249259
249497
  var import_undici2 = __toESM(require_undici(), 1);
@@ -249748,7 +249986,7 @@ function generateInjectedScript(projectId, targetOrigin, proxyWsPrefix) {
249748
249986
  })();
249749
249987
  </script>`;
249750
249988
  }
249751
- var routes29 = async (fastify2) => {
249989
+ var routes28 = async (fastify2) => {
249752
249990
  fastify2.get("/api/projects/:id/browser/proxy/*", async (req, reply) => {
249753
249991
  const userId = requireUserFacingOrTrustedProxyUserId(req, reply);
249754
249992
  if (userId === null) return;
@@ -249843,7 +250081,7 @@ var routes29 = async (fastify2) => {
249843
250081
  const rcm = fastify2.reverseConnectManager;
249844
250082
  if (resolved.remoteServerId && rcm.isConnected(resolved.remoteServerId)) {
249845
250083
  const remoteServerId = resolved.remoteServerId;
249846
- const channelId = randomUUID21();
250084
+ const channelId = randomUUID20();
249847
250085
  const parsed = new URL(resolved.fetchUrl);
249848
250086
  const wsPath = parsed.pathname;
249849
250087
  const wsQuery = parsed.search ? parsed.search.slice(1) : void 0;
@@ -249920,10 +250158,10 @@ var routes29 = async (fastify2) => {
249920
250158
  });
249921
250159
  });
249922
250160
  };
249923
- var browser_proxy_routes_default = (0, import_fastify_plugin30.default)(routes29, { name: "browser-proxy-routes" });
250161
+ var browser_proxy_routes_default = (0, import_fastify_plugin29.default)(routes28, { name: "browser-proxy-routes" });
249924
250162
 
249925
250163
  // src/routes/cross-remote-target-routes.ts
249926
- var import_fastify_plugin31 = __toESM(require_plugin2(), 1);
250164
+ var import_fastify_plugin30 = __toESM(require_plugin2(), 1);
249927
250165
  import path14 from "path";
249928
250166
  import { promises as fs3 } from "fs";
249929
250167
 
@@ -250003,7 +250241,7 @@ var clampTimeoutMs = (timeoutSec) => {
250003
250241
  const requested = typeof timeoutSec === "number" && Number.isFinite(timeoutSec) && timeoutSec > 0 ? timeoutSec : DEFAULT_TIMEOUT_SEC;
250004
250242
  return Math.min(requested, MAX_TIMEOUT_SEC) * 1e3;
250005
250243
  };
250006
- var routes30 = async (fastify2) => {
250244
+ var routes29 = async (fastify2) => {
250007
250245
  fastify2.post(
250008
250246
  "/api/path/cross-remote/exec",
250009
250247
  async (request, reply) => {
@@ -250111,10 +250349,10 @@ var routes30 = async (fastify2) => {
250111
250349
  return reply.send(result);
250112
250350
  });
250113
250351
  };
250114
- var cross_remote_target_routes_default = (0, import_fastify_plugin31.default)(routes30, { name: "cross-remote-target-routes" });
250352
+ var cross_remote_target_routes_default = (0, import_fastify_plugin30.default)(routes29, { name: "cross-remote-target-routes" });
250115
250353
 
250116
250354
  // src/routes/cross-remote-mcp-routes.ts
250117
- var import_fastify_plugin32 = __toESM(require_plugin2(), 1);
250355
+ var import_fastify_plugin31 = __toESM(require_plugin2(), 1);
250118
250356
  var PROTOCOL_VERSION = "2024-11-05";
250119
250357
  var AUDIT_ARGS_MAX = 1024;
250120
250358
  var NOT_ACCESSIBLE = "remote not found or not accessible";
@@ -250217,7 +250455,7 @@ var textResult = (text2, isError = false) => ({
250217
250455
  content: [{ type: "text", text: text2 }],
250218
250456
  ...isError ? { isError: true } : {}
250219
250457
  });
250220
- var routes31 = async (fastify2) => {
250458
+ var routes30 = async (fastify2) => {
250221
250459
  const guard = new SessionConcurrencyGuard();
250222
250460
  let cachedSecret;
250223
250461
  const getSecret = () => {
@@ -250338,11 +250576,11 @@ var routes31 = async (fastify2) => {
250338
250576
  }
250339
250577
  });
250340
250578
  };
250341
- var cross_remote_mcp_routes_default = (0, import_fastify_plugin32.default)(routes31, { name: "cross-remote-mcp-routes" });
250579
+ var cross_remote_mcp_routes_default = (0, import_fastify_plugin31.default)(routes30, { name: "cross-remote-mcp-routes" });
250342
250580
 
250343
250581
  // src/routes/schedule-routes.ts
250344
- var import_fastify_plugin33 = __toESM(require_plugin2(), 1);
250345
- import { randomUUID as randomUUID22 } from "crypto";
250582
+ var import_fastify_plugin32 = __toESM(require_plugin2(), 1);
250583
+ import { randomUUID as randomUUID21 } from "crypto";
250346
250584
  import path15 from "path";
250347
250585
  var RUN_TYPES = ["command", "prompt"];
250348
250586
  var CWD_MODES = ["branch", "directory"];
@@ -250360,7 +250598,7 @@ function validateResolved(b2) {
250360
250598
  if (cronError) return `Invalid cron expression: ${cronError}`;
250361
250599
  return null;
250362
250600
  }
250363
- var routes32 = async (fastify2) => {
250601
+ var routes31 = async (fastify2) => {
250364
250602
  const sendTerminalManualOutcome = (reply, request, replay) => {
250365
250603
  if (!request.terminalStatus || request.terminalResponseStatus === null) return null;
250366
250604
  const common = { runId: request.runId, status: request.terminalStatus, durable: true, replay };
@@ -250431,7 +250669,7 @@ var routes32 = async (fastify2) => {
250431
250669
  return reply.code(400).send({ error: "Unknown remote target" });
250432
250670
  }
250433
250671
  const schedule = await fastify2.storage.scheduledTasks.create({
250434
- id: randomUUID22(),
250672
+ id: randomUUID21(),
250435
250673
  project_id: req.params.projectId,
250436
250674
  name: b2.name.trim(),
250437
250675
  cron_expr: resolved.cron_expr,
@@ -250591,7 +250829,7 @@ var routes32 = async (fastify2) => {
250591
250829
  }
250592
250830
  );
250593
250831
  };
250594
- var schedule_routes_default = (0, import_fastify_plugin33.default)(routes32, { name: "schedule-routes" });
250832
+ var schedule_routes_default = (0, import_fastify_plugin32.default)(routes31, { name: "schedule-routes" });
250595
250833
 
250596
250834
  // src/search/catalog.ts
250597
250835
  var parseDbTimestamp5 = (ts) => {
@@ -250891,10 +251129,10 @@ var searchRoutes = async (fastify2) => {
250891
251129
  var search_routes_default = searchRoutes;
250892
251130
 
250893
251131
  // src/routes/notification-routes.ts
250894
- var import_fastify_plugin34 = __toESM(require_plugin2(), 1);
251132
+ var import_fastify_plugin33 = __toESM(require_plugin2(), 1);
250895
251133
  var MAX_LIMIT = 500;
250896
251134
  var DEFAULT_LIMIT = 100;
250897
- var routes33 = async (fastify2) => {
251135
+ var routes32 = async (fastify2) => {
250898
251136
  fastify2.get(
250899
251137
  "/api/notifications",
250900
251138
  async (req, reply) => {
@@ -250926,7 +251164,7 @@ var routes33 = async (fastify2) => {
250926
251164
  return reply.code(200).send({ ok: true });
250927
251165
  });
250928
251166
  };
250929
- var notification_routes_default = (0, import_fastify_plugin34.default)(routes33, { name: "notification-routes" });
251167
+ var notification_routes_default = (0, import_fastify_plugin33.default)(routes32, { name: "notification-routes" });
250930
251168
 
250931
251169
  // ../../node_modules/.pnpm/@clerk+fastify@3.1.2_fastify@5.7.2_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@clerk/fastify/dist/chunk-RY4T2JMQ.mjs
250932
251170
  import { Readable as Readable2 } from "stream";
@@ -250978,7 +251216,7 @@ var requestToProxyRequest = (req) => {
250978
251216
 
250979
251217
  // ../../node_modules/.pnpm/@clerk+fastify@3.1.2_fastify@5.7.2_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@clerk/fastify/dist/index.mjs
250980
251218
  init_dist();
250981
- var import_fastify_plugin35 = __toESM(require_plugin2(), 1);
251219
+ var import_fastify_plugin34 = __toESM(require_plugin2(), 1);
250982
251220
 
250983
251221
  // ../../node_modules/.pnpm/@clerk+backend@3.2.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@clerk/backend/dist/internal.mjs
250984
251222
  init_chunk_JW73PKED();
@@ -251266,7 +251504,7 @@ var plugin = (instance, opts, done) => {
251266
251504
  instance.addHook(hookName, withClerkMiddleware(opts));
251267
251505
  done();
251268
251506
  };
251269
- var clerkPlugin = (0, import_fastify_plugin35.default)(plugin, {
251507
+ var clerkPlugin = (0, import_fastify_plugin34.default)(plugin, {
251270
251508
  name: "@clerk/fastify",
251271
251509
  fastify: "5.x"
251272
251510
  });
@@ -252188,7 +252426,6 @@ var createServer = async (opts) => {
252188
252426
  server.register(worker_stats_routes_default);
252189
252427
  server.register(project_remote_routes_default);
252190
252428
  server.register(search_routes_default);
252191
- server.register(executor_group_routes_default);
252192
252429
  server.register(executor_routes_default);
252193
252430
  server.register(schedule_routes_default);
252194
252431
  server.register(process_routes_default);
@@ -252466,6 +252703,9 @@ var WORKER_CAPABILITIES = {
252466
252703
  "http:GET /api/path/worktrees": { since: "0.2.0", summary: "worktree \u5217\u8868/\u72B6\u6001" },
252467
252704
  "http:POST /api/path/worktrees": { since: "0.2.0", summary: "\u5EFA worktree" },
252468
252705
  "http:DELETE /api/path/worktrees": { since: "0.2.0", summary: "\u5220 worktree" },
252706
+ // Additive: a worker below 0.3.13 404s it and the hub answers 501 with an
252707
+ // "update the worker" message instead of proxying the failure through.
252708
+ "http:POST /api/path/worktrees/anchor": { since: "0.3.13", summary: "\u91CD\u951A\u4E3B\u5DE5\u4F5C\u533A\u5206\u652F" },
252469
252709
  "http:GET /api/path/branches": { since: "0.2.0", summary: "\u5206\u652F\u5217\u8868" },
252470
252710
  "http:GET /api/path/branches/activity": { since: "0.2.0", summary: "\u5206\u652F\u6D3B\u52A8\u6982\u89C8" },
252471
252711
  "http:POST /api/path/branches/merge-status": { since: "0.2.0", summary: "\u5206\u652F\u5408\u5E76\u72B6\u6001\u68C0\u6D4B" },
@@ -252822,7 +253062,7 @@ var ReverseConnectClient = class {
252822
253062
 
252823
253063
  // src/connect-daemon.ts
252824
253064
  import { spawn as spawn5 } from "node:child_process";
252825
- import { randomUUID as randomUUID23 } from "node:crypto";
253065
+ import { randomUUID as randomUUID22 } from "node:crypto";
252826
253066
  import fs8 from "node:fs";
252827
253067
  import path19 from "node:path";
252828
253068
  var CONNECT_DAEMON_CHILD_ENV = "VIBEDECKX_INTERNAL_CONNECT_DAEMON";
@@ -253216,7 +253456,7 @@ function createDaemonStateLockCandidate(lockPath) {
253216
253456
  schemaVersion: 1,
253217
253457
  pid: process.pid,
253218
253458
  processStartTicks,
253219
- nonce: randomUUID23()
253459
+ nonce: randomUUID22()
253220
253460
  };
253221
253461
  const candidatePath = `${lockPath}.candidate-${process.pid}-${owner.nonce}`;
253222
253462
  fs8.mkdirSync(candidatePath, { mode: 448 });
@@ -254584,7 +254824,7 @@ var connectRoutes = buildRouteMap({
254584
254824
  defaultCommand: "run",
254585
254825
  docs: { brief: "Connect to a Vibedeckx server as an inbound node" }
254586
254826
  });
254587
- var routes34 = buildRouteMap({
254827
+ var routes33 = buildRouteMap({
254588
254828
  routes: {
254589
254829
  start: startCommand,
254590
254830
  connect: connectRoutes
@@ -254594,7 +254834,7 @@ var routes34 = buildRouteMap({
254594
254834
  brief: "Vibedeckx - AI-powered app generator"
254595
254835
  }
254596
254836
  });
254597
- var program = buildApplication(routes34, {
254837
+ var program = buildApplication(routes33, {
254598
254838
  name: "vibedeckx",
254599
254839
  versionInfo: {
254600
254840
  currentVersion: readPackageVersion()