automata-cli 0.4.0-develop.152 → 0.4.0-develop.164
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/README.md +13 -0
- package/dist/ConfigWizard-WUGEM3PT.js +320 -0
- package/dist/chunk-LAIP3B6F.js +80 -0
- package/dist/index.js +46 -424
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,6 +113,19 @@ See [docs/execute.md](docs/execute.md) for full details.
|
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
116
|
+
## `automata execute-prompt`
|
|
117
|
+
|
|
118
|
+
Run predefined AI workflows that gather context from the current branch before invoking Claude or Codex.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
automata execute-prompt sonar --with claude
|
|
122
|
+
automata execute-prompt fix-comments --with codex --model o3
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
See [docs/execute-prompt.md](docs/execute-prompt.md) for full details.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
116
129
|
## Development
|
|
117
130
|
|
|
118
131
|
### Prerequisites
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_FIX_COMMENTS_PROMPT,
|
|
4
|
+
DEFAULT_SONAR_PROMPT,
|
|
5
|
+
readConfig,
|
|
6
|
+
readRawConfig,
|
|
7
|
+
writeConfig
|
|
8
|
+
} from "./chunk-LAIP3B6F.js";
|
|
9
|
+
|
|
10
|
+
// src/config/ConfigWizard.tsx
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import { Box, Text, useInput, useApp } from "ink";
|
|
13
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
+
function writePromptFile(filename, content) {
|
|
17
|
+
const dir = join(process.cwd(), ".automata");
|
|
18
|
+
mkdirSync(dir, { recursive: true });
|
|
19
|
+
writeFileSync(join(dir, filename), content, "utf8");
|
|
20
|
+
}
|
|
21
|
+
var REMOTE_OPTIONS = [
|
|
22
|
+
{ label: "GitHub", value: "gh" },
|
|
23
|
+
{ label: "Azure DevOps", value: "azdo" }
|
|
24
|
+
];
|
|
25
|
+
var TECHNIQUE_OPTIONS = [
|
|
26
|
+
{ label: "By Label", value: "label" },
|
|
27
|
+
{ label: "By Assignee", value: "assignee" },
|
|
28
|
+
{ label: "By Title Contains", value: "title-contains" }
|
|
29
|
+
];
|
|
30
|
+
var MAIN_MENU_OPTIONS = ["Remote / Mode", "Implement-Next", "Prompts"];
|
|
31
|
+
var PROMPTS_MENU_OPTIONS = ["Sonar", "Fix-Comments"];
|
|
32
|
+
function ConfigWizard() {
|
|
33
|
+
const existing = readConfig();
|
|
34
|
+
const rawExisting = readRawConfig();
|
|
35
|
+
const initialRemoteIndex = REMOTE_OPTIONS.findIndex((o) => o.value === existing.remoteType);
|
|
36
|
+
const initialTechIndex = TECHNIQUE_OPTIONS.findIndex((o) => o.value === existing.issueDiscoveryTechnique);
|
|
37
|
+
const [screen, setScreen] = useState("main");
|
|
38
|
+
const [mainMenuIndex, setMainMenuIndex] = useState(0);
|
|
39
|
+
const [selectedRemoteIndex, setSelectedRemoteIndex] = useState(initialRemoteIndex >= 0 ? initialRemoteIndex : 0);
|
|
40
|
+
const [selectedTechIndex, setSelectedTechIndex] = useState(initialTechIndex >= 0 ? initialTechIndex : 0);
|
|
41
|
+
const [discoveryValue, setDiscoveryValue] = useState(existing.issueDiscoveryValue ?? "");
|
|
42
|
+
const [systemPrompt, setSystemPrompt] = useState(existing.claudeSystemPrompt ?? "");
|
|
43
|
+
const [promptsMenuIndex, setPromptsMenuIndex] = useState(0);
|
|
44
|
+
const [sonarPrompt, setSonarPrompt] = useState(existing.prompts?.sonar ?? DEFAULT_SONAR_PROMPT);
|
|
45
|
+
const [fixCommentsPrompt, setFixCommentsPrompt] = useState(
|
|
46
|
+
existing.prompts?.fixComments ?? DEFAULT_FIX_COMMENTS_PROMPT
|
|
47
|
+
);
|
|
48
|
+
const [pendingRemote, setPendingRemote] = useState(existing.remoteType ?? "gh");
|
|
49
|
+
const [pendingTechnique, setPendingTechnique] = useState(
|
|
50
|
+
existing.issueDiscoveryTechnique ?? "label"
|
|
51
|
+
);
|
|
52
|
+
const { exit } = useApp();
|
|
53
|
+
useInput((input, key) => {
|
|
54
|
+
if (screen === "main") {
|
|
55
|
+
if (key.upArrow) {
|
|
56
|
+
setMainMenuIndex((i) => i > 0 ? i - 1 : MAIN_MENU_OPTIONS.length - 1);
|
|
57
|
+
} else if (key.downArrow) {
|
|
58
|
+
setMainMenuIndex((i) => i < MAIN_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
59
|
+
} else if (key.return) {
|
|
60
|
+
const chosen = MAIN_MENU_OPTIONS[mainMenuIndex];
|
|
61
|
+
if (chosen === "Remote / Mode") {
|
|
62
|
+
setScreen("remote");
|
|
63
|
+
} else if (chosen === "Implement-Next") {
|
|
64
|
+
setScreen("technique");
|
|
65
|
+
} else {
|
|
66
|
+
setScreen("prompts-menu");
|
|
67
|
+
}
|
|
68
|
+
} else if (key.escape || key.ctrl && input === "c") {
|
|
69
|
+
exit();
|
|
70
|
+
}
|
|
71
|
+
} else if (screen === "remote") {
|
|
72
|
+
if (key.upArrow) {
|
|
73
|
+
setSelectedRemoteIndex((i) => i > 0 ? i - 1 : REMOTE_OPTIONS.length - 1);
|
|
74
|
+
} else if (key.downArrow) {
|
|
75
|
+
setSelectedRemoteIndex((i) => i < REMOTE_OPTIONS.length - 1 ? i + 1 : 0);
|
|
76
|
+
} else if (key.return) {
|
|
77
|
+
const chosen = REMOTE_OPTIONS[selectedRemoteIndex];
|
|
78
|
+
setPendingRemote(chosen.value);
|
|
79
|
+
if (chosen.value === "gh") {
|
|
80
|
+
setScreen("technique");
|
|
81
|
+
} else {
|
|
82
|
+
writeConfig({ ...rawExisting, remoteType: chosen.value });
|
|
83
|
+
exit();
|
|
84
|
+
}
|
|
85
|
+
} else if (key.escape) {
|
|
86
|
+
setScreen("main");
|
|
87
|
+
} else if (key.ctrl && input === "c") {
|
|
88
|
+
exit();
|
|
89
|
+
}
|
|
90
|
+
} else if (screen === "technique") {
|
|
91
|
+
if (key.upArrow) {
|
|
92
|
+
setSelectedTechIndex((i) => i > 0 ? i - 1 : TECHNIQUE_OPTIONS.length - 1);
|
|
93
|
+
} else if (key.downArrow) {
|
|
94
|
+
setSelectedTechIndex((i) => i < TECHNIQUE_OPTIONS.length - 1 ? i + 1 : 0);
|
|
95
|
+
} else if (key.return) {
|
|
96
|
+
const chosen = TECHNIQUE_OPTIONS[selectedTechIndex];
|
|
97
|
+
setPendingTechnique(chosen.value);
|
|
98
|
+
setScreen("value");
|
|
99
|
+
} else if (key.escape) {
|
|
100
|
+
setScreen("main");
|
|
101
|
+
} else if (key.ctrl && input === "c") {
|
|
102
|
+
exit();
|
|
103
|
+
}
|
|
104
|
+
} else if (screen === "value") {
|
|
105
|
+
if (key.return) {
|
|
106
|
+
setScreen("system-prompt");
|
|
107
|
+
} else if (key.backspace || key.delete) {
|
|
108
|
+
setDiscoveryValue((v) => v.slice(0, -1));
|
|
109
|
+
} else if (key.escape) {
|
|
110
|
+
setScreen("main");
|
|
111
|
+
} else if (key.ctrl && input === "c") {
|
|
112
|
+
exit();
|
|
113
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
114
|
+
setDiscoveryValue((v) => v + input);
|
|
115
|
+
}
|
|
116
|
+
} else if (screen === "system-prompt") {
|
|
117
|
+
if (key.return) {
|
|
118
|
+
let claudeSystemPromptValue;
|
|
119
|
+
if (systemPrompt) {
|
|
120
|
+
writePromptFile("claude-system-prompt.md", systemPrompt);
|
|
121
|
+
claudeSystemPromptValue = "claude-system-prompt.md";
|
|
122
|
+
}
|
|
123
|
+
writeConfig({
|
|
124
|
+
...rawExisting,
|
|
125
|
+
remoteType: pendingRemote,
|
|
126
|
+
issueDiscoveryTechnique: pendingTechnique,
|
|
127
|
+
issueDiscoveryValue: discoveryValue || void 0,
|
|
128
|
+
claudeSystemPrompt: claudeSystemPromptValue
|
|
129
|
+
});
|
|
130
|
+
exit();
|
|
131
|
+
} else if (key.backspace || key.delete) {
|
|
132
|
+
setSystemPrompt((v) => v.slice(0, -1));
|
|
133
|
+
} else if (key.escape) {
|
|
134
|
+
setScreen("main");
|
|
135
|
+
} else if (key.ctrl && input === "c") {
|
|
136
|
+
exit();
|
|
137
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
138
|
+
setSystemPrompt((v) => v + input);
|
|
139
|
+
}
|
|
140
|
+
} else if (screen === "prompts-menu") {
|
|
141
|
+
if (key.upArrow) {
|
|
142
|
+
setPromptsMenuIndex((i) => i > 0 ? i - 1 : PROMPTS_MENU_OPTIONS.length - 1);
|
|
143
|
+
} else if (key.downArrow) {
|
|
144
|
+
setPromptsMenuIndex((i) => i < PROMPTS_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
145
|
+
} else if (key.return) {
|
|
146
|
+
const chosen = PROMPTS_MENU_OPTIONS[promptsMenuIndex];
|
|
147
|
+
if (chosen === "Sonar") {
|
|
148
|
+
setScreen("sonar-prompt");
|
|
149
|
+
} else {
|
|
150
|
+
setScreen("fix-comments-prompt");
|
|
151
|
+
}
|
|
152
|
+
} else if (key.escape) {
|
|
153
|
+
setScreen("main");
|
|
154
|
+
} else if (key.ctrl && input === "c") {
|
|
155
|
+
exit();
|
|
156
|
+
}
|
|
157
|
+
} else if (screen === "sonar-prompt") {
|
|
158
|
+
if (key.return) {
|
|
159
|
+
let sonarValue;
|
|
160
|
+
if (sonarPrompt) {
|
|
161
|
+
writePromptFile("sonar-prompt.md", sonarPrompt);
|
|
162
|
+
sonarValue = "sonar-prompt.md";
|
|
163
|
+
}
|
|
164
|
+
const current = readRawConfig();
|
|
165
|
+
writeConfig({
|
|
166
|
+
...current,
|
|
167
|
+
prompts: { ...current.prompts, sonar: sonarValue }
|
|
168
|
+
});
|
|
169
|
+
setScreen("prompts-menu");
|
|
170
|
+
} else if (key.backspace || key.delete) {
|
|
171
|
+
setSonarPrompt((v) => v.slice(0, -1));
|
|
172
|
+
} else if (key.escape) {
|
|
173
|
+
setScreen("prompts-menu");
|
|
174
|
+
} else if (key.ctrl && input === "c") {
|
|
175
|
+
exit();
|
|
176
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
177
|
+
setSonarPrompt((v) => v + input);
|
|
178
|
+
}
|
|
179
|
+
} else if (screen === "fix-comments-prompt") {
|
|
180
|
+
if (key.return) {
|
|
181
|
+
let fixCommentsValue;
|
|
182
|
+
if (fixCommentsPrompt) {
|
|
183
|
+
writePromptFile("fix-comments-prompt.md", fixCommentsPrompt);
|
|
184
|
+
fixCommentsValue = "fix-comments-prompt.md";
|
|
185
|
+
}
|
|
186
|
+
const current = readRawConfig();
|
|
187
|
+
writeConfig({
|
|
188
|
+
...current,
|
|
189
|
+
prompts: { ...current.prompts, fixComments: fixCommentsValue }
|
|
190
|
+
});
|
|
191
|
+
setScreen("prompts-menu");
|
|
192
|
+
} else if (key.backspace || key.delete) {
|
|
193
|
+
setFixCommentsPrompt((v) => v.slice(0, -1));
|
|
194
|
+
} else if (key.escape) {
|
|
195
|
+
setScreen("prompts-menu");
|
|
196
|
+
} else if (key.ctrl && input === "c") {
|
|
197
|
+
exit();
|
|
198
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
199
|
+
setFixCommentsPrompt((v) => v + input);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
if (screen === "main") {
|
|
204
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
205
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Configure Automata" }),
|
|
206
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
207
|
+
MAIN_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === mainMenuIndex ? "cyan" : void 0, children: [
|
|
208
|
+
index === mainMenuIndex ? "\u276F " : " ",
|
|
209
|
+
option
|
|
210
|
+
] }) }, option)),
|
|
211
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
212
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to cancel" })
|
|
213
|
+
] });
|
|
214
|
+
}
|
|
215
|
+
if (screen === "remote") {
|
|
216
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
217
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Remote / Mode" }),
|
|
218
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
219
|
+
/* @__PURE__ */ jsx(Text, { children: "Remote environment type:" }),
|
|
220
|
+
REMOTE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedRemoteIndex ? "cyan" : void 0, children: [
|
|
221
|
+
index === selectedRemoteIndex ? "\u276F " : " ",
|
|
222
|
+
option.label
|
|
223
|
+
] }) }, option.value)),
|
|
224
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
225
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
226
|
+
] });
|
|
227
|
+
}
|
|
228
|
+
if (screen === "technique") {
|
|
229
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
230
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Technique" }),
|
|
231
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
232
|
+
/* @__PURE__ */ jsx(Text, { children: "How to find the next issue to work on:" }),
|
|
233
|
+
TECHNIQUE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedTechIndex ? "cyan" : void 0, children: [
|
|
234
|
+
index === selectedTechIndex ? "\u276F " : " ",
|
|
235
|
+
option.label
|
|
236
|
+
] }) }, option.value)),
|
|
237
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
238
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
239
|
+
] });
|
|
240
|
+
}
|
|
241
|
+
if (screen === "value") {
|
|
242
|
+
const techLabel = TECHNIQUE_OPTIONS.find((t) => t.value === pendingTechnique)?.label ?? pendingTechnique;
|
|
243
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
244
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Value" }),
|
|
245
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
246
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
247
|
+
techLabel,
|
|
248
|
+
" value:",
|
|
249
|
+
" ",
|
|
250
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
251
|
+
discoveryValue,
|
|
252
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
253
|
+
] })
|
|
254
|
+
] }),
|
|
255
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
256
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type value \xB7 Enter to continue \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
257
|
+
] });
|
|
258
|
+
}
|
|
259
|
+
if (screen === "system-prompt") {
|
|
260
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
261
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Claude System Prompt" }),
|
|
262
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
263
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
264
|
+
"System prompt (optional):",
|
|
265
|
+
" ",
|
|
266
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
267
|
+
systemPrompt,
|
|
268
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
269
|
+
] })
|
|
270
|
+
] }),
|
|
271
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
272
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save and exit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
273
|
+
] });
|
|
274
|
+
}
|
|
275
|
+
if (screen === "prompts-menu") {
|
|
276
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
277
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts" }),
|
|
278
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
279
|
+
PROMPTS_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === promptsMenuIndex ? "cyan" : void 0, children: [
|
|
280
|
+
index === promptsMenuIndex ? "\u276F " : " ",
|
|
281
|
+
option
|
|
282
|
+
] }) }, option)),
|
|
283
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
284
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to edit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
285
|
+
] });
|
|
286
|
+
}
|
|
287
|
+
if (screen === "sonar-prompt") {
|
|
288
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
289
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Sonar" }),
|
|
290
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
291
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
292
|
+
"Sonar prompt:",
|
|
293
|
+
" ",
|
|
294
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
295
|
+
sonarPrompt,
|
|
296
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
297
|
+
] })
|
|
298
|
+
] }),
|
|
299
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
300
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
301
|
+
] });
|
|
302
|
+
}
|
|
303
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
304
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Fix-Comments" }),
|
|
305
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
306
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
307
|
+
"Fix-Comments prompt:",
|
|
308
|
+
" ",
|
|
309
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
310
|
+
fixCommentsPrompt,
|
|
311
|
+
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
312
|
+
] })
|
|
313
|
+
] }),
|
|
314
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
315
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
316
|
+
] });
|
|
317
|
+
}
|
|
318
|
+
export {
|
|
319
|
+
ConfigWizard
|
|
320
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/config/configStore.ts
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
5
|
+
import { join, resolve, sep } from "path";
|
|
6
|
+
var DEFAULT_CLAUDE_SYSTEM_PROMPT = "You are an expert software engineer. Implement the following issue according to the project's existing conventions and style. Make minimal, targeted changes that satisfy the requirements. Run tests and linting before finishing.";
|
|
7
|
+
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.";
|
|
8
|
+
var DEFAULT_SONAR_PROMPT = "You are an expert software engineer. You have been given the URL of a SonarCloud analysis for this pull request. If the `sonar-quality-gate` skill is available in this repository, use it. The project is public, so use the SonarCloud REST API directly (no authentication required) rather than scraping the URL. Inspect both the quality gate and the list of issues for this pull request. If the quality gate fails because of duplication or another metric-based condition, use the relevant Sonar APIs to identify the affected files and details instead of relying only on the issues endpoint. Fix all new issues and quality-gate failures reported. Focus on code smells, bugs, vulnerabilities, and blocking quality-gate conditions flagged in this PR. Make targeted, minimal changes that resolve each issue without altering unrelated code.";
|
|
9
|
+
var CONFIG_DIR = ".automata";
|
|
10
|
+
var CONFIG_FILE = "config.json";
|
|
11
|
+
function configPath() {
|
|
12
|
+
return join(process.cwd(), CONFIG_DIR, CONFIG_FILE);
|
|
13
|
+
}
|
|
14
|
+
function automataDir() {
|
|
15
|
+
return join(process.cwd(), CONFIG_DIR);
|
|
16
|
+
}
|
|
17
|
+
function resolvePromptRef(value, dir) {
|
|
18
|
+
if (!value.endsWith(".md")) return value;
|
|
19
|
+
if (value.includes("/") || value.includes("\\")) {
|
|
20
|
+
throw new Error(`Prompt file "${value}" must be a plain filename with no subdirectories`);
|
|
21
|
+
}
|
|
22
|
+
const fullPath = resolve(dir, value);
|
|
23
|
+
const safeBase = resolve(dir) + sep;
|
|
24
|
+
if (!fullPath.startsWith(safeBase)) {
|
|
25
|
+
throw new Error(`Prompt file "${value}" resolves outside .automata/`);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return readFileSync(fullPath, "utf8");
|
|
29
|
+
} catch (err) {
|
|
30
|
+
if (err?.code === "ENOENT") {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Prompt file "${value}" not found in "${dir}". Expected path: ${fullPath}`,
|
|
33
|
+
{ cause: err }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function readRawConfig() {
|
|
40
|
+
try {
|
|
41
|
+
const raw = readFileSync(configPath(), "utf8");
|
|
42
|
+
return JSON.parse(raw);
|
|
43
|
+
} catch {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function readConfig() {
|
|
48
|
+
let config;
|
|
49
|
+
try {
|
|
50
|
+
const raw = readFileSync(configPath(), "utf8");
|
|
51
|
+
config = JSON.parse(raw);
|
|
52
|
+
} catch {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
const dir = automataDir();
|
|
56
|
+
if (config.claudeSystemPrompt) {
|
|
57
|
+
config.claudeSystemPrompt = resolvePromptRef(config.claudeSystemPrompt, dir);
|
|
58
|
+
}
|
|
59
|
+
if (config.prompts?.sonar) {
|
|
60
|
+
config.prompts.sonar = resolvePromptRef(config.prompts.sonar, dir);
|
|
61
|
+
}
|
|
62
|
+
if (config.prompts?.fixComments) {
|
|
63
|
+
config.prompts.fixComments = resolvePromptRef(config.prompts.fixComments, dir);
|
|
64
|
+
}
|
|
65
|
+
return config;
|
|
66
|
+
}
|
|
67
|
+
function writeConfig(config) {
|
|
68
|
+
const dir = join(process.cwd(), CONFIG_DIR);
|
|
69
|
+
mkdirSync(dir, { recursive: true });
|
|
70
|
+
writeFileSync(configPath(), JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
DEFAULT_CLAUDE_SYSTEM_PROMPT,
|
|
75
|
+
DEFAULT_FIX_COMMENTS_PROMPT,
|
|
76
|
+
DEFAULT_SONAR_PROMPT,
|
|
77
|
+
readRawConfig,
|
|
78
|
+
readConfig,
|
|
79
|
+
writeConfig
|
|
80
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_CLAUDE_SYSTEM_PROMPT,
|
|
4
|
+
DEFAULT_FIX_COMMENTS_PROMPT,
|
|
5
|
+
DEFAULT_SONAR_PROMPT,
|
|
6
|
+
readConfig,
|
|
7
|
+
readRawConfig,
|
|
8
|
+
writeConfig
|
|
9
|
+
} from "./chunk-LAIP3B6F.js";
|
|
2
10
|
|
|
3
11
|
// src/index.ts
|
|
4
12
|
import { Command as Command6 } from "commander";
|
|
@@ -13,391 +21,6 @@ var version = packageJson.version;
|
|
|
13
21
|
|
|
14
22
|
// src/commands/config.ts
|
|
15
23
|
import { Command } from "commander";
|
|
16
|
-
import { render } from "ink";
|
|
17
|
-
import React2 from "react";
|
|
18
|
-
|
|
19
|
-
// src/config/ConfigWizard.tsx
|
|
20
|
-
import { useState } from "react";
|
|
21
|
-
import { Box, Text, useInput, useApp } from "ink";
|
|
22
|
-
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
23
|
-
import { join as join2 } from "path";
|
|
24
|
-
|
|
25
|
-
// src/config/configStore.ts
|
|
26
|
-
import { readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
27
|
-
import { join, resolve as resolve2, sep } from "path";
|
|
28
|
-
var DEFAULT_CLAUDE_SYSTEM_PROMPT = "You are an expert software engineer. Implement the following issue according to the project's existing conventions and style. Make minimal, targeted changes that satisfy the requirements. Run tests and linting before finishing.";
|
|
29
|
-
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.";
|
|
30
|
-
var DEFAULT_SONAR_PROMPT = "You are an expert software engineer. You have been given the URL of a SonarCloud analysis for this pull request. If the `sonar-quality-gate` skill is available in this repository, use it. The project is public, so use the SonarCloud REST API directly (no authentication required) rather than scraping the URL. Inspect both the quality gate and the list of issues for this pull request. If the quality gate fails because of duplication or another metric-based condition, use the relevant Sonar APIs to identify the affected files and details instead of relying only on the issues endpoint. Fix all new issues and quality-gate failures reported. Focus on code smells, bugs, vulnerabilities, and blocking quality-gate conditions flagged in this PR. Make targeted, minimal changes that resolve each issue without altering unrelated code.";
|
|
31
|
-
var CONFIG_DIR = ".automata";
|
|
32
|
-
var CONFIG_FILE = "config.json";
|
|
33
|
-
function configPath() {
|
|
34
|
-
return join(process.cwd(), CONFIG_DIR, CONFIG_FILE);
|
|
35
|
-
}
|
|
36
|
-
function automataDir() {
|
|
37
|
-
return join(process.cwd(), CONFIG_DIR);
|
|
38
|
-
}
|
|
39
|
-
function resolvePromptRef(value, dir) {
|
|
40
|
-
if (!value.endsWith(".md")) return value;
|
|
41
|
-
if (value.includes("/") || value.includes("\\")) {
|
|
42
|
-
throw new Error(`Prompt file "${value}" must be a plain filename with no subdirectories`);
|
|
43
|
-
}
|
|
44
|
-
const fullPath = resolve2(dir, value);
|
|
45
|
-
const safeBase = resolve2(dir) + sep;
|
|
46
|
-
if (!fullPath.startsWith(safeBase)) {
|
|
47
|
-
throw new Error(`Prompt file "${value}" resolves outside .automata/`);
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
return readFileSync2(fullPath, "utf8");
|
|
51
|
-
} catch (err) {
|
|
52
|
-
if (err?.code === "ENOENT") {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Prompt file "${value}" not found in "${dir}". Expected path: ${fullPath}`,
|
|
55
|
-
{ cause: err }
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
throw err;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function readRawConfig() {
|
|
62
|
-
try {
|
|
63
|
-
const raw = readFileSync2(configPath(), "utf8");
|
|
64
|
-
return JSON.parse(raw);
|
|
65
|
-
} catch {
|
|
66
|
-
return {};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function readConfig() {
|
|
70
|
-
let config;
|
|
71
|
-
try {
|
|
72
|
-
const raw = readFileSync2(configPath(), "utf8");
|
|
73
|
-
config = JSON.parse(raw);
|
|
74
|
-
} catch {
|
|
75
|
-
return {};
|
|
76
|
-
}
|
|
77
|
-
const dir = automataDir();
|
|
78
|
-
if (config.claudeSystemPrompt) {
|
|
79
|
-
config.claudeSystemPrompt = resolvePromptRef(config.claudeSystemPrompt, dir);
|
|
80
|
-
}
|
|
81
|
-
if (config.prompts?.sonar) {
|
|
82
|
-
config.prompts.sonar = resolvePromptRef(config.prompts.sonar, dir);
|
|
83
|
-
}
|
|
84
|
-
if (config.prompts?.fixComments) {
|
|
85
|
-
config.prompts.fixComments = resolvePromptRef(config.prompts.fixComments, dir);
|
|
86
|
-
}
|
|
87
|
-
return config;
|
|
88
|
-
}
|
|
89
|
-
function writeConfig(config) {
|
|
90
|
-
const dir = join(process.cwd(), CONFIG_DIR);
|
|
91
|
-
mkdirSync(dir, { recursive: true });
|
|
92
|
-
writeFileSync(configPath(), JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// src/config/ConfigWizard.tsx
|
|
96
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
97
|
-
function writePromptFile(filename, content) {
|
|
98
|
-
const dir = join2(process.cwd(), ".automata");
|
|
99
|
-
mkdirSync2(dir, { recursive: true });
|
|
100
|
-
writeFileSync2(join2(dir, filename), content, "utf8");
|
|
101
|
-
}
|
|
102
|
-
var REMOTE_OPTIONS = [
|
|
103
|
-
{ label: "GitHub", value: "gh" },
|
|
104
|
-
{ label: "Azure DevOps", value: "azdo" }
|
|
105
|
-
];
|
|
106
|
-
var TECHNIQUE_OPTIONS = [
|
|
107
|
-
{ label: "By Label", value: "label" },
|
|
108
|
-
{ label: "By Assignee", value: "assignee" },
|
|
109
|
-
{ label: "By Title Contains", value: "title-contains" }
|
|
110
|
-
];
|
|
111
|
-
var MAIN_MENU_OPTIONS = ["Remote / Mode", "Implement-Next", "Prompts"];
|
|
112
|
-
var PROMPTS_MENU_OPTIONS = ["Sonar", "Fix-Comments"];
|
|
113
|
-
function ConfigWizard() {
|
|
114
|
-
const existing = readConfig();
|
|
115
|
-
const rawExisting = readRawConfig();
|
|
116
|
-
const initialRemoteIndex = REMOTE_OPTIONS.findIndex((o) => o.value === existing.remoteType);
|
|
117
|
-
const initialTechIndex = TECHNIQUE_OPTIONS.findIndex((o) => o.value === existing.issueDiscoveryTechnique);
|
|
118
|
-
const [screen, setScreen] = useState("main");
|
|
119
|
-
const [mainMenuIndex, setMainMenuIndex] = useState(0);
|
|
120
|
-
const [selectedRemoteIndex, setSelectedRemoteIndex] = useState(initialRemoteIndex >= 0 ? initialRemoteIndex : 0);
|
|
121
|
-
const [selectedTechIndex, setSelectedTechIndex] = useState(initialTechIndex >= 0 ? initialTechIndex : 0);
|
|
122
|
-
const [discoveryValue, setDiscoveryValue] = useState(existing.issueDiscoveryValue ?? "");
|
|
123
|
-
const [systemPrompt, setSystemPrompt] = useState(existing.claudeSystemPrompt ?? "");
|
|
124
|
-
const [promptsMenuIndex, setPromptsMenuIndex] = useState(0);
|
|
125
|
-
const [sonarPrompt, setSonarPrompt] = useState(existing.prompts?.sonar ?? DEFAULT_SONAR_PROMPT);
|
|
126
|
-
const [fixCommentsPrompt, setFixCommentsPrompt] = useState(
|
|
127
|
-
existing.prompts?.fixComments ?? DEFAULT_FIX_COMMENTS_PROMPT
|
|
128
|
-
);
|
|
129
|
-
const [pendingRemote, setPendingRemote] = useState(existing.remoteType ?? "gh");
|
|
130
|
-
const [pendingTechnique, setPendingTechnique] = useState(
|
|
131
|
-
existing.issueDiscoveryTechnique ?? "label"
|
|
132
|
-
);
|
|
133
|
-
const { exit } = useApp();
|
|
134
|
-
useInput((input, key) => {
|
|
135
|
-
if (screen === "main") {
|
|
136
|
-
if (key.upArrow) {
|
|
137
|
-
setMainMenuIndex((i) => i > 0 ? i - 1 : MAIN_MENU_OPTIONS.length - 1);
|
|
138
|
-
} else if (key.downArrow) {
|
|
139
|
-
setMainMenuIndex((i) => i < MAIN_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
140
|
-
} else if (key.return) {
|
|
141
|
-
const chosen = MAIN_MENU_OPTIONS[mainMenuIndex];
|
|
142
|
-
if (chosen === "Remote / Mode") {
|
|
143
|
-
setScreen("remote");
|
|
144
|
-
} else if (chosen === "Implement-Next") {
|
|
145
|
-
setScreen("technique");
|
|
146
|
-
} else {
|
|
147
|
-
setScreen("prompts-menu");
|
|
148
|
-
}
|
|
149
|
-
} else if (key.escape || key.ctrl && input === "c") {
|
|
150
|
-
exit();
|
|
151
|
-
}
|
|
152
|
-
} else if (screen === "remote") {
|
|
153
|
-
if (key.upArrow) {
|
|
154
|
-
setSelectedRemoteIndex((i) => i > 0 ? i - 1 : REMOTE_OPTIONS.length - 1);
|
|
155
|
-
} else if (key.downArrow) {
|
|
156
|
-
setSelectedRemoteIndex((i) => i < REMOTE_OPTIONS.length - 1 ? i + 1 : 0);
|
|
157
|
-
} else if (key.return) {
|
|
158
|
-
const chosen = REMOTE_OPTIONS[selectedRemoteIndex];
|
|
159
|
-
setPendingRemote(chosen.value);
|
|
160
|
-
if (chosen.value === "gh") {
|
|
161
|
-
setScreen("technique");
|
|
162
|
-
} else {
|
|
163
|
-
writeConfig({ ...rawExisting, remoteType: chosen.value });
|
|
164
|
-
exit();
|
|
165
|
-
}
|
|
166
|
-
} else if (key.escape) {
|
|
167
|
-
setScreen("main");
|
|
168
|
-
} else if (key.ctrl && input === "c") {
|
|
169
|
-
exit();
|
|
170
|
-
}
|
|
171
|
-
} else if (screen === "technique") {
|
|
172
|
-
if (key.upArrow) {
|
|
173
|
-
setSelectedTechIndex((i) => i > 0 ? i - 1 : TECHNIQUE_OPTIONS.length - 1);
|
|
174
|
-
} else if (key.downArrow) {
|
|
175
|
-
setSelectedTechIndex((i) => i < TECHNIQUE_OPTIONS.length - 1 ? i + 1 : 0);
|
|
176
|
-
} else if (key.return) {
|
|
177
|
-
const chosen = TECHNIQUE_OPTIONS[selectedTechIndex];
|
|
178
|
-
setPendingTechnique(chosen.value);
|
|
179
|
-
setScreen("value");
|
|
180
|
-
} else if (key.escape) {
|
|
181
|
-
setScreen("main");
|
|
182
|
-
} else if (key.ctrl && input === "c") {
|
|
183
|
-
exit();
|
|
184
|
-
}
|
|
185
|
-
} else if (screen === "value") {
|
|
186
|
-
if (key.return) {
|
|
187
|
-
setScreen("system-prompt");
|
|
188
|
-
} else if (key.backspace || key.delete) {
|
|
189
|
-
setDiscoveryValue((v) => v.slice(0, -1));
|
|
190
|
-
} else if (key.escape) {
|
|
191
|
-
setScreen("main");
|
|
192
|
-
} else if (key.ctrl && input === "c") {
|
|
193
|
-
exit();
|
|
194
|
-
} else if (input && !key.ctrl && !key.meta) {
|
|
195
|
-
setDiscoveryValue((v) => v + input);
|
|
196
|
-
}
|
|
197
|
-
} else if (screen === "system-prompt") {
|
|
198
|
-
if (key.return) {
|
|
199
|
-
let claudeSystemPromptValue;
|
|
200
|
-
if (systemPrompt) {
|
|
201
|
-
writePromptFile("claude-system-prompt.md", systemPrompt);
|
|
202
|
-
claudeSystemPromptValue = "claude-system-prompt.md";
|
|
203
|
-
}
|
|
204
|
-
writeConfig({
|
|
205
|
-
...rawExisting,
|
|
206
|
-
remoteType: pendingRemote,
|
|
207
|
-
issueDiscoveryTechnique: pendingTechnique,
|
|
208
|
-
issueDiscoveryValue: discoveryValue || void 0,
|
|
209
|
-
claudeSystemPrompt: claudeSystemPromptValue
|
|
210
|
-
});
|
|
211
|
-
exit();
|
|
212
|
-
} else if (key.backspace || key.delete) {
|
|
213
|
-
setSystemPrompt((v) => v.slice(0, -1));
|
|
214
|
-
} else if (key.escape) {
|
|
215
|
-
setScreen("main");
|
|
216
|
-
} else if (key.ctrl && input === "c") {
|
|
217
|
-
exit();
|
|
218
|
-
} else if (input && !key.ctrl && !key.meta) {
|
|
219
|
-
setSystemPrompt((v) => v + input);
|
|
220
|
-
}
|
|
221
|
-
} else if (screen === "prompts-menu") {
|
|
222
|
-
if (key.upArrow) {
|
|
223
|
-
setPromptsMenuIndex((i) => i > 0 ? i - 1 : PROMPTS_MENU_OPTIONS.length - 1);
|
|
224
|
-
} else if (key.downArrow) {
|
|
225
|
-
setPromptsMenuIndex((i) => i < PROMPTS_MENU_OPTIONS.length - 1 ? i + 1 : 0);
|
|
226
|
-
} else if (key.return) {
|
|
227
|
-
const chosen = PROMPTS_MENU_OPTIONS[promptsMenuIndex];
|
|
228
|
-
if (chosen === "Sonar") {
|
|
229
|
-
setScreen("sonar-prompt");
|
|
230
|
-
} else {
|
|
231
|
-
setScreen("fix-comments-prompt");
|
|
232
|
-
}
|
|
233
|
-
} else if (key.escape) {
|
|
234
|
-
setScreen("main");
|
|
235
|
-
} else if (key.ctrl && input === "c") {
|
|
236
|
-
exit();
|
|
237
|
-
}
|
|
238
|
-
} else if (screen === "sonar-prompt") {
|
|
239
|
-
if (key.return) {
|
|
240
|
-
let sonarValue;
|
|
241
|
-
if (sonarPrompt) {
|
|
242
|
-
writePromptFile("sonar-prompt.md", sonarPrompt);
|
|
243
|
-
sonarValue = "sonar-prompt.md";
|
|
244
|
-
}
|
|
245
|
-
const current = readRawConfig();
|
|
246
|
-
writeConfig({
|
|
247
|
-
...current,
|
|
248
|
-
prompts: { ...current.prompts, sonar: sonarValue }
|
|
249
|
-
});
|
|
250
|
-
setScreen("prompts-menu");
|
|
251
|
-
} else if (key.backspace || key.delete) {
|
|
252
|
-
setSonarPrompt((v) => v.slice(0, -1));
|
|
253
|
-
} else if (key.escape) {
|
|
254
|
-
setScreen("prompts-menu");
|
|
255
|
-
} else if (key.ctrl && input === "c") {
|
|
256
|
-
exit();
|
|
257
|
-
} else if (input && !key.ctrl && !key.meta) {
|
|
258
|
-
setSonarPrompt((v) => v + input);
|
|
259
|
-
}
|
|
260
|
-
} else if (screen === "fix-comments-prompt") {
|
|
261
|
-
if (key.return) {
|
|
262
|
-
let fixCommentsValue;
|
|
263
|
-
if (fixCommentsPrompt) {
|
|
264
|
-
writePromptFile("fix-comments-prompt.md", fixCommentsPrompt);
|
|
265
|
-
fixCommentsValue = "fix-comments-prompt.md";
|
|
266
|
-
}
|
|
267
|
-
const current = readRawConfig();
|
|
268
|
-
writeConfig({
|
|
269
|
-
...current,
|
|
270
|
-
prompts: { ...current.prompts, fixComments: fixCommentsValue }
|
|
271
|
-
});
|
|
272
|
-
setScreen("prompts-menu");
|
|
273
|
-
} else if (key.backspace || key.delete) {
|
|
274
|
-
setFixCommentsPrompt((v) => v.slice(0, -1));
|
|
275
|
-
} else if (key.escape) {
|
|
276
|
-
setScreen("prompts-menu");
|
|
277
|
-
} else if (key.ctrl && input === "c") {
|
|
278
|
-
exit();
|
|
279
|
-
} else if (input && !key.ctrl && !key.meta) {
|
|
280
|
-
setFixCommentsPrompt((v) => v + input);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
if (screen === "main") {
|
|
285
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
286
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Configure Automata" }),
|
|
287
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
288
|
-
MAIN_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === mainMenuIndex ? "cyan" : void 0, children: [
|
|
289
|
-
index === mainMenuIndex ? "\u276F " : " ",
|
|
290
|
-
option
|
|
291
|
-
] }) }, option)),
|
|
292
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
293
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to cancel" })
|
|
294
|
-
] });
|
|
295
|
-
}
|
|
296
|
-
if (screen === "remote") {
|
|
297
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
298
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Remote / Mode" }),
|
|
299
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
300
|
-
/* @__PURE__ */ jsx(Text, { children: "Remote environment type:" }),
|
|
301
|
-
REMOTE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedRemoteIndex ? "cyan" : void 0, children: [
|
|
302
|
-
index === selectedRemoteIndex ? "\u276F " : " ",
|
|
303
|
-
option.label
|
|
304
|
-
] }) }, option.value)),
|
|
305
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
306
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
307
|
-
] });
|
|
308
|
-
}
|
|
309
|
-
if (screen === "technique") {
|
|
310
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
311
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Technique" }),
|
|
312
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
313
|
-
/* @__PURE__ */ jsx(Text, { children: "How to find the next issue to work on:" }),
|
|
314
|
-
TECHNIQUE_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === selectedTechIndex ? "cyan" : void 0, children: [
|
|
315
|
-
index === selectedTechIndex ? "\u276F " : " ",
|
|
316
|
-
option.label
|
|
317
|
-
] }) }, option.value)),
|
|
318
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
319
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to confirm \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
320
|
-
] });
|
|
321
|
-
}
|
|
322
|
-
if (screen === "value") {
|
|
323
|
-
const techLabel = TECHNIQUE_OPTIONS.find((t) => t.value === pendingTechnique)?.label ?? pendingTechnique;
|
|
324
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
325
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Issue Discovery Value" }),
|
|
326
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
327
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
328
|
-
techLabel,
|
|
329
|
-
" value:",
|
|
330
|
-
" ",
|
|
331
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
332
|
-
discoveryValue,
|
|
333
|
-
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
334
|
-
] })
|
|
335
|
-
] }),
|
|
336
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
337
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type value \xB7 Enter to continue \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
338
|
-
] });
|
|
339
|
-
}
|
|
340
|
-
if (screen === "system-prompt") {
|
|
341
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
342
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Implement-Next \u2014 Claude System Prompt" }),
|
|
343
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
344
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
345
|
-
"System prompt (optional):",
|
|
346
|
-
" ",
|
|
347
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
348
|
-
systemPrompt,
|
|
349
|
-
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
350
|
-
] })
|
|
351
|
-
] }),
|
|
352
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
353
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save and exit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
354
|
-
] });
|
|
355
|
-
}
|
|
356
|
-
if (screen === "prompts-menu") {
|
|
357
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
358
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts" }),
|
|
359
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
360
|
-
PROMPTS_MENU_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: index === promptsMenuIndex ? "cyan" : void 0, children: [
|
|
361
|
-
index === promptsMenuIndex ? "\u276F " : " ",
|
|
362
|
-
option
|
|
363
|
-
] }) }, option)),
|
|
364
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
365
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move \xB7 Enter to edit \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
366
|
-
] });
|
|
367
|
-
}
|
|
368
|
-
if (screen === "sonar-prompt") {
|
|
369
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
370
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Sonar" }),
|
|
371
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
372
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
373
|
-
"Sonar prompt:",
|
|
374
|
-
" ",
|
|
375
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
376
|
-
sonarPrompt,
|
|
377
|
-
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
378
|
-
] })
|
|
379
|
-
] }),
|
|
380
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
381
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
382
|
-
] });
|
|
383
|
-
}
|
|
384
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
385
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Prompts \u2014 Fix-Comments" }),
|
|
386
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
387
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
388
|
-
"Fix-Comments prompt:",
|
|
389
|
-
" ",
|
|
390
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
391
|
-
fixCommentsPrompt,
|
|
392
|
-
/* @__PURE__ */ jsx(Text, { children: "_" })
|
|
393
|
-
] })
|
|
394
|
-
] }),
|
|
395
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
396
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type prompt \xB7 Enter to save \xB7 Esc to go back \xB7 Ctrl+C to cancel" })
|
|
397
|
-
] });
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// src/commands/config.ts
|
|
401
24
|
var VALID_TYPES = ["gh", "azdo"];
|
|
402
25
|
var VALID_TECHNIQUES = ["label", "assignee", "title-contains"];
|
|
403
26
|
var configSetType = new Command("type").description("Set the remote environment type").argument("<value>", "Remote type: gh (GitHub) or azdo (Azure DevOps)").action((value) => {
|
|
@@ -436,7 +59,12 @@ var configSetClaudeSystemPrompt = new Command("claude-system-prompt").descriptio
|
|
|
436
59
|
});
|
|
437
60
|
var configSet = new Command("set").description("Set a configuration value").addCommand(configSetType).addCommand(configSetIssueDiscoveryTechnique).addCommand(configSetIssueDiscoveryValue).addCommand(configSetClaudeSystemPrompt);
|
|
438
61
|
var configCommand = new Command("config").description("Configure automata settings").addCommand(configSet).action(async () => {
|
|
439
|
-
const {
|
|
62
|
+
const [{ render }, React, { ConfigWizard }] = await Promise.all([
|
|
63
|
+
import("ink"),
|
|
64
|
+
import("react"),
|
|
65
|
+
import("./ConfigWizard-WUGEM3PT.js")
|
|
66
|
+
]);
|
|
67
|
+
const { waitUntilExit } = render(React.createElement(ConfigWizard));
|
|
440
68
|
await waitUntilExit();
|
|
441
69
|
});
|
|
442
70
|
|
|
@@ -1140,7 +768,7 @@ function formatChecks(checks) {
|
|
|
1140
768
|
return lines.join("\n") + "\n";
|
|
1141
769
|
}
|
|
1142
770
|
function sleep(ms) {
|
|
1143
|
-
return new Promise((
|
|
771
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
1144
772
|
}
|
|
1145
773
|
function isSonarCheck(check) {
|
|
1146
774
|
try {
|
|
@@ -1687,7 +1315,7 @@ function addCopilotReviewer(prNumber) {
|
|
|
1687
1315
|
import { spawn, spawnSync as spawnSync4 } from "child_process";
|
|
1688
1316
|
import { createInterface } from "readline";
|
|
1689
1317
|
import { existsSync } from "fs";
|
|
1690
|
-
import { delimiter, join
|
|
1318
|
+
import { delimiter, join } from "path";
|
|
1691
1319
|
|
|
1692
1320
|
// src/cli/spawnUtils.ts
|
|
1693
1321
|
function truncate(str, max) {
|
|
@@ -1722,25 +1350,11 @@ function handleExitCode(status, toolName) {
|
|
|
1722
1350
|
function resolveCommand(name) {
|
|
1723
1351
|
const pathDirs = (process.env["PATH"] ?? "").split(delimiter);
|
|
1724
1352
|
for (const dir of pathDirs) {
|
|
1725
|
-
const candidate =
|
|
1353
|
+
const candidate = join(dir, name);
|
|
1726
1354
|
if (existsSync(candidate)) return candidate;
|
|
1727
1355
|
}
|
|
1728
1356
|
return name;
|
|
1729
1357
|
}
|
|
1730
|
-
var MODEL_IDS = {
|
|
1731
|
-
opus: "claude-opus-4-6",
|
|
1732
|
-
sonnet: "claude-sonnet-4-6",
|
|
1733
|
-
haiku: "claude-haiku-4-5-20251001"
|
|
1734
|
-
};
|
|
1735
|
-
function resolveModelOption(opts) {
|
|
1736
|
-
const selected = ["opus", "sonnet", "haiku"].filter((m) => opts[m]);
|
|
1737
|
-
if (selected.length > 1) {
|
|
1738
|
-
process.stderr.write(`Error: --${selected[0]} and --${selected[1]} are mutually exclusive.
|
|
1739
|
-
`);
|
|
1740
|
-
process.exit(1);
|
|
1741
|
-
}
|
|
1742
|
-
return selected.length === 1 ? MODEL_IDS[selected[0]] : void 0;
|
|
1743
|
-
}
|
|
1744
1358
|
function invokeClaudeCode(prompt, options = {}) {
|
|
1745
1359
|
if (options.verbose) {
|
|
1746
1360
|
return invokeClaudeCodeVerbose(prompt, options.yolo ?? false, options.model);
|
|
@@ -1758,7 +1372,7 @@ function invokeClaudeCodeSync(prompt, yolo, model) {
|
|
|
1758
1372
|
handleExitCode(result.status, "Claude Code");
|
|
1759
1373
|
}
|
|
1760
1374
|
function invokeClaudeCodeVerbose(prompt, yolo, model) {
|
|
1761
|
-
return new Promise((
|
|
1375
|
+
return new Promise((resolve2) => {
|
|
1762
1376
|
const claudeBin = resolveCommand("claude");
|
|
1763
1377
|
const args = [];
|
|
1764
1378
|
if (yolo) args.push("--dangerously-skip-permissions");
|
|
@@ -1780,7 +1394,7 @@ function invokeClaudeCodeVerbose(prompt, yolo, model) {
|
|
|
1780
1394
|
});
|
|
1781
1395
|
child.on("close", (code) => {
|
|
1782
1396
|
handleExitCode(code, "Claude Code");
|
|
1783
|
-
|
|
1397
|
+
resolve2();
|
|
1784
1398
|
});
|
|
1785
1399
|
});
|
|
1786
1400
|
}
|
|
@@ -1886,8 +1500,8 @@ async function promptSelection(issues, limit, output) {
|
|
|
1886
1500
|
writeIssueList(output, issues, limit);
|
|
1887
1501
|
const rl = createInterface2({ input: process.stdin, output });
|
|
1888
1502
|
const answer = await new Promise(
|
|
1889
|
-
(
|
|
1890
|
-
Select issue (1-${issues.length}): `,
|
|
1503
|
+
(resolve2) => rl.question(`
|
|
1504
|
+
Select issue (1-${issues.length}): `, resolve2)
|
|
1891
1505
|
);
|
|
1892
1506
|
rl.close();
|
|
1893
1507
|
const n = Number.parseInt(answer.trim(), 10);
|
|
@@ -2043,13 +1657,13 @@ ${issue.body}`;
|
|
|
2043
1657
|
});
|
|
2044
1658
|
|
|
2045
1659
|
// src/commands/execute.ts
|
|
2046
|
-
import { readFileSync as
|
|
1660
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
2047
1661
|
import { Command as Command4 } from "commander";
|
|
2048
1662
|
function readStdin() {
|
|
2049
|
-
return new Promise((
|
|
1663
|
+
return new Promise((resolve2, reject) => {
|
|
2050
1664
|
const chunks = [];
|
|
2051
1665
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
2052
|
-
process.stdin.on("end", () =>
|
|
1666
|
+
process.stdin.on("end", () => resolve2(Buffer.concat(chunks).toString("utf8")));
|
|
2053
1667
|
process.stdin.on("error", reject);
|
|
2054
1668
|
});
|
|
2055
1669
|
}
|
|
@@ -2066,7 +1680,7 @@ async function resolvePrompt(options) {
|
|
|
2066
1680
|
if (hasFile) {
|
|
2067
1681
|
const path = options.filePrompt;
|
|
2068
1682
|
try {
|
|
2069
|
-
return
|
|
1683
|
+
return readFileSync2(path, "utf8");
|
|
2070
1684
|
} catch {
|
|
2071
1685
|
process.stderr.write(`Error: Cannot read file: ${path}
|
|
2072
1686
|
`);
|
|
@@ -2111,13 +1725,30 @@ function formatPrInfoContext(pr) {
|
|
|
2111
1725
|
return JSON.stringify(pr, null, 2);
|
|
2112
1726
|
}
|
|
2113
1727
|
function addAiOptions(cmd) {
|
|
2114
|
-
return cmd.
|
|
1728
|
+
return cmd.requiredOption("--with <executor>", "Executor to use: claude or codex").option("--model <string>", "Model identifier to pass to the executor").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--push", "Append instruction to commit and push changes after the AI finishes");
|
|
1729
|
+
}
|
|
1730
|
+
function resolveExecutor(withOption) {
|
|
1731
|
+
const executor = withOption.toLowerCase();
|
|
1732
|
+
if (executor !== "claude" && executor !== "codex") {
|
|
1733
|
+
process.stderr.write(`Error: --with must be 'claude' or 'codex', got '${withOption}'.
|
|
1734
|
+
`);
|
|
1735
|
+
process.exit(1);
|
|
1736
|
+
}
|
|
1737
|
+
return executor;
|
|
1738
|
+
}
|
|
1739
|
+
function invokeSelectedExecutor(prompt, executor, options) {
|
|
1740
|
+
if (executor === "codex") {
|
|
1741
|
+
invokeCodexCode(prompt, { yolo: true, model: options.model });
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
return invokeClaudeCode(prompt, { yolo: true, verbose: !options.silent, model: options.model });
|
|
2115
1745
|
}
|
|
2116
1746
|
var executeSonarCmd = addAiOptions(
|
|
2117
1747
|
new Command5("sonar").description(
|
|
2118
1748
|
"Check the current branch for a SonarCloud analysis and invoke the AI with the Sonar prompt and analysis URL"
|
|
2119
1749
|
)
|
|
2120
1750
|
).action(async (options) => {
|
|
1751
|
+
const executor = resolveExecutor(options.with);
|
|
2121
1752
|
let branch;
|
|
2122
1753
|
try {
|
|
2123
1754
|
branch = getCurrentBranch();
|
|
@@ -2157,12 +1788,7 @@ Current PR context from automata git get-pr-info --json:
|
|
|
2157
1788
|
${formatPrInfoContext(pr)}`,
|
|
2158
1789
|
options.push
|
|
2159
1790
|
);
|
|
2160
|
-
|
|
2161
|
-
invokeCodexCode(fullPrompt, { yolo: true });
|
|
2162
|
-
} else {
|
|
2163
|
-
const model = resolveModelOption(options);
|
|
2164
|
-
await invokeClaudeCode(fullPrompt, { yolo: true, verbose: options.verbose, model });
|
|
2165
|
-
}
|
|
1791
|
+
await invokeSelectedExecutor(fullPrompt, executor, options);
|
|
2166
1792
|
});
|
|
2167
1793
|
function formatComments(comments) {
|
|
2168
1794
|
return comments.map((c) => {
|
|
@@ -2176,6 +1802,7 @@ var executeFixCommentsCmd = addAiOptions(
|
|
|
2176
1802
|
"Fetch open review comments on the current PR and invoke the AI with the Fix-Comments prompt"
|
|
2177
1803
|
)
|
|
2178
1804
|
).action(async (options) => {
|
|
1805
|
+
const executor = resolveExecutor(options.with);
|
|
2179
1806
|
const result = resolveCurrentBranchComments();
|
|
2180
1807
|
if (!result.ok) {
|
|
2181
1808
|
if (result.kind === "error") {
|
|
@@ -2212,12 +1839,7 @@ Open review comments:
|
|
|
2212
1839
|
${formatComments(comments)}`,
|
|
2213
1840
|
options.push
|
|
2214
1841
|
);
|
|
2215
|
-
|
|
2216
|
-
invokeCodexCode(fullPrompt, { yolo: true });
|
|
2217
|
-
} else {
|
|
2218
|
-
const model = resolveModelOption(options);
|
|
2219
|
-
await invokeClaudeCode(fullPrompt, { yolo: true, verbose: options.verbose, model });
|
|
2220
|
-
}
|
|
1842
|
+
await invokeSelectedExecutor(fullPrompt, executor, options);
|
|
2221
1843
|
});
|
|
2222
1844
|
var executePromptCommand = new Command5("execute-prompt").description("Execute a configured custom prompt using an AI assistant").addCommand(executeSonarCmd).addCommand(executeFixCommentsCmd);
|
|
2223
1845
|
|