automata-cli 0.1.0-009-codex-flag-implement-next.73 → 0.1.0-010-sonarcloud-prompts-execute.79
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 +218 -95
- package/package.json +1 -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,7 @@ 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_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
27
|
var CONFIG_DIR = ".automata";
|
|
27
28
|
var CONFIG_FILE = "config.json";
|
|
28
29
|
function configPath() {
|
|
@@ -53,22 +54,42 @@ var TECHNIQUE_OPTIONS = [
|
|
|
53
54
|
{ label: "By Assignee", value: "assignee" },
|
|
54
55
|
{ label: "By Title Contains", value: "title-contains" }
|
|
55
56
|
];
|
|
57
|
+
var MAIN_MENU_OPTIONS = ["Remote / Mode", "Implement-Next", "Prompts"];
|
|
56
58
|
function ConfigWizard() {
|
|
57
59
|
const existing = readConfig();
|
|
58
60
|
const initialRemoteIndex = REMOTE_OPTIONS.findIndex((o) => o.value === existing.remoteType);
|
|
59
61
|
const initialTechIndex = TECHNIQUE_OPTIONS.findIndex((o) => o.value === existing.issueDiscoveryTechnique);
|
|
60
|
-
const [screen, setScreen] = useState("
|
|
62
|
+
const [screen, setScreen] = useState("main");
|
|
63
|
+
const [mainMenuIndex, setMainMenuIndex] = useState(0);
|
|
61
64
|
const [selectedRemoteIndex, setSelectedRemoteIndex] = useState(initialRemoteIndex >= 0 ? initialRemoteIndex : 0);
|
|
62
65
|
const [selectedTechIndex, setSelectedTechIndex] = useState(initialTechIndex >= 0 ? initialTechIndex : 0);
|
|
63
66
|
const [discoveryValue, setDiscoveryValue] = useState(existing.issueDiscoveryValue ?? "");
|
|
64
67
|
const [systemPrompt, setSystemPrompt] = useState(existing.claudeSystemPrompt ?? "");
|
|
68
|
+
const [sonarPrompt, setSonarPrompt] = useState(existing.prompts?.sonar ?? DEFAULT_SONAR_PROMPT);
|
|
65
69
|
const [pendingRemote, setPendingRemote] = useState(existing.remoteType ?? "gh");
|
|
66
70
|
const [pendingTechnique, setPendingTechnique] = useState(
|
|
67
71
|
existing.issueDiscoveryTechnique ?? "label"
|
|
68
72
|
);
|
|
69
73
|
const { exit } = useApp();
|
|
70
74
|
useInput((input, key) => {
|
|
71
|
-
if (screen === "
|
|
75
|
+
if (screen === "main") {
|
|
76
|
+
if (key.upArrow) {
|
|
77
|
+
setMainMenuIndex((i) => i > 0 ? i - 1 : MAIN_MENU_OPTIONS.length - 1);
|
|
78
|
+
} else if (key.downArrow) {
|
|
79
|
+
setMainMenuIndex((i) => i < MAIN_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
80
|
+
} else if (key.return) {
|
|
81
|
+
const chosen = MAIN_MENU_OPTIONS[mainMenuIndex];
|
|
82
|
+
if (chosen === "Remote / Mode") {
|
|
83
|
+
setScreen("remote");
|
|
84
|
+
} else if (chosen === "Implement-Next") {
|
|
85
|
+
setScreen("technique");
|
|
86
|
+
} else {
|
|
87
|
+
setScreen("prompts-menu");
|
|
88
|
+
}
|
|
89
|
+
} else if (key.escape || key.ctrl && input === "c") {
|
|
90
|
+
exit();
|
|
91
|
+
}
|
|
92
|
+
} else if (screen === "remote") {
|
|
72
93
|
if (key.upArrow) {
|
|
73
94
|
setSelectedRemoteIndex((i) => i > 0 ? i - 1 : REMOTE_OPTIONS.length - 1);
|
|
74
95
|
} else if (key.downArrow) {
|
|
@@ -82,7 +103,9 @@ function ConfigWizard() {
|
|
|
82
103
|
writeConfig({ ...existing, remoteType: chosen.value });
|
|
83
104
|
exit();
|
|
84
105
|
}
|
|
85
|
-
} else if (key.escape
|
|
106
|
+
} else if (key.escape) {
|
|
107
|
+
setScreen("main");
|
|
108
|
+
} else if (key.ctrl && input === "c") {
|
|
86
109
|
exit();
|
|
87
110
|
}
|
|
88
111
|
} else if (screen === "technique") {
|
|
@@ -94,7 +117,9 @@ function ConfigWizard() {
|
|
|
94
117
|
const chosen = TECHNIQUE_OPTIONS[selectedTechIndex];
|
|
95
118
|
setPendingTechnique(chosen.value);
|
|
96
119
|
setScreen("value");
|
|
97
|
-
} else if (key.escape
|
|
120
|
+
} else if (key.escape) {
|
|
121
|
+
setScreen("main");
|
|
122
|
+
} else if (key.ctrl && input === "c") {
|
|
98
123
|
exit();
|
|
99
124
|
}
|
|
100
125
|
} else if (screen === "value") {
|
|
@@ -102,7 +127,9 @@ function ConfigWizard() {
|
|
|
102
127
|
setScreen("system-prompt");
|
|
103
128
|
} else if (key.backspace || key.delete) {
|
|
104
129
|
setDiscoveryValue((v) => v.slice(0, -1));
|
|
105
|
-
} else if (key.escape
|
|
130
|
+
} else if (key.escape) {
|
|
131
|
+
setScreen("main");
|
|
132
|
+
} else if (key.ctrl && input === "c") {
|
|
106
133
|
exit();
|
|
107
134
|
} else if (input && !key.ctrl && !key.meta) {
|
|
108
135
|
setDiscoveryValue((v) => v + input);
|
|
@@ -119,29 +146,67 @@ function ConfigWizard() {
|
|
|
119
146
|
exit();
|
|
120
147
|
} else if (key.backspace || key.delete) {
|
|
121
148
|
setSystemPrompt((v) => v.slice(0, -1));
|
|
122
|
-
} else if (key.escape
|
|
149
|
+
} else if (key.escape) {
|
|
150
|
+
setScreen("main");
|
|
151
|
+
} else if (key.ctrl && input === "c") {
|
|
123
152
|
exit();
|
|
124
153
|
} else if (input && !key.ctrl && !key.meta) {
|
|
125
154
|
setSystemPrompt((v) => v + input);
|
|
126
155
|
}
|
|
156
|
+
} else if (screen === "prompts-menu") {
|
|
157
|
+
if (key.return) {
|
|
158
|
+
setScreen("sonar-prompt");
|
|
159
|
+
} else if (key.escape) {
|
|
160
|
+
setScreen("main");
|
|
161
|
+
} else if (key.ctrl && input === "c") {
|
|
162
|
+
exit();
|
|
163
|
+
}
|
|
164
|
+
} else if (screen === "sonar-prompt") {
|
|
165
|
+
if (key.return) {
|
|
166
|
+
writeConfig({
|
|
167
|
+
...existing,
|
|
168
|
+
prompts: { ...existing.prompts, sonar: sonarPrompt || void 0 }
|
|
169
|
+
});
|
|
170
|
+
exit();
|
|
171
|
+
} else if (key.backspace || key.delete) {
|
|
172
|
+
setSonarPrompt((v) => v.slice(0, -1));
|
|
173
|
+
} else if (key.escape) {
|
|
174
|
+
setScreen("prompts-menu");
|
|
175
|
+
} else if (key.ctrl && input === "c") {
|
|
176
|
+
exit();
|
|
177
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
178
|
+
setSonarPrompt((v) => v + input);
|
|
179
|
+
}
|
|
127
180
|
}
|
|
128
181
|
});
|
|
129
|
-
if (screen === "
|
|
182
|
+
if (screen === "main") {
|
|
130
183
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
131
184
|
/* @__PURE__ */ jsx(Text, { bold: true, children: "Configure Automata" }),
|
|
132
185
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
186
|
+
MAIN_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === mainMenuIndex ? "cyan" : void 0, children: [
|
|
187
|
+
index === mainMenuIndex ? "\u276F " : " ",
|
|
188
|
+
option
|
|
189
|
+
] }) }, option)),
|
|
190
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
191
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to cancel" })
|
|
192
|
+
] });
|
|
193
|
+
}
|
|
194
|
+
if (screen === "remote") {
|
|
195
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
196
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Remote / Mode" }),
|
|
197
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
133
198
|
/* @__PURE__ */ jsx(Text, { children: "Remote environment type:" }),
|
|
134
199
|
REMOTE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedRemoteIndex ? "cyan" : void 0, children: [
|
|
135
200
|
index === selectedRemoteIndex ? "\u276F " : " ",
|
|
136
201
|
option.label
|
|
137
202
|
] }) }, option.value)),
|
|
138
203
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
139
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Ctrl+C to cancel" })
|
|
204
|
+
/* @__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
205
|
] });
|
|
141
206
|
}
|
|
142
207
|
if (screen === "technique") {
|
|
143
208
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
144
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "
|
|
209
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Technique" }),
|
|
145
210
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
146
211
|
/* @__PURE__ */ jsx(Text, { children: "How to find the next issue to work on:" }),
|
|
147
212
|
TECHNIQUE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedTechIndex ? "cyan" : void 0, children: [
|
|
@@ -149,13 +214,13 @@ function ConfigWizard() {
|
|
|
149
214
|
option.label
|
|
150
215
|
] }) }, option.value)),
|
|
151
216
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
152
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Ctrl+C to cancel" })
|
|
217
|
+
/* @__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
218
|
] });
|
|
154
219
|
}
|
|
155
220
|
if (screen === "value") {
|
|
156
221
|
const techLabel = TECHNIQUE_OPTIONS.find((t) => t.value === pendingTechnique)?.label ?? pendingTechnique;
|
|
157
222
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
158
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "
|
|
223
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Value" }),
|
|
159
224
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
160
225
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
161
226
|
techLabel,
|
|
@@ -167,22 +232,50 @@ function ConfigWizard() {
|
|
|
167
232
|
] })
|
|
168
233
|
] }),
|
|
169
234
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
170
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type value \xB7 Enter to
|
|
235
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type value \xB7 Enter to continue \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
236
|
+
] });
|
|
237
|
+
}
|
|
238
|
+
if (screen === "system-prompt") {
|
|
239
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
240
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Claude System Prompt" }),
|
|
241
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
242
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
243
|
+
"System prompt (optional):",
|
|
244
|
+
" ",
|
|
245
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
246
|
+
systemPrompt,
|
|
247
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
248
|
+
] })
|
|
249
|
+
] }),
|
|
250
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
251
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save and exit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
252
|
+
] });
|
|
253
|
+
}
|
|
254
|
+
if (screen === "prompts-menu") {
|
|
255
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
256
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts" }),
|
|
257
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
258
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
259
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u276F " }),
|
|
260
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "Sonar" })
|
|
261
|
+
] }),
|
|
262
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
263
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Enter to edit Sonar prompt \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
171
264
|
] });
|
|
172
265
|
}
|
|
173
266
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
174
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "
|
|
267
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Sonar" }),
|
|
175
268
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
176
269
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
177
|
-
"
|
|
270
|
+
"Sonar prompt:",
|
|
178
271
|
" ",
|
|
179
272
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
180
|
-
|
|
273
|
+
sonarPrompt,
|
|
181
274
|
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
182
275
|
] })
|
|
183
276
|
] }),
|
|
184
277
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
185
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save and exit \xB7 Ctrl+C to cancel" })
|
|
278
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save and exit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
186
279
|
] });
|
|
187
280
|
}
|
|
188
281
|
|
|
@@ -335,7 +428,27 @@ function fetchCheckRunOutputs(ownerRepo, sha) {
|
|
|
335
428
|
}
|
|
336
429
|
return map;
|
|
337
430
|
}
|
|
338
|
-
function
|
|
431
|
+
function extractSonarProjectKey(url) {
|
|
432
|
+
try {
|
|
433
|
+
const parsed = new URL(url);
|
|
434
|
+
const id = parsed.searchParams.get("id");
|
|
435
|
+
return id ?? null;
|
|
436
|
+
} catch {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
async function fetchSonarNewIssues(projectKey, prNumber) {
|
|
441
|
+
const apiUrl = `https://sonarcloud.io/api/issues/search?componentKeys=${encodeURIComponent(projectKey)}&pullRequest=${String(prNumber)}&resolved=false&ps=1`;
|
|
442
|
+
try {
|
|
443
|
+
const response = await fetch(apiUrl);
|
|
444
|
+
if (!response.ok) return null;
|
|
445
|
+
const data = await response.json();
|
|
446
|
+
return data.paging?.total ?? null;
|
|
447
|
+
} catch {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async function getPrInfoGh(branch) {
|
|
339
452
|
const { stdout, stderr, status } = run2("gh", [
|
|
340
453
|
"pr",
|
|
341
454
|
"view",
|
|
@@ -365,9 +478,28 @@ function getPrInfoGh(branch) {
|
|
|
365
478
|
detailsUrl: enriched?.detailsUrl || c.detailsUrl || ""
|
|
366
479
|
};
|
|
367
480
|
});
|
|
368
|
-
|
|
481
|
+
const sonarCheck = checks.find((c) => c.detailsUrl.includes("sonarcloud.io"));
|
|
482
|
+
let sonarcloudUrl;
|
|
483
|
+
let sonarNewIssues;
|
|
484
|
+
if (sonarCheck) {
|
|
485
|
+
sonarcloudUrl = sonarCheck.detailsUrl;
|
|
486
|
+
const projectKey = extractSonarProjectKey(sonarCheck.detailsUrl);
|
|
487
|
+
if (projectKey) {
|
|
488
|
+
sonarNewIssues = await fetchSonarNewIssues(projectKey, raw.number);
|
|
489
|
+
} else {
|
|
490
|
+
sonarNewIssues = null;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return {
|
|
494
|
+
number: raw.number,
|
|
495
|
+
title: raw.title,
|
|
496
|
+
state: raw.state,
|
|
497
|
+
url: raw.url,
|
|
498
|
+
checks,
|
|
499
|
+
...sonarcloudUrl !== void 0 ? { sonarcloudUrl, sonarNewIssues } : {}
|
|
500
|
+
};
|
|
369
501
|
}
|
|
370
|
-
function getPrInfo2(branch) {
|
|
502
|
+
async function getPrInfo2(branch) {
|
|
371
503
|
const config = readConfig();
|
|
372
504
|
if (config.remoteType === "azdo") {
|
|
373
505
|
return getPrInfo();
|
|
@@ -603,7 +735,7 @@ See docs/git.md for full output reference.`
|
|
|
603
735
|
let pr2;
|
|
604
736
|
while (true) {
|
|
605
737
|
try {
|
|
606
|
-
pr2 = getPrInfo2(branch);
|
|
738
|
+
pr2 = await getPrInfo2(branch);
|
|
607
739
|
} catch (err) {
|
|
608
740
|
process.stderr.write(`Error: ${err.message}
|
|
609
741
|
`);
|
|
@@ -643,7 +775,7 @@ See docs/git.md for full output reference.`
|
|
|
643
775
|
}
|
|
644
776
|
let pr;
|
|
645
777
|
try {
|
|
646
|
-
pr = getPrInfo2(branch);
|
|
778
|
+
pr = await getPrInfo2(branch);
|
|
647
779
|
} catch (err) {
|
|
648
780
|
process.stderr.write(`Error: ${err.message}
|
|
649
781
|
`);
|
|
@@ -662,6 +794,13 @@ Title: ${pr.title}
|
|
|
662
794
|
State: ${pr.state}
|
|
663
795
|
URL: ${pr.url}
|
|
664
796
|
`);
|
|
797
|
+
if (pr.sonarcloudUrl !== void 0) {
|
|
798
|
+
process.stdout.write(`Sonar: ${pr.sonarcloudUrl}
|
|
799
|
+
`);
|
|
800
|
+
const issueStr = pr.sonarNewIssues === null || pr.sonarNewIssues === void 0 ? "unavailable" : String(pr.sonarNewIssues);
|
|
801
|
+
process.stdout.write(`Sonar New Issues: ${issueStr}
|
|
802
|
+
`);
|
|
803
|
+
}
|
|
665
804
|
process.stdout.write(formatCheckSummary(pr.checks));
|
|
666
805
|
process.stdout.write(formatChecks(pr.checks));
|
|
667
806
|
}
|
|
@@ -724,7 +863,7 @@ ${safeBody}`);
|
|
|
724
863
|
}
|
|
725
864
|
process.stdout.write(lines.join("\n\n") + "\n");
|
|
726
865
|
});
|
|
727
|
-
var finishFeatureCmd = new Command2("finish-feature").description("Clean up a merged feature branch: checkout develop, pull, and delete local branch").action(() => {
|
|
866
|
+
var finishFeatureCmd = new Command2("finish-feature").description("Clean up a merged feature branch: checkout develop, pull, and delete local branch").action(async () => {
|
|
728
867
|
let branch;
|
|
729
868
|
try {
|
|
730
869
|
branch = getCurrentBranch();
|
|
@@ -745,7 +884,7 @@ var finishFeatureCmd = new Command2("finish-feature").description("Clean up a me
|
|
|
745
884
|
}
|
|
746
885
|
let pr;
|
|
747
886
|
try {
|
|
748
|
-
pr = getPrInfo2(branch);
|
|
887
|
+
pr = await getPrInfo2(branch);
|
|
749
888
|
} catch (err) {
|
|
750
889
|
process.stderr.write(`Error: ${err.message}
|
|
751
890
|
`);
|
|
@@ -1100,11 +1239,10 @@ function summarizeTool(name, input) {
|
|
|
1100
1239
|
}
|
|
1101
1240
|
|
|
1102
1241
|
// src/codex/codexService.ts
|
|
1103
|
-
import {
|
|
1104
|
-
import { createInterface as createInterface2 } from "readline";
|
|
1242
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
1105
1243
|
function invokeCodexCode(prompt, options = {}) {
|
|
1106
1244
|
if (options.verbose) {
|
|
1107
|
-
|
|
1245
|
+
process.stderr.write("Warning: --verbose is not supported for Codex and will be ignored.\n");
|
|
1108
1246
|
}
|
|
1109
1247
|
invokeCodexCodeSync(prompt, options.yolo ?? false);
|
|
1110
1248
|
}
|
|
@@ -1117,71 +1255,6 @@ function invokeCodexCodeSync(prompt, yolo) {
|
|
|
1117
1255
|
handleSpawnError(result.error, "codex");
|
|
1118
1256
|
handleExitCode(result.status, "Codex");
|
|
1119
1257
|
}
|
|
1120
|
-
function invokeCodexCodeVerbose(prompt, yolo) {
|
|
1121
|
-
return new Promise((resolve2) => {
|
|
1122
|
-
const codexBin = resolveCommand("codex");
|
|
1123
|
-
const args = ["exec"];
|
|
1124
|
-
if (yolo) args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
1125
|
-
args.push("--json", prompt);
|
|
1126
|
-
const child = spawn2(codexBin, args, { stdio: ["inherit", "pipe", "inherit"] });
|
|
1127
|
-
const rl = createInterface2({ input: child.stdout });
|
|
1128
|
-
let stepCount = 0;
|
|
1129
|
-
child.on("error", (err) => {
|
|
1130
|
-
handleSpawnError(err, "codex");
|
|
1131
|
-
});
|
|
1132
|
-
rl.on("line", (line) => {
|
|
1133
|
-
try {
|
|
1134
|
-
const event = JSON.parse(line);
|
|
1135
|
-
formatCodexEvent(event, stepCount);
|
|
1136
|
-
if (event["type"] === "agent_message" || event["type"] === "tool_call") stepCount++;
|
|
1137
|
-
} catch {
|
|
1138
|
-
}
|
|
1139
|
-
});
|
|
1140
|
-
child.on("close", (code) => {
|
|
1141
|
-
handleExitCode(code, "Codex");
|
|
1142
|
-
resolve2();
|
|
1143
|
-
});
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1146
|
-
function formatCodexEvent(event, stepCount) {
|
|
1147
|
-
const type = event["type"];
|
|
1148
|
-
if (type === "tool_call") {
|
|
1149
|
-
const name = event["name"];
|
|
1150
|
-
const input = event["input"];
|
|
1151
|
-
const summary = name ? summarizeCodexTool(name, input) : "tool call";
|
|
1152
|
-
process.stderr.write(` [step ${stepCount + 1}] ${summary}
|
|
1153
|
-
`);
|
|
1154
|
-
} else if (type === "agent_message") {
|
|
1155
|
-
const content = event["content"];
|
|
1156
|
-
if (content && content.length > 0) {
|
|
1157
|
-
const preview = content.length > 120 ? content.slice(0, 120) + "..." : content;
|
|
1158
|
-
const firstLine = preview.split("\n")[0] ?? preview;
|
|
1159
|
-
process.stderr.write(` [step ${stepCount + 1}] ${firstLine}
|
|
1160
|
-
`);
|
|
1161
|
-
}
|
|
1162
|
-
} else if (type === "session_complete" || type === "completed") {
|
|
1163
|
-
const result = event["result"];
|
|
1164
|
-
process.stderr.write("\n--- Result ---\n");
|
|
1165
|
-
if (result) {
|
|
1166
|
-
process.stdout.write(result + "\n");
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
function summarizeCodexTool(name, input) {
|
|
1171
|
-
if (!input) return `tool: ${name}`;
|
|
1172
|
-
switch (name) {
|
|
1173
|
-
case "shell":
|
|
1174
|
-
return `running: ${truncate(String(input["cmd"] ?? input["command"] ?? ""), 80)}`;
|
|
1175
|
-
case "read_file":
|
|
1176
|
-
return `reading ${String(input["path"] ?? "file")}`;
|
|
1177
|
-
case "write_file":
|
|
1178
|
-
return `writing ${String(input["path"] ?? "file")}`;
|
|
1179
|
-
case "list_files":
|
|
1180
|
-
return `listing files: ${String(input["path"] ?? ".")}`;
|
|
1181
|
-
default:
|
|
1182
|
-
return `tool: ${name}`;
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
1258
|
|
|
1186
1259
|
// src/commands/getReady.ts
|
|
1187
1260
|
var implementNextCommand = new Command3("implement-next").description("Find the next open GitHub issue matching the configured filter, claim it, and invoke the AI code assistant (Claude or Codex)").option("--json", "Output issue details as JSON").option("--no-claude", "Skip all AI invocation (Claude or Codex) after claiming the issue").option("--codex", "Use Codex CLI instead of Claude Code").option("--query-only", "Print issue content and exit without claiming or invoking any AI tools").option("--yolo", "Launch with --dangerously-skip-permissions (Claude) or --dangerously-bypass-approvals-and-sandbox (Codex)").option("--verbose", "Show step-by-step progress summary and final result").option("--opus", "Use claude-opus-4-6").option("--sonnet", "Use claude-sonnet-4-6").option("--haiku", "Use claude-haiku-4-5-20251001").action(async (options) => {
|
|
@@ -1255,18 +1328,68 @@ var testClaudeCmd = new Command4("claude").description("Test Claude Code invocat
|
|
|
1255
1328
|
const model = resolveModelOption(options);
|
|
1256
1329
|
await invokeClaudeCode(options.prompt, { yolo: options.yolo, verbose: options.verbose, model });
|
|
1257
1330
|
});
|
|
1258
|
-
var testCodexCmd = new Command4("codex").description("Test Codex CLI invocation with a user-supplied prompt").requiredOption("--prompt <string>", "Prompt to send to Codex CLI").option("--yolo", "Launch Codex with --dangerously-bypass-approvals-and-sandbox").option("--verbose", "
|
|
1259
|
-
|
|
1331
|
+
var testCodexCmd = new Command4("codex").description("Test Codex CLI invocation with a user-supplied prompt").requiredOption("--prompt <string>", "Prompt to send to Codex CLI").option("--yolo", "Launch Codex with --dangerously-bypass-approvals-and-sandbox").option("--verbose", "Not supported for Codex; prints a warning and is otherwise ignored").action((options) => {
|
|
1332
|
+
invokeCodexCode(options.prompt, { yolo: options.yolo, verbose: options.verbose });
|
|
1260
1333
|
});
|
|
1261
1334
|
var testCommand = new Command4("test").description("Test commands for verifying automata integrations").addCommand(testClaudeCmd).addCommand(testCodexCmd);
|
|
1262
1335
|
|
|
1336
|
+
// src/commands/executePrompt.ts
|
|
1337
|
+
import { Command as Command5 } from "commander";
|
|
1338
|
+
var executeSonarCmd = new Command5("sonar").description(
|
|
1339
|
+
"Check the current branch for a SonarCloud analysis and invoke the AI with the Sonar prompt and analysis URL"
|
|
1340
|
+
).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(
|
|
1341
|
+
async (options) => {
|
|
1342
|
+
let branch;
|
|
1343
|
+
try {
|
|
1344
|
+
branch = getCurrentBranch();
|
|
1345
|
+
} catch (err) {
|
|
1346
|
+
process.stderr.write(`Error: ${err.message}
|
|
1347
|
+
`);
|
|
1348
|
+
process.exit(1);
|
|
1349
|
+
}
|
|
1350
|
+
let pr;
|
|
1351
|
+
try {
|
|
1352
|
+
pr = await getPrInfo2(branch);
|
|
1353
|
+
} catch (err) {
|
|
1354
|
+
process.stderr.write(`Error: ${err.message}
|
|
1355
|
+
`);
|
|
1356
|
+
process.exit(1);
|
|
1357
|
+
}
|
|
1358
|
+
if (pr === null) {
|
|
1359
|
+
process.stderr.write(`Error: No pull request found for branch: ${branch}
|
|
1360
|
+
`);
|
|
1361
|
+
process.exit(1);
|
|
1362
|
+
}
|
|
1363
|
+
if (!pr.sonarcloudUrl) {
|
|
1364
|
+
process.stderr.write(
|
|
1365
|
+
`Error: No SonarCloud analysis found for PR #${pr.number}. Ensure a SonarCloud check is configured on this repository.
|
|
1366
|
+
`
|
|
1367
|
+
);
|
|
1368
|
+
process.exit(1);
|
|
1369
|
+
}
|
|
1370
|
+
const config = readConfig();
|
|
1371
|
+
const sonarPromptText = config.prompts?.sonar ?? DEFAULT_SONAR_PROMPT;
|
|
1372
|
+
const fullPrompt = `${sonarPromptText}
|
|
1373
|
+
|
|
1374
|
+
SonarCloud analysis URL: ${pr.sonarcloudUrl}`;
|
|
1375
|
+
if (options.codex) {
|
|
1376
|
+
invokeCodexCode(fullPrompt, { verbose: options.verbose });
|
|
1377
|
+
} else {
|
|
1378
|
+
const model = resolveModelOption(options);
|
|
1379
|
+
await invokeClaudeCode(fullPrompt, { verbose: options.verbose, model });
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
);
|
|
1383
|
+
var executePromptCommand = new Command5("execute-prompt").description("Execute a configured custom prompt using an AI assistant").addCommand(executeSonarCmd);
|
|
1384
|
+
|
|
1263
1385
|
// src/index.ts
|
|
1264
|
-
var program = new
|
|
1386
|
+
var program = new Command6();
|
|
1265
1387
|
program.name("automata").description("Automata CLI tool").version(version, "-v, --version");
|
|
1266
1388
|
program.addCommand(configCommand);
|
|
1267
1389
|
program.addCommand(gitCommand);
|
|
1268
1390
|
program.addCommand(implementNextCommand);
|
|
1269
1391
|
program.addCommand(testCommand);
|
|
1392
|
+
program.addCommand(executePromptCommand);
|
|
1270
1393
|
program.showHelpAfterError();
|
|
1271
1394
|
program.parse();
|
|
1272
1395
|
if (process.argv.length <= 2) {
|