@pmate/cli 0.12.7 → 0.12.8

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 (145) hide show
  1. package/dist/index.d.ts +346 -3
  2. package/dist/index.js +20884 -1474
  3. package/package.json +6 -5
  4. package/dist/agentCommandParser.d.ts +0 -2
  5. package/dist/agentCommandParser.js +0 -151
  6. package/dist/agentCommandParser.js.map +0 -1
  7. package/dist/alioss.d.ts +0 -21
  8. package/dist/alioss.js +0 -281
  9. package/dist/alioss.js.map +0 -1
  10. package/dist/appCommandParser.d.ts +0 -2
  11. package/dist/appCommandParser.js +0 -106
  12. package/dist/appCommandParser.js.map +0 -1
  13. package/dist/appDir.d.ts +0 -2
  14. package/dist/appDir.js +0 -33
  15. package/dist/appDir.js.map +0 -1
  16. package/dist/cli.d.ts +0 -8
  17. package/dist/cli.js +0 -43
  18. package/dist/cli.js.map +0 -1
  19. package/dist/commands/AddDnsCommandHandler.d.ts +0 -4
  20. package/dist/commands/AddDnsCommandHandler.js +0 -26
  21. package/dist/commands/AddDnsCommandHandler.js.map +0 -1
  22. package/dist/commands/AgentCommandHandler.d.ts +0 -11
  23. package/dist/commands/AgentCommandHandler.js +0 -146
  24. package/dist/commands/AgentCommandHandler.js.map +0 -1
  25. package/dist/commands/AppCommandHandler.d.ts +0 -10
  26. package/dist/commands/AppCommandHandler.js +0 -125
  27. package/dist/commands/AppCommandHandler.js.map +0 -1
  28. package/dist/commands/BucketCommandHandler.d.ts +0 -4
  29. package/dist/commands/BucketCommandHandler.js +0 -14
  30. package/dist/commands/BucketCommandHandler.js.map +0 -1
  31. package/dist/commands/CollectCommandHandler.d.ts +0 -20
  32. package/dist/commands/CollectCommandHandler.js +0 -470
  33. package/dist/commands/CollectCommandHandler.js.map +0 -1
  34. package/dist/commands/CommitCommandHandler.d.ts +0 -4
  35. package/dist/commands/CommitCommandHandler.js +0 -12
  36. package/dist/commands/CommitCommandHandler.js.map +0 -1
  37. package/dist/commands/DeployCommandHandler.d.ts +0 -20
  38. package/dist/commands/DeployCommandHandler.js +0 -297
  39. package/dist/commands/DeployCommandHandler.js.map +0 -1
  40. package/dist/commands/DevCommandHandler.d.ts +0 -8
  41. package/dist/commands/DevCommandHandler.js +0 -81
  42. package/dist/commands/DevCommandHandler.js.map +0 -1
  43. package/dist/commands/EnvCommandHandler.d.ts +0 -12
  44. package/dist/commands/EnvCommandHandler.js +0 -346
  45. package/dist/commands/EnvCommandHandler.js.map +0 -1
  46. package/dist/commands/InitCommandHandler.d.ts +0 -21
  47. package/dist/commands/InitCommandHandler.js +0 -468
  48. package/dist/commands/InitCommandHandler.js.map +0 -1
  49. package/dist/commands/LinearCommandHandler.d.ts +0 -52
  50. package/dist/commands/LinearCommandHandler.js +0 -1652
  51. package/dist/commands/LinearCommandHandler.js.map +0 -1
  52. package/dist/commands/ListCommandHandler.d.ts +0 -6
  53. package/dist/commands/ListCommandHandler.js +0 -43
  54. package/dist/commands/ListCommandHandler.js.map +0 -1
  55. package/dist/commands/LogCommandHandler.d.ts +0 -15
  56. package/dist/commands/LogCommandHandler.js +0 -201
  57. package/dist/commands/LogCommandHandler.js.map +0 -1
  58. package/dist/commands/LoginCommandHandler.d.ts +0 -11
  59. package/dist/commands/LoginCommandHandler.js +0 -178
  60. package/dist/commands/LoginCommandHandler.js.map +0 -1
  61. package/dist/commands/NotionCommandHandler.d.ts +0 -5
  62. package/dist/commands/NotionCommandHandler.js +0 -59
  63. package/dist/commands/NotionCommandHandler.js.map +0 -1
  64. package/dist/commands/OssCommandHandler.d.ts +0 -7
  65. package/dist/commands/OssCommandHandler.js +0 -82
  66. package/dist/commands/OssCommandHandler.js.map +0 -1
  67. package/dist/commands/PrCommandHandler.d.ts +0 -44
  68. package/dist/commands/PrCommandHandler.js +0 -673
  69. package/dist/commands/PrCommandHandler.js.map +0 -1
  70. package/dist/commands/QrcodeCommandHandler.d.ts +0 -9
  71. package/dist/commands/QrcodeCommandHandler.js +0 -135
  72. package/dist/commands/QrcodeCommandHandler.js.map +0 -1
  73. package/dist/commands/RandomCommandHandler.d.ts +0 -6
  74. package/dist/commands/RandomCommandHandler.js +0 -201
  75. package/dist/commands/RandomCommandHandler.js.map +0 -1
  76. package/dist/commands/StsCommandHandler.d.ts +0 -5
  77. package/dist/commands/StsCommandHandler.js +0 -45
  78. package/dist/commands/StsCommandHandler.js.map +0 -1
  79. package/dist/commands/SummaryCommandHandler.d.ts +0 -16
  80. package/dist/commands/SummaryCommandHandler.js +0 -190
  81. package/dist/commands/SummaryCommandHandler.js.map +0 -1
  82. package/dist/commands/VercelCommandHandler.d.ts +0 -38
  83. package/dist/commands/VercelCommandHandler.js +0 -126
  84. package/dist/commands/VercelCommandHandler.js.map +0 -1
  85. package/dist/config.d.ts +0 -62
  86. package/dist/config.js +0 -265
  87. package/dist/config.js.map +0 -1
  88. package/dist/index.js.map +0 -1
  89. package/dist/llm/AgentLlmClient.d.ts +0 -14
  90. package/dist/llm/AgentLlmClient.js +0 -81
  91. package/dist/llm/AgentLlmClient.js.map +0 -1
  92. package/dist/llm/types.d.ts +0 -37
  93. package/dist/llm/types.js +0 -3
  94. package/dist/llm/types.js.map +0 -1
  95. package/dist/serverAddress.d.ts +0 -2
  96. package/dist/serverAddress.js +0 -21
  97. package/dist/serverAddress.js.map +0 -1
  98. package/dist/services/AliyunService.d.ts +0 -68
  99. package/dist/services/AliyunService.js +0 -622
  100. package/dist/services/AliyunService.js.map +0 -1
  101. package/dist/services/NotionService.d.ts +0 -47
  102. package/dist/services/NotionService.js +0 -292
  103. package/dist/services/NotionService.js.map +0 -1
  104. package/dist/shell.d.ts +0 -2
  105. package/dist/shell.js +0 -11
  106. package/dist/shell.js.map +0 -1
  107. package/dist/tests/AgentCommandHandler.test.d.ts +0 -1
  108. package/dist/tests/AgentCommandHandler.test.js +0 -138
  109. package/dist/tests/AgentCommandHandler.test.js.map +0 -1
  110. package/dist/tests/AppCommandHandler.test.d.ts +0 -1
  111. package/dist/tests/AppCommandHandler.test.js +0 -94
  112. package/dist/tests/AppCommandHandler.test.js.map +0 -1
  113. package/dist/tests/LoginCommandHandler.test.d.ts +0 -1
  114. package/dist/tests/LoginCommandHandler.test.js +0 -13
  115. package/dist/tests/LoginCommandHandler.test.js.map +0 -1
  116. package/dist/tests/PrCommandHandler.test.d.ts +0 -1
  117. package/dist/tests/PrCommandHandler.test.js +0 -27
  118. package/dist/tests/PrCommandHandler.test.js.map +0 -1
  119. package/dist/tests/VercelCommandHandler.test.d.ts +0 -1
  120. package/dist/tests/VercelCommandHandler.test.js +0 -84
  121. package/dist/tests/VercelCommandHandler.test.js.map +0 -1
  122. package/dist/tests/agentCommandParser.test.d.ts +0 -1
  123. package/dist/tests/agentCommandParser.test.js +0 -75
  124. package/dist/tests/agentCommandParser.test.js.map +0 -1
  125. package/dist/tests/appCommandParser.test.d.ts +0 -1
  126. package/dist/tests/appCommandParser.test.js +0 -28
  127. package/dist/tests/appCommandParser.test.js.map +0 -1
  128. package/dist/tests/config.test.d.ts +0 -1
  129. package/dist/tests/config.test.js +0 -41
  130. package/dist/tests/config.test.js.map +0 -1
  131. package/dist/tests/pythonAppSupport.test.d.ts +0 -1
  132. package/dist/tests/pythonAppSupport.test.js +0 -47
  133. package/dist/tests/pythonAppSupport.test.js.map +0 -1
  134. package/dist/tests/serverAddress.test.d.ts +0 -1
  135. package/dist/tests/serverAddress.test.js +0 -14
  136. package/dist/tests/serverAddress.test.js.map +0 -1
  137. package/dist/tests/shell.test.d.ts +0 -1
  138. package/dist/tests/shell.test.js +0 -16
  139. package/dist/tests/shell.test.js.map +0 -1
  140. package/dist/tests/vercelParser.test.d.ts +0 -1
  141. package/dist/tests/vercelParser.test.js +0 -39
  142. package/dist/tests/vercelParser.test.js.map +0 -1
  143. package/dist/types.d.ts +0 -394
  144. package/dist/types.js +0 -30
  145. package/dist/types.js.map +0 -1
@@ -1,673 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.PrCommandHandler = void 0;
37
- const node_child_process_1 = require("node:child_process");
38
- const cli_1 = require("../cli");
39
- const config_1 = require("../config");
40
- class PrCommandHandler {
41
- constructor(cwd = process.cwd()) {
42
- this.cwd = cwd;
43
- }
44
- async handle(args) {
45
- if (args.action === "merge") {
46
- await this.handleMerge(args.prRef);
47
- return;
48
- }
49
- await this.ensureGitRepo();
50
- // await this.ensureGitHubRepo()
51
- await this.ensureGhCli();
52
- await this.ensureGhAuth();
53
- const context = await this.getRepoContext();
54
- let existingPrUrl = await this.findExistingPrUrl(context.currentBranch);
55
- if (!this.hasLocalChanges(context)) {
56
- await this.handleNoLocalChanges(context, existingPrUrl);
57
- return;
58
- }
59
- const recentLog = await this.runCapture("git", [
60
- "log",
61
- "--oneline",
62
- "-n",
63
- "20",
64
- ]);
65
- console.log("Generating PR metadata using PMate agents...");
66
- const suggestion = await this.getAiSuggestion({
67
- status: context.status,
68
- diff: truncate(context.diff, 6000),
69
- diffCached: truncate(context.diffCached, 6000),
70
- recentLog: truncate(recentLog, 2000),
71
- baseBranch: context.baseBranch,
72
- });
73
- this.assertNonEmpty("PR title", suggestion.prTitle);
74
- this.assertNonEmpty("Commit message", suggestion.commitMessage);
75
- const prTitle = normalizePrTitle(suggestion.prTitle);
76
- if (prTitle !== suggestion.prTitle.trim()) {
77
- cli_1.ui.info("Normalized PR title", prTitle);
78
- }
79
- const headBranch = await this.ensureWorkBranch(context, suggestion);
80
- if (headBranch !== context.currentBranch) {
81
- existingPrUrl = await this.findExistingPrUrl(headBranch);
82
- }
83
- await this.commitIfNeeded(suggestion.commitMessage);
84
- await this.rebaseOntoBase(context.baseBranch);
85
- await this.pushBranchIfNeeded(headBranch, context.baseBranch);
86
- await this.ensurePr(existingPrUrl, context.baseBranch, headBranch, prTitle);
87
- }
88
- async handleCommit(push = false) {
89
- await this.ensureGitRepo();
90
- const context = await this.getRepoContext();
91
- if (!this.hasLocalChanges(context)) {
92
- throw new Error("No local changes to commit.");
93
- }
94
- const recentLog = await this.runCapture("git", [
95
- "log",
96
- "--oneline",
97
- "-n",
98
- "20",
99
- ]);
100
- console.log("Generating commit message using PMate agents...");
101
- const suggestion = await this.getAiCommitSuggestion({
102
- status: context.status,
103
- diff: truncate(context.diff, 6000),
104
- diffCached: truncate(context.diffCached, 6000),
105
- recentLog: truncate(recentLog, 2000),
106
- baseBranch: context.baseBranch,
107
- });
108
- this.assertNonEmpty("Commit title", suggestion.commitTitle);
109
- this.assertNonEmpty("Commit log", suggestion.commitLog);
110
- await this.commitIfNeeded(suggestion.commitTitle, suggestion.commitLog);
111
- cli_1.ui.success("Committed changes", suggestion.commitTitle);
112
- cli_1.ui.info("Commit log", suggestion.commitLog);
113
- if (push) {
114
- await this.pushCurrentBranch();
115
- }
116
- }
117
- async handleMerge(prRef) {
118
- await this.ensureGitRepo();
119
- await this.ensureGhCli();
120
- await this.ensureGhAuth();
121
- const targetPr = (prRef === null || prRef === void 0 ? void 0 : prRef.trim()) || (await this.resolveCurrentPrRef());
122
- if (!targetPr) {
123
- throw new Error("No PR found for current branch. Pass a PR number/url, e.g. `pmate pr merge 123`.");
124
- }
125
- const pr = await this.getPrMergeCheck(targetPr);
126
- if (pr.state !== "OPEN") {
127
- throw new Error(`PR #${pr.number} is not open (state: ${pr.state}).`);
128
- }
129
- if (!this.isSquashMergeable(pr)) {
130
- const reason = this.getNonMergeableReason(pr);
131
- throw new Error(`PR #${pr.number} cannot be squash-merged: ${reason}`);
132
- }
133
- cli_1.ui.info(`Merging PR #${pr.number} with squash strategy`);
134
- await this.runGh(["pr", "merge", String(pr.number), "--squash", "--delete-branch"]);
135
- cli_1.ui.success(`Merged PR #${pr.number}`, pr.url);
136
- }
137
- async resolveCurrentPrRef() {
138
- const branch = (await this.runCapture("git", ["rev-parse", "--abbrev-ref", "HEAD"])).trim();
139
- if (!branch) {
140
- return "";
141
- }
142
- const output = await this.runCaptureGh([
143
- "pr",
144
- "list",
145
- "--head",
146
- branch,
147
- "--state",
148
- "open",
149
- "--json",
150
- "number",
151
- "--jq",
152
- ".[0].number",
153
- ]);
154
- return output.trim();
155
- }
156
- async getPrMergeCheck(prRef) {
157
- const output = await this.runCaptureGh([
158
- "pr",
159
- "view",
160
- prRef,
161
- "--json",
162
- "number,url,isDraft,state,mergeStateStatus,reviewDecision,statusCheckRollup",
163
- ]);
164
- try {
165
- return JSON.parse(output);
166
- }
167
- catch {
168
- throw new Error("Failed to parse PR metadata from gh.");
169
- }
170
- }
171
- isSquashMergeable(pr) {
172
- if (pr.isDraft) {
173
- return false;
174
- }
175
- const status = (pr.mergeStateStatus || "").toUpperCase();
176
- if (status === "CLEAN" || status === "HAS_HOOKS") {
177
- return true;
178
- }
179
- return false;
180
- }
181
- getNonMergeableReason(pr) {
182
- if (pr.isDraft || pr.mergeStateStatus === "DRAFT") {
183
- return "PR is in draft state.";
184
- }
185
- const state = (pr.mergeStateStatus || "").toUpperCase();
186
- switch (state) {
187
- case "BEHIND":
188
- return "branch is behind base branch.";
189
- case "DIRTY":
190
- return "merge conflicts must be resolved.";
191
- case "BLOCKED":
192
- return this.formatBlockedReason(pr);
193
- case "UNSTABLE":
194
- return this.formatUnstableReason(pr);
195
- case "UNKNOWN":
196
- return "GitHub mergeability is still being computed. Retry shortly.";
197
- default:
198
- return `merge state is ${pr.mergeStateStatus || "unknown"}.`;
199
- }
200
- }
201
- formatBlockedReason(pr) {
202
- const parts = ["blocked by repository rules"];
203
- if (pr.reviewDecision === "CHANGES_REQUESTED") {
204
- parts.push("changes were requested in review");
205
- }
206
- else if (pr.reviewDecision === "REVIEW_REQUIRED") {
207
- parts.push("review is still required");
208
- }
209
- const checkSummary = this.summarizeChecks(pr.statusCheckRollup);
210
- if (checkSummary) {
211
- parts.push(checkSummary);
212
- }
213
- return `${parts.join("; ")}.`;
214
- }
215
- formatUnstableReason(pr) {
216
- const checkSummary = this.summarizeChecks(pr.statusCheckRollup);
217
- if (checkSummary) {
218
- return `required checks are not green; ${checkSummary}.`;
219
- }
220
- return "required checks are still pending or failing.";
221
- }
222
- summarizeChecks(checks) {
223
- const items = checks !== null && checks !== void 0 ? checks : [];
224
- const failing = [];
225
- const pending = [];
226
- for (const check of items) {
227
- const name = check.name || check.context || "unknown-check";
228
- const rawState = (check.conclusion || check.status || check.state || "")
229
- .toString()
230
- .toUpperCase();
231
- if (!rawState || rawState === "PENDING" || rawState === "IN_PROGRESS" || rawState === "QUEUED") {
232
- pending.push(name);
233
- continue;
234
- }
235
- if (rawState === "FAILURE" ||
236
- rawState === "FAILED" ||
237
- rawState === "ERROR" ||
238
- rawState === "TIMED_OUT" ||
239
- rawState === "CANCELLED" ||
240
- rawState === "ACTION_REQUIRED") {
241
- failing.push(name);
242
- }
243
- }
244
- const parts = [];
245
- if (failing.length > 0) {
246
- parts.push(`failing checks: ${failing.join(", ")}`);
247
- }
248
- if (pending.length > 0) {
249
- parts.push(`pending checks: ${pending.join(", ")}`);
250
- }
251
- return parts.join("; ");
252
- }
253
- async getRepoContext() {
254
- const status = await this.runCapture("git", ["status", "--porcelain"]);
255
- const diff = await this.runCapture("git", ["diff"]);
256
- const diffCached = await this.runCapture("git", ["diff", "--cached"]);
257
- const baseBranch = await this.detectBaseBranch();
258
- const currentBranch = (await this.runCapture("git", ["rev-parse", "--abbrev-ref", "HEAD"])).trim();
259
- return { status, diff, diffCached, baseBranch, currentBranch };
260
- }
261
- hasLocalChanges(context) {
262
- return (Boolean(context.status.trim()) ||
263
- Boolean(context.diff.trim()) ||
264
- Boolean(context.diffCached.trim()));
265
- }
266
- async handleNoLocalChanges(context, existingPrUrl) {
267
- if (existingPrUrl) {
268
- await this.pushBranchIfNeeded(context.currentBranch, context.baseBranch);
269
- cli_1.ui.info(`PR already exists: ${existingPrUrl}`);
270
- return;
271
- }
272
- if (context.currentBranch === context.baseBranch) {
273
- throw new Error("No commits to include in a PR.");
274
- }
275
- const aheadLog = await this.getAheadLog(context.baseBranch);
276
- if (!aheadLog.trim()) {
277
- throw new Error("No commits to include in a PR.");
278
- }
279
- const prTitle = normalizePrTitle(this.getPrTitleFromLog(aheadLog));
280
- const prBody = await this.buildPrBody(context.baseBranch);
281
- await this.pushBranchIfNeeded(context.currentBranch, context.baseBranch);
282
- await this.createPr(context.baseBranch, context.currentBranch, prTitle, prBody);
283
- }
284
- async ensureWorkBranch(context, suggestion) {
285
- if (context.currentBranch !== context.baseBranch) {
286
- return context.currentBranch;
287
- }
288
- const branchName = sanitizeBranchName(suggestion.branchName);
289
- this.assertValidBranchName(branchName);
290
- await this.ensureBranchAvailable(branchName);
291
- cli_1.ui.info(`Creating branch ${branchName}`);
292
- await this.run("git", ["checkout", "-b", branchName]);
293
- return branchName;
294
- }
295
- async ensurePr(existingPrUrl, baseBranch, headBranch, prTitle) {
296
- if (existingPrUrl) {
297
- cli_1.ui.info(`PR already exists: ${existingPrUrl}`);
298
- return;
299
- }
300
- const prBody = await this.buildPrBody(baseBranch);
301
- await this.createPr(baseBranch, headBranch, prTitle, prBody);
302
- }
303
- async createPr(baseBranch, headBranch, prTitle, prBody) {
304
- cli_1.ui.info("Creating GitHub PR");
305
- await this.runGh([
306
- "pr",
307
- "create",
308
- "--base",
309
- baseBranch,
310
- "--head",
311
- headBranch,
312
- "--title",
313
- prTitle,
314
- "--body",
315
- prBody,
316
- ]);
317
- }
318
- async getAheadLog(baseBranch) {
319
- return this.runCapture("git", [
320
- "log",
321
- "--oneline",
322
- `origin/${baseBranch}..HEAD`,
323
- ]);
324
- }
325
- async rebaseOntoBase(baseBranch) {
326
- cli_1.ui.info(`Rebasing onto origin/${baseBranch}`);
327
- await this.run("git", ["fetch", "origin", baseBranch]);
328
- await this.run("git", ["rebase", `origin/${baseBranch}`]);
329
- }
330
- async ensureGitRepo() {
331
- const inside = await this.runCapture("git", [
332
- "rev-parse",
333
- "--is-inside-work-tree",
334
- ]);
335
- if (inside.trim() !== "true") {
336
- throw new Error("This command must be run inside a git repository.");
337
- }
338
- }
339
- async ensureGhAuth() {
340
- // Auth check (works for GH_TOKEN too)
341
- const code = await this.runGh(["auth", "status"], true);
342
- if (code !== 0) {
343
- throw new Error("GitHub CLI is not authenticated. Run: gh auth login.");
344
- }
345
- }
346
- async ensureGhCli() {
347
- await this.runGh(["--version"]);
348
- }
349
- async detectBaseBranch() {
350
- const originHead = await this.runCapture("git", ["symbolic-ref", "-q", "refs/remotes/origin/HEAD"], true);
351
- const originHeadBranch = originHead
352
- ? originHead.trim().split("/").pop()
353
- : "";
354
- if (originHeadBranch) {
355
- return originHeadBranch;
356
- }
357
- const candidates = ["main", "master", "develop"];
358
- for (const candidate of candidates) {
359
- const hasBranch = await this.run("git", ["show-ref", "--verify", "--quiet", `refs/remotes/origin/${candidate}`], true);
360
- if (hasBranch === 0) {
361
- return candidate;
362
- }
363
- }
364
- return "main";
365
- }
366
- async getAiSuggestion(context) {
367
- const { AgentLlmClient } = await Promise.resolve().then(() => __importStar(require("../llm/AgentLlmClient")));
368
- const client = new AgentLlmClient();
369
- const parsed = await client.prompt("pr-metadata", {
370
- baseBranch: context.baseBranch,
371
- status: context.status,
372
- diff: context.diff,
373
- diffCached: context.diffCached,
374
- recentLog: context.recentLog,
375
- });
376
- if (!parsed) {
377
- throw new Error("Agent response missing content.");
378
- }
379
- const suggestion = {
380
- prTitle: normalizeAgentStringField(parsed.prTitle),
381
- branchName: normalizeAgentStringField(parsed.branchName),
382
- commitMessage: normalizeAgentStringField(parsed.commitMessage),
383
- };
384
- if (!suggestion.prTitle || !suggestion.branchName || !suggestion.commitMessage) {
385
- throw new Error("Agent response missing required fields.");
386
- }
387
- return suggestion;
388
- }
389
- async getAiCommitSuggestion(context) {
390
- const { AgentLlmClient } = await Promise.resolve().then(() => __importStar(require("../llm/AgentLlmClient")));
391
- const client = new AgentLlmClient();
392
- const parsed = await client.prompt("commit-metadata", {
393
- baseBranch: context.baseBranch,
394
- status: context.status,
395
- diff: context.diff,
396
- diffCached: context.diffCached,
397
- recentLog: context.recentLog,
398
- });
399
- if (!parsed) {
400
- throw new Error("Agent response missing content.");
401
- }
402
- const suggestion = {
403
- commitTitle: normalizeAgentStringField(parsed.commitTitle),
404
- commitLog: normalizeAgentStringField(parsed.commitLog),
405
- };
406
- if (!suggestion.commitTitle || !suggestion.commitLog) {
407
- throw new Error("Agent response missing required fields.");
408
- }
409
- return suggestion;
410
- }
411
- async ensureBranchAvailable(branchName) {
412
- const exists = await this.run("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], true);
413
- if (exists === 0) {
414
- throw new Error(`Branch ${branchName} already exists locally.`);
415
- }
416
- }
417
- async commitIfNeeded(message, body) {
418
- const status = await this.runCapture("git", ["status", "--porcelain"]);
419
- if (!status.trim()) {
420
- cli_1.ui.info("No new changes to commit.");
421
- return;
422
- }
423
- cli_1.ui.info("Committing changes");
424
- await this.run("git", ["add", "-A"]);
425
- const bodyText = body === null || body === void 0 ? void 0 : body.trim();
426
- const commitArgs = ["commit", "-m", message];
427
- if (bodyText) {
428
- commitArgs.push("-m", bodyText);
429
- }
430
- await this.run("git", commitArgs);
431
- }
432
- async buildPrBody(baseBranch) {
433
- const log = await this.runCapture("git", [
434
- "log",
435
- "--oneline",
436
- `origin/${baseBranch}..HEAD`,
437
- ]);
438
- if (!log.trim()) {
439
- return "";
440
- }
441
- const lines = log
442
- .trim()
443
- .split(/\r?\n/)
444
- .map((line) => `- ${line}`)
445
- .join("\n");
446
- return `Changes:\n${lines}`;
447
- }
448
- async pushBranchIfNeeded(branchName, baseBranch) {
449
- if (branchName === baseBranch) {
450
- return;
451
- }
452
- cli_1.ui.info(`Pushing branch ${branchName}`);
453
- await this.run("git", ["push", "-u", "origin", branchName]);
454
- }
455
- async pushCurrentBranch() {
456
- const branchName = (await this.runCapture("git", ["rev-parse", "--abbrev-ref", "HEAD"])).trim();
457
- if (!branchName || branchName === "HEAD") {
458
- throw new Error("Cannot push from detached HEAD.");
459
- }
460
- cli_1.ui.info(`Pushing branch ${branchName}`);
461
- await this.run("git", ["push", "-u", "origin", branchName]);
462
- }
463
- async findExistingPrUrl(branchName) {
464
- var _a, _b;
465
- const output = await this.runCaptureGh([
466
- "pr",
467
- "list",
468
- "--head",
469
- branchName,
470
- "--state",
471
- "open",
472
- "--json",
473
- "url",
474
- ]);
475
- console.log(`Existing PR list output: ${output}`);
476
- if (!output.trim()) {
477
- return "";
478
- }
479
- try {
480
- const data = JSON.parse(output);
481
- return (_b = (_a = data[0]) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : "";
482
- }
483
- catch {
484
- return "";
485
- }
486
- }
487
- getPrTitleFromLog(log) {
488
- var _a;
489
- const firstLine = (_a = log.trim().split(/\r?\n/)[0]) !== null && _a !== void 0 ? _a : "";
490
- const subject = firstLine.replace(/^[0-9a-f]+\s+/, "").trim();
491
- return subject || "Auto-generated PR";
492
- }
493
- assertValidBranchName(branchName) {
494
- if (!/^[a-z0-9._/-]+$/.test(branchName) || branchName.endsWith("/")) {
495
- throw new Error(`Invalid branch name: ${branchName}`);
496
- }
497
- }
498
- assertNonEmpty(label, value) {
499
- if (!value.trim()) {
500
- throw new Error(`${label} cannot be empty.`);
501
- }
502
- }
503
- run(command, args, quietError = false, env, cwd) {
504
- return new Promise((resolve, reject) => {
505
- const child = (0, node_child_process_1.spawn)(command, args, {
506
- stdio: quietError ? "ignore" : "inherit",
507
- env: env !== null && env !== void 0 ? env : process.env,
508
- cwd: cwd !== null && cwd !== void 0 ? cwd : this.cwd,
509
- });
510
- child.on("error", (error) => {
511
- reject(error);
512
- });
513
- child.on("close", (code) => {
514
- if (code === 0 || quietError) {
515
- resolve(code !== null && code !== void 0 ? code : 1);
516
- return;
517
- }
518
- reject(new Error(`${command} exited with code ${code}`));
519
- });
520
- });
521
- }
522
- runCapture(command, args, allowFailure = false, env, cwd) {
523
- return new Promise((resolve, reject) => {
524
- var _a, _b;
525
- const child = (0, node_child_process_1.spawn)(command, args, {
526
- stdio: ["ignore", "pipe", "pipe"],
527
- env: env !== null && env !== void 0 ? env : process.env,
528
- cwd: cwd !== null && cwd !== void 0 ? cwd : this.cwd,
529
- });
530
- let output = "";
531
- let errorOutput = "";
532
- (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (chunk) => {
533
- output += chunk.toString();
534
- });
535
- (_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (chunk) => {
536
- errorOutput += chunk.toString();
537
- });
538
- child.on("error", (error) => {
539
- reject(error);
540
- });
541
- child.on("close", (code) => {
542
- if (code === 0 || allowFailure) {
543
- resolve(output);
544
- return;
545
- }
546
- const trimmed = errorOutput.trim();
547
- reject(new Error(trimmed
548
- ? `${command} failed: ${trimmed}`
549
- : `${command} exited with code ${code}`));
550
- });
551
- });
552
- }
553
- getResponseText(response) {
554
- var _a, _b;
555
- const data = response;
556
- const output = (_a = data.output) !== null && _a !== void 0 ? _a : [];
557
- for (const item of output) {
558
- const content = (_b = item.content) !== null && _b !== void 0 ? _b : [];
559
- for (const part of content) {
560
- if (part.type === "output_text" && typeof part.text === "string") {
561
- return part.text.trim();
562
- }
563
- }
564
- }
565
- return "";
566
- }
567
- async getGhEnv(cwd) {
568
- var _a;
569
- const env = { ...process.env };
570
- delete env.GH_TOKEN;
571
- const repoConfig = (0, config_1.loadRepoConfig)(cwd !== null && cwd !== void 0 ? cwd : this.cwd);
572
- const githubUser = (_a = repoConfig === null || repoConfig === void 0 ? void 0 : repoConfig.githubUser) === null || _a === void 0 ? void 0 : _a.trim();
573
- if (!githubUser) {
574
- return env;
575
- }
576
- const token = (await this.runCapture("gh", ["auth", "token", "--user", githubUser], false, env, cwd)).trim();
577
- if (!token) {
578
- throw new Error(`Failed to resolve GitHub token for ${githubUser}.`);
579
- }
580
- env.GH_TOKEN = token;
581
- return env;
582
- }
583
- async runGh(args, quietError = false, cwd) {
584
- return this.run("gh", args, quietError, await this.getGhEnv(cwd), cwd);
585
- }
586
- async runCaptureGh(args, allowFailure = false, cwd) {
587
- return this.runCapture("gh", args, allowFailure, await this.getGhEnv(cwd), cwd);
588
- }
589
- }
590
- exports.PrCommandHandler = PrCommandHandler;
591
- function truncate(value, limit) {
592
- if (value.length <= limit) {
593
- return value;
594
- }
595
- return `${value.slice(0, limit)}\n...[truncated]`;
596
- }
597
- function normalizeAgentStringField(value) {
598
- if (typeof value === "string") {
599
- return value;
600
- }
601
- if (Array.isArray(value)) {
602
- return value
603
- .filter((item) => typeof item === "string")
604
- .join("\n");
605
- }
606
- if (value &&
607
- typeof value === "object" &&
608
- "content" in value &&
609
- typeof value.content === "string") {
610
- return value.content;
611
- }
612
- return "";
613
- }
614
- function parseJson(raw) {
615
- const trimmed = raw.trim();
616
- try {
617
- return JSON.parse(trimmed);
618
- }
619
- catch {
620
- const match = trimmed.match(/\{[\s\S]*\}/);
621
- if (!match) {
622
- throw new Error("Failed to parse JSON from OpenAI response.");
623
- }
624
- return JSON.parse(match[0]);
625
- }
626
- }
627
- function sanitizeBranchName(value) {
628
- return value
629
- .trim()
630
- .toLowerCase()
631
- .replace(/[^a-z0-9._/-]+/g, "-")
632
- .replace(/--+/g, "-")
633
- .replace(/^-+|-+$/g, "");
634
- }
635
- function normalizePrTitle(raw) {
636
- var _a;
637
- const trimmed = raw.trim();
638
- if (!trimmed) {
639
- return trimmed;
640
- }
641
- const typed = trimmed.match(/^(feat|fix|chore)(?:\([^)]+\))?:\s*(.*)$/i);
642
- if (typed) {
643
- const type = typed[1].toLowerCase();
644
- const rest = ((_a = typed[2]) !== null && _a !== void 0 ? _a : "").trim();
645
- if (!rest) {
646
- throw new Error("PR title cannot be empty after the type prefix.");
647
- }
648
- return `${type}: ${rest}`;
649
- }
650
- const rest = stripConventionalPrefix(trimmed);
651
- const type = inferPrTitleType(rest);
652
- return `${type}: ${rest}`;
653
- }
654
- function stripConventionalPrefix(value) {
655
- var _a;
656
- const match = value.match(/^([a-z][a-z0-9-]{1,15})(?:\([^)]+\))?:\s+(.*)$/i);
657
- if (!match) {
658
- return value.trim();
659
- }
660
- const rest = ((_a = match[2]) !== null && _a !== void 0 ? _a : "").trim();
661
- return rest || value.trim();
662
- }
663
- function inferPrTitleType(title) {
664
- const t = title.toLowerCase();
665
- if (/\b(fix|bug|error|crash|regress|regression|hotfix)\b/.test(t)) {
666
- return "fix";
667
- }
668
- if (/\b(chore|refactor|deps|dependency|dependencies|bump|upgrade|update|ci|build|tooling|lint|format)\b/.test(t)) {
669
- return "chore";
670
- }
671
- return "feat";
672
- }
673
- //# sourceMappingURL=PrCommandHandler.js.map