@ariso-ai/ivan 1.0.37 → 1.0.39
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 +8 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +52 -18
- package/dist/config.js.map +1 -1
- package/dist/services/address-task-executor.d.ts.map +1 -1
- package/dist/services/address-task-executor.js +4 -3
- package/dist/services/address-task-executor.js.map +1 -1
- package/dist/services/claude-cli-executor.d.ts +2 -0
- package/dist/services/claude-cli-executor.d.ts.map +1 -1
- package/dist/services/claude-cli-executor.js +113 -85
- package/dist/services/claude-cli-executor.js.map +1 -1
- package/dist/services/claude-executor.d.ts.map +1 -1
- package/dist/services/claude-executor.js +102 -16
- package/dist/services/claude-executor.js.map +1 -1
- package/dist/services/interjection-manager.d.ts +102 -0
- package/dist/services/interjection-manager.d.ts.map +1 -0
- package/dist/services/interjection-manager.js +332 -0
- package/dist/services/interjection-manager.js.map +1 -0
- package/dist/services/risk-analysis-executor.d.ts.map +1 -1
- package/dist/services/risk-analysis-executor.js +18 -16
- package/dist/services/risk-analysis-executor.js.map +1 -1
- package/dist/services/task-executor.d.ts.map +1 -1
- package/dist/services/task-executor.js +5 -4
- package/dist/services/task-executor.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
/**
|
|
5
|
+
* Captures additional context the user types while an Ivan command is running,
|
|
6
|
+
* similar to interjecting in an interactive Claude Code session.
|
|
7
|
+
*
|
|
8
|
+
* Input is read in raw mode with the echo rendered by this class on its own
|
|
9
|
+
* input line — a spinner redrawing its line would otherwise wipe the
|
|
10
|
+
* terminal's native echo, making typing invisible. While the user is
|
|
11
|
+
* composing, the active spinner (registered via claudeSpinner) is paused, and
|
|
12
|
+
* resumed when the input is submitted or cancelled.
|
|
13
|
+
*
|
|
14
|
+
* Each submitted line is either delivered immediately to a live listener (the
|
|
15
|
+
* SDK executor streams it into the running session mid-turn) or buffered until
|
|
16
|
+
* the next turn starts (the CLI executor applies it in an automatic follow-up
|
|
17
|
+
* turn).
|
|
18
|
+
*/
|
|
19
|
+
export class InterjectionManager {
|
|
20
|
+
static instance = null;
|
|
21
|
+
static getInstance() {
|
|
22
|
+
if (!InterjectionManager.instance) {
|
|
23
|
+
InterjectionManager.instance = new InterjectionManager();
|
|
24
|
+
}
|
|
25
|
+
return InterjectionManager.instance;
|
|
26
|
+
}
|
|
27
|
+
refCount = 0;
|
|
28
|
+
listening = false;
|
|
29
|
+
keypressAttached = false;
|
|
30
|
+
rawModeSet = false;
|
|
31
|
+
buffer = '';
|
|
32
|
+
pending = [];
|
|
33
|
+
liveListener = null;
|
|
34
|
+
hintShown = false;
|
|
35
|
+
activeSpinner = null;
|
|
36
|
+
pausedSpinner = null;
|
|
37
|
+
keypressHandler = (str, key) => this.handleKeypress(str, key);
|
|
38
|
+
selfWrite = false;
|
|
39
|
+
inputLineVisible = false;
|
|
40
|
+
externalMidLine = false;
|
|
41
|
+
unhookStreams = null;
|
|
42
|
+
/** Interjections require an interactive terminal. */
|
|
43
|
+
isAvailable() {
|
|
44
|
+
return Boolean(process.stdin.isTTY);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Begin capturing keystrokes. Ref-counted so overlapping turns can
|
|
48
|
+
* start/stop freely; the listener is only torn down when the outermost
|
|
49
|
+
* stop() is reached.
|
|
50
|
+
*/
|
|
51
|
+
start(quiet = false) {
|
|
52
|
+
if (!this.isAvailable())
|
|
53
|
+
return;
|
|
54
|
+
this.refCount++;
|
|
55
|
+
if (this.listening)
|
|
56
|
+
return;
|
|
57
|
+
this.listening = true;
|
|
58
|
+
if (!this.keypressAttached) {
|
|
59
|
+
readline.emitKeypressEvents(process.stdin);
|
|
60
|
+
this.keypressAttached = true;
|
|
61
|
+
}
|
|
62
|
+
if (typeof process.stdin.setRawMode === 'function') {
|
|
63
|
+
process.stdin.setRawMode(true);
|
|
64
|
+
this.rawModeSet = true;
|
|
65
|
+
}
|
|
66
|
+
process.stdin.on('keypress', this.keypressHandler);
|
|
67
|
+
process.stdin.resume();
|
|
68
|
+
this.hookOutputStreams();
|
|
69
|
+
if (!this.hintShown && !quiet) {
|
|
70
|
+
console.log(chalk.cyan('💬 Type a message and press Enter at any time to give Ivan additional context'));
|
|
71
|
+
this.hintShown = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Stop capturing keystrokes once all active turns have finished. */
|
|
75
|
+
stop() {
|
|
76
|
+
if (!this.isAvailable())
|
|
77
|
+
return;
|
|
78
|
+
if (this.refCount > 0)
|
|
79
|
+
this.refCount--;
|
|
80
|
+
if (this.refCount === 0 && this.listening) {
|
|
81
|
+
this.listening = false;
|
|
82
|
+
process.stdin.removeListener('keypress', this.keypressHandler);
|
|
83
|
+
if (this.rawModeSet) {
|
|
84
|
+
process.stdin.setRawMode(false);
|
|
85
|
+
this.rawModeSet = false;
|
|
86
|
+
}
|
|
87
|
+
// Release stdin so the process can exit and later prompts (inquirer)
|
|
88
|
+
// get a clean stream.
|
|
89
|
+
process.stdin.pause();
|
|
90
|
+
// Abandon any partially typed input and restore the spinner.
|
|
91
|
+
if (this.buffer) {
|
|
92
|
+
this.buffer = '';
|
|
93
|
+
this.clearInputLine();
|
|
94
|
+
}
|
|
95
|
+
this.unhookStreams?.();
|
|
96
|
+
this.unhookStreams = null;
|
|
97
|
+
this.resumeSpinner();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* While the user is composing, the `💬 > ` echo owns the cursor row with no
|
|
102
|
+
* trailing newline — anything the executors print (tool-usage lines,
|
|
103
|
+
* streamed CLI output) would land right after the typed text and shove the
|
|
104
|
+
* echo onto a new line. Intercept stdout/stderr so external output clears
|
|
105
|
+
* the echo, prints on its own line, and the echo is redrawn beneath it.
|
|
106
|
+
*/
|
|
107
|
+
hookOutputStreams() {
|
|
108
|
+
if (this.unhookStreams)
|
|
109
|
+
return;
|
|
110
|
+
const hook = (stream) => {
|
|
111
|
+
const original = stream.write.bind(stream);
|
|
112
|
+
const manager = this;
|
|
113
|
+
stream.write = function (chunk, encoding, callback) {
|
|
114
|
+
if (manager.selfWrite || manager.buffer.length === 0) {
|
|
115
|
+
return original(chunk, encoding, callback);
|
|
116
|
+
}
|
|
117
|
+
if (manager.inputLineVisible) {
|
|
118
|
+
manager.selfWrite = true;
|
|
119
|
+
original('\r\x1b[2K');
|
|
120
|
+
manager.selfWrite = false;
|
|
121
|
+
manager.inputLineVisible = false;
|
|
122
|
+
}
|
|
123
|
+
const result = original(chunk, encoding, callback);
|
|
124
|
+
const text = typeof chunk === 'string'
|
|
125
|
+
? chunk
|
|
126
|
+
: globalThis.Buffer.from(chunk).toString('utf8');
|
|
127
|
+
if (text.length > 0) {
|
|
128
|
+
manager.externalMidLine = !text.endsWith('\n');
|
|
129
|
+
if (!manager.externalMidLine)
|
|
130
|
+
manager.render();
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
};
|
|
134
|
+
return () => {
|
|
135
|
+
stream.write = original;
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
const unhookStdout = hook(process.stdout);
|
|
139
|
+
const unhookStderr = hook(process.stderr);
|
|
140
|
+
this.unhookStreams = () => {
|
|
141
|
+
unhookStdout();
|
|
142
|
+
unhookStderr();
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Registers the spinner currently rendering so it can be paused while the
|
|
147
|
+
* user types (its line redraws would erase the input echo otherwise).
|
|
148
|
+
*/
|
|
149
|
+
attachSpinner(spinner) {
|
|
150
|
+
this.activeSpinner = spinner;
|
|
151
|
+
}
|
|
152
|
+
detachSpinner(spinner) {
|
|
153
|
+
if (this.activeSpinner === spinner)
|
|
154
|
+
this.activeSpinner = null;
|
|
155
|
+
if (this.pausedSpinner === spinner)
|
|
156
|
+
this.pausedSpinner = null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Register a handler that receives interjections the moment they are typed
|
|
160
|
+
* (used by the SDK executor to stream them into the running session).
|
|
161
|
+
* Returns a release function; after release, new input buffers again.
|
|
162
|
+
*/
|
|
163
|
+
setLiveListener(listener) {
|
|
164
|
+
this.liveListener = listener;
|
|
165
|
+
return () => {
|
|
166
|
+
if (this.liveListener === listener)
|
|
167
|
+
this.liveListener = null;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/** Returns and clears any buffered interjections. */
|
|
171
|
+
drainPending() {
|
|
172
|
+
return this.pending.splice(0);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Puts interjections back at the front of the buffer — used when a turn
|
|
176
|
+
* ends before delivering input it had already accepted.
|
|
177
|
+
*/
|
|
178
|
+
requeue(texts) {
|
|
179
|
+
if (texts.length > 0)
|
|
180
|
+
this.pending.unshift(...texts);
|
|
181
|
+
}
|
|
182
|
+
hasPending() {
|
|
183
|
+
return this.pending.length > 0;
|
|
184
|
+
}
|
|
185
|
+
handleKeypress(str, key = {}) {
|
|
186
|
+
if (key.ctrl && key.name === 'c') {
|
|
187
|
+
// Raw mode suppresses the terminal's own SIGINT; re-emit it so the
|
|
188
|
+
// executors' Ctrl+C handlers still fire.
|
|
189
|
+
if (this.rawModeSet)
|
|
190
|
+
process.kill(process.pid, 'SIGINT');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
194
|
+
this.submit();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (key.name === 'backspace') {
|
|
198
|
+
if (this.buffer) {
|
|
199
|
+
this.buffer = this.buffer.slice(0, -1);
|
|
200
|
+
this.render();
|
|
201
|
+
}
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (key.ctrl && key.name === 'u') {
|
|
205
|
+
this.buffer = '';
|
|
206
|
+
this.render();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (key.name === 'escape') {
|
|
210
|
+
this.buffer = '';
|
|
211
|
+
this.clearInputLine();
|
|
212
|
+
this.resumeSpinner();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (key.ctrl || key.meta)
|
|
216
|
+
return;
|
|
217
|
+
// Printable input only (pasted text arrives as a multi-char str).
|
|
218
|
+
if (!str)
|
|
219
|
+
return;
|
|
220
|
+
const printable = Array.from(str)
|
|
221
|
+
.filter((ch) => {
|
|
222
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
223
|
+
return code >= 0x20 && code !== 0x7f;
|
|
224
|
+
})
|
|
225
|
+
.join('');
|
|
226
|
+
if (!printable)
|
|
227
|
+
return;
|
|
228
|
+
if (this.buffer.length === 0)
|
|
229
|
+
this.pauseSpinner();
|
|
230
|
+
this.buffer += printable;
|
|
231
|
+
this.render();
|
|
232
|
+
}
|
|
233
|
+
submit() {
|
|
234
|
+
const text = this.buffer.trim();
|
|
235
|
+
this.buffer = '';
|
|
236
|
+
this.clearInputLine();
|
|
237
|
+
if (text) {
|
|
238
|
+
if (this.liveListener) {
|
|
239
|
+
this.liveListener(text);
|
|
240
|
+
console.log(chalk.cyan('💬 Context sent to Claude — it will be incorporated into the current task'));
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
this.pending.push(text);
|
|
244
|
+
console.log(chalk.cyan('💬 Context queued — Ivan will include it in the next turn'));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
this.resumeSpinner();
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Redraws the input line. The spinner is paused while composing, so this
|
|
251
|
+
* line owns the cursor row; hooked stdout/stderr writes clear and redraw it
|
|
252
|
+
* around any external output so the echo always sits on the bottom line.
|
|
253
|
+
*/
|
|
254
|
+
render() {
|
|
255
|
+
if (!this.listening)
|
|
256
|
+
return;
|
|
257
|
+
this.selfWrite = true;
|
|
258
|
+
// If external output left the cursor mid-line, move past it instead of
|
|
259
|
+
// overwriting the partial line.
|
|
260
|
+
if (this.externalMidLine) {
|
|
261
|
+
process.stderr.write('\n');
|
|
262
|
+
this.externalMidLine = false;
|
|
263
|
+
}
|
|
264
|
+
process.stderr.write('\r\x1b[2K' + chalk.cyan('💬 > ') + this.buffer);
|
|
265
|
+
this.selfWrite = false;
|
|
266
|
+
this.inputLineVisible = true;
|
|
267
|
+
}
|
|
268
|
+
clearInputLine() {
|
|
269
|
+
this.selfWrite = true;
|
|
270
|
+
process.stderr.write('\r\x1b[2K');
|
|
271
|
+
this.selfWrite = false;
|
|
272
|
+
this.inputLineVisible = false;
|
|
273
|
+
}
|
|
274
|
+
pauseSpinner() {
|
|
275
|
+
const spinner = this.activeSpinner;
|
|
276
|
+
if (spinner && spinner.isSpinning) {
|
|
277
|
+
this.pausedSpinner = spinner;
|
|
278
|
+
spinner.stop();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
resumeSpinner() {
|
|
282
|
+
// Only restart a spinner we paused ourselves that is still the active
|
|
283
|
+
// one — if the executor finished it (succeed/fail) while the user was
|
|
284
|
+
// typing, detachSpinner has already cleared it.
|
|
285
|
+
if (this.pausedSpinner && this.pausedSpinner === this.activeSpinner) {
|
|
286
|
+
this.pausedSpinner.start();
|
|
287
|
+
}
|
|
288
|
+
this.pausedSpinner = null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Creates a spinner for phases where a Claude turn runs and interjections are
|
|
293
|
+
* being captured: stdin stays readable (no discardStdin) and the spinner is
|
|
294
|
+
* registered with the InterjectionManager so it pauses while the user types.
|
|
295
|
+
* Finishing the spinner (succeed/fail/warn/info/stopAndPersist) detaches it;
|
|
296
|
+
* plain stop() is left unwrapped because the manager itself uses it to pause.
|
|
297
|
+
*/
|
|
298
|
+
export function claudeSpinner(text) {
|
|
299
|
+
const spinner = ora({ text, discardStdin: false });
|
|
300
|
+
const manager = InterjectionManager.getInstance();
|
|
301
|
+
manager.attachSpinner(spinner);
|
|
302
|
+
const finish = (fn) => (...args) => {
|
|
303
|
+
manager.detachSpinner(spinner);
|
|
304
|
+
return fn(...args);
|
|
305
|
+
};
|
|
306
|
+
spinner.succeed = finish(spinner.succeed.bind(spinner));
|
|
307
|
+
spinner.fail = finish(spinner.fail.bind(spinner));
|
|
308
|
+
spinner.warn = finish(spinner.warn.bind(spinner));
|
|
309
|
+
spinner.info = finish(spinner.info.bind(spinner));
|
|
310
|
+
spinner.stopAndPersist = finish(spinner.stopAndPersist.bind(spinner));
|
|
311
|
+
return spinner;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Appends buffered interjections to the initial prompt of the next turn.
|
|
315
|
+
*/
|
|
316
|
+
export function appendInterjections(prompt, texts) {
|
|
317
|
+
if (texts.length === 0)
|
|
318
|
+
return prompt;
|
|
319
|
+
return `${prompt}\n\nAdditional context from the user (provided while Ivan was running — treat it as part of the task):\n${texts
|
|
320
|
+
.map((t) => `- ${t}`)
|
|
321
|
+
.join('\n')}`;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Formats interjections delivered as their own message — either streamed into
|
|
325
|
+
* a running SDK session or sent as a CLI follow-up turn.
|
|
326
|
+
*/
|
|
327
|
+
export function interjectionMessage(texts) {
|
|
328
|
+
return `The user interjected with additional context while you were working:\n${texts
|
|
329
|
+
.map((t) => `- ${t}`)
|
|
330
|
+
.join('\n')}\nIncorporate this guidance into the task you are working on, adjusting anything you have already done if needed.`;
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=interjection-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interjection-manager.js","sourceRoot":"","sources":["../../src/services/interjection-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"risk-analysis-executor.d.ts","sourceRoot":"","sources":["../../src/services/risk-analysis-executor.ts"],"names":[],"mappings":"AAmGA,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAqB;;IAOxC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"risk-analysis-executor.d.ts","sourceRoot":"","sources":["../../src/services/risk-analysis-executor.ts"],"names":[],"mappings":"AAmGA,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAqB;;IAOxC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAiF7C,UAAU;CAqCzB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import ora from 'ora';
|
|
3
2
|
import { ExecutorFactory } from './executor-factory.js';
|
|
4
3
|
import { createRepositoryManager } from './service-factory.js';
|
|
4
|
+
import { claudeSpinner } from './interjection-manager.js';
|
|
5
5
|
const RISK_ANALYSIS_SYSTEM_PROMPT = `You are a principal engineer performing a pre-deployment risk analysis of a set of proposed changes.
|
|
6
6
|
|
|
7
7
|
Your job is NOT to review code style or suggest improvements — it is to identify what could go wrong when these changes ship, how likely that is, how bad the blast radius would be, and what mitigations should be in place before rollout.
|
|
@@ -108,28 +108,30 @@ export class RiskAnalysisExecutor {
|
|
|
108
108
|
// Suppress the executor's per-turn logging so the tree output stays readable
|
|
109
109
|
this.claudeExecutor.quietMode = true;
|
|
110
110
|
const changesSection = buildChangesSection(changes);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
// Run all dimensions concurrently. Individual per-dimension spinners
|
|
112
|
+
// aren't used here since ora/InterjectionManager only support a single
|
|
113
|
+
// active spinner at a time — a batch spinner covers the parallel work.
|
|
114
|
+
const batchSpinner = claudeSpinner(`Analyzing ${RISK_DIMENSIONS.length} risk dimensions in parallel`).start();
|
|
115
|
+
let dimensionResults;
|
|
116
|
+
try {
|
|
117
|
+
dimensionResults = await Promise.all(RISK_DIMENSIONS.map(async (dimension) => {
|
|
116
118
|
const result = await this.claudeExecutor.executeTurn(`${changesSection}\n\n${dimension.prompt}`, workingDir, {
|
|
117
119
|
systemPrompt: RISK_ANALYSIS_SYSTEM_PROMPT,
|
|
118
120
|
readOnly: true,
|
|
119
121
|
permissionMode: 'plan'
|
|
120
122
|
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
catch (err) {
|
|
128
|
-
spinner.fail(`${branch} ${dimension.label}`);
|
|
129
|
-
throw err;
|
|
123
|
+
return { label: dimension.label, analysis: result.lastMessage };
|
|
124
|
+
}));
|
|
125
|
+
batchSpinner.succeed(`Completed ${RISK_DIMENSIONS.length} risk dimension analyses`);
|
|
126
|
+
for (const { label } of dimensionResults) {
|
|
127
|
+
console.log(chalk.gray(` ✔ ${label}`));
|
|
130
128
|
}
|
|
131
129
|
}
|
|
132
|
-
|
|
130
|
+
catch (err) {
|
|
131
|
+
batchSpinner.fail('Risk dimension analysis failed');
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
const synthesisSpinner = claudeSpinner('Synthesizing final risk analysis').start();
|
|
133
135
|
let finalReport;
|
|
134
136
|
try {
|
|
135
137
|
finalReport = await this.synthesize(changes, dimensionResults, workingDir);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"risk-analysis-executor.js","sourceRoot":"","sources":["../../src/services/risk-analysis-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"risk-analysis-executor.js","sourceRoot":"","sources":["../../src/services/risk-analysis-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-executor.d.ts","sourceRoot":"","sources":["../../src/services/task-executor.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"task-executor.d.ts","sourceRoot":"","sources":["../../src/services/task-executor.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAc/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAOxE,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,cAAc,CAAgC;IACtD,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,iBAAiB,CAAU;;IAanC;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAmBvB;;;;OAIG;YACW,iBAAiB;IA8B/B,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,gBAAgB;IAOxB;;;;OAIG;YACW,iBAAiB;IAkI/B;;;;OAIG;YACW,aAAa;IA2DrB,eAAe,CACnB,aAAa,GAAE,OAAe,EAC9B,UAAU,CAAC,EAAE,MAAM,EACnB,IAAI,GAAE,aAAwB,EAC9B,UAAU,GAAE,OAAe,EAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC;YAyRF,0BAA0B;YA6D1B,WAAW;YAwMX,wBAAwB;IAwNhC,6BAA6B,CACjC,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC;CAsJjB"}
|
|
@@ -7,6 +7,7 @@ import { ConfigManager } from '../config.js';
|
|
|
7
7
|
import { AddressTaskExecutor } from './address-task-executor.js';
|
|
8
8
|
import { createGitManager, createPRService, createRepositoryManager } from './service-factory.js';
|
|
9
9
|
import { PromptRewriter } from './prompt-rewriter.js';
|
|
10
|
+
import { claudeSpinner } from './interjection-manager.js';
|
|
10
11
|
import { CollaborativeExecutor } from './collaborative-executor.js';
|
|
11
12
|
const SELF_REVIEW_PROMPT = "ok review the changes in the current branch carefully. make sure it follows repo convention, reusable component/utils/etc. don't over-engineer, dont reinvent.";
|
|
12
13
|
export class TaskExecutor {
|
|
@@ -144,7 +145,7 @@ export class TaskExecutor {
|
|
|
144
145
|
// Prepare prompt for Claude to fix the errors
|
|
145
146
|
const fixPrompt = `Fix the following pre-commit hook errors:\n\n${errorDetails}\n\nPlease fix all TypeScript errors, linting issues, and any other problems preventing the commit.`;
|
|
146
147
|
if (!quiet)
|
|
147
|
-
spinner =
|
|
148
|
+
spinner = claudeSpinner('Running Claude to fix pre-commit errors...').start();
|
|
148
149
|
try {
|
|
149
150
|
// Run Claude to fix the errors (pass session ID to maintain context)
|
|
150
151
|
const fixResult = await this.getClaudeExecutor().executeTask(fixPrompt, executionPath, sessionId);
|
|
@@ -186,7 +187,7 @@ export class TaskExecutor {
|
|
|
186
187
|
async runSelfReview(executionPath, taskUuid, quiet, sessionId) {
|
|
187
188
|
let spinner = quiet
|
|
188
189
|
? null
|
|
189
|
-
:
|
|
190
|
+
: claudeSpinner('Running self-review with Claude Code...').start();
|
|
190
191
|
const reviewResult = await this.getClaudeExecutor().executeTask(SELF_REVIEW_PROMPT, executionPath, sessionId);
|
|
191
192
|
sessionId = reviewResult.sessionId;
|
|
192
193
|
if (spinner)
|
|
@@ -482,7 +483,7 @@ export class TaskExecutor {
|
|
|
482
483
|
spinner.succeed(`Worktree created: ${worktreePath}`);
|
|
483
484
|
await this.jobManager.updateTaskBranch(task.uuid, branchName);
|
|
484
485
|
if (!quiet)
|
|
485
|
-
spinner =
|
|
486
|
+
spinner = claudeSpinner('Executing task with Claude Code...').start();
|
|
486
487
|
// Append repository-specific instructions to the task if they exist
|
|
487
488
|
let taskWithInstructions = task.description;
|
|
488
489
|
if (this.repoInstructions) {
|
|
@@ -649,7 +650,7 @@ export class TaskExecutor {
|
|
|
649
650
|
if (spinner)
|
|
650
651
|
spinner.succeed('Task marked as active');
|
|
651
652
|
if (!quiet)
|
|
652
|
-
spinner =
|
|
653
|
+
spinner = claudeSpinner('Executing task with Claude Code...').start();
|
|
653
654
|
// Append repository-specific instructions to the task if they exist
|
|
654
655
|
let taskWithInstructions = task.description;
|
|
655
656
|
if (this.repoInstructions) {
|