spec-cat 0.1.60 → 0.1.62

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 (62) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/2zamijve.js +1 -0
  3. package/.output/public/_nuxt/{hL590mW_.js → BEjIzkrM.js} +54 -54
  4. package/.output/public/_nuxt/{0b9erTT7.js → BaSsfm-t.js} +1 -1
  5. package/.output/public/_nuxt/BjdLSVUw.js +1 -0
  6. package/.output/public/_nuxt/{fOeB-VHQ.js → Bz2rU2zs.js} +1 -1
  7. package/.output/public/_nuxt/{oZWZjCpV.js → D4LyIv_t.js} +1 -1
  8. package/.output/public/_nuxt/{CeUwIKdG.js → DIOhMCOf.js} +2 -2
  9. package/.output/public/_nuxt/{PyyEm6pa.js → DPOGSCeV.js} +1 -1
  10. package/.output/public/_nuxt/{BBjCHYA6.js → DeqM2TrP.js} +1 -1
  11. package/.output/public/_nuxt/{C7bEjS62.js → DwpuOtAP.js} +1 -1
  12. package/.output/public/_nuxt/{soqWbP5S.js → FfyCVKRU.js} +1 -1
  13. package/.output/public/_nuxt/{Ritd1ZTh.js → Su-Cl_JF.js} +1 -1
  14. package/.output/public/_nuxt/builds/latest.json +1 -1
  15. package/.output/public/_nuxt/builds/meta/df07a2f8-c6d6-420d-a863-ac6e0e7673e0.json +1 -0
  16. package/.output/public/_nuxt/{CtkWRKR5.js → zrVRZSxq.js} +1 -1
  17. package/.output/server/chunks/_/asyncLock.mjs +17 -0
  18. package/.output/server/chunks/_/asyncLock.mjs.map +1 -0
  19. package/.output/server/chunks/_/chatGit.mjs +19 -0
  20. package/.output/server/chunks/_/chatGit.mjs.map +1 -0
  21. package/.output/server/chunks/_/claude.mjs +2 -1
  22. package/.output/server/chunks/_/claude.mjs.map +1 -1
  23. package/.output/server/chunks/_/claudeProvider.mjs +2 -1
  24. package/.output/server/chunks/_/claudeProvider.mjs.map +1 -1
  25. package/.output/server/chunks/_/codexProvider.mjs +14 -2
  26. package/.output/server/chunks/_/codexProvider.mjs.map +1 -1
  27. package/.output/server/chunks/_/conversationStore.mjs.map +1 -1
  28. package/.output/server/chunks/_/jobQueue.mjs +1 -1
  29. package/.output/server/chunks/_/validateWorktree.mjs +1 -1
  30. package/.output/server/chunks/_/worktreePaths.mjs +1 -1
  31. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  32. package/.output/server/chunks/build/client.precomputed.mjs.map +1 -1
  33. package/.output/server/chunks/nitro/nitro.mjs +558 -558
  34. package/.output/server/chunks/routes/_ws.mjs +7 -6
  35. package/.output/server/chunks/routes/_ws.mjs.map +1 -1
  36. package/.output/server/chunks/routes/api/chat/compare.get.mjs +5 -0
  37. package/.output/server/chunks/routes/api/chat/compare.get.mjs.map +1 -1
  38. package/.output/server/chunks/routes/api/chat/finalize.post.mjs +94 -93
  39. package/.output/server/chunks/routes/api/chat/finalize.post.mjs.map +1 -1
  40. package/.output/server/chunks/routes/api/chat/generate-commit-message.post.mjs +2 -0
  41. package/.output/server/chunks/routes/api/chat/generate-commit-message.post.mjs.map +1 -1
  42. package/.output/server/chunks/routes/api/chat/preview-sync.post.mjs +28 -22
  43. package/.output/server/chunks/routes/api/chat/preview-sync.post.mjs.map +1 -1
  44. package/.output/server/chunks/routes/api/chat/preview.delete.mjs +24 -23
  45. package/.output/server/chunks/routes/api/chat/preview.delete.mjs.map +1 -1
  46. package/.output/server/chunks/routes/api/chat/preview.post.mjs +53 -48
  47. package/.output/server/chunks/routes/api/chat/preview.post.mjs.map +1 -1
  48. package/.output/server/chunks/routes/api/chat/rebase.post.mjs +39 -41
  49. package/.output/server/chunks/routes/api/chat/rebase.post.mjs.map +1 -1
  50. package/.output/server/chunks/routes/api/chat/worktree-commit.post.mjs +56 -46
  51. package/.output/server/chunks/routes/api/chat/worktree-commit.post.mjs.map +1 -1
  52. package/.output/server/chunks/routes/api/chat/worktree.delete.mjs +38 -30
  53. package/.output/server/chunks/routes/api/chat/worktree.delete.mjs.map +1 -1
  54. package/.output/server/chunks/routes/api/chat/worktree.post.mjs +73 -65
  55. package/.output/server/chunks/routes/api/chat/worktree.post.mjs.map +1 -1
  56. package/.output/server/chunks/routes/api/chat.post.mjs +16 -3
  57. package/.output/server/chunks/routes/api/chat.post.mjs.map +1 -1
  58. package/.output/server/package.json +1 -1
  59. package/package.json +1 -1
  60. package/.output/public/_nuxt/Bq8BNs4s.js +0 -1
  61. package/.output/public/_nuxt/CvPsR12A.js +0 -1
  62. package/.output/public/_nuxt/builds/meta/9d41800a-a604-4f15-8938-30e3b775a2dc.json +0 -1
@@ -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 { exec } from 'node:child_process';
3
- import { promisify } from 'node:util';
4
2
  import { existsSync } from 'node:fs';
3
+ import { v as validateWorktreePath } from '../../../_/validateWorktree.mjs';
4
+ import { a as assertSafeBranchName, g as git } from '../../../_/chatGit.mjs';
5
+ import { a as autoCommitChanges } from '../../../_/claudeService.mjs';
6
+ import { w as withLock } from '../../../_/asyncLock.mjs';
5
7
  import 'node:http';
6
8
  import 'node:https';
7
9
  import 'node:crypto';
@@ -22,12 +24,13 @@ import 'node:os';
22
24
  import 'node:module';
23
25
  import 'node:fs/promises';
24
26
  import 'node:url';
27
+ import '../../../_/worktreePaths.mjs';
28
+ import '../../../_/gitExec.mjs';
29
+ import 'child_process';
30
+ import 'util';
31
+ import 'node:child_process';
32
+ import '../../../_/claude.mjs';
25
33
 
26
- const execAsync = promisify(exec);
27
- async function git(cwd, cmd) {
28
- const { stdout } = await execAsync(`git ${cmd}`, { cwd });
29
- return stdout.trim();
30
- }
31
34
  const preview_post = defineEventHandler(async (event) => {
32
35
  const body = await readBody(event);
33
36
  if (!(body == null ? void 0 : body.conversationId) || !(body == null ? void 0 : body.worktreePath) || !(body == null ? void 0 : body.baseBranch)) {
@@ -36,54 +39,56 @@ const preview_post = defineEventHandler(async (event) => {
36
39
  message: "conversationId, worktreePath, and baseBranch are required"
37
40
  });
38
41
  }
39
- const { conversationId, worktreePath, baseBranch } = body;
42
+ const { conversationId, worktreePath } = body;
43
+ assertSafeBranchName(body.baseBranch, "base branch");
40
44
  const projectDir = getProjectDir();
41
45
  const previewBranch = "sc/preview";
46
+ if (existsSync(worktreePath)) {
47
+ validateWorktreePath(worktreePath);
48
+ }
42
49
  logger.chat.info("Creating preview branch", { conversationId, previewBranch });
43
- try {
44
- if (!existsSync(worktreePath)) {
45
- return { success: false, error: "Worktree directory not found." };
46
- }
47
- const status = await git(worktreePath, "status --porcelain");
48
- if (status) {
49
- await git(worktreePath, "add -A");
50
- await git(worktreePath, 'commit -m "auto-commit for preview"');
51
- }
52
- const worktreeHead = await git(worktreePath, "rev-parse HEAD");
53
- const mainStatus = await git(projectDir, "status --porcelain");
54
- if (mainStatus) {
50
+ return withLock(projectDir, async () => {
51
+ try {
52
+ if (!existsSync(worktreePath)) {
53
+ return { success: false, error: "Worktree directory not found." };
54
+ }
55
+ await autoCommitChanges(worktreePath);
56
+ const worktreeHead = await git(worktreePath, ["rev-parse", "HEAD"]);
57
+ const mainStatus = await git(projectDir, ["status", "--porcelain"]);
58
+ if (mainStatus) {
59
+ return {
60
+ success: false,
61
+ error: "Main worktree has uncommitted changes. Please commit or stash them first."
62
+ };
63
+ }
64
+ let branchExists = false;
65
+ try {
66
+ await git(projectDir, ["rev-parse", "--verify", `refs/heads/${previewBranch}`]);
67
+ branchExists = true;
68
+ } catch {
69
+ }
70
+ if (branchExists) {
71
+ await git(projectDir, ["checkout", previewBranch]);
72
+ await git(projectDir, ["reset", "--hard", worktreeHead]);
73
+ } else {
74
+ await git(projectDir, ["branch", previewBranch, worktreeHead]);
75
+ await git(projectDir, ["checkout", previewBranch]);
76
+ }
77
+ logger.chat.info("Preview branch active", { previewBranch, worktreeHead });
78
+ return {
79
+ success: true,
80
+ previewBranch,
81
+ commit: worktreeHead
82
+ };
83
+ } catch (error) {
84
+ const errorMessage = error instanceof Error ? error.message : String(error);
85
+ logger.chat.error("Failed to create preview", { conversationId, error: errorMessage });
55
86
  return {
56
87
  success: false,
57
- error: "Main worktree has uncommitted changes. Please commit or stash them first."
88
+ error: errorMessage
58
89
  };
59
90
  }
60
- let branchExists = false;
61
- try {
62
- await git(projectDir, `rev-parse --verify "refs/heads/${previewBranch}"`);
63
- branchExists = true;
64
- } catch {
65
- }
66
- if (branchExists) {
67
- await git(projectDir, `checkout "${previewBranch}"`);
68
- await git(projectDir, `reset --hard ${worktreeHead}`);
69
- } else {
70
- await git(projectDir, `branch "${previewBranch}" ${worktreeHead}`);
71
- await git(projectDir, `checkout "${previewBranch}"`);
72
- }
73
- logger.chat.info("Preview branch active", { previewBranch, worktreeHead });
74
- return {
75
- success: true,
76
- previewBranch,
77
- commit: worktreeHead
78
- };
79
- } catch (error) {
80
- const errorMessage = error instanceof Error ? error.message : String(error);
81
- logger.chat.error("Failed to create preview", { conversationId, error: errorMessage });
82
- return {
83
- success: false,
84
- error: errorMessage
85
- };
86
- }
91
+ });
87
92
  });
88
93
 
89
94
  export { preview_post as default };
@@ -1 +1 @@
1
- {"version":3,"file":"preview.post.mjs","sources":["../../../../../../server/api/chat/preview.post.ts"],"names":[],"mappings":"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"}
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
- try {
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
- await git(worktreePath, `rebase ${baseBranch}`);
78
- } catch {
79
- logger.chat.warn("Rebase conflict during sync", { conversationId });
80
- let conflictFiles = [];
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
- const diffOutput = await git(worktreePath, "diff --name-only --diff-filter=U");
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 statusOutput = await git(worktreePath, "status --porcelain");
87
- conflictFiles = statusOutput.split("\n").filter((line) => /^(UU|AA|DU|UD|UA|AU|DD)\s/.test(line)).map((line) => line.substring(3).trim());
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
- return {
92
- success: false,
93
- error: `Rebase conflict with "${baseBranch}". Resolve conflicts to continue.`,
94
- conflictFiles,
95
- rebaseInProgress: true
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
- logger.chat.info("Worktree rebased successfully", { conversationId, baseBranch });
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,MAAA,SAAA,GAAA,UAAA,IAAA,CAAA;AAEA,eAAA,GAAA,CAAA,KAAA,GAAA,EAAA;AACA,EAAA,MAAA,EAAA,MAAA,EAAA,GAAA,MAAA,SAAA,CAAA,OAAA,GAAA,CAAA,CAAA,EAAA,EAAA,GAAA,EAAA,CAAA;AACA,EAAA,OAAA,OAAA,IAAA,EAAA;AACA;AAKA,eAAA,kBAAA,YAAA,EAAA;AACA,EAAA,MAAA,MAAA,GAAA,MAAA,GAAA,CAAA,YAAA,EAAA,oBAAA,CAAA;AACA,EAAA,IAAA,CAAA,QAAA,OAAA,KAAA;AAEA,EAAA,MAAA,GAAA,CAAA,cAAA,QAAA,CAAA;AAEA,EAAA,QAAA,CAAA,iBAAA,EAAA,EAAA,GAAA,EAAA,YAAA,EAAA,OAAA,iCAAA,EAAA,QAAA,EAAA,SAAA,CAAA;AACA,EAAA,OAAA,IAAA;AACA;AAEA,oBAAA,kBAAA,CAAA,OAAA,KAAA,KAAA;AACA,EAAA,MAAA,IAAA,GAAA,MAAA,QAAA,CAAA,KAAA,CAAA;AAEA,EAAA,IAAA,EAAA,6BAAA,cAAA,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,gBAAA,GAAA,IAAA;AACA,EAAA,MAAA,aAAA,aAAA,EAAA;AACA,EAAA,MAAA,YAAA,GAAA,IAAA,CAAA,YAAA,IAAA,mBAAA,CAAA,cAAA,CAAA;AAEA,EAAA,IAAA,cAAA,GAAA,EAAA;AACA,EAAA,IAAA,UAAA,CAAA,YAAA,CAAA,EAAA;AACA,IAAA,IAAA;AACA,MAAA,cAAA,GAAA,MAAA,GAAA,CAAA,YAAA,EAAA,6BAAA,CAAA;AAAA,IACA,CAAA,CAAA,MAAA;AACA,MAAA,cAAA,GAAA,EAAA;AAAA,IACA;AAAA,EACA;AAEA,EAAA,MAAA,UAAA,GAAA,MAAA,yBAAA,CAAA;AAAA,IACA,GAAA,EAAA,UAAA;AAAA,IACA,qBAAA,IAAA,CAAA,UAAA;AAAA,IACA;AAAA,GACA,CAAA;AACA,EAAA,IAAA,CAAA,UAAA,EAAA;AACA,IAAA,OAAA,EAAA,OAAA,EAAA,KAAA,EAAA,KAAA,EAAA,0DAAA,EAAA;AAAA,EACA;AAEA,EAAA,MAAA,CAAA,KAAA,IAAA,CAAA,6BAAA,EAAA,EAAA,cAAA,EAAA,YAAA,CAAA;AAEA,EAAA,IAAA;AAEA,IAAA,IAAA,CAAA,UAAA,CAAA,YAAA,CAAA,EAAA;AACA,MAAA,OAAA,EAAA,OAAA,EAAA,KAAA,EAAA,KAAA,EAAA,4DAAA,EAAA;AAAA,IACA;AAGA,IAAA,MAAA,kBAAA,YAAA,CAAA;AAGA,IAAA,IAAA;AACA,MAAA,MAAA,GAAA,CAAA,YAAA,EAAA,CAAA,OAAA,EAAA,UAAA,CAAA,CAAA,CAAA;AAAA,IACA,CAAA,CAAA,MAAA;AAEA,MAAA,MAAA,CAAA,IAAA,CAAA,IAAA,CAAA,6BAAA,EAAA,EAAA,gBAAA,CAAA;AAEA,MAAA,IAAA,gBAAA,EAAA;AACA,MAAA,IAAA;AACA,QAAA,MAAA,UAAA,GAAA,MAAA,GAAA,CAAA,YAAA,EAAA,kCAAA,CAAA;AACA,QAAA,aAAA,GAAA,UAAA,CAAA,KAAA,CAAA,IAAA,CAAA,CAAA,OAAA,OAAA,CAAA;AAAA,MACA,CAAA,CAAA,MAAA;AACA,QAAA,IAAA;AACA,UAAA,MAAA,YAAA,GAAA,MAAA,GAAA,CAAA,YAAA,EAAA,oBAAA,CAAA;AACA,UAAA,aAAA,GAAA,aACA,KAAA,CAAA,IAAA,EACA,MAAA,CAAA,CAAA,IAAA,KAAA,4BAAA,IAAA,CAAA,IAAA,CAAA,CAAA,CACA,IAAA,CAAA,IAAA,KAAA,IAAA,CAAA,UAAA,CAAA,CAAA,CAAA,MAAA,CAAA;AAAA,QACA,CAAA,CAAA,MAAA;AAAA,QAAA;AAAA,MACA;AAEA,MAAA,OAAA;AAAA,QACA,OAAA,EAAA,KAAA;AAAA,QACA,KAAA,EAAA,yBAAA,UAAA,CAAA,iCAAA,CAAA;AAAA,QACA,aAAA;AAAA,QACA,gBAAA,EAAA;AAAA,OACA;AAAA,IACA;AAEA,IAAA,MAAA,CAAA,KAAA,IAAA,CAAA,+BAAA,EAAA,EAAA,cAAA,EAAA,YAAA,CAAA;AAEA,IAAA,OAAA,EAAA,SAAA,IAAA,EAAA;AAAA,EACA,SAAA,KAAA,EAAA;AACA,IAAA,MAAA,eAAA,KAAA,YAAA,KAAA,GAAA,KAAA,CAAA,OAAA,GAAA,OAAA,KAAA,CAAA;AACA,IAAA,MAAA,CAAA,KAAA,KAAA,CAAA,oBAAA,EAAA,EAAA,cAAA,EAAA,KAAA,EAAA,cAAA,CAAA;AACA,IAAA,OAAA,EAAA,OAAA,EAAA,KAAA,EAAA,KAAA,EAAA,YAAA,EAAA;AAAA,EACA;AACA,CAAA,CAAA;;;;"}
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 { exec } from 'node:child_process';
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
- try {
40
- const result = await autoCommitChanges(worktreePath);
41
- let deletedPreviousBranch = false;
42
- if (result.success) {
43
- const branchChanged = Boolean(
44
- previousBranch && result.currentBranch && previousBranch !== result.currentBranch
45
- );
46
- if (branchChanged && previousBranch && !PROTECTED_BRANCHES.has(previousBranch)) {
47
- try {
48
- await execAsync(`git branch -D "${previousBranch}"`, { cwd: getProjectDir() });
49
- deletedPreviousBranch = true;
50
- logger.chat.info("Deleted previous worktree branch after branch switch", {
51
- conversationId,
52
- previousBranch,
53
- currentBranch: result.currentBranch
54
- });
55
- } catch (deleteError) {
56
- logger.chat.warn("Failed to delete previous worktree branch after branch switch", {
57
- conversationId,
58
- previousBranch,
59
- currentBranch: result.currentBranch,
60
- error: deleteError instanceof Error ? deleteError.message : String(deleteError)
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
- logger.chat.info("Worktree auto-commit done", {
65
- conversationId,
81
+ return {
82
+ success: result.success,
66
83
  message: result.message,
67
84
  currentBranch: result.currentBranch,
68
- previousBranch,
69
- deletedPreviousBranch
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
- return {
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAA,SAAA,GAAA,UAAA,IAAA,CAAA;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;AACA,IAAA,MAAA,MAAA,GAAA,MAAA,iBAAA,CAAA,YAAA,CAAA;AACA,IAAA,IAAA,qBAAA,GAAA,KAAA;AAEA,IAAA,IAAA,OAAA,OAAA,EAAA;AACA,MAAA,MAAA,aAAA,GAAA,OAAA;AAAA,QACA,cAAA,IACA,MAAA,CAAA,aAAA,IACA,cAAA,KAAA,MAAA,CAAA;AAAA,OACA;AAEA,MAAA,IAAA,iBAAA,cAAA,IAAA,CAAA,kBAAA,CAAA,GAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,IAAA;AACA,UAAA,MAAA,SAAA,CAAA,kBAAA,cAAA,CAAA,CAAA,CAAA,EAAA,EAAA,GAAA,EAAA,aAAA,IAAA,CAAA;AACA,UAAA,qBAAA,GAAA,IAAA;AACA,UAAA,MAAA,CAAA,IAAA,CAAA,KAAA,sDAAA,EAAA;AAAA,YACA,cAAA;AAAA,YACA,cAAA;AAAA,YACA,eAAA,MAAA,CAAA;AAAA,WACA,CAAA;AAAA,QACA,SAAA,WAAA,EAAA;AACA,UAAA,MAAA,CAAA,IAAA,CAAA,KAAA,+DAAA,EAAA;AAAA,YACA,cAAA;AAAA,YACA,cAAA;AAAA,YACA,eAAA,MAAA,CAAA,aAAA;AAAA,YACA,OAAA,WAAA,YAAA,KAAA,GAAA,WAAA,CAAA,OAAA,GAAA,OAAA,WAAA;AAAA,WACA,CAAA;AAAA,QACA;AAAA,MACA;AAEA,MAAA,MAAA,CAAA,IAAA,CAAA,KAAA,2BAAA,EAAA;AAAA,QACA,cAAA;AAAA,QACA,SAAA,MAAA,CAAA,OAAA;AAAA,QACA,eAAA,MAAA,CAAA,aAAA;AAAA,QACA,cAAA;AAAA,QACA;AAAA,OACA,CAAA;AAAA,IACA;AAEA,IAAA,OAAA;AAAA,MACA,SAAA,MAAA,CAAA,OAAA;AAAA,MACA,SAAA,MAAA,CAAA,OAAA;AAAA,MACA,eAAA,MAAA,CAAA,aAAA;AAAA,MACA,qBAAA;AAAA,MACA,OAAA,MAAA,CAAA;AAAA,KACA;AAAA,EACA,SAAA,KAAA,EAAA;AACA,IAAA,MAAA,eAAA,KAAA,YAAA,KAAA,GAAA,KAAA,CAAA,OAAA,GAAA,OAAA,KAAA,CAAA;AACA,IAAA,MAAA,CAAA,IAAA,CAAA,MAAA,6BAAA,EAAA;AAAA,MACA,cAAA;AAAA,MACA,KAAA,EAAA;AAAA,KACA,CAAA;AAEA,IAAA,OAAA,EAAA,OAAA,EAAA,KAAA,EAAA,KAAA,EAAA,YAAA,EAAA;AAAA,EACA;AACA,CAAA,CAAA;;;;"}
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, branch } = body;
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
- try {
39
- if (existsSync(worktreePath)) {
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 execAsync(`git worktree remove "${worktreePath}" --force`, {
42
- cwd: projectDir
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
- await execAsync("git worktree prune", { cwd: projectDir });
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":";;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAA,SAAA,GAAA,UAAA,IAAA,CAAA;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,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;AACA,EAAA,MAAA,aAAA,aAAA,EAAA;AAEA,EAAA,MAAA,CAAA,KAAA,IAAA,CAAA,wBAAA,EAAA,EAAA,YAAA,EAAA,QAAA,CAAA;AAEA,EAAA,IAAA;AAEA,IAAA,IAAA,UAAA,CAAA,YAAA,CAAA,EAAA;AACA,MAAA,IAAA;AACA,QAAA,MAAA,SAAA,CAAA,CAAA,qBAAA,EAAA,YAAA,CAAA,SAAA,CAAA,EAAA;AAAA,UACA,GAAA,EAAA;AAAA,SACA,CAAA;AAAA,MACA,CAAA,CAAA,MAAA;AAEA,QAAA,MAAA,GAAA,YAAA,EAAA,EAAA,WAAA,IAAA,EAAA,KAAA,EAAA,MAAA,CAAA;AAAA,MACA;AAAA,IACA;AAGA,IAAA,MAAA,SAAA,CAAA,oBAAA,EAAA,EAAA,GAAA,EAAA,YAAA,CAAA;AAGA,IAAA,IAAA;AACA,MAAA,MAAA,UAAA,CAAA,eAAA,EAAA,MAAA,KAAA,EAAA,GAAA,EAAA,YAAA,CAAA;AACA,MAAA,MAAA,CAAA,IAAA,CAAA,IAAA,CAAA,qBAAA,EAAA,EAAA,QAAA,CAAA;AAAA,IACA,SAAA,WAAA,EAAA;AACA,MAAA,MAAA,CAAA,IAAA,CAAA,KAAA,8BAAA,EAAA;AAAA,QACA,MAAA;AAAA,QACA,OAAA,WAAA,YAAA,KAAA,GAAA,WAAA,CAAA,OAAA,GAAA,OAAA,WAAA;AAAA,OACA,CAAA;AAAA,IACA;AAEA,IAAA,MAAA,CAAA,KAAA,IAAA,CAAA,uBAAA,EAAA,EAAA,YAAA,EAAA,QAAA,CAAA;AAEA,IAAA,OAAA,EAAA,SAAA,IAAA,EAAA;AAAA,EACA,SAAA,KAAA,EAAA;AACA,IAAA,MAAA,eAAA,KAAA,YAAA,KAAA,GAAA,KAAA,CAAA,OAAA,GAAA,OAAA,KAAA,CAAA;AACA,IAAA,MAAA,CAAA,IAAA,CAAA,MAAA,gCAAA,EAAA,EAAA,cAAA,MAAA,EAAA,KAAA,EAAA,cAAA,CAAA;AAEA,IAAA,OAAA;AAAA,MACA,OAAA,EAAA,KAAA;AAAA,MACA,KAAA,EAAA;AAAA,KACA;AAAA,EACA;AACA,CAAA,CAAA;;;;"}
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;;;;"}