@vibedeckx/linux-x64 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +508 -84
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -128797,8 +128797,8 @@ var require_snapshot_utils = __commonJS({
|
|
|
128797
128797
|
match: new Set(matchHeaders.map((header) => caseSensitive ? header : header.toLowerCase()))
|
|
128798
128798
|
};
|
|
128799
128799
|
}
|
|
128800
|
-
var
|
|
128801
|
-
var hashId =
|
|
128800
|
+
var crypto6 = runtimeFeatures.has("crypto") ? __require("node:crypto") : null;
|
|
128801
|
+
var hashId = crypto6?.hash ? (value) => crypto6.hash("sha256", value, "base64url") : (value) => Buffer.from(value).toString("base64url");
|
|
128802
128802
|
function isUndiciHeaders(headers) {
|
|
128803
128803
|
return Array.isArray(headers) && (headers.length & 1) === 0;
|
|
128804
128804
|
}
|
|
@@ -134600,10 +134600,10 @@ var require_subresource_integrity = __commonJS({
|
|
|
134600
134600
|
var assert2 = __require("node:assert");
|
|
134601
134601
|
var { runtimeFeatures } = require_runtime_features();
|
|
134602
134602
|
var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]);
|
|
134603
|
-
var
|
|
134603
|
+
var crypto6;
|
|
134604
134604
|
if (runtimeFeatures.has("crypto")) {
|
|
134605
|
-
|
|
134606
|
-
const cryptoHashes =
|
|
134605
|
+
crypto6 = __require("node:crypto");
|
|
134606
|
+
const cryptoHashes = crypto6.getHashes();
|
|
134607
134607
|
if (cryptoHashes.length === 0) {
|
|
134608
134608
|
validSRIHashAlgorithmTokenSet.clear();
|
|
134609
134609
|
}
|
|
@@ -134693,7 +134693,7 @@ var require_subresource_integrity = __commonJS({
|
|
|
134693
134693
|
return result;
|
|
134694
134694
|
}
|
|
134695
134695
|
var applyAlgorithmToBytes = (algorithm, bytes) => {
|
|
134696
|
-
return
|
|
134696
|
+
return crypto6.hash(algorithm, bytes, "base64");
|
|
134697
134697
|
};
|
|
134698
134698
|
function caseSensitiveMatch(actualValue, expectedValue) {
|
|
134699
134699
|
let actualValueLength = actualValue.length;
|
|
@@ -137614,7 +137614,7 @@ var require_connection = __commonJS({
|
|
|
137614
137614
|
var { WebsocketFrameSend } = require_frame();
|
|
137615
137615
|
var assert2 = __require("node:assert");
|
|
137616
137616
|
var { runtimeFeatures } = require_runtime_features();
|
|
137617
|
-
var
|
|
137617
|
+
var crypto6 = runtimeFeatures.has("crypto") ? __require("node:crypto") : null;
|
|
137618
137618
|
var warningEmitted = false;
|
|
137619
137619
|
function establishWebSocketConnection(url2, protocols, client, handler, options) {
|
|
137620
137620
|
const requestURL = url2;
|
|
@@ -137634,7 +137634,7 @@ var require_connection = __commonJS({
|
|
|
137634
137634
|
const headersList = getHeadersList(new Headers4(options.headers));
|
|
137635
137635
|
request.headersList = headersList;
|
|
137636
137636
|
}
|
|
137637
|
-
const keyValue =
|
|
137637
|
+
const keyValue = crypto6.randomBytes(16).toString("base64");
|
|
137638
137638
|
request.headersList.append("sec-websocket-key", keyValue, true);
|
|
137639
137639
|
request.headersList.append("sec-websocket-version", "13", true);
|
|
137640
137640
|
for (const protocol of protocols) {
|
|
@@ -137674,7 +137674,7 @@ var require_connection = __commonJS({
|
|
|
137674
137674
|
return;
|
|
137675
137675
|
}
|
|
137676
137676
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
137677
|
-
const digest =
|
|
137677
|
+
const digest = crypto6.hash("sha1", keyValue + uid, "base64");
|
|
137678
137678
|
if (secWSAccept !== digest) {
|
|
137679
137679
|
failWebsocketConnection(handler, 1002, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
137680
137680
|
return;
|
|
@@ -184842,7 +184842,7 @@ var SqliteDialect = class {
|
|
|
184842
184842
|
// src/storage/sqlite.ts
|
|
184843
184843
|
import { mkdir } from "fs/promises";
|
|
184844
184844
|
import path4 from "path";
|
|
184845
|
-
import
|
|
184845
|
+
import crypto5 from "crypto";
|
|
184846
184846
|
|
|
184847
184847
|
// src/storage/dialect.ts
|
|
184848
184848
|
var fromDbBool = (v2) => v2 === 1 || v2 === true;
|
|
@@ -202550,6 +202550,164 @@ var createProjectChatRepos = (kdb) => ({
|
|
|
202550
202550
|
}
|
|
202551
202551
|
});
|
|
202552
202552
|
|
|
202553
|
+
// src/storage/repositories/workspace-registry.ts
|
|
202554
|
+
import crypto4 from "crypto";
|
|
202555
|
+
var mapWorkspace = (row) => ({
|
|
202556
|
+
id: row.id,
|
|
202557
|
+
project_id: row.project_id,
|
|
202558
|
+
branch: row.branch,
|
|
202559
|
+
status: row.status,
|
|
202560
|
+
error: row.error,
|
|
202561
|
+
created_at: row.created_at,
|
|
202562
|
+
updated_at: row.updated_at
|
|
202563
|
+
});
|
|
202564
|
+
var mapCheckout = (row) => ({
|
|
202565
|
+
id: row.id,
|
|
202566
|
+
workspace_id: row.workspace_id,
|
|
202567
|
+
target_id: row.target_id,
|
|
202568
|
+
worktree_path: row.worktree_path,
|
|
202569
|
+
expected_branch: row.expected_branch,
|
|
202570
|
+
status: row.status,
|
|
202571
|
+
error: row.error,
|
|
202572
|
+
created_at: row.created_at,
|
|
202573
|
+
updated_at: row.updated_at
|
|
202574
|
+
});
|
|
202575
|
+
async function recomputeWorkspace(db, workspaceId, h) {
|
|
202576
|
+
const rows = await db.selectFrom("workspace_checkouts").select(["status", "error"]).where("workspace_id", "=", workspaceId).execute();
|
|
202577
|
+
if (rows.length === 0) return;
|
|
202578
|
+
const statuses = new Set(rows.map((row) => row.status));
|
|
202579
|
+
const status = statuses.has("ready") ? "ready" : statuses.has("creating") ? "creating" : statuses.has("deleting") ? "deleting" : "error";
|
|
202580
|
+
const error48 = status === "error" ? rows.map((row) => row.error).find((value) => Boolean(value)) ?? "Checkout failed" : null;
|
|
202581
|
+
await db.updateTable("workspaces").set({ status, error: error48, updated_at: h.nowMs() }).where("id", "=", workspaceId).execute();
|
|
202582
|
+
}
|
|
202583
|
+
async function upsertCheckout(trx, h, opts) {
|
|
202584
|
+
const now3 = h.nowMs();
|
|
202585
|
+
let workspaceRow = await trx.selectFrom("workspaces").selectAll().where("project_id", "=", opts.projectId).where("branch", "=", opts.branch).executeTakeFirst();
|
|
202586
|
+
if (!workspaceRow) {
|
|
202587
|
+
const workspaceId = crypto4.randomUUID();
|
|
202588
|
+
await trx.insertInto("workspaces").values({
|
|
202589
|
+
id: workspaceId,
|
|
202590
|
+
project_id: opts.projectId,
|
|
202591
|
+
branch: opts.branch,
|
|
202592
|
+
status: opts.status,
|
|
202593
|
+
error: null,
|
|
202594
|
+
created_at: now3,
|
|
202595
|
+
updated_at: now3
|
|
202596
|
+
}).execute();
|
|
202597
|
+
workspaceRow = await trx.selectFrom("workspaces").selectAll().where("id", "=", workspaceId).executeTakeFirstOrThrow();
|
|
202598
|
+
}
|
|
202599
|
+
const checkoutId = crypto4.randomUUID();
|
|
202600
|
+
await trx.insertInto("workspace_checkouts").values({
|
|
202601
|
+
id: checkoutId,
|
|
202602
|
+
workspace_id: workspaceRow.id,
|
|
202603
|
+
target_id: opts.targetId,
|
|
202604
|
+
worktree_path: opts.worktreePath,
|
|
202605
|
+
expected_branch: opts.expectedBranch,
|
|
202606
|
+
status: opts.status,
|
|
202607
|
+
error: null,
|
|
202608
|
+
created_at: now3,
|
|
202609
|
+
updated_at: now3
|
|
202610
|
+
}).onConflict((oc) => oc.columns(["workspace_id", "target_id"]).doUpdateSet({
|
|
202611
|
+
worktree_path: opts.worktreePath,
|
|
202612
|
+
expected_branch: opts.expectedBranch,
|
|
202613
|
+
status: opts.status,
|
|
202614
|
+
error: null,
|
|
202615
|
+
updated_at: now3
|
|
202616
|
+
})).execute();
|
|
202617
|
+
await recomputeWorkspace(trx, workspaceRow.id, h);
|
|
202618
|
+
const [workspace, checkout] = await Promise.all([
|
|
202619
|
+
trx.selectFrom("workspaces").selectAll().where("id", "=", workspaceRow.id).executeTakeFirstOrThrow(),
|
|
202620
|
+
trx.selectFrom("workspace_checkouts").selectAll().where("workspace_id", "=", workspaceRow.id).where("target_id", "=", opts.targetId).executeTakeFirstOrThrow()
|
|
202621
|
+
]);
|
|
202622
|
+
return { workspace: mapWorkspace(workspace), checkout: mapCheckout(checkout) };
|
|
202623
|
+
}
|
|
202624
|
+
var createWorkspaceRegistryRepo = (kdb, h) => ({
|
|
202625
|
+
workspaceRegistry: {
|
|
202626
|
+
beginCheckout: (opts) => kdb.transaction().execute((trx) => upsertCheckout(trx, h, { ...opts, status: "creating" })),
|
|
202627
|
+
registerReadyCheckout: (opts) => kdb.transaction().execute((trx) => upsertCheckout(trx, h, { ...opts, status: "ready" })),
|
|
202628
|
+
setCheckoutStatus: async (workspaceId, targetId, status, error48 = null) => {
|
|
202629
|
+
await kdb.transaction().execute(async (trx) => {
|
|
202630
|
+
await trx.updateTable("workspace_checkouts").set({ status, error: error48, updated_at: h.nowMs() }).where("workspace_id", "=", workspaceId).where("target_id", "=", targetId).execute();
|
|
202631
|
+
await recomputeWorkspace(trx, workspaceId, h);
|
|
202632
|
+
});
|
|
202633
|
+
},
|
|
202634
|
+
setCheckoutStatusIfCurrent: async (workspaceId, targetId, expected, status, error48 = null) => kdb.transaction().execute(async (trx) => {
|
|
202635
|
+
const result = await trx.updateTable("workspace_checkouts").set({ status, error: error48, updated_at: h.nowMs() }).where("workspace_id", "=", workspaceId).where("target_id", "=", targetId).where("status", "=", expected.status).where("updated_at", "=", expected.updatedAt).executeTakeFirst();
|
|
202636
|
+
const changed = result.numUpdatedRows > 0n;
|
|
202637
|
+
if (changed) await recomputeWorkspace(trx, workspaceId, h);
|
|
202638
|
+
return changed;
|
|
202639
|
+
}),
|
|
202640
|
+
listByProject: async (projectId, targetId) => {
|
|
202641
|
+
let query = kdb.selectFrom("workspaces as workspace").innerJoin("workspace_checkouts as checkout", "checkout.workspace_id", "workspace.id").selectAll("workspace").select([
|
|
202642
|
+
"checkout.id as checkout_id",
|
|
202643
|
+
"checkout.workspace_id as checkout_workspace_id",
|
|
202644
|
+
"checkout.target_id as checkout_target_id",
|
|
202645
|
+
"checkout.worktree_path as checkout_worktree_path",
|
|
202646
|
+
"checkout.expected_branch as checkout_expected_branch",
|
|
202647
|
+
"checkout.status as checkout_status",
|
|
202648
|
+
"checkout.error as checkout_error",
|
|
202649
|
+
"checkout.created_at as checkout_created_at",
|
|
202650
|
+
"checkout.updated_at as checkout_updated_at"
|
|
202651
|
+
]).where("workspace.project_id", "=", projectId);
|
|
202652
|
+
if (targetId) query = query.where("checkout.target_id", "=", targetId);
|
|
202653
|
+
const rows = await query.orderBy("workspace.created_at", "asc").execute();
|
|
202654
|
+
return rows.map((row) => ({
|
|
202655
|
+
workspace: mapWorkspace(row),
|
|
202656
|
+
checkout: {
|
|
202657
|
+
id: row.checkout_id,
|
|
202658
|
+
workspace_id: row.checkout_workspace_id,
|
|
202659
|
+
target_id: row.checkout_target_id,
|
|
202660
|
+
worktree_path: row.checkout_worktree_path,
|
|
202661
|
+
expected_branch: row.checkout_expected_branch,
|
|
202662
|
+
status: row.checkout_status,
|
|
202663
|
+
error: row.checkout_error,
|
|
202664
|
+
created_at: row.checkout_created_at,
|
|
202665
|
+
updated_at: row.checkout_updated_at
|
|
202666
|
+
}
|
|
202667
|
+
}));
|
|
202668
|
+
},
|
|
202669
|
+
getByProjectBranch: async (projectId, branch, targetId) => {
|
|
202670
|
+
const rows = await kdb.selectFrom("workspaces as workspace").innerJoin("workspace_checkouts as checkout", "checkout.workspace_id", "workspace.id").selectAll("workspace").select([
|
|
202671
|
+
"checkout.id as checkout_id",
|
|
202672
|
+
"checkout.workspace_id as checkout_workspace_id",
|
|
202673
|
+
"checkout.target_id as checkout_target_id",
|
|
202674
|
+
"checkout.worktree_path as checkout_worktree_path",
|
|
202675
|
+
"checkout.expected_branch as checkout_expected_branch",
|
|
202676
|
+
"checkout.status as checkout_status",
|
|
202677
|
+
"checkout.error as checkout_error",
|
|
202678
|
+
"checkout.created_at as checkout_created_at",
|
|
202679
|
+
"checkout.updated_at as checkout_updated_at"
|
|
202680
|
+
]).where("workspace.project_id", "=", projectId).where("workspace.branch", "=", branch).where("checkout.target_id", "=", targetId).executeTakeFirst();
|
|
202681
|
+
if (!rows) return void 0;
|
|
202682
|
+
return {
|
|
202683
|
+
workspace: mapWorkspace(rows),
|
|
202684
|
+
checkout: {
|
|
202685
|
+
id: rows.checkout_id,
|
|
202686
|
+
workspace_id: rows.checkout_workspace_id,
|
|
202687
|
+
target_id: rows.checkout_target_id,
|
|
202688
|
+
worktree_path: rows.checkout_worktree_path,
|
|
202689
|
+
expected_branch: rows.checkout_expected_branch,
|
|
202690
|
+
status: rows.checkout_status,
|
|
202691
|
+
error: rows.checkout_error,
|
|
202692
|
+
created_at: rows.checkout_created_at,
|
|
202693
|
+
updated_at: rows.checkout_updated_at
|
|
202694
|
+
}
|
|
202695
|
+
};
|
|
202696
|
+
},
|
|
202697
|
+
removeCheckout: async (workspaceId, targetId) => {
|
|
202698
|
+
await kdb.transaction().execute(async (trx) => {
|
|
202699
|
+
await trx.deleteFrom("workspace_checkouts").where("workspace_id", "=", workspaceId).where("target_id", "=", targetId).execute();
|
|
202700
|
+
const remaining = await trx.selectFrom("workspace_checkouts").select("id").where("workspace_id", "=", workspaceId).limit(1).executeTakeFirst();
|
|
202701
|
+
if (!remaining) {
|
|
202702
|
+
await trx.deleteFrom("workspaces").where("id", "=", workspaceId).execute();
|
|
202703
|
+
} else {
|
|
202704
|
+
await recomputeWorkspace(trx, workspaceId, h);
|
|
202705
|
+
}
|
|
202706
|
+
});
|
|
202707
|
+
}
|
|
202708
|
+
}
|
|
202709
|
+
});
|
|
202710
|
+
|
|
202553
202711
|
// src/storage/sqlite.ts
|
|
202554
202712
|
var createDatabase = (dbPath) => {
|
|
202555
202713
|
const db = new Database(dbPath);
|
|
@@ -202569,6 +202727,37 @@ var createDatabase = (dbPath) => {
|
|
|
202569
202727
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
202570
202728
|
);
|
|
202571
202729
|
|
|
202730
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
202731
|
+
id TEXT PRIMARY KEY,
|
|
202732
|
+
project_id TEXT NOT NULL,
|
|
202733
|
+
branch TEXT NOT NULL DEFAULT '',
|
|
202734
|
+
status TEXT NOT NULL CHECK (status IN ('creating', 'ready', 'deleting', 'error')),
|
|
202735
|
+
error TEXT,
|
|
202736
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
|
202737
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
|
202738
|
+
UNIQUE(project_id, branch),
|
|
202739
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
202740
|
+
);
|
|
202741
|
+
|
|
202742
|
+
CREATE TABLE IF NOT EXISTS workspace_checkouts (
|
|
202743
|
+
id TEXT PRIMARY KEY,
|
|
202744
|
+
workspace_id TEXT NOT NULL,
|
|
202745
|
+
target_id TEXT NOT NULL,
|
|
202746
|
+
worktree_path TEXT NOT NULL,
|
|
202747
|
+
expected_branch TEXT NOT NULL,
|
|
202748
|
+
status TEXT NOT NULL CHECK (status IN ('creating', 'ready', 'deleting', 'error')),
|
|
202749
|
+
error TEXT,
|
|
202750
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
|
202751
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
|
202752
|
+
UNIQUE(workspace_id, target_id),
|
|
202753
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
|
|
202754
|
+
);
|
|
202755
|
+
|
|
202756
|
+
CREATE INDEX IF NOT EXISTS idx_workspaces_project_status
|
|
202757
|
+
ON workspaces(project_id, status, branch);
|
|
202758
|
+
CREATE INDEX IF NOT EXISTS idx_workspace_checkouts_workspace_status
|
|
202759
|
+
ON workspace_checkouts(workspace_id, status, target_id);
|
|
202760
|
+
|
|
202572
202761
|
CREATE TABLE IF NOT EXISTS project_chat_threads (
|
|
202573
202762
|
id TEXT PRIMARY KEY,
|
|
202574
202763
|
project_id TEXT NOT NULL,
|
|
@@ -202873,6 +203062,34 @@ var createDatabase = (dbPath) => {
|
|
|
202873
203062
|
|
|
202874
203063
|
CREATE INDEX IF NOT EXISTS idx_cross_remote_audit_target ON cross_remote_audit(target_remote_id, seq);
|
|
202875
203064
|
`);
|
|
203065
|
+
const workspaceCheckoutsTable = db.prepare(
|
|
203066
|
+
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'workspace_checkouts'"
|
|
203067
|
+
).get();
|
|
203068
|
+
if (/UNIQUE\s*\(\s*target_id\s*,\s*worktree_path\s*\)/i.test(workspaceCheckoutsTable?.sql ?? "")) {
|
|
203069
|
+
db.transaction(() => db.exec(`
|
|
203070
|
+
ALTER TABLE workspace_checkouts RENAME TO workspace_checkouts_global_path_unique;
|
|
203071
|
+
CREATE TABLE workspace_checkouts (
|
|
203072
|
+
id TEXT PRIMARY KEY,
|
|
203073
|
+
workspace_id TEXT NOT NULL,
|
|
203074
|
+
target_id TEXT NOT NULL,
|
|
203075
|
+
worktree_path TEXT NOT NULL,
|
|
203076
|
+
expected_branch TEXT NOT NULL,
|
|
203077
|
+
status TEXT NOT NULL CHECK (status IN ('creating', 'ready', 'deleting', 'error')),
|
|
203078
|
+
error TEXT,
|
|
203079
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
|
203080
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
|
203081
|
+
UNIQUE(workspace_id, target_id),
|
|
203082
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
|
|
203083
|
+
);
|
|
203084
|
+
INSERT INTO workspace_checkouts
|
|
203085
|
+
(id, workspace_id, target_id, worktree_path, expected_branch, status, error, created_at, updated_at)
|
|
203086
|
+
SELECT id, workspace_id, target_id, worktree_path, expected_branch, status, error, created_at, updated_at
|
|
203087
|
+
FROM workspace_checkouts_global_path_unique;
|
|
203088
|
+
DROP TABLE workspace_checkouts_global_path_unique;
|
|
203089
|
+
CREATE INDEX idx_workspace_checkouts_workspace_status
|
|
203090
|
+
ON workspace_checkouts(workspace_id, status, target_id);
|
|
203091
|
+
`))();
|
|
203092
|
+
}
|
|
202876
203093
|
const instructionDeliveryCols = db.prepare("PRAGMA table_info(agent_instruction_deliveries)").all();
|
|
202877
203094
|
if (!instructionDeliveryCols.some((c) => c.name === "owner_token")) {
|
|
202878
203095
|
db.exec("ALTER TABLE agent_instruction_deliveries ADD COLUMN owner_token TEXT");
|
|
@@ -203209,7 +203426,7 @@ var createDatabase = (dbPath) => {
|
|
|
203209
203426
|
} catch {
|
|
203210
203427
|
name25 = row.remote_url;
|
|
203211
203428
|
}
|
|
203212
|
-
const id =
|
|
203429
|
+
const id = crypto5.randomUUID();
|
|
203213
203430
|
db.prepare(
|
|
203214
203431
|
`INSERT INTO remote_servers (id, name, url, api_key, created_at, updated_at) VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))`
|
|
203215
203432
|
).run(id, name25, row.remote_url, row.remote_api_key);
|
|
@@ -203227,7 +203444,7 @@ var createDatabase = (dbPath) => {
|
|
|
203227
203444
|
if (!existingLink && proj.remote_path) {
|
|
203228
203445
|
db.prepare(
|
|
203229
203446
|
`INSERT INTO project_remotes (id, project_id, remote_server_id, remote_path, sort_order, sync_up_config, sync_down_config) VALUES (?, ?, ?, ?, 0, ?, ?)`
|
|
203230
|
-
).run(
|
|
203447
|
+
).run(crypto5.randomUUID(), proj.id, server.id, proj.remote_path, proj.sync_up_config, proj.sync_down_config);
|
|
203231
203448
|
}
|
|
203232
203449
|
if (proj.agent_mode === "remote") {
|
|
203233
203450
|
db.prepare(`UPDATE projects SET agent_mode = ? WHERE id = ?`).run(server.id, proj.id);
|
|
@@ -203896,6 +204113,7 @@ var createSqliteStorage = async (dbPath) => {
|
|
|
203896
204113
|
const h = sqliteHelpers;
|
|
203897
204114
|
return {
|
|
203898
204115
|
...createCoreRepos(kdb, h),
|
|
204116
|
+
...createWorkspaceRegistryRepo(kdb, h),
|
|
203899
204117
|
...createRemoteServerRepos(kdb, h),
|
|
203900
204118
|
...createExecutorRepos(kdb, h),
|
|
203901
204119
|
...createScheduledRepos(kdb, h),
|
|
@@ -206163,16 +206381,88 @@ function resolveWorktreePath(projectPath, branch) {
|
|
|
206163
206381
|
function getWorktreeBaseForProject(projectPath) {
|
|
206164
206382
|
return path6.join(WORKTREE_BASE_DIR, getProjectIdentifier(projectPath));
|
|
206165
206383
|
}
|
|
206166
|
-
function
|
|
206167
|
-
|
|
206168
|
-
|
|
206384
|
+
function conventionalWorktreePath(projectPath, branch) {
|
|
206385
|
+
return path6.join(getWorktreeBaseForProject(projectPath), branch.replace(/\//g, "-"));
|
|
206386
|
+
}
|
|
206387
|
+
function reconcileWorktreeBranches(projectPath, entries, sessionBranches = [], registry2 = []) {
|
|
206388
|
+
const registryByPath = /* @__PURE__ */ new Map();
|
|
206389
|
+
for (const anchor of registry2) registryByPath.set(path6.resolve(anchor.worktreePath), anchor);
|
|
206390
|
+
const stableBranchByPath = /* @__PURE__ */ new Map();
|
|
206391
|
+
for (const branch of sessionBranches) {
|
|
206392
|
+
if (!branch) continue;
|
|
206393
|
+
stableBranchByPath.set(path6.resolve(conventionalWorktreePath(projectPath, branch)), branch);
|
|
206394
|
+
}
|
|
206395
|
+
const rootEntry = entries[0];
|
|
206396
|
+
const rootAnchor = rootEntry ? registryByPath.get(path6.resolve(rootEntry.path)) : void 0;
|
|
206397
|
+
const worktrees = [rootAnchor && rootEntry?.branch !== rootAnchor.expectedBranch ? { branch: null, currentBranch: rootEntry?.branch ?? null } : { branch: null }];
|
|
206169
206398
|
for (let i = 1; i < entries.length; i++) {
|
|
206170
|
-
|
|
206171
|
-
|
|
206399
|
+
const entry = entries[i];
|
|
206400
|
+
const anchor = registryByPath.get(path6.resolve(entry.path));
|
|
206401
|
+
const stableBranch = anchor?.branch || stableBranchByPath.get(path6.resolve(entry.path));
|
|
206402
|
+
if (stableBranch) {
|
|
206403
|
+
const expectedBranch = anchor?.expectedBranch ?? stableBranch;
|
|
206404
|
+
worktrees.push(entry.branch === expectedBranch ? { branch: stableBranch } : { branch: stableBranch, currentBranch: entry.branch });
|
|
206405
|
+
} else if (entry.branch) {
|
|
206406
|
+
worktrees.push({ branch: entry.branch });
|
|
206172
206407
|
}
|
|
206173
206408
|
}
|
|
206174
206409
|
return worktrees;
|
|
206175
206410
|
}
|
|
206411
|
+
async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
|
|
206412
|
+
const entries = parseGitWorktreeList(projectPath);
|
|
206413
|
+
const sessions = await storage.agentSessions.getByProjectId(projectId);
|
|
206414
|
+
const sessionBranches = sessions.map((session) => session.branch);
|
|
206415
|
+
const sessionBranchByPath = /* @__PURE__ */ new Map();
|
|
206416
|
+
for (const branch of sessionBranches) {
|
|
206417
|
+
if (branch) sessionBranchByPath.set(path6.resolve(conventionalWorktreePath(projectPath, branch)), branch);
|
|
206418
|
+
}
|
|
206419
|
+
let registered = await storage.workspaceRegistry.listByProject(projectId, "local");
|
|
206420
|
+
const livePaths = new Set(entries.map((entry) => path6.resolve(entry.path)));
|
|
206421
|
+
for (const row of registered) {
|
|
206422
|
+
if (livePaths.has(path6.resolve(row.checkout.worktree_path))) continue;
|
|
206423
|
+
if (row.checkout.status === "deleting") {
|
|
206424
|
+
await storage.workspaceRegistry.removeCheckout(row.workspace.id, "local");
|
|
206425
|
+
} else if (row.checkout.status !== "error" || row.checkout.error !== "Worktree is missing") {
|
|
206426
|
+
await storage.workspaceRegistry.setCheckoutStatusIfCurrent(
|
|
206427
|
+
row.workspace.id,
|
|
206428
|
+
"local",
|
|
206429
|
+
{ status: row.checkout.status, updatedAt: row.checkout.updated_at },
|
|
206430
|
+
"error",
|
|
206431
|
+
"Worktree is missing"
|
|
206432
|
+
);
|
|
206433
|
+
}
|
|
206434
|
+
}
|
|
206435
|
+
registered = await storage.workspaceRegistry.listByProject(projectId, "local");
|
|
206436
|
+
const registeredPaths = new Set(registered.map((row) => path6.resolve(row.checkout.worktree_path)));
|
|
206437
|
+
for (let index = 0; index < entries.length; index++) {
|
|
206438
|
+
const entry = entries[index];
|
|
206439
|
+
const resolvedPath = path6.resolve(entry.path);
|
|
206440
|
+
const existing = registered.find((row) => path6.resolve(row.checkout.worktree_path) === resolvedPath);
|
|
206441
|
+
if (existing) {
|
|
206442
|
+
if (existing.checkout.status === "creating" || existing.checkout.status === "error") {
|
|
206443
|
+
await storage.workspaceRegistry.setCheckoutStatus(existing.workspace.id, "local", "ready");
|
|
206444
|
+
}
|
|
206445
|
+
continue;
|
|
206446
|
+
}
|
|
206447
|
+
if (registeredPaths.has(resolvedPath) || entry.branch === null) continue;
|
|
206448
|
+
const stableBranch = index === 0 ? "" : sessionBranchByPath.get(resolvedPath) ?? entry.branch;
|
|
206449
|
+
await storage.workspaceRegistry.registerReadyCheckout({
|
|
206450
|
+
projectId,
|
|
206451
|
+
branch: stableBranch,
|
|
206452
|
+
targetId: "local",
|
|
206453
|
+
worktreePath: entry.path,
|
|
206454
|
+
expectedBranch: index === 0 ? entry.branch : stableBranch
|
|
206455
|
+
});
|
|
206456
|
+
registeredPaths.add(resolvedPath);
|
|
206457
|
+
}
|
|
206458
|
+
registered = await storage.workspaceRegistry.listByProject(projectId, "local");
|
|
206459
|
+
const anchors = registered.map((row) => ({
|
|
206460
|
+
branch: row.workspace.branch,
|
|
206461
|
+
worktreePath: row.checkout.worktree_path,
|
|
206462
|
+
expectedBranch: row.checkout.expected_branch
|
|
206463
|
+
}));
|
|
206464
|
+
return reconcileWorktreeBranches(projectPath, entries, sessionBranches, anchors);
|
|
206465
|
+
}
|
|
206176
206466
|
|
|
206177
206467
|
// ../../node_modules/.pnpm/@ai-sdk+provider@3.0.8/node_modules/@ai-sdk/provider/dist/index.mjs
|
|
206178
206468
|
var marker = "vercel.ai.error";
|
|
@@ -239804,6 +240094,23 @@ var process_routes_default = (0, import_fastify_plugin9.default)(routes8, { name
|
|
|
239804
240094
|
// src/routes/worktree-routes.ts
|
|
239805
240095
|
var import_fastify_plugin10 = __toESM(require_plugin2(), 1);
|
|
239806
240096
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
240097
|
+
|
|
240098
|
+
// src/utils/path-project.ts
|
|
240099
|
+
async function ensurePathProjectId(fastify2, projectPath) {
|
|
240100
|
+
const pseudoProjectId = `path:${projectPath}`;
|
|
240101
|
+
if (await fastify2.storage.projects.getById(pseudoProjectId)) return pseudoProjectId;
|
|
240102
|
+
const existingByPath = await fastify2.storage.projects.getByPath(projectPath);
|
|
240103
|
+
if (existingByPath) return existingByPath.id;
|
|
240104
|
+
const name25 = projectPath.split("/").filter(Boolean).pop() || projectPath;
|
|
240105
|
+
try {
|
|
240106
|
+
await fastify2.storage.projects.create({ id: pseudoProjectId, name: name25, path: projectPath });
|
|
240107
|
+
} catch (err) {
|
|
240108
|
+
if (!(err instanceof Error && err.message.includes("UNIQUE constraint failed"))) throw err;
|
|
240109
|
+
}
|
|
240110
|
+
return pseudoProjectId;
|
|
240111
|
+
}
|
|
240112
|
+
|
|
240113
|
+
// src/routes/worktree-routes.ts
|
|
239807
240114
|
async function getAllRemoteConfigs(fastify2, project) {
|
|
239808
240115
|
const remotes = await fastify2.storage.projectRemotes.getByProject(project.id);
|
|
239809
240116
|
return remotes.map((r) => ({
|
|
@@ -239815,6 +240122,12 @@ async function getRemoteConfig(fastify2, project) {
|
|
|
239815
240122
|
const all = await getAllRemoteConfigs(fastify2, project);
|
|
239816
240123
|
return all.length > 0 ? all[0] : null;
|
|
239817
240124
|
}
|
|
240125
|
+
async function ensurePathProject(fastify2, projectPath) {
|
|
240126
|
+
const projectId = await ensurePathProjectId(fastify2, projectPath);
|
|
240127
|
+
const project = await fastify2.storage.projects.getById(projectId);
|
|
240128
|
+
if (!project) throw new Error(`Path project '${projectId}' was not persisted`);
|
|
240129
|
+
return project;
|
|
240130
|
+
}
|
|
239818
240131
|
var routes9 = async (fastify2) => {
|
|
239819
240132
|
fastify2.get("/api/path/branches", async (req, reply) => {
|
|
239820
240133
|
const projectPath = req.query.path;
|
|
@@ -239842,7 +240155,8 @@ var routes9 = async (fastify2) => {
|
|
|
239842
240155
|
}
|
|
239843
240156
|
try {
|
|
239844
240157
|
pruneWorktrees(projectPath);
|
|
239845
|
-
const
|
|
240158
|
+
const project = await ensurePathProject(fastify2, projectPath);
|
|
240159
|
+
const worktrees = await getRegisteredWorktreeBranches(fastify2.storage, project.id, projectPath);
|
|
239846
240160
|
return reply.code(200).send({ worktrees });
|
|
239847
240161
|
} catch (error48) {
|
|
239848
240162
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
@@ -239864,6 +240178,7 @@ var routes9 = async (fastify2) => {
|
|
|
239864
240178
|
return reply.code(400).send({ error: "Invalid base branch name format" });
|
|
239865
240179
|
}
|
|
239866
240180
|
console.log(`[worktree] ${requestId} Creating: branch=${trimmedBranch}, base=${startPoint}, path=${projectPath}`);
|
|
240181
|
+
let pendingWorkspaceId = null;
|
|
239867
240182
|
try {
|
|
239868
240183
|
const { execFileSync: execFileSync7 } = await import("child_process");
|
|
239869
240184
|
try {
|
|
@@ -239876,6 +240191,15 @@ var routes9 = async (fastify2) => {
|
|
|
239876
240191
|
} catch {
|
|
239877
240192
|
}
|
|
239878
240193
|
const worktreeAbsolutePath = resolveWorktreePath(projectPath, trimmedBranch);
|
|
240194
|
+
const project = await ensurePathProject(fastify2, projectPath);
|
|
240195
|
+
const pending = await fastify2.storage.workspaceRegistry.beginCheckout({
|
|
240196
|
+
projectId: project.id,
|
|
240197
|
+
branch: trimmedBranch,
|
|
240198
|
+
targetId: "local",
|
|
240199
|
+
worktreePath: worktreeAbsolutePath,
|
|
240200
|
+
expectedBranch: trimmedBranch
|
|
240201
|
+
});
|
|
240202
|
+
pendingWorkspaceId = pending.workspace.id;
|
|
239879
240203
|
await mkdir3(getWorktreeBaseForProject(projectPath), { recursive: true });
|
|
239880
240204
|
execFileSync7("git", ["worktree", "add", "-b", trimmedBranch, worktreeAbsolutePath, startPoint], {
|
|
239881
240205
|
cwd: projectPath,
|
|
@@ -239883,12 +240207,16 @@ var routes9 = async (fastify2) => {
|
|
|
239883
240207
|
stdio: ["pipe", "pipe", "pipe"]
|
|
239884
240208
|
});
|
|
239885
240209
|
invalidateWorktreeListCache(projectPath);
|
|
240210
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.workspace.id, "local", "ready");
|
|
239886
240211
|
console.log(`[worktree] ${requestId} Created: branch=${trimmedBranch}`);
|
|
239887
240212
|
return reply.code(201).send({
|
|
239888
240213
|
worktree: { branch: trimmedBranch }
|
|
239889
240214
|
});
|
|
239890
240215
|
} catch (error48) {
|
|
239891
240216
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
240217
|
+
if (pendingWorkspaceId) {
|
|
240218
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pendingWorkspaceId, "local", "error", errorMessage).catch((registryError) => console.error("[worktree] Failed to record checkout error:", registryError));
|
|
240219
|
+
}
|
|
239892
240220
|
const stderr = error48?.stderr || "";
|
|
239893
240221
|
console.error(`[worktree] ${requestId} Failed: ${errorMessage}${stderr ? `, stderr: ${stderr}` : ""}`);
|
|
239894
240222
|
return reply.code(500).send({ error: `Failed to create worktree: ${errorMessage}` });
|
|
@@ -239902,6 +240230,12 @@ var routes9 = async (fastify2) => {
|
|
|
239902
240230
|
if (!/^[a-zA-Z0-9]/.test(branch) || /[^a-zA-Z0-9/_-]/.test(branch)) {
|
|
239903
240231
|
return reply.code(400).send({ error: "Invalid branch name format" });
|
|
239904
240232
|
}
|
|
240233
|
+
const pathProject = await fastify2.storage.projects.getByPath(projectPath);
|
|
240234
|
+
const registered = pathProject ? await fastify2.storage.workspaceRegistry.getByProjectBranch(pathProject.id, branch, "local") : void 0;
|
|
240235
|
+
if (registered) {
|
|
240236
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.workspace.id, "local", "deleting");
|
|
240237
|
+
}
|
|
240238
|
+
let worktreeRemoved = false;
|
|
239905
240239
|
try {
|
|
239906
240240
|
const { execSync: execSync2, execFileSync: execFileSync7 } = await import("child_process");
|
|
239907
240241
|
const worktreeAbsPath = resolveWorktreePath(projectPath, branch);
|
|
@@ -239912,6 +240246,9 @@ var routes9 = async (fastify2) => {
|
|
|
239912
240246
|
stdio: ["pipe", "pipe", "pipe"]
|
|
239913
240247
|
});
|
|
239914
240248
|
if (statusOutput.trim() !== "") {
|
|
240249
|
+
if (registered) {
|
|
240250
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.workspace.id, "local", "ready");
|
|
240251
|
+
}
|
|
239915
240252
|
return reply.code(409).send({
|
|
239916
240253
|
error: "Worktree has uncommitted changes"
|
|
239917
240254
|
});
|
|
@@ -239930,6 +240267,7 @@ var routes9 = async (fastify2) => {
|
|
|
239930
240267
|
encoding: "utf-8",
|
|
239931
240268
|
stdio: ["pipe", "pipe", "pipe"]
|
|
239932
240269
|
});
|
|
240270
|
+
worktreeRemoved = true;
|
|
239933
240271
|
invalidateWorktreeListCache(projectPath);
|
|
239934
240272
|
if (branchToDelete) {
|
|
239935
240273
|
try {
|
|
@@ -239941,9 +240279,15 @@ var routes9 = async (fastify2) => {
|
|
|
239941
240279
|
} catch {
|
|
239942
240280
|
}
|
|
239943
240281
|
}
|
|
240282
|
+
if (registered) {
|
|
240283
|
+
await fastify2.storage.workspaceRegistry.removeCheckout(registered.workspace.id, "local");
|
|
240284
|
+
}
|
|
239944
240285
|
return reply.code(200).send({ success: true });
|
|
239945
240286
|
} catch (error48) {
|
|
239946
240287
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
240288
|
+
if (registered && !worktreeRemoved) {
|
|
240289
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.workspace.id, "local", "error", errorMessage).catch((registryError) => console.error("[worktree] Failed to record delete error:", registryError));
|
|
240290
|
+
}
|
|
239947
240291
|
return reply.code(500).send({ error: `Failed to delete worktree: ${errorMessage}` });
|
|
239948
240292
|
}
|
|
239949
240293
|
});
|
|
@@ -239983,7 +240327,7 @@ var routes9 = async (fastify2) => {
|
|
|
239983
240327
|
}
|
|
239984
240328
|
try {
|
|
239985
240329
|
pruneWorktrees(project.path);
|
|
239986
|
-
const worktrees =
|
|
240330
|
+
const worktrees = await getRegisteredWorktreeBranches(fastify2.storage, project.id, project.path);
|
|
239987
240331
|
return reply.code(200).send({ worktrees });
|
|
239988
240332
|
} catch (error48) {
|
|
239989
240333
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
@@ -240055,13 +240399,44 @@ var routes9 = async (fastify2) => {
|
|
|
240055
240399
|
const remoteConfigs = await getAllRemoteConfigs(fastify2, project);
|
|
240056
240400
|
const hasRemote = remoteConfigs.length > 0;
|
|
240057
240401
|
const deleteOnRemote = async (rc) => {
|
|
240058
|
-
|
|
240059
|
-
|
|
240060
|
-
|
|
240061
|
-
|
|
240062
|
-
|
|
240063
|
-
|
|
240064
|
-
|
|
240402
|
+
const registered = await fastify2.storage.workspaceRegistry.getByProjectBranch(project.id, branch, rc.serverId);
|
|
240403
|
+
const restorePreviousStatus = async () => {
|
|
240404
|
+
if (!registered) return;
|
|
240405
|
+
const current = await fastify2.storage.workspaceRegistry.getByProjectBranch(project.id, branch, rc.serverId);
|
|
240406
|
+
if (!current || current.checkout.status !== "deleting") return;
|
|
240407
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatusIfCurrent(
|
|
240408
|
+
registered.workspace.id,
|
|
240409
|
+
rc.serverId,
|
|
240410
|
+
{ status: "deleting", updatedAt: current.checkout.updated_at },
|
|
240411
|
+
registered.checkout.status,
|
|
240412
|
+
registered.checkout.error
|
|
240413
|
+
);
|
|
240414
|
+
};
|
|
240415
|
+
if (registered) {
|
|
240416
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.workspace.id, rc.serverId, "deleting");
|
|
240417
|
+
}
|
|
240418
|
+
try {
|
|
240419
|
+
const result = await proxyToRemoteAuto(
|
|
240420
|
+
rc.serverId,
|
|
240421
|
+
"DELETE",
|
|
240422
|
+
`/api/path/worktrees`,
|
|
240423
|
+
{ path: rc.remotePath, branch },
|
|
240424
|
+
{ reverseConnectManager: fastify2.reverseConnectManager }
|
|
240425
|
+
);
|
|
240426
|
+
if (registered) {
|
|
240427
|
+
if (result.ok) {
|
|
240428
|
+
await fastify2.storage.workspaceRegistry.removeCheckout(registered.workspace.id, rc.serverId);
|
|
240429
|
+
} else {
|
|
240430
|
+
await restorePreviousStatus();
|
|
240431
|
+
}
|
|
240432
|
+
}
|
|
240433
|
+
return result;
|
|
240434
|
+
} catch (error48) {
|
|
240435
|
+
if (registered) {
|
|
240436
|
+
await restorePreviousStatus().catch((registryError) => console.error("[worktree] Failed to restore remote checkout status:", registryError));
|
|
240437
|
+
}
|
|
240438
|
+
throw error48;
|
|
240439
|
+
}
|
|
240065
240440
|
};
|
|
240066
240441
|
if (!hasLocal && hasRemote) {
|
|
240067
240442
|
if (remoteConfigs.length === 1) {
|
|
@@ -240098,40 +240473,58 @@ var routes9 = async (fastify2) => {
|
|
|
240098
240473
|
const deleteLocal = async () => {
|
|
240099
240474
|
const { execSync: execSync2, execFileSync: execFileSync7 } = await import("child_process");
|
|
240100
240475
|
const worktreeAbsPath = resolveWorktreePath(project.path, branch);
|
|
240101
|
-
|
|
240102
|
-
|
|
240103
|
-
|
|
240104
|
-
encoding: "utf-8",
|
|
240105
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
240106
|
-
});
|
|
240107
|
-
if (statusOutput.trim() !== "") {
|
|
240108
|
-
throw new Error("Worktree has uncommitted changes. Please commit or discard changes before deleting.");
|
|
240109
|
-
}
|
|
240110
|
-
} catch (err) {
|
|
240111
|
-
if (err instanceof Error && err.message.includes("uncommitted changes")) throw err;
|
|
240476
|
+
const registered = await fastify2.storage.workspaceRegistry.getByProjectBranch(project.id, branch, "local");
|
|
240477
|
+
if (registered) {
|
|
240478
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.workspace.id, "local", "deleting");
|
|
240112
240479
|
}
|
|
240113
|
-
let
|
|
240480
|
+
let worktreeRemoved = false;
|
|
240114
240481
|
try {
|
|
240115
|
-
const entries = parseGitWorktreeList(project.path);
|
|
240116
|
-
const match2 = entries.find((e) => e.path === worktreeAbsPath);
|
|
240117
|
-
if (match2) branchToDelete = match2.branch;
|
|
240118
|
-
} catch {
|
|
240119
|
-
}
|
|
240120
|
-
execFileSync7("git", ["worktree", "remove", worktreeAbsPath], {
|
|
240121
|
-
cwd: project.path,
|
|
240122
|
-
encoding: "utf-8",
|
|
240123
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
240124
|
-
});
|
|
240125
|
-
invalidateWorktreeListCache(project.path);
|
|
240126
|
-
if (branchToDelete) {
|
|
240127
240482
|
try {
|
|
240128
|
-
|
|
240129
|
-
cwd:
|
|
240483
|
+
const statusOutput = execSync2("git status --porcelain", {
|
|
240484
|
+
cwd: worktreeAbsPath,
|
|
240130
240485
|
encoding: "utf-8",
|
|
240131
240486
|
stdio: ["pipe", "pipe", "pipe"]
|
|
240132
240487
|
});
|
|
240488
|
+
if (statusOutput.trim() !== "") {
|
|
240489
|
+
throw new Error("Worktree has uncommitted changes. Please commit or discard changes before deleting.");
|
|
240490
|
+
}
|
|
240491
|
+
} catch (err) {
|
|
240492
|
+
if (err instanceof Error && err.message.includes("uncommitted changes")) throw err;
|
|
240493
|
+
}
|
|
240494
|
+
let branchToDelete = null;
|
|
240495
|
+
try {
|
|
240496
|
+
const entries = parseGitWorktreeList(project.path);
|
|
240497
|
+
const match2 = entries.find((e) => e.path === worktreeAbsPath);
|
|
240498
|
+
if (match2) branchToDelete = match2.branch;
|
|
240133
240499
|
} catch {
|
|
240134
240500
|
}
|
|
240501
|
+
execFileSync7("git", ["worktree", "remove", worktreeAbsPath], {
|
|
240502
|
+
cwd: project.path,
|
|
240503
|
+
encoding: "utf-8",
|
|
240504
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
240505
|
+
});
|
|
240506
|
+
worktreeRemoved = true;
|
|
240507
|
+
invalidateWorktreeListCache(project.path);
|
|
240508
|
+
if (branchToDelete) {
|
|
240509
|
+
try {
|
|
240510
|
+
execFileSync7("git", ["branch", "-d", branchToDelete], {
|
|
240511
|
+
cwd: project.path,
|
|
240512
|
+
encoding: "utf-8",
|
|
240513
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
240514
|
+
});
|
|
240515
|
+
} catch {
|
|
240516
|
+
}
|
|
240517
|
+
}
|
|
240518
|
+
if (registered) {
|
|
240519
|
+
await fastify2.storage.workspaceRegistry.removeCheckout(registered.workspace.id, "local");
|
|
240520
|
+
}
|
|
240521
|
+
} catch (error48) {
|
|
240522
|
+
if (registered && !worktreeRemoved) {
|
|
240523
|
+
const message = error48 instanceof Error ? error48.message : "Local deletion failed";
|
|
240524
|
+
const status = message.includes("uncommitted changes") ? "ready" : "error";
|
|
240525
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(registered.workspace.id, "local", status, status === "error" ? message : null).catch((registryError) => console.error("[worktree] Failed to record local delete error:", registryError));
|
|
240526
|
+
}
|
|
240527
|
+
throw error48;
|
|
240135
240528
|
}
|
|
240136
240529
|
};
|
|
240137
240530
|
if (!hasRemote) {
|
|
@@ -240218,13 +240611,47 @@ var routes9 = async (fastify2) => {
|
|
|
240218
240611
|
return reply.code(400).send({ error: "Project has no remote configuration" });
|
|
240219
240612
|
}
|
|
240220
240613
|
const createOnRemote = async (rc) => {
|
|
240221
|
-
|
|
240222
|
-
|
|
240223
|
-
|
|
240224
|
-
|
|
240225
|
-
|
|
240226
|
-
|
|
240227
|
-
|
|
240614
|
+
const previous = await fastify2.storage.workspaceRegistry.getByProjectBranch(project.id, trimmedBranch, rc.serverId);
|
|
240615
|
+
const preserveReady = previous?.checkout.status === "ready";
|
|
240616
|
+
const pending = preserveReady && previous ? previous : await fastify2.storage.workspaceRegistry.beginCheckout({
|
|
240617
|
+
projectId: project.id,
|
|
240618
|
+
branch: trimmedBranch,
|
|
240619
|
+
targetId: rc.serverId,
|
|
240620
|
+
worktreePath: conventionalWorktreePath(rc.remotePath, trimmedBranch),
|
|
240621
|
+
expectedBranch: trimmedBranch
|
|
240622
|
+
});
|
|
240623
|
+
try {
|
|
240624
|
+
const result = await proxyToRemoteAuto(
|
|
240625
|
+
rc.serverId,
|
|
240626
|
+
"POST",
|
|
240627
|
+
`/api/path/worktrees`,
|
|
240628
|
+
{ path: rc.remotePath, branchName: trimmedBranch, baseBranch: remoteStartPoint },
|
|
240629
|
+
{ reverseConnectManager: fastify2.reverseConnectManager }
|
|
240630
|
+
);
|
|
240631
|
+
if (result.ok) {
|
|
240632
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.workspace.id, rc.serverId, "ready");
|
|
240633
|
+
} else if (preserveReady) {
|
|
240634
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.workspace.id, rc.serverId, "ready");
|
|
240635
|
+
} else {
|
|
240636
|
+
const detail = result.data;
|
|
240637
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(
|
|
240638
|
+
pending.workspace.id,
|
|
240639
|
+
rc.serverId,
|
|
240640
|
+
"error",
|
|
240641
|
+
detail.error ?? result.errorCode ?? "Remote creation failed"
|
|
240642
|
+
);
|
|
240643
|
+
}
|
|
240644
|
+
return result;
|
|
240645
|
+
} catch (error48) {
|
|
240646
|
+
const message = error48 instanceof Error ? error48.message : "Remote creation failed";
|
|
240647
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(
|
|
240648
|
+
pending.workspace.id,
|
|
240649
|
+
rc.serverId,
|
|
240650
|
+
preserveReady ? "ready" : "error",
|
|
240651
|
+
preserveReady ? null : message
|
|
240652
|
+
).catch((registryError) => console.error("[worktree] Failed to record remote checkout error:", registryError));
|
|
240653
|
+
throw error48;
|
|
240654
|
+
}
|
|
240228
240655
|
};
|
|
240229
240656
|
if (targets.length === 1 && targets[0] === "remote") {
|
|
240230
240657
|
if (remoteConfigs.length === 1) {
|
|
@@ -240275,14 +240702,28 @@ var routes9 = async (fastify2) => {
|
|
|
240275
240702
|
if (err instanceof Error && err.message.includes("already exists")) throw err;
|
|
240276
240703
|
}
|
|
240277
240704
|
const worktreeAbsolutePath = resolveWorktreePath(project.path, trimmedBranch);
|
|
240278
|
-
await
|
|
240279
|
-
|
|
240280
|
-
|
|
240281
|
-
|
|
240282
|
-
|
|
240705
|
+
const pending = await fastify2.storage.workspaceRegistry.beginCheckout({
|
|
240706
|
+
projectId: project.id,
|
|
240707
|
+
branch: trimmedBranch,
|
|
240708
|
+
targetId: "local",
|
|
240709
|
+
worktreePath: worktreeAbsolutePath,
|
|
240710
|
+
expectedBranch: trimmedBranch
|
|
240283
240711
|
});
|
|
240284
|
-
|
|
240285
|
-
|
|
240712
|
+
try {
|
|
240713
|
+
await mkdir3(getWorktreeBaseForProject(project.path), { recursive: true });
|
|
240714
|
+
execFileSync7("git", ["worktree", "add", "-b", trimmedBranch, worktreeAbsolutePath, localStartPoint], {
|
|
240715
|
+
cwd: project.path,
|
|
240716
|
+
encoding: "utf-8",
|
|
240717
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
240718
|
+
});
|
|
240719
|
+
invalidateWorktreeListCache(project.path);
|
|
240720
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.workspace.id, "local", "ready");
|
|
240721
|
+
return { branch: trimmedBranch };
|
|
240722
|
+
} catch (error48) {
|
|
240723
|
+
const message = error48 instanceof Error ? error48.message : "Local creation failed";
|
|
240724
|
+
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.workspace.id, "local", "error", message).catch((registryError) => console.error("[worktree] Failed to record local checkout error:", registryError));
|
|
240725
|
+
throw error48;
|
|
240726
|
+
}
|
|
240286
240727
|
};
|
|
240287
240728
|
if (targets.length === 1 && targets[0] === "local") {
|
|
240288
240729
|
try {
|
|
@@ -246516,23 +246957,6 @@ var event_routes_default = (0, import_fastify_plugin27.default)(routes26, { name
|
|
|
246516
246957
|
// src/routes/terminal-routes.ts
|
|
246517
246958
|
var import_fastify_plugin28 = __toESM(require_plugin2(), 1);
|
|
246518
246959
|
import path13 from "path";
|
|
246519
|
-
|
|
246520
|
-
// src/utils/path-project.ts
|
|
246521
|
-
async function ensurePathProjectId(fastify2, projectPath) {
|
|
246522
|
-
const pseudoProjectId = `path:${projectPath}`;
|
|
246523
|
-
if (await fastify2.storage.projects.getById(pseudoProjectId)) return pseudoProjectId;
|
|
246524
|
-
const existingByPath = await fastify2.storage.projects.getByPath(projectPath);
|
|
246525
|
-
if (existingByPath) return existingByPath.id;
|
|
246526
|
-
const name25 = projectPath.split("/").filter(Boolean).pop() || projectPath;
|
|
246527
|
-
try {
|
|
246528
|
-
await fastify2.storage.projects.create({ id: pseudoProjectId, name: name25, path: projectPath });
|
|
246529
|
-
} catch (err) {
|
|
246530
|
-
if (!(err instanceof Error && err.message.includes("UNIQUE constraint failed"))) throw err;
|
|
246531
|
-
}
|
|
246532
|
-
return pseudoProjectId;
|
|
246533
|
-
}
|
|
246534
|
-
|
|
246535
|
-
// src/routes/terminal-routes.ts
|
|
246536
246960
|
async function getRemoteConfig5(fastify2, project, remoteServerId) {
|
|
246537
246961
|
const remotes = await fastify2.storage.projectRemotes.getByProject(project.id);
|
|
246538
246962
|
const target = remoteServerId ? remotes.find((r) => r.remote_server_id === remoteServerId) : remotes[0];
|
|
@@ -248145,8 +248569,8 @@ var parseDbTimestamp5 = (ts) => {
|
|
|
248145
248569
|
};
|
|
248146
248570
|
async function buildSearchCatalog(deps, projectId, projectPath) {
|
|
248147
248571
|
pruneWorktrees(projectPath);
|
|
248148
|
-
const workspaces = getWorktreeBranches(projectPath);
|
|
248149
248572
|
const sessions = await deps.storage.agentSessions.getByProjectId(projectId);
|
|
248573
|
+
const workspaces = await getRegisteredWorktreeBranches(deps.storage, projectId, projectPath);
|
|
248150
248574
|
const counts = new Map(
|
|
248151
248575
|
(await deps.storage.agentSessions.countEntries()).map((r) => [r.session_id, r.cnt])
|
|
248152
248576
|
);
|