spec-cat 0.1.61 → 0.1.63
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/.output/nitro.json +1 -1
- package/.output/public/_nuxt/2zamijve.js +1 -0
- package/.output/public/_nuxt/{Bhr6Zo3T.js → BEjIzkrM.js} +54 -54
- package/.output/public/_nuxt/{DVCRp6I2.js → BaSsfm-t.js} +1 -1
- package/.output/public/_nuxt/BjdLSVUw.js +1 -0
- package/.output/public/_nuxt/{qOn4ZFdM.js → Bz2rU2zs.js} +1 -1
- package/.output/public/_nuxt/{8Elu-15_.js → D4LyIv_t.js} +1 -1
- package/.output/public/_nuxt/{C7AMOFY8.js → DIOhMCOf.js} +2 -2
- package/.output/public/_nuxt/{BpYxF7v5.js → DPOGSCeV.js} +1 -1
- package/.output/public/_nuxt/{CbE7c0sD.js → DeqM2TrP.js} +1 -1
- package/.output/public/_nuxt/{C8fQuSPf.js → DwpuOtAP.js} +1 -1
- package/.output/public/_nuxt/{DTRKuZ1Z.js → FfyCVKRU.js} +1 -1
- package/.output/public/_nuxt/{C4M037xP.js → Su-Cl_JF.js} +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/74089fa1-2fbb-4792-94aa-7535d2aec557.json +1 -0
- package/.output/public/_nuxt/{DCnFPBGM.js → zrVRZSxq.js} +1 -1
- package/.output/server/chunks/_/asyncLock.mjs +17 -0
- package/.output/server/chunks/_/asyncLock.mjs.map +1 -0
- package/.output/server/chunks/_/chatGit.mjs +22 -0
- package/.output/server/chunks/_/chatGit.mjs.map +1 -0
- package/.output/server/chunks/_/claude.mjs +2 -1
- package/.output/server/chunks/_/claude.mjs.map +1 -1
- package/.output/server/chunks/_/claudeProvider.mjs +2 -1
- package/.output/server/chunks/_/claudeProvider.mjs.map +1 -1
- package/.output/server/chunks/_/codexProvider.mjs +14 -2
- package/.output/server/chunks/_/codexProvider.mjs.map +1 -1
- package/.output/server/chunks/_/jobQueue.mjs +1 -1
- package/.output/server/chunks/_/validateWorktree.mjs +1 -1
- package/.output/server/chunks/_/worktreePaths.mjs +1 -1
- package/.output/server/chunks/build/client.precomputed.mjs +1 -1
- package/.output/server/chunks/build/client.precomputed.mjs.map +1 -1
- package/.output/server/chunks/nitro/nitro.mjs +611 -611
- package/.output/server/chunks/routes/api/chat/compare.get.mjs +5 -0
- package/.output/server/chunks/routes/api/chat/compare.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/finalize.post.mjs +94 -93
- package/.output/server/chunks/routes/api/chat/finalize.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/generate-commit-message.post.mjs +2 -0
- package/.output/server/chunks/routes/api/chat/generate-commit-message.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/preview-sync.post.mjs +28 -22
- package/.output/server/chunks/routes/api/chat/preview-sync.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/preview.delete.mjs +24 -23
- package/.output/server/chunks/routes/api/chat/preview.delete.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/preview.post.mjs +53 -48
- package/.output/server/chunks/routes/api/chat/preview.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/rebase.post.mjs +39 -41
- package/.output/server/chunks/routes/api/chat/rebase.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/worktree-commit.post.mjs +56 -46
- package/.output/server/chunks/routes/api/chat/worktree-commit.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/worktree.delete.mjs +38 -30
- package/.output/server/chunks/routes/api/chat/worktree.delete.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat/worktree.post.mjs +73 -65
- package/.output/server/chunks/routes/api/chat/worktree.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/chat.post.mjs +16 -3
- package/.output/server/chunks/routes/api/chat.post.mjs.map +1 -1
- package/.output/server/package.json +1 -1
- package/package.json +1 -1
- package/.output/public/_nuxt/BeBeZcRQ.js +0 -1
- package/.output/public/_nuxt/C_6kiUg6.js +0 -1
- package/.output/public/_nuxt/builds/meta/81746bdb-ce0f-42a7-9dd1-65c11a21de2d.json +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.post.mjs","sources":["../../../../../../server/api/chat/preview.post.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preview.post.mjs","sources":["../../../../../../server/api/chat/preview.post.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { d as defineEventHandler, b as readBody, c as createError, e as getProjectDir, l as logger } from '../../../nitro/nitro.mjs';
|
|
2
|
-
import { execSync, exec } from 'node:child_process';
|
|
3
|
-
import { promisify } from 'node:util';
|
|
4
2
|
import { existsSync } from 'node:fs';
|
|
5
3
|
import { r as resolveExistingBaseBranch } from '../../../_/baseBranch.mjs';
|
|
6
4
|
import { g as getChatWorktreePath } from '../../../_/worktreePaths.mjs';
|
|
5
|
+
import { v as validateWorktreePath } from '../../../_/validateWorktree.mjs';
|
|
6
|
+
import { g as git, a as assertSafeBranchName } from '../../../_/chatGit.mjs';
|
|
7
|
+
import { a as autoCommitChanges } from '../../../_/claudeService.mjs';
|
|
8
|
+
import { w as withLock } from '../../../_/asyncLock.mjs';
|
|
7
9
|
import 'node:http';
|
|
8
10
|
import 'node:https';
|
|
9
11
|
import 'node:crypto';
|
|
@@ -27,19 +29,9 @@ import 'node:url';
|
|
|
27
29
|
import '../../../_/gitExec.mjs';
|
|
28
30
|
import 'child_process';
|
|
29
31
|
import 'util';
|
|
32
|
+
import 'node:child_process';
|
|
33
|
+
import '../../../_/claude.mjs';
|
|
30
34
|
|
|
31
|
-
const execAsync = promisify(exec);
|
|
32
|
-
async function git(cwd, cmd) {
|
|
33
|
-
const { stdout } = await execAsync(`git ${cmd}`, { cwd });
|
|
34
|
-
return stdout.trim();
|
|
35
|
-
}
|
|
36
|
-
async function autoCommitChanges(worktreePath) {
|
|
37
|
-
const status = await git(worktreePath, "status --porcelain");
|
|
38
|
-
if (!status) return false;
|
|
39
|
-
await git(worktreePath, "add -A");
|
|
40
|
-
execSync("git commit -F -", { cwd: worktreePath, input: "auto-commit uncommitted changes", encoding: "utf-8" });
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
35
|
const rebase_post = defineEventHandler(async (event) => {
|
|
44
36
|
const body = await readBody(event);
|
|
45
37
|
if (!(body == null ? void 0 : body.conversationId)) {
|
|
@@ -51,10 +43,13 @@ const rebase_post = defineEventHandler(async (event) => {
|
|
|
51
43
|
const { conversationId } = body;
|
|
52
44
|
const projectDir = getProjectDir();
|
|
53
45
|
const worktreePath = body.worktreePath || getChatWorktreePath(conversationId);
|
|
46
|
+
if (existsSync(worktreePath)) {
|
|
47
|
+
validateWorktreePath(worktreePath);
|
|
48
|
+
}
|
|
54
49
|
let worktreeBranch = "";
|
|
55
50
|
if (existsSync(worktreePath)) {
|
|
56
51
|
try {
|
|
57
|
-
worktreeBranch = await git(worktreePath, "rev-parse --abbrev-ref HEAD");
|
|
52
|
+
worktreeBranch = await git(worktreePath, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
58
53
|
} catch {
|
|
59
54
|
worktreeBranch = "";
|
|
60
55
|
}
|
|
@@ -67,41 +62,44 @@ const rebase_post = defineEventHandler(async (event) => {
|
|
|
67
62
|
if (!baseBranch) {
|
|
68
63
|
return { success: false, error: "Unable to resolve a valid base branch for this worktree." };
|
|
69
64
|
}
|
|
65
|
+
assertSafeBranchName(baseBranch, "base branch");
|
|
70
66
|
logger.chat.info("Rebasing worktree onto base", { conversationId, baseBranch });
|
|
71
|
-
|
|
72
|
-
if (!existsSync(worktreePath)) {
|
|
73
|
-
return { success: false, error: "Worktree directory not found. It may have been cleaned up." };
|
|
74
|
-
}
|
|
75
|
-
await autoCommitChanges(worktreePath);
|
|
67
|
+
return withLock(projectDir, async () => {
|
|
76
68
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
if (!existsSync(worktreePath)) {
|
|
70
|
+
return { success: false, error: "Worktree directory not found. It may have been cleaned up." };
|
|
71
|
+
}
|
|
72
|
+
await autoCommitChanges(worktreePath);
|
|
81
73
|
try {
|
|
82
|
-
|
|
83
|
-
conflictFiles = diffOutput.split("\n").filter(Boolean);
|
|
74
|
+
await git(worktreePath, ["rebase", baseBranch]);
|
|
84
75
|
} catch {
|
|
76
|
+
logger.chat.warn("Rebase conflict during sync", { conversationId });
|
|
77
|
+
let conflictFiles = [];
|
|
85
78
|
try {
|
|
86
|
-
const
|
|
87
|
-
conflictFiles =
|
|
79
|
+
const diffOutput = await git(worktreePath, ["diff", "--name-only", "--diff-filter=U"]);
|
|
80
|
+
conflictFiles = diffOutput.split("\n").filter(Boolean);
|
|
88
81
|
} catch {
|
|
82
|
+
try {
|
|
83
|
+
const statusOutput = await git(worktreePath, ["status", "--porcelain"]);
|
|
84
|
+
conflictFiles = statusOutput.split("\n").filter((line) => /^(UU|AA|DU|UD|UA|AU|DD)\s/.test(line)).map((line) => line.substring(3).trim());
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
89
87
|
}
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: `Rebase conflict with "${baseBranch}". Resolve conflicts to continue.`,
|
|
91
|
+
conflictFiles,
|
|
92
|
+
rebaseInProgress: true
|
|
93
|
+
};
|
|
90
94
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
};
|
|
95
|
+
logger.chat.info("Worktree rebased successfully", { conversationId, baseBranch });
|
|
96
|
+
return { success: true };
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
99
|
+
logger.chat.error("Rebase sync failed", { conversationId, error: errorMessage });
|
|
100
|
+
return { success: false, error: errorMessage };
|
|
97
101
|
}
|
|
98
|
-
|
|
99
|
-
return { success: true };
|
|
100
|
-
} catch (error) {
|
|
101
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
102
|
-
logger.chat.error("Rebase sync failed", { conversationId, error: errorMessage });
|
|
103
|
-
return { success: false, error: errorMessage };
|
|
104
|
-
}
|
|
102
|
+
});
|
|
105
103
|
});
|
|
106
104
|
|
|
107
105
|
export { rebase_post as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebase.post.mjs","sources":["../../../../../../server/api/chat/rebase.post.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rebase.post.mjs","sources":["../../../../../../server/api/chat/rebase.post.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { d as defineEventHandler, b as readBody, c as createError, e as getProjectDir, l as logger } from '../../../nitro/nitro.mjs';
|
|
2
|
-
import {
|
|
3
|
-
import { promisify } from 'node:util';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
4
3
|
import { a as autoCommitChanges } from '../../../_/claudeService.mjs';
|
|
4
|
+
import { v as validateWorktreePath } from '../../../_/validateWorktree.mjs';
|
|
5
|
+
import { i as isSafeBranchName, g as git } from '../../../_/chatGit.mjs';
|
|
6
|
+
import { w as withLock } from '../../../_/asyncLock.mjs';
|
|
5
7
|
import 'node:http';
|
|
6
8
|
import 'node:https';
|
|
7
9
|
import 'node:crypto';
|
|
@@ -17,15 +19,18 @@ import 'tls';
|
|
|
17
19
|
import 'url';
|
|
18
20
|
import 'node:events';
|
|
19
21
|
import 'node:buffer';
|
|
20
|
-
import 'node:fs';
|
|
21
22
|
import 'node:path';
|
|
22
23
|
import 'node:os';
|
|
23
24
|
import 'node:module';
|
|
24
25
|
import 'node:fs/promises';
|
|
25
26
|
import 'node:url';
|
|
27
|
+
import 'node:child_process';
|
|
26
28
|
import '../../../_/claude.mjs';
|
|
29
|
+
import '../../../_/worktreePaths.mjs';
|
|
30
|
+
import '../../../_/gitExec.mjs';
|
|
31
|
+
import 'child_process';
|
|
32
|
+
import 'util';
|
|
27
33
|
|
|
28
|
-
const execAsync = promisify(exec);
|
|
29
34
|
const PROTECTED_BRANCHES = /* @__PURE__ */ new Set(["main", "master", "develop", "dev"]);
|
|
30
35
|
const worktreeCommit_post = defineEventHandler(async (event) => {
|
|
31
36
|
const body = await readBody(event);
|
|
@@ -36,54 +41,59 @@ const worktreeCommit_post = defineEventHandler(async (event) => {
|
|
|
36
41
|
});
|
|
37
42
|
}
|
|
38
43
|
const { worktreePath, conversationId, previousBranch } = body;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
previousBranch
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
44
|
+
if (existsSync(worktreePath)) {
|
|
45
|
+
validateWorktreePath(worktreePath);
|
|
46
|
+
}
|
|
47
|
+
return withLock(getProjectDir(), async () => {
|
|
48
|
+
try {
|
|
49
|
+
const result = await autoCommitChanges(worktreePath);
|
|
50
|
+
let deletedPreviousBranch = false;
|
|
51
|
+
if (result.success) {
|
|
52
|
+
const branchChanged = Boolean(
|
|
53
|
+
previousBranch && result.currentBranch && previousBranch !== result.currentBranch
|
|
54
|
+
);
|
|
55
|
+
if (branchChanged && previousBranch && !PROTECTED_BRANCHES.has(previousBranch) && isSafeBranchName(previousBranch)) {
|
|
56
|
+
try {
|
|
57
|
+
await git(getProjectDir(), ["branch", "-D", previousBranch]);
|
|
58
|
+
deletedPreviousBranch = true;
|
|
59
|
+
logger.chat.info("Deleted previous worktree branch after branch switch", {
|
|
60
|
+
conversationId,
|
|
61
|
+
previousBranch,
|
|
62
|
+
currentBranch: result.currentBranch
|
|
63
|
+
});
|
|
64
|
+
} catch (deleteError) {
|
|
65
|
+
logger.chat.warn("Failed to delete previous worktree branch after branch switch", {
|
|
66
|
+
conversationId,
|
|
67
|
+
previousBranch,
|
|
68
|
+
currentBranch: result.currentBranch,
|
|
69
|
+
error: deleteError instanceof Error ? deleteError.message : String(deleteError)
|
|
70
|
+
});
|
|
71
|
+
}
|
|
62
72
|
}
|
|
73
|
+
logger.chat.info("Worktree auto-commit done", {
|
|
74
|
+
conversationId,
|
|
75
|
+
message: result.message,
|
|
76
|
+
currentBranch: result.currentBranch,
|
|
77
|
+
previousBranch,
|
|
78
|
+
deletedPreviousBranch
|
|
79
|
+
});
|
|
63
80
|
}
|
|
64
|
-
|
|
65
|
-
|
|
81
|
+
return {
|
|
82
|
+
success: result.success,
|
|
66
83
|
message: result.message,
|
|
67
84
|
currentBranch: result.currentBranch,
|
|
68
|
-
|
|
69
|
-
|
|
85
|
+
deletedPreviousBranch,
|
|
86
|
+
error: result.error
|
|
87
|
+
};
|
|
88
|
+
} catch (error) {
|
|
89
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
90
|
+
logger.chat.error("Worktree auto-commit failed", {
|
|
91
|
+
conversationId,
|
|
92
|
+
error: errorMessage
|
|
70
93
|
});
|
|
94
|
+
return { success: false, error: errorMessage };
|
|
71
95
|
}
|
|
72
|
-
|
|
73
|
-
success: result.success,
|
|
74
|
-
message: result.message,
|
|
75
|
-
currentBranch: result.currentBranch,
|
|
76
|
-
deletedPreviousBranch,
|
|
77
|
-
error: result.error
|
|
78
|
-
};
|
|
79
|
-
} catch (error) {
|
|
80
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
81
|
-
logger.chat.error("Worktree auto-commit failed", {
|
|
82
|
-
conversationId,
|
|
83
|
-
error: errorMessage
|
|
84
|
-
});
|
|
85
|
-
return { success: false, error: errorMessage };
|
|
86
|
-
}
|
|
96
|
+
});
|
|
87
97
|
});
|
|
88
98
|
|
|
89
99
|
export { worktreeCommit_post as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktree-commit.post.mjs","sources":["../../../../../../server/api/chat/worktree-commit.post.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"worktree-commit.post.mjs","sources":["../../../../../../server/api/chat/worktree-commit.post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAA,kBAAA,uBAAA,GAAA,CAAA,CAAA,QAAA,QAAA,EAAA,SAAA,EAAA,KAAA,CAAA,CAAA;AAEA,4BAAA,kBAAA,CAAA,OAAA,KAAA,KAAA;AACA,EAAA,MAAA,IAAA,GAAA,MAAA,QAAA,CAIA,KAAA,CAAA;AAEA,EAAA,IAAA,EAAA,6BAAA,YAAA,CAAA,EAAA;AACA,IAAA,MAAA,WAAA,CAAA;AAAA,MACA,UAAA,EAAA,GAAA;AAAA,MACA,OAAA,EAAA;AAAA,KACA,CAAA;AAAA,EACA;AAEA,EAAA,MAAA,EAAA,YAAA,EAAA,cAAA,EAAA,cAAA,EAAA,GAAA,IAAA;AAEA,EAAA,IAAA,UAAA,CAAA,YAAA,CAAA,EAAA;AACA,IAAA,oBAAA,CAAA,YAAA,CAAA;AAAA,EACA;AAEA,EAAA,OAAA,QAAA,CAAA,aAAA,EAAA,EAAA,YAAA;AACA,IAAA,IAAA;AACA,MAAA,MAAA,MAAA,GAAA,MAAA,iBAAA,CAAA,YAAA,CAAA;AACA,MAAA,IAAA,qBAAA,GAAA,KAAA;AAEA,MAAA,IAAA,OAAA,OAAA,EAAA;AACA,QAAA,MAAA,aAAA,GAAA,OAAA;AAAA,UACA,cAAA,IACA,MAAA,CAAA,aAAA,IACA,cAAA,KAAA,MAAA,CAAA;AAAA,SACA;AAEA,QAAA,IAAA,aAAA,IAAA,kBAAA,CAAA,kBAAA,CAAA,IAAA,cAAA,CAAA,IAAA,gBAAA,CAAA,cAAA,CAAA,EAAA;AACA,UAAA,IAAA;AACA,YAAA,MAAA,IAAA,aAAA,EAAA,EAAA,CAAA,QAAA,EAAA,IAAA,EAAA,cAAA,CAAA,CAAA;AACA,YAAA,qBAAA,GAAA,IAAA;AACA,YAAA,MAAA,CAAA,IAAA,CAAA,KAAA,sDAAA,EAAA;AAAA,cACA,cAAA;AAAA,cACA,cAAA;AAAA,cACA,eAAA,MAAA,CAAA;AAAA,aACA,CAAA;AAAA,UACA,SAAA,WAAA,EAAA;AACA,YAAA,MAAA,CAAA,IAAA,CAAA,KAAA,+DAAA,EAAA;AAAA,cACA,cAAA;AAAA,cACA,cAAA;AAAA,cACA,eAAA,MAAA,CAAA,aAAA;AAAA,cACA,OAAA,WAAA,YAAA,KAAA,GAAA,WAAA,CAAA,OAAA,GAAA,OAAA,WAAA;AAAA,aACA,CAAA;AAAA,UACA;AAAA,QACA;AAEA,QAAA,MAAA,CAAA,IAAA,CAAA,KAAA,2BAAA,EAAA;AAAA,UACA,cAAA;AAAA,UACA,SAAA,MAAA,CAAA,OAAA;AAAA,UACA,eAAA,MAAA,CAAA,aAAA;AAAA,UACA,cAAA;AAAA,UACA;AAAA,SACA,CAAA;AAAA,MACA;AAEA,MAAA,OAAA;AAAA,QACA,SAAA,MAAA,CAAA,OAAA;AAAA,QACA,SAAA,MAAA,CAAA,OAAA;AAAA,QACA,eAAA,MAAA,CAAA,aAAA;AAAA,QACA,qBAAA;AAAA,QACA,OAAA,MAAA,CAAA;AAAA,OACA;AAAA,IACA,SAAA,KAAA,EAAA;AACA,MAAA,MAAA,eAAA,KAAA,YAAA,KAAA,GAAA,KAAA,CAAA,OAAA,GAAA,OAAA,KAAA,CAAA;AACA,MAAA,MAAA,CAAA,IAAA,CAAA,MAAA,6BAAA,EAAA;AAAA,QACA,cAAA;AAAA,QACA,KAAA,EAAA;AAAA,OACA,CAAA;AAEA,MAAA,OAAA,EAAA,OAAA,EAAA,KAAA,EAAA,KAAA,EAAA,YAAA,EAAA;AAAA,IACA;AAAA,EACA,CAAA,CAAA;AACA,CAAA,CAAA;;;;"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { d as defineEventHandler, b as readBody, c as createError, e as getProjectDir, l as logger } from '../../../nitro/nitro.mjs';
|
|
2
|
-
import { exec } from 'node:child_process';
|
|
3
|
-
import { promisify } from 'node:util';
|
|
4
2
|
import { existsSync } from 'node:fs';
|
|
5
3
|
import { rm } from 'node:fs/promises';
|
|
4
|
+
import { v as validateWorktreePath } from '../../../_/validateWorktree.mjs';
|
|
5
|
+
import { a as assertSafeBranchName, g as git } from '../../../_/chatGit.mjs';
|
|
6
|
+
import { w as withLock } from '../../../_/asyncLock.mjs';
|
|
6
7
|
import 'node:http';
|
|
7
8
|
import 'node:https';
|
|
8
9
|
import 'node:crypto';
|
|
@@ -22,8 +23,11 @@ import 'node:path';
|
|
|
22
23
|
import 'node:os';
|
|
23
24
|
import 'node:module';
|
|
24
25
|
import 'node:url';
|
|
26
|
+
import '../../../_/worktreePaths.mjs';
|
|
27
|
+
import '../../../_/gitExec.mjs';
|
|
28
|
+
import 'child_process';
|
|
29
|
+
import 'util';
|
|
25
30
|
|
|
26
|
-
const execAsync = promisify(exec);
|
|
27
31
|
const worktree_delete = defineEventHandler(async (event) => {
|
|
28
32
|
const body = await readBody(event);
|
|
29
33
|
if (!(body == null ? void 0 : body.worktreePath) || !(body == null ? void 0 : body.branch)) {
|
|
@@ -32,39 +36,43 @@ const worktree_delete = defineEventHandler(async (event) => {
|
|
|
32
36
|
message: "worktreePath and branch are required"
|
|
33
37
|
});
|
|
34
38
|
}
|
|
35
|
-
const { worktreePath
|
|
39
|
+
const { worktreePath } = body;
|
|
40
|
+
const branch = assertSafeBranchName(body.branch, "branch");
|
|
36
41
|
const projectDir = getProjectDir();
|
|
42
|
+
if (existsSync(worktreePath)) {
|
|
43
|
+
validateWorktreePath(worktreePath);
|
|
44
|
+
}
|
|
37
45
|
logger.chat.info("Deleting chat worktree", { worktreePath, branch });
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
return withLock(projectDir, async () => {
|
|
47
|
+
try {
|
|
48
|
+
if (existsSync(worktreePath)) {
|
|
49
|
+
try {
|
|
50
|
+
await git(projectDir, ["worktree", "remove", worktreePath, "--force"]);
|
|
51
|
+
} catch {
|
|
52
|
+
await rm(worktreePath, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
await git(projectDir, ["worktree", "prune"]);
|
|
40
56
|
try {
|
|
41
|
-
await
|
|
42
|
-
|
|
57
|
+
await git(projectDir, ["branch", "-D", branch]);
|
|
58
|
+
logger.chat.info("Chat branch deleted", { branch });
|
|
59
|
+
} catch (branchError) {
|
|
60
|
+
logger.chat.warn("Failed to delete chat branch", {
|
|
61
|
+
branch,
|
|
62
|
+
error: branchError instanceof Error ? branchError.message : String(branchError)
|
|
43
63
|
});
|
|
44
|
-
} catch {
|
|
45
|
-
await rm(worktreePath, { recursive: true, force: true });
|
|
46
64
|
}
|
|
65
|
+
logger.chat.info("Chat worktree deleted", { worktreePath, branch });
|
|
66
|
+
return { success: true };
|
|
67
|
+
} catch (error) {
|
|
68
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
69
|
+
logger.chat.error("Failed to delete chat worktree", { worktreePath, branch, error: errorMessage });
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: errorMessage
|
|
73
|
+
};
|
|
47
74
|
}
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
await execAsync(`git branch -D "${branch}"`, { cwd: projectDir });
|
|
51
|
-
logger.chat.info("Chat branch deleted", { branch });
|
|
52
|
-
} catch (branchError) {
|
|
53
|
-
logger.chat.warn("Failed to delete chat branch", {
|
|
54
|
-
branch,
|
|
55
|
-
error: branchError instanceof Error ? branchError.message : String(branchError)
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
logger.chat.info("Chat worktree deleted", { worktreePath, branch });
|
|
59
|
-
return { success: true };
|
|
60
|
-
} catch (error) {
|
|
61
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
62
|
-
logger.chat.error("Failed to delete chat worktree", { worktreePath, branch, error: errorMessage });
|
|
63
|
-
return {
|
|
64
|
-
success: false,
|
|
65
|
-
error: errorMessage
|
|
66
|
-
};
|
|
67
|
-
}
|
|
75
|
+
});
|
|
68
76
|
});
|
|
69
77
|
|
|
70
78
|
export { worktree_delete as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktree.delete.mjs","sources":["../../../../../../server/api/chat/worktree.delete.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"worktree.delete.mjs","sources":["../../../../../../server/api/chat/worktree.delete.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,wBAAA,kBAAA,CAAA,OAAA,KAAA,KAAA;AACA,EAAA,MAAA,IAAA,GAAA,MAAA,QAAA,CAAA,KAAA,CAAA;AAEA,EAAA,IAAA,EAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,YAAA,CAAA,IAAA,EAAA,6BAAA,MAAA,CAAA,EAAA;AACA,IAAA,MAAA,WAAA,CAAA;AAAA,MACA,UAAA,EAAA,GAAA;AAAA,MACA,OAAA,EAAA;AAAA,KACA,CAAA;AAAA,EACA;AAEA,EAAA,MAAA,EAAA,cAAA,GAAA,IAAA;AACA,EAAA,MAAA,MAAA,GAAA,oBAAA,CAAA,IAAA,CAAA,MAAA,EAAA,QAAA,CAAA;AACA,EAAA,MAAA,aAAA,aAAA,EAAA;AAKA,EAAA,IAAA,UAAA,CAAA,YAAA,CAAA,EAAA;AACA,IAAA,oBAAA,CAAA,YAAA,CAAA;AAAA,EACA;AAEA,EAAA,MAAA,CAAA,KAAA,IAAA,CAAA,wBAAA,EAAA,EAAA,YAAA,EAAA,QAAA,CAAA;AAEA,EAAA,OAAA,QAAA,CAAA,YAAA,YAAA;AACA,IAAA,IAAA;AAEA,MAAA,IAAA,UAAA,CAAA,YAAA,CAAA,EAAA;AACA,QAAA,IAAA;AACA,UAAA,MAAA,IAAA,UAAA,EAAA,CAAA,YAAA,QAAA,EAAA,YAAA,EAAA,SAAA,CAAA,CAAA;AAAA,QACA,CAAA,CAAA,MAAA;AAEA,UAAA,MAAA,GAAA,YAAA,EAAA,EAAA,WAAA,IAAA,EAAA,KAAA,EAAA,MAAA,CAAA;AAAA,QACA;AAAA,MACA;AAGA,MAAA,MAAA,GAAA,CAAA,UAAA,EAAA,CAAA,UAAA,EAAA,OAAA,CAAA,CAAA;AAGA,MAAA,IAAA;AACA,QAAA,MAAA,IAAA,UAAA,EAAA,CAAA,QAAA,EAAA,IAAA,EAAA,MAAA,CAAA,CAAA;AACA,QAAA,MAAA,CAAA,IAAA,CAAA,IAAA,CAAA,qBAAA,EAAA,EAAA,QAAA,CAAA;AAAA,MACA,SAAA,WAAA,EAAA;AACA,QAAA,MAAA,CAAA,IAAA,CAAA,KAAA,8BAAA,EAAA;AAAA,UACA,MAAA;AAAA,UACA,OAAA,WAAA,YAAA,KAAA,GAAA,WAAA,CAAA,OAAA,GAAA,OAAA,WAAA;AAAA,SACA,CAAA;AAAA,MACA;AAEA,MAAA,MAAA,CAAA,KAAA,IAAA,CAAA,uBAAA,EAAA,EAAA,YAAA,EAAA,QAAA,CAAA;AAEA,MAAA,OAAA,EAAA,SAAA,IAAA,EAAA;AAAA,IACA,SAAA,KAAA,EAAA;AACA,MAAA,MAAA,eAAA,KAAA,YAAA,KAAA,GAAA,KAAA,CAAA,OAAA,GAAA,OAAA,KAAA,CAAA;AACA,MAAA,MAAA,CAAA,IAAA,CAAA,MAAA,gCAAA,EAAA,EAAA,cAAA,MAAA,EAAA,KAAA,EAAA,cAAA,CAAA;AAEA,MAAA,OAAA;AAAA,QACA,OAAA,EAAA,KAAA;AAAA,QACA,KAAA,EAAA;AAAA,OACA;AAAA,IACA;AAAA,EACA,CAAA,CAAA;AACA,CAAA,CAAA;;;;"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { d as defineEventHandler, b as readBody, c as createError, e as getProjectDir, l as logger } from '../../../nitro/nitro.mjs';
|
|
2
|
-
import {
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { a as resolvePreferredBaseBranch } from '../../../_/baseBranch.mjs';
|
|
5
5
|
import { g as getChatWorktreePath } from '../../../_/worktreePaths.mjs';
|
|
6
|
+
import { a as assertSafeBranchName } from '../../../_/chatGit.mjs';
|
|
7
|
+
import { w as withLock } from '../../../_/asyncLock.mjs';
|
|
6
8
|
import 'node:http';
|
|
7
9
|
import 'node:https';
|
|
8
10
|
import 'node:crypto';
|
|
@@ -28,7 +30,8 @@ import '../../../_/gitExec.mjs';
|
|
|
28
30
|
import 'child_process';
|
|
29
31
|
import 'util';
|
|
30
32
|
|
|
31
|
-
const
|
|
33
|
+
const execFileAsync = promisify(execFile);
|
|
34
|
+
const CONVERSATION_ID_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
32
35
|
const worktree_post = defineEventHandler(async (event) => {
|
|
33
36
|
var _a;
|
|
34
37
|
const body = await readBody(event);
|
|
@@ -39,17 +42,20 @@ const worktree_post = defineEventHandler(async (event) => {
|
|
|
39
42
|
});
|
|
40
43
|
}
|
|
41
44
|
const { conversationId, featureId } = body;
|
|
45
|
+
if (!CONVERSATION_ID_PATTERN.test(conversationId)) {
|
|
46
|
+
throw createError({ statusCode: 400, message: "Invalid conversationId" });
|
|
47
|
+
}
|
|
42
48
|
const requestedBaseBranch = (_a = body.baseBranch) == null ? void 0 : _a.trim();
|
|
43
49
|
const projectDir = getProjectDir();
|
|
44
|
-
const branchName = featureId || `sc/${conversationId}
|
|
50
|
+
const branchName = assertSafeBranchName(featureId || `sc/${conversationId}`, "branch");
|
|
45
51
|
const worktreePath = getChatWorktreePath(conversationId, featureId);
|
|
46
52
|
logger.chat.info("Creating chat worktree", { conversationId, branchName, worktreePath });
|
|
47
53
|
const requestStart = process.hrtime.bigint();
|
|
48
54
|
const stepDurations = {};
|
|
49
|
-
async function execTimed(step,
|
|
55
|
+
async function execTimed(step, args, options) {
|
|
50
56
|
const start = process.hrtime.bigint();
|
|
51
57
|
try {
|
|
52
|
-
const result = await
|
|
58
|
+
const result = await execFileAsync("git", args, { cwd: projectDir });
|
|
53
59
|
const durationMs = Number(process.hrtime.bigint() - start) / 1e6;
|
|
54
60
|
stepDurations[step] = durationMs;
|
|
55
61
|
logger.chat.debug("Chat worktree step completed", { conversationId, step, durationMs });
|
|
@@ -63,73 +69,75 @@ const worktree_post = defineEventHandler(async (event) => {
|
|
|
63
69
|
throw error;
|
|
64
70
|
}
|
|
65
71
|
}
|
|
66
|
-
|
|
67
|
-
let baseBranch = requestedBaseBranch || "";
|
|
68
|
-
if (!baseBranch) {
|
|
69
|
-
baseBranch = await resolvePreferredBaseBranch(projectDir) || "";
|
|
70
|
-
}
|
|
71
|
-
if (!baseBranch) {
|
|
72
|
-
return {
|
|
73
|
-
success: false,
|
|
74
|
-
error: "Unable to resolve a base branch for this worktree"
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (baseBranch.startsWith("sc/")) {
|
|
78
|
-
return {
|
|
79
|
-
success: false,
|
|
80
|
-
error: `Invalid base branch "${baseBranch}"`
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
let base = "";
|
|
72
|
+
return withLock(projectDir, async () => {
|
|
84
73
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
error: `Base branch "${baseBranch}" does not exist`
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
if (featureId) {
|
|
94
|
-
try {
|
|
95
|
-
await execTimed("check-feature-branch-exists", `git rev-parse --verify "${branchName}"`, { logFailure: false });
|
|
74
|
+
let baseBranch = requestedBaseBranch || "";
|
|
75
|
+
if (!baseBranch) {
|
|
76
|
+
baseBranch = await resolvePreferredBaseBranch(projectDir) || "";
|
|
77
|
+
}
|
|
78
|
+
if (!baseBranch) {
|
|
96
79
|
return {
|
|
97
80
|
success: false,
|
|
98
|
-
error:
|
|
81
|
+
error: "Unable to resolve a base branch for this worktree"
|
|
99
82
|
};
|
|
83
|
+
}
|
|
84
|
+
if (baseBranch.startsWith("sc/")) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: `Invalid base branch "${baseBranch}"`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
let base = "";
|
|
91
|
+
try {
|
|
92
|
+
const { stdout: head } = await execTimed("resolve-base-head", ["rev-parse", "--verify", `refs/heads/${baseBranch}^{commit}`]);
|
|
93
|
+
base = head.trim();
|
|
100
94
|
} catch {
|
|
95
|
+
return {
|
|
96
|
+
success: false,
|
|
97
|
+
error: `Base branch "${baseBranch}" does not exist`
|
|
98
|
+
};
|
|
101
99
|
}
|
|
100
|
+
if (featureId) {
|
|
101
|
+
try {
|
|
102
|
+
await execTimed("check-feature-branch-exists", ["rev-parse", "--verify", branchName], { logFailure: false });
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: `Branch "${branchName}" already exists. Delete the existing branch or worktree first.`
|
|
106
|
+
};
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
await execTimed("worktree-add", ["worktree", "add", "-b", branchName, worktreePath, base]);
|
|
111
|
+
const totalDurationMs = Number(process.hrtime.bigint() - requestStart) / 1e6;
|
|
112
|
+
logger.chat.info("Chat worktree created", {
|
|
113
|
+
conversationId,
|
|
114
|
+
worktreePath,
|
|
115
|
+
branchName,
|
|
116
|
+
baseBranch,
|
|
117
|
+
totalDurationMs,
|
|
118
|
+
steps: stepDurations
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
success: true,
|
|
122
|
+
worktreePath,
|
|
123
|
+
branch: branchName,
|
|
124
|
+
baseBranch
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
128
|
+
const totalDurationMs = Number(process.hrtime.bigint() - requestStart) / 1e6;
|
|
129
|
+
logger.chat.error("Failed to create chat worktree", {
|
|
130
|
+
conversationId,
|
|
131
|
+
error: errorMessage,
|
|
132
|
+
totalDurationMs,
|
|
133
|
+
steps: stepDurations
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
error: errorMessage
|
|
138
|
+
};
|
|
102
139
|
}
|
|
103
|
-
|
|
104
|
-
const totalDurationMs = Number(process.hrtime.bigint() - requestStart) / 1e6;
|
|
105
|
-
logger.chat.info("Chat worktree created", {
|
|
106
|
-
conversationId,
|
|
107
|
-
worktreePath,
|
|
108
|
-
branchName,
|
|
109
|
-
baseBranch,
|
|
110
|
-
totalDurationMs,
|
|
111
|
-
steps: stepDurations
|
|
112
|
-
});
|
|
113
|
-
return {
|
|
114
|
-
success: true,
|
|
115
|
-
worktreePath,
|
|
116
|
-
branch: branchName,
|
|
117
|
-
baseBranch
|
|
118
|
-
};
|
|
119
|
-
} catch (error) {
|
|
120
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
121
|
-
const totalDurationMs = Number(process.hrtime.bigint() - requestStart) / 1e6;
|
|
122
|
-
logger.chat.error("Failed to create chat worktree", {
|
|
123
|
-
conversationId,
|
|
124
|
-
error: errorMessage,
|
|
125
|
-
totalDurationMs,
|
|
126
|
-
steps: stepDurations
|
|
127
|
-
});
|
|
128
|
-
return {
|
|
129
|
-
success: false,
|
|
130
|
-
error: errorMessage
|
|
131
|
-
};
|
|
132
|
-
}
|
|
140
|
+
});
|
|
133
141
|
});
|
|
134
142
|
|
|
135
143
|
export { worktree_post as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktree.post.mjs","sources":["../../../../../../server/api/chat/worktree.post.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"worktree.post.mjs","sources":["../../../../../../server/api/chat/worktree.post.ts"],"names":[],"mappings":"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"}
|