automata-cli 0.1.0-009-codex-flag-implement-next.75 → 0.1.0-010-sonarcloud-prompts-execute.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +320 -25
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command6 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
7
|
import { readFileSync } from "fs";
|
|
@@ -23,6 +23,8 @@ import { Box, Text, useInput, useApp } from "ink";
|
|
|
23
23
|
// src/config/configStore.ts
|
|
24
24
|
import { readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
25
25
|
import { join } from "path";
|
|
26
|
+
var DEFAULT_FIX_COMMENTS_PROMPT = "You are an expert software engineer reviewing a pull request. Below are the open review comments left by reviewers on this PR. Please address each comment by making the appropriate code changes. Focus on the reviewer's concerns and make minimal, targeted changes that resolve each comment without altering unrelated code.";
|
|
27
|
+
var DEFAULT_SONAR_PROMPT = "You are an expert software engineer. You have been given the URL of a SonarCloud analysis for this pull request. Please visit the SonarCloud analysis URL provided and fix all new issues reported. Focus on code smells, bugs, and vulnerabilities flagged as new in this PR. Make targeted, minimal changes that resolve each issue without altering unrelated code.";
|
|
26
28
|
var CONFIG_DIR = ".automata";
|
|
27
29
|
var CONFIG_FILE = "config.json";
|
|
28
30
|
function configPath() {
|
|
@@ -53,22 +55,47 @@ var TECHNIQUE_OPTIONS = [
|
|
|
53
55
|
{ label: "By Assignee", value: "assignee" },
|
|
54
56
|
{ label: "By Title Contains", value: "title-contains" }
|
|
55
57
|
];
|
|
58
|
+
var MAIN_MENU_OPTIONS = ["Remote / Mode", "Implement-Next", "Prompts"];
|
|
59
|
+
var PROMPTS_MENU_OPTIONS = ["Sonar", "Fix-Comments"];
|
|
56
60
|
function ConfigWizard() {
|
|
57
61
|
const existing = readConfig();
|
|
58
62
|
const initialRemoteIndex = REMOTE_OPTIONS.findIndex((o) => o.value === existing.remoteType);
|
|
59
63
|
const initialTechIndex = TECHNIQUE_OPTIONS.findIndex((o) => o.value === existing.issueDiscoveryTechnique);
|
|
60
|
-
const [screen, setScreen] = useState("
|
|
64
|
+
const [screen, setScreen] = useState("main");
|
|
65
|
+
const [mainMenuIndex, setMainMenuIndex] = useState(0);
|
|
61
66
|
const [selectedRemoteIndex, setSelectedRemoteIndex] = useState(initialRemoteIndex >= 0 ? initialRemoteIndex : 0);
|
|
62
67
|
const [selectedTechIndex, setSelectedTechIndex] = useState(initialTechIndex >= 0 ? initialTechIndex : 0);
|
|
63
68
|
const [discoveryValue, setDiscoveryValue] = useState(existing.issueDiscoveryValue ?? "");
|
|
64
69
|
const [systemPrompt, setSystemPrompt] = useState(existing.claudeSystemPrompt ?? "");
|
|
70
|
+
const [promptsMenuIndex, setPromptsMenuIndex] = useState(0);
|
|
71
|
+
const [sonarPrompt, setSonarPrompt] = useState(existing.prompts?.sonar ?? DEFAULT_SONAR_PROMPT);
|
|
72
|
+
const [fixCommentsPrompt, setFixCommentsPrompt] = useState(
|
|
73
|
+
existing.prompts?.fixComments ?? DEFAULT_FIX_COMMENTS_PROMPT
|
|
74
|
+
);
|
|
65
75
|
const [pendingRemote, setPendingRemote] = useState(existing.remoteType ?? "gh");
|
|
66
76
|
const [pendingTechnique, setPendingTechnique] = useState(
|
|
67
77
|
existing.issueDiscoveryTechnique ?? "label"
|
|
68
78
|
);
|
|
69
79
|
const { exit } = useApp();
|
|
70
80
|
useInput((input, key) => {
|
|
71
|
-
if (screen === "
|
|
81
|
+
if (screen === "main") {
|
|
82
|
+
if (key.upArrow) {
|
|
83
|
+
setMainMenuIndex((i) => i > 0 ? i - 1 : MAIN_MENU_OPTIONS.length - 1);
|
|
84
|
+
} else if (key.downArrow) {
|
|
85
|
+
setMainMenuIndex((i) => i < MAIN_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
86
|
+
} else if (key.return) {
|
|
87
|
+
const chosen = MAIN_MENU_OPTIONS[mainMenuIndex];
|
|
88
|
+
if (chosen === "Remote / Mode") {
|
|
89
|
+
setScreen("remote");
|
|
90
|
+
} else if (chosen === "Implement-Next") {
|
|
91
|
+
setScreen("technique");
|
|
92
|
+
} else {
|
|
93
|
+
setScreen("prompts-menu");
|
|
94
|
+
}
|
|
95
|
+
} else if (key.escape || key.ctrl && input === "c") {
|
|
96
|
+
exit();
|
|
97
|
+
}
|
|
98
|
+
} else if (screen === "remote") {
|
|
72
99
|
if (key.upArrow) {
|
|
73
100
|
setSelectedRemoteIndex((i) => i > 0 ? i - 1 : REMOTE_OPTIONS.length - 1);
|
|
74
101
|
} else if (key.downArrow) {
|
|
@@ -82,7 +109,9 @@ function ConfigWizard() {
|
|
|
82
109
|
writeConfig({ ...existing, remoteType: chosen.value });
|
|
83
110
|
exit();
|
|
84
111
|
}
|
|
85
|
-
} else if (key.escape
|
|
112
|
+
} else if (key.escape) {
|
|
113
|
+
setScreen("main");
|
|
114
|
+
} else if (key.ctrl && input === "c") {
|
|
86
115
|
exit();
|
|
87
116
|
}
|
|
88
117
|
} else if (screen === "technique") {
|
|
@@ -94,7 +123,9 @@ function ConfigWizard() {
|
|
|
94
123
|
const chosen = TECHNIQUE_OPTIONS[selectedTechIndex];
|
|
95
124
|
setPendingTechnique(chosen.value);
|
|
96
125
|
setScreen("value");
|
|
97
|
-
} else if (key.escape
|
|
126
|
+
} else if (key.escape) {
|
|
127
|
+
setScreen("main");
|
|
128
|
+
} else if (key.ctrl && input === "c") {
|
|
98
129
|
exit();
|
|
99
130
|
}
|
|
100
131
|
} else if (screen === "value") {
|
|
@@ -102,7 +133,9 @@ function ConfigWizard() {
|
|
|
102
133
|
setScreen("system-prompt");
|
|
103
134
|
} else if (key.backspace || key.delete) {
|
|
104
135
|
setDiscoveryValue((v) => v.slice(0, -1));
|
|
105
|
-
} else if (key.escape
|
|
136
|
+
} else if (key.escape) {
|
|
137
|
+
setScreen("main");
|
|
138
|
+
} else if (key.ctrl && input === "c") {
|
|
106
139
|
exit();
|
|
107
140
|
} else if (input && !key.ctrl && !key.meta) {
|
|
108
141
|
setDiscoveryValue((v) => v + input);
|
|
@@ -119,29 +152,92 @@ function ConfigWizard() {
|
|
|
119
152
|
exit();
|
|
120
153
|
} else if (key.backspace || key.delete) {
|
|
121
154
|
setSystemPrompt((v) => v.slice(0, -1));
|
|
122
|
-
} else if (key.escape
|
|
155
|
+
} else if (key.escape) {
|
|
156
|
+
setScreen("main");
|
|
157
|
+
} else if (key.ctrl && input === "c") {
|
|
123
158
|
exit();
|
|
124
159
|
} else if (input && !key.ctrl && !key.meta) {
|
|
125
160
|
setSystemPrompt((v) => v + input);
|
|
126
161
|
}
|
|
162
|
+
} else if (screen === "prompts-menu") {
|
|
163
|
+
if (key.upArrow) {
|
|
164
|
+
setPromptsMenuIndex((i) => i > 0 ? i - 1 : PROMPTS_MENU_OPTIONS.length - 1);
|
|
165
|
+
} else if (key.downArrow) {
|
|
166
|
+
setPromptsMenuIndex((i) => i < PROMPTS_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
167
|
+
} else if (key.return) {
|
|
168
|
+
const chosen = PROMPTS_MENU_OPTIONS[promptsMenuIndex];
|
|
169
|
+
if (chosen === "Sonar") {
|
|
170
|
+
setScreen("sonar-prompt");
|
|
171
|
+
} else {
|
|
172
|
+
setScreen("fix-comments-prompt");
|
|
173
|
+
}
|
|
174
|
+
} else if (key.escape) {
|
|
175
|
+
setScreen("main");
|
|
176
|
+
} else if (key.ctrl && input === "c") {
|
|
177
|
+
exit();
|
|
178
|
+
}
|
|
179
|
+
} else if (screen === "sonar-prompt") {
|
|
180
|
+
if (key.return) {
|
|
181
|
+
writeConfig({
|
|
182
|
+
...existing,
|
|
183
|
+
prompts: { ...existing.prompts, sonar: sonarPrompt || void 0 }
|
|
184
|
+
});
|
|
185
|
+
setScreen("prompts-menu");
|
|
186
|
+
} else if (key.backspace || key.delete) {
|
|
187
|
+
setSonarPrompt((v) => v.slice(0, -1));
|
|
188
|
+
} else if (key.escape) {
|
|
189
|
+
setScreen("prompts-menu");
|
|
190
|
+
} else if (key.ctrl && input === "c") {
|
|
191
|
+
exit();
|
|
192
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
193
|
+
setSonarPrompt((v) => v + input);
|
|
194
|
+
}
|
|
195
|
+
} else if (screen === "fix-comments-prompt") {
|
|
196
|
+
if (key.return) {
|
|
197
|
+
writeConfig({
|
|
198
|
+
...existing,
|
|
199
|
+
prompts: { ...existing.prompts, fixComments: fixCommentsPrompt || void 0 }
|
|
200
|
+
});
|
|
201
|
+
setScreen("prompts-menu");
|
|
202
|
+
} else if (key.backspace || key.delete) {
|
|
203
|
+
setFixCommentsPrompt((v) => v.slice(0, -1));
|
|
204
|
+
} else if (key.escape) {
|
|
205
|
+
setScreen("prompts-menu");
|
|
206
|
+
} else if (key.ctrl && input === "c") {
|
|
207
|
+
exit();
|
|
208
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
209
|
+
setFixCommentsPrompt((v) => v + input);
|
|
210
|
+
}
|
|
127
211
|
}
|
|
128
212
|
});
|
|
129
|
-
if (screen === "
|
|
213
|
+
if (screen === "main") {
|
|
130
214
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
131
215
|
/* @__PURE__ */ jsx(Text, { bold: true, children: "Configure Automata" }),
|
|
132
216
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
217
|
+
MAIN_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === mainMenuIndex ? "cyan" : void 0, children: [
|
|
218
|
+
index === mainMenuIndex ? "\u276F " : " ",
|
|
219
|
+
option
|
|
220
|
+
] }) }, option)),
|
|
221
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
222
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to cancel" })
|
|
223
|
+
] });
|
|
224
|
+
}
|
|
225
|
+
if (screen === "remote") {
|
|
226
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
227
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Remote / Mode" }),
|
|
228
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
133
229
|
/* @__PURE__ */ jsx(Text, { children: "Remote environment type:" }),
|
|
134
230
|
REMOTE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedRemoteIndex ? "cyan" : void 0, children: [
|
|
135
231
|
index === selectedRemoteIndex ? "\u276F " : " ",
|
|
136
232
|
option.label
|
|
137
233
|
] }) }, option.value)),
|
|
138
234
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
139
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Ctrl+C to cancel" })
|
|
235
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
140
236
|
] });
|
|
141
237
|
}
|
|
142
238
|
if (screen === "technique") {
|
|
143
239
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
144
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "
|
|
240
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Technique" }),
|
|
145
241
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
146
242
|
/* @__PURE__ */ jsx(Text, { children: "How to find the next issue to work on:" }),
|
|
147
243
|
TECHNIQUE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedTechIndex ? "cyan" : void 0, children: [
|
|
@@ -149,13 +245,13 @@ function ConfigWizard() {
|
|
|
149
245
|
option.label
|
|
150
246
|
] }) }, option.value)),
|
|
151
247
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
152
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Ctrl+C to cancel" })
|
|
248
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
153
249
|
] });
|
|
154
250
|
}
|
|
155
251
|
if (screen === "value") {
|
|
156
252
|
const techLabel = TECHNIQUE_OPTIONS.find((t) => t.value === pendingTechnique)?.label ?? pendingTechnique;
|
|
157
253
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
158
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "
|
|
254
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Value" }),
|
|
159
255
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
160
256
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
161
257
|
techLabel,
|
|
@@ -167,22 +263,66 @@ function ConfigWizard() {
|
|
|
167
263
|
] })
|
|
168
264
|
] }),
|
|
169
265
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
170
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type value \xB7 Enter to
|
|
266
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type value \xB7 Enter to continue \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
267
|
+
] });
|
|
268
|
+
}
|
|
269
|
+
if (screen === "system-prompt") {
|
|
270
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
271
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Claude System Prompt" }),
|
|
272
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
273
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
274
|
+
"System prompt (optional):",
|
|
275
|
+
" ",
|
|
276
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
277
|
+
systemPrompt,
|
|
278
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
279
|
+
] })
|
|
280
|
+
] }),
|
|
281
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
282
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save and exit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
283
|
+
] });
|
|
284
|
+
}
|
|
285
|
+
if (screen === "prompts-menu") {
|
|
286
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
287
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts" }),
|
|
288
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
289
|
+
PROMPTS_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === promptsMenuIndex ? "cyan" : void 0, children: [
|
|
290
|
+
index === promptsMenuIndex ? "\u276F " : " ",
|
|
291
|
+
option
|
|
292
|
+
] }) }, option)),
|
|
293
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
294
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to edit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
295
|
+
] });
|
|
296
|
+
}
|
|
297
|
+
if (screen === "sonar-prompt") {
|
|
298
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
299
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Sonar" }),
|
|
300
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
301
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
302
|
+
"Sonar prompt:",
|
|
303
|
+
" ",
|
|
304
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
305
|
+
sonarPrompt,
|
|
306
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
307
|
+
] })
|
|
308
|
+
] }),
|
|
309
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
310
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
171
311
|
] });
|
|
172
312
|
}
|
|
173
313
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
174
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "
|
|
314
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Fix-Comments" }),
|
|
175
315
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
176
316
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
177
|
-
"
|
|
317
|
+
"Fix-Comments prompt:",
|
|
178
318
|
" ",
|
|
179
319
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
180
|
-
|
|
320
|
+
fixCommentsPrompt,
|
|
181
321
|
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
182
322
|
] })
|
|
183
323
|
] }),
|
|
184
324
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
185
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save
|
|
325
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
186
326
|
] });
|
|
187
327
|
}
|
|
188
328
|
|
|
@@ -335,7 +475,27 @@ function fetchCheckRunOutputs(ownerRepo, sha) {
|
|
|
335
475
|
}
|
|
336
476
|
return map;
|
|
337
477
|
}
|
|
338
|
-
function
|
|
478
|
+
function extractSonarProjectKey(url) {
|
|
479
|
+
try {
|
|
480
|
+
const parsed = new URL(url);
|
|
481
|
+
const id = parsed.searchParams.get("id");
|
|
482
|
+
return id ?? null;
|
|
483
|
+
} catch {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async function fetchSonarNewIssues(projectKey, prNumber) {
|
|
488
|
+
const apiUrl = `https://sonarcloud.io/api/issues/search?componentKeys=${encodeURIComponent(projectKey)}&pullRequest=${String(prNumber)}&resolved=false&ps=1`;
|
|
489
|
+
try {
|
|
490
|
+
const response = await fetch(apiUrl);
|
|
491
|
+
if (!response.ok) return null;
|
|
492
|
+
const data = await response.json();
|
|
493
|
+
return data.paging?.total ?? null;
|
|
494
|
+
} catch {
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
async function getPrInfoGh(branch) {
|
|
339
499
|
const { stdout, stderr, status } = run2("gh", [
|
|
340
500
|
"pr",
|
|
341
501
|
"view",
|
|
@@ -365,9 +525,35 @@ function getPrInfoGh(branch) {
|
|
|
365
525
|
detailsUrl: enriched?.detailsUrl || c.detailsUrl || ""
|
|
366
526
|
};
|
|
367
527
|
});
|
|
368
|
-
|
|
528
|
+
const sonarCheck = checks.find((c) => {
|
|
529
|
+
try {
|
|
530
|
+
const hostname = new URL(c.detailsUrl).hostname;
|
|
531
|
+
return hostname === "sonarcloud.io" || hostname.endsWith(".sonarcloud.io");
|
|
532
|
+
} catch {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
let sonarcloudUrl;
|
|
537
|
+
let sonarNewIssues;
|
|
538
|
+
if (sonarCheck) {
|
|
539
|
+
sonarcloudUrl = sonarCheck.detailsUrl;
|
|
540
|
+
const projectKey = extractSonarProjectKey(sonarCheck.detailsUrl);
|
|
541
|
+
if (projectKey) {
|
|
542
|
+
sonarNewIssues = await fetchSonarNewIssues(projectKey, raw.number);
|
|
543
|
+
} else {
|
|
544
|
+
sonarNewIssues = null;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
number: raw.number,
|
|
549
|
+
title: raw.title,
|
|
550
|
+
state: raw.state,
|
|
551
|
+
url: raw.url,
|
|
552
|
+
checks,
|
|
553
|
+
...sonarcloudUrl !== void 0 ? { sonarcloudUrl, sonarNewIssues } : {}
|
|
554
|
+
};
|
|
369
555
|
}
|
|
370
|
-
function getPrInfo2(branch) {
|
|
556
|
+
async function getPrInfo2(branch) {
|
|
371
557
|
const config = readConfig();
|
|
372
558
|
if (config.remoteType === "azdo") {
|
|
373
559
|
return getPrInfo();
|
|
@@ -603,7 +789,7 @@ See docs/git.md for full output reference.`
|
|
|
603
789
|
let pr2;
|
|
604
790
|
while (true) {
|
|
605
791
|
try {
|
|
606
|
-
pr2 = getPrInfo2(branch);
|
|
792
|
+
pr2 = await getPrInfo2(branch);
|
|
607
793
|
} catch (err) {
|
|
608
794
|
process.stderr.write(`Error: ${err.message}
|
|
609
795
|
`);
|
|
@@ -643,7 +829,7 @@ See docs/git.md for full output reference.`
|
|
|
643
829
|
}
|
|
644
830
|
let pr;
|
|
645
831
|
try {
|
|
646
|
-
pr = getPrInfo2(branch);
|
|
832
|
+
pr = await getPrInfo2(branch);
|
|
647
833
|
} catch (err) {
|
|
648
834
|
process.stderr.write(`Error: ${err.message}
|
|
649
835
|
`);
|
|
@@ -662,6 +848,13 @@ Title: ${pr.title}
|
|
|
662
848
|
State: ${pr.state}
|
|
663
849
|
URL: ${pr.url}
|
|
664
850
|
`);
|
|
851
|
+
if (pr.sonarcloudUrl !== void 0) {
|
|
852
|
+
process.stdout.write(`Sonar: ${pr.sonarcloudUrl}
|
|
853
|
+
`);
|
|
854
|
+
const issueStr = pr.sonarNewIssues === null || pr.sonarNewIssues === void 0 ? "unavailable" : String(pr.sonarNewIssues);
|
|
855
|
+
process.stdout.write(`Sonar New Issues: ${issueStr}
|
|
856
|
+
`);
|
|
857
|
+
}
|
|
665
858
|
process.stdout.write(formatCheckSummary(pr.checks));
|
|
666
859
|
process.stdout.write(formatChecks(pr.checks));
|
|
667
860
|
}
|
|
@@ -724,7 +917,7 @@ ${safeBody}`);
|
|
|
724
917
|
}
|
|
725
918
|
process.stdout.write(lines.join("\n\n") + "\n");
|
|
726
919
|
});
|
|
727
|
-
var finishFeatureCmd = new Command2("finish-feature").description("Clean up a merged feature branch: checkout develop, pull, and delete local branch").action(() => {
|
|
920
|
+
var finishFeatureCmd = new Command2("finish-feature").description("Clean up a merged feature branch: checkout develop, pull, and delete local branch").action(async () => {
|
|
728
921
|
let branch;
|
|
729
922
|
try {
|
|
730
923
|
branch = getCurrentBranch();
|
|
@@ -745,7 +938,7 @@ var finishFeatureCmd = new Command2("finish-feature").description("Clean up a me
|
|
|
745
938
|
}
|
|
746
939
|
let pr;
|
|
747
940
|
try {
|
|
748
|
-
pr = getPrInfo2(branch);
|
|
941
|
+
pr = await getPrInfo2(branch);
|
|
749
942
|
} catch (err) {
|
|
750
943
|
process.stderr.write(`Error: ${err.message}
|
|
751
944
|
`);
|
|
@@ -1194,13 +1387,115 @@ var testCodexCmd = new Command4("codex").description("Test Codex CLI invocation
|
|
|
1194
1387
|
});
|
|
1195
1388
|
var testCommand = new Command4("test").description("Test commands for verifying automata integrations").addCommand(testClaudeCmd).addCommand(testCodexCmd);
|
|
1196
1389
|
|
|
1390
|
+
// src/commands/executePrompt.ts
|
|
1391
|
+
import { Command as Command5 } from "commander";
|
|
1392
|
+
var executeSonarCmd = new Command5("sonar").description(
|
|
1393
|
+
"Check the current branch for a SonarCloud analysis and invoke the AI with the Sonar prompt and analysis URL"
|
|
1394
|
+
).option("--codex", "Use Codex CLI instead of Claude Code").option("--verbose", "Show step-by-step progress (Claude only; ignored for Codex)").option("--opus", "Use claude-opus-4-6 (Claude only)").option("--sonnet", "Use claude-sonnet-4-6 (Claude only)").option("--haiku", "Use claude-haiku-4-5-20251001 (Claude only)").action(
|
|
1395
|
+
async (options) => {
|
|
1396
|
+
let branch;
|
|
1397
|
+
try {
|
|
1398
|
+
branch = getCurrentBranch();
|
|
1399
|
+
} catch (err) {
|
|
1400
|
+
process.stderr.write(`Error: ${err.message}
|
|
1401
|
+
`);
|
|
1402
|
+
process.exit(1);
|
|
1403
|
+
}
|
|
1404
|
+
let pr;
|
|
1405
|
+
try {
|
|
1406
|
+
pr = await getPrInfo2(branch);
|
|
1407
|
+
} catch (err) {
|
|
1408
|
+
process.stderr.write(`Error: ${err.message}
|
|
1409
|
+
`);
|
|
1410
|
+
process.exit(1);
|
|
1411
|
+
}
|
|
1412
|
+
if (pr === null) {
|
|
1413
|
+
process.stderr.write(`Error: No pull request found for branch: ${branch}
|
|
1414
|
+
`);
|
|
1415
|
+
process.exit(1);
|
|
1416
|
+
}
|
|
1417
|
+
if (!pr.sonarcloudUrl) {
|
|
1418
|
+
process.stderr.write(
|
|
1419
|
+
`Error: No SonarCloud analysis found for PR #${pr.number}. Ensure a SonarCloud check is configured on this repository.
|
|
1420
|
+
`
|
|
1421
|
+
);
|
|
1422
|
+
process.exit(1);
|
|
1423
|
+
}
|
|
1424
|
+
const config = readConfig();
|
|
1425
|
+
const sonarPromptText = config.prompts?.sonar ?? DEFAULT_SONAR_PROMPT;
|
|
1426
|
+
const fullPrompt = `${sonarPromptText}
|
|
1427
|
+
|
|
1428
|
+
SonarCloud analysis URL: ${pr.sonarcloudUrl}`;
|
|
1429
|
+
if (options.codex) {
|
|
1430
|
+
invokeCodexCode(fullPrompt, { yolo: true, verbose: options.verbose });
|
|
1431
|
+
} else {
|
|
1432
|
+
const model = resolveModelOption(options);
|
|
1433
|
+
await invokeClaudeCode(fullPrompt, { yolo: true, verbose: options.verbose, model });
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
);
|
|
1437
|
+
function formatComments(comments) {
|
|
1438
|
+
return comments.map((c) => {
|
|
1439
|
+
const loc = c.line !== null ? `${c.path}:${String(c.line)}` : `${c.path}:(file)`;
|
|
1440
|
+
return `[${c.author}] on ${loc}
|
|
1441
|
+
${c.body}`;
|
|
1442
|
+
}).join("\n\n");
|
|
1443
|
+
}
|
|
1444
|
+
var executeFixCommentsCmd = new Command5("fix-comments").description(
|
|
1445
|
+
"Fetch open review comments on the current PR and invoke the AI with the Fix-Comments prompt"
|
|
1446
|
+
).option("--codex", "Use Codex CLI instead of Claude Code").option("--verbose", "Show step-by-step progress (Claude only; ignored for Codex)").option("--opus", "Use claude-opus-4-6 (Claude only)").option("--sonnet", "Use claude-sonnet-4-6 (Claude only)").option("--haiku", "Use claude-haiku-4-5-20251001 (Claude only)").action(
|
|
1447
|
+
async (options) => {
|
|
1448
|
+
let branch;
|
|
1449
|
+
try {
|
|
1450
|
+
branch = getCurrentBranch();
|
|
1451
|
+
} catch (err) {
|
|
1452
|
+
process.stderr.write(`Error: ${err.message}
|
|
1453
|
+
`);
|
|
1454
|
+
process.exit(1);
|
|
1455
|
+
}
|
|
1456
|
+
const comments = getPrComments(branch);
|
|
1457
|
+
if (comments === "unsupported") {
|
|
1458
|
+
process.stderr.write(
|
|
1459
|
+
`Error: fix-comments is not supported for Azure DevOps. See docs/azdo-gap.md for details.
|
|
1460
|
+
`
|
|
1461
|
+
);
|
|
1462
|
+
process.exit(1);
|
|
1463
|
+
}
|
|
1464
|
+
if (comments === null) {
|
|
1465
|
+
process.stderr.write(`Error: No pull request found for branch: ${branch}
|
|
1466
|
+
`);
|
|
1467
|
+
process.exit(1);
|
|
1468
|
+
}
|
|
1469
|
+
if (comments.length === 0) {
|
|
1470
|
+
process.stderr.write(`Error: No open review comments found on the pull request.
|
|
1471
|
+
`);
|
|
1472
|
+
process.exit(1);
|
|
1473
|
+
}
|
|
1474
|
+
const config = readConfig();
|
|
1475
|
+
const promptText = config.prompts?.fixComments ?? DEFAULT_FIX_COMMENTS_PROMPT;
|
|
1476
|
+
const fullPrompt = `${promptText}
|
|
1477
|
+
|
|
1478
|
+
Open review comments:
|
|
1479
|
+
|
|
1480
|
+
${formatComments(comments)}`;
|
|
1481
|
+
if (options.codex) {
|
|
1482
|
+
invokeCodexCode(fullPrompt, { yolo: true, verbose: options.verbose });
|
|
1483
|
+
} else {
|
|
1484
|
+
const model = resolveModelOption(options);
|
|
1485
|
+
await invokeClaudeCode(fullPrompt, { yolo: true, verbose: options.verbose, model });
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
);
|
|
1489
|
+
var executePromptCommand = new Command5("execute-prompt").description("Execute a configured custom prompt using an AI assistant").addCommand(executeSonarCmd).addCommand(executeFixCommentsCmd);
|
|
1490
|
+
|
|
1197
1491
|
// src/index.ts
|
|
1198
|
-
var program = new
|
|
1492
|
+
var program = new Command6();
|
|
1199
1493
|
program.name("automata").description("Automata CLI tool").version(version, "-v, --version");
|
|
1200
1494
|
program.addCommand(configCommand);
|
|
1201
1495
|
program.addCommand(gitCommand);
|
|
1202
1496
|
program.addCommand(implementNextCommand);
|
|
1203
1497
|
program.addCommand(testCommand);
|
|
1498
|
+
program.addCommand(executePromptCommand);
|
|
1204
1499
|
program.showHelpAfterError();
|
|
1205
1500
|
program.parse();
|
|
1206
1501
|
if (process.argv.length <= 2) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "automata-cli",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-010-sonarcloud-prompts-execute.81",
|
|
4
4
|
"description": "Automata CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"@types/node": "^25.5.0",
|
|
34
34
|
"@types/react": "^19.2.14",
|
|
35
35
|
"eslint": "^10.1.0",
|
|
36
|
+
"ink-testing-library": "^4.0.0",
|
|
36
37
|
"prettier": "^3.8.1",
|
|
37
38
|
"tsup": "^8.5.1",
|
|
38
39
|
"typescript": "^5.9.3",
|