diffsplain 0.8.3 → 0.10.0
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 +26 -5
- package/dist/assets/{angular-html-e4D_THVy.js → angular-html-2u-u5H-N.js} +1 -1
- package/dist/assets/{angular-ts-Cx3870JF.js → angular-ts-4_HVGlKp.js} +1 -1
- package/dist/assets/{apl-DZuu22Wh.js → apl-icaNWZX3.js} +1 -1
- package/dist/assets/{astro-K-NemFAk.js → astro-HvIOE4vz.js} +1 -1
- package/dist/assets/{blade-ConbVu3U.js → blade-BpKJV8ev.js} +1 -1
- package/dist/assets/{c-DtmaBqln.js → c-BNvtxyRQ.js} +1 -1
- package/dist/assets/{cobol-BMHoPOfB.js → cobol-8js4hfxa.js} +1 -1
- package/dist/assets/{coffee-DfweJ19Y.js → coffee-DXg_piQ9.js} +1 -1
- package/dist/assets/{cpp-CPh_zIOW.js → cpp-BZDFAjyh.js} +1 -1
- package/dist/assets/{crystal-CAEX7C1J.js → crystal-aCF3ira4.js} +1 -1
- package/dist/assets/{css-C8ihGqCA.js → css-DfRtUkhE.js} +1 -1
- package/dist/assets/{edge-DVZPwQ9j.js → edge-vS6_AmQv.js} +1 -1
- package/dist/assets/{elixir-D03TKulP.js → elixir-Ce0nUHSq.js} +1 -1
- package/dist/assets/{elm-JUX-2xVV.js → elm-DmaeyizZ.js} +1 -1
- package/dist/assets/{erb-HbktAFZJ.js → erb-DD6OUyvt.js} +1 -1
- package/dist/assets/{git-rebase-Ccd_ELAP.js → git-rebase-HbJMn7iS.js} +1 -1
- package/dist/assets/{glimmer-js-BcinUfi2.js → glimmer-js-BRuqbNaV.js} +1 -1
- package/dist/assets/{glimmer-ts-DuN2UkN9.js → glimmer-ts-ZBpkdEEA.js} +1 -1
- package/dist/assets/{glsl-BWmCEPsR.js → glsl-CrQ4GScf.js} +1 -1
- package/dist/assets/{graphql-DJGYoBFW.js → graphql-Tn6PBdQY.js} +1 -1
- package/dist/assets/{hack-ZPqBE9w3.js → hack-CoApvrbo.js} +1 -1
- package/dist/assets/{haml-CZDZk6Gw.js → haml-COKq8Xjp.js} +1 -1
- package/dist/assets/{handlebars-d23PDS0n.js → handlebars-CAna2DTA.js} +1 -1
- package/dist/assets/{html-BgzX2DyB.js → html-Ch4xJ7YF.js} +1 -1
- package/dist/assets/{html-derivative-Bq6M-ZFw.js → html-derivative-0ITK-MAI.js} +1 -1
- package/dist/assets/{http-DVhMl_cW.js → http-DiMWQ8Qr.js} +1 -1
- package/dist/assets/{hurl-CbspBAqF.js → hurl-OcXymC0J.js} +1 -1
- package/dist/assets/index-BmcCug2M.js +1574 -0
- package/dist/assets/index-CADUNiTy.css +2 -0
- package/dist/assets/{java--YZbq0z2.js → java-CFb3qN4r.js} +1 -1
- package/dist/assets/{javascript-cvRuifRJ.js → javascript-CRmk2JrF.js} +1 -1
- package/dist/assets/{jinja-BeZmr3LP.js → jinja-Da6lDTEy.js} +1 -1
- package/dist/assets/{jison-qrpGZaxs.js → jison-Bnivzmtu.js} +1 -1
- package/dist/assets/{json-4xUzsNJn.js → json-m8vJP_KK.js} +1 -1
- package/dist/assets/{jsx-BlXrTlSg.js → jsx-C3HX_Sbu.js} +1 -1
- package/dist/assets/{julia-IN3jzmBc.js → julia-Ckg-wSHA.js} +1 -1
- package/dist/assets/{just-C_50nLQH.js → just-DCjIAyvO.js} +1 -1
- package/dist/assets/{latex-Cd-_2IS1.js → latex-CrYSm4pl.js} +1 -1
- package/dist/assets/{liquid-CEJf6Xg5.js → liquid-MQUFSPYU.js} +1 -1
- package/dist/assets/{lua-BlaV_n8i.js → lua-DcuzJJ77.js} +1 -1
- package/dist/assets/{marko-Cb-NPdc_.js → marko-4JNmQaB4.js} +1 -1
- package/dist/assets/{mdc-Dt4ywVAS.js → mdc-C_j8HvRL.js} +1 -1
- package/dist/assets/{nginx-C_6SKViP.js → nginx-ta3Gn1HE.js} +1 -1
- package/dist/assets/{nim-BbkBjoeZ.js → nim-BwWLst9M.js} +1 -1
- package/dist/assets/{perl-CYPU6TVa.js → perl-DfW7Uq5O.js} +1 -1
- package/dist/assets/{php-B6Oqilrc.js → php-DGf5G3Cf.js} +1 -1
- package/dist/assets/{pug-C9Poo2KU.js → pug-CWI-NaYz.js} +1 -1
- package/dist/assets/{qml-DkMURMPv.js → qml-Csblgh7U.js} +1 -1
- package/dist/assets/{r-Bm-Gfi0p.js → r-QGooaGDI.js} +1 -1
- package/dist/assets/{razor-B0LqOok3.js → razor-Dp9ihLYf.js} +1 -1
- package/dist/assets/{regexp-jAbMHzwe.js → regexp-DwUnLcVr.js} +1 -1
- package/dist/assets/{rst-BlWHfg8c.js → rst-BY8GIwDJ.js} +1 -1
- package/dist/assets/{ruby-Bt5lKwPL.js → ruby-VgzI9htT.js} +1 -1
- package/dist/assets/{sas-TuY2-8EF.js → sas-DYLsm-0j.js} +1 -1
- package/dist/assets/{scss-Dh1SsWlK.js → scss-tIFkeUQX.js} +1 -1
- package/dist/assets/{shellscript-CThiwmnp.js → shellscript-CHjuQ4Pl.js} +1 -1
- package/dist/assets/{shellsession-DQ5iRUWd.js → shellsession-Bv0S0hj9.js} +1 -1
- package/dist/assets/{soy-BfM-BrZG.js → soy-D6U1tZod.js} +1 -1
- package/dist/assets/{sql-F617W1uN.js → sql-CGz8kjKv.js} +1 -1
- package/dist/assets/{stata-Ctov3ki2.js → stata-C9ytERUq.js} +1 -1
- package/dist/assets/{surrealql-C-i2bJGB.js → surrealql-DRfRnaYu.js} +1 -1
- package/dist/assets/{svelte-oZT41pTl.js → svelte-wYnk_1sI.js} +1 -1
- package/dist/assets/{templ-CxX9Hf3e.js → templ-DWrGVE0u.js} +1 -1
- package/dist/assets/{tex-GyzJq8GJ.js → tex-CYTzoUJh.js} +1 -1
- package/dist/assets/{ts-tags-BugzKu0x.js → ts-tags-1TIXEGea.js} +1 -1
- package/dist/assets/{tsx-DLqwDEUq.js → tsx-a3BoAoOh.js} +1 -1
- package/dist/assets/{twig-DADiR9Vq.js → twig-e3dvNv6o.js} +1 -1
- package/dist/assets/{typescript-BlDIG_FO.js → typescript-BBhnpnTf.js} +1 -1
- package/dist/assets/{vue-COXmmg2A.js → vue-DzzVbu9q.js} +1 -1
- package/dist/assets/{vue-html-Cy_3KYj1.js → vue-html-quBNv38K.js} +1 -1
- package/dist/assets/{vue-vine-CUqOY8dY.js → vue-vine-CDuR69FE.js} +1 -1
- package/dist/assets/{xml-C9JY7Wf6.js → xml-DMifOLSe.js} +1 -1
- package/dist/assets/{xsl-DBCl8hSu.js → xsl-D8Ef-5HK.js} +1 -1
- package/dist/assets/{yaml-BbMebKkS.js → yaml-5c38gpmA.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +12 -3
- package/scripts/agent-config.mjs +184 -0
- package/scripts/agent-exclusions.mjs +10 -0
- package/scripts/agent-review.mjs +94 -0
- package/scripts/build-diff-data.mjs +211 -49
- package/scripts/cli-args.mjs +63 -9
- package/scripts/coding-agents.mjs +255 -77
- package/scripts/generate-summaries.mjs +872 -426
- package/scripts/local-target.mjs +106 -0
- package/scripts/present.mjs +333 -117
- package/scripts/review-chat-context.mjs +510 -0
- package/scripts/review-chat-controller.mjs +691 -0
- package/scripts/review-chat-provider.mjs +363 -0
- package/scripts/review-chat.mjs +8 -0
- package/scripts/serve-built.mjs +245 -27
- package/scripts/summary-path.mjs +32 -11
- package/dist/assets/index-C2p_1iAk.css +0 -2
- package/dist/assets/index-divlsuKs.js +0 -1568
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import {
|
|
3
|
+
mkdtempSync,
|
|
4
|
+
rmSync,
|
|
5
|
+
writeFileSync,
|
|
6
|
+
} from 'node:fs';
|
|
7
|
+
import { tmpdir } from 'node:os';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import {
|
|
10
|
+
agentCommand,
|
|
11
|
+
parseAgentResponse,
|
|
12
|
+
} from './coding-agents.mjs';
|
|
13
|
+
|
|
14
|
+
const maximumProviderOutputBytes = 1024 * 1024;
|
|
15
|
+
const forcedChildKillDelayMs = 250;
|
|
16
|
+
const noChange = () => {};
|
|
17
|
+
|
|
18
|
+
function removeTemporary(path) {
|
|
19
|
+
rmSync(path, { force: true, recursive: true });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function cancelledError() {
|
|
23
|
+
return new Error('The chat request was cancelled.');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function spawnProcess(invocation) {
|
|
27
|
+
try {
|
|
28
|
+
return {
|
|
29
|
+
child: spawn(invocation.command, invocation.args, {
|
|
30
|
+
cwd: invocation.cwd,
|
|
31
|
+
env: invocation.env,
|
|
32
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
} catch (error) {
|
|
36
|
+
return { error };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function childOutput(chunks) {
|
|
41
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function childStatus(status, signal) {
|
|
45
|
+
return status ?? signal;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function childDiagnosticSuffix(stdout, stderr) {
|
|
49
|
+
const detail = stderr.trim() || stdout.trim();
|
|
50
|
+
return detail ? `: ${detail.slice(-600)}` : '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function childFailure(agent, status, signal, stdout, stderr) {
|
|
54
|
+
const observedStatus = childStatus(status, signal);
|
|
55
|
+
const suffix = childDiagnosticSuffix(stdout, stderr);
|
|
56
|
+
const error = new Error(`${agent} exited with status ${observedStatus}${suffix}`);
|
|
57
|
+
error.lifecycleMessage = `${agent} exited with status ${observedStatus}`;
|
|
58
|
+
return error;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function aborted(signal) {
|
|
62
|
+
return Boolean(signal?.aborted);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function successfulExit(status, signal) {
|
|
66
|
+
return status === 0 && !signal;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function closeError(execution, status, signal) {
|
|
70
|
+
if (aborted(execution.signal)) return cancelledError();
|
|
71
|
+
if (successfulExit(status, signal)) return undefined;
|
|
72
|
+
return childFailure(
|
|
73
|
+
execution.agent,
|
|
74
|
+
status,
|
|
75
|
+
signal,
|
|
76
|
+
childOutput(execution.stdout),
|
|
77
|
+
childOutput(execution.stderr),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function providerAgent(options) {
|
|
82
|
+
const agent = options?.agent;
|
|
83
|
+
if (!agent) throw new Error('Chat provider needs a coding agent');
|
|
84
|
+
return agent;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function providerBinary(options, agent) {
|
|
88
|
+
return options.binary || agent;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function providerEnvironment(options) {
|
|
92
|
+
return options.env || process.env;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function providerOptions(options) {
|
|
96
|
+
const agent = providerAgent(options);
|
|
97
|
+
return {
|
|
98
|
+
agent,
|
|
99
|
+
binary: providerBinary(options, agent),
|
|
100
|
+
model: options.model,
|
|
101
|
+
reasoning: options.reasoning,
|
|
102
|
+
accessMode: options.accessMode,
|
|
103
|
+
env: providerEnvironment(options),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function temporaryRequest() {
|
|
108
|
+
const temporary = mkdtempSync(join(tmpdir(), 'diffsplain-review-chat-'));
|
|
109
|
+
return {
|
|
110
|
+
temporary,
|
|
111
|
+
inputPath: join(temporary, 'input.json'),
|
|
112
|
+
schemaPath: join(temporary, 'schema.json'),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function writeRequest(paths, request) {
|
|
117
|
+
writeFileSync(paths.inputPath, JSON.stringify(request));
|
|
118
|
+
writeFileSync(paths.schemaPath, JSON.stringify(request.responseSchema));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function providerInvocation(options, request, paths) {
|
|
122
|
+
return agentCommand({
|
|
123
|
+
agent: options.agent,
|
|
124
|
+
binary: options.binary,
|
|
125
|
+
model: options.model,
|
|
126
|
+
reasoning: options.reasoning,
|
|
127
|
+
prompt: request.prompt,
|
|
128
|
+
schema: request.responseSchema,
|
|
129
|
+
schemaPath: paths.schemaPath,
|
|
130
|
+
inputPath: paths.inputPath,
|
|
131
|
+
accessMode: options.accessMode,
|
|
132
|
+
env: options.env,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function preparedProviderRequest(options, request) {
|
|
137
|
+
const paths = temporaryRequest();
|
|
138
|
+
try {
|
|
139
|
+
writeRequest(paths, request);
|
|
140
|
+
return { temporary: paths.temporary, invocation: providerInvocation(options, request, paths) };
|
|
141
|
+
} catch (error) {
|
|
142
|
+
removeTemporary(paths.temporary);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
class ChildExecution {
|
|
148
|
+
constructor({ invocation, input, agent, signal, temporary }) {
|
|
149
|
+
this.invocation = invocation;
|
|
150
|
+
this.input = input;
|
|
151
|
+
this.agent = agent;
|
|
152
|
+
this.signal = signal;
|
|
153
|
+
this.temporary = temporary;
|
|
154
|
+
this.child = undefined;
|
|
155
|
+
this.settled = false;
|
|
156
|
+
this.closed = false;
|
|
157
|
+
this.forceKillTimer = undefined;
|
|
158
|
+
this.stdout = [];
|
|
159
|
+
this.stderr = [];
|
|
160
|
+
this.outputBytes = 0;
|
|
161
|
+
this.promise = new Promise((resolvePromise, rejectPromise) => {
|
|
162
|
+
this.resolvePromise = resolvePromise;
|
|
163
|
+
this.rejectPromise = rejectPromise;
|
|
164
|
+
});
|
|
165
|
+
this.finished = new Promise((resolveFinished) => {
|
|
166
|
+
this.resolveFinished = resolveFinished;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
open() {
|
|
171
|
+
const result = spawnProcess(this.invocation);
|
|
172
|
+
if (result.error) {
|
|
173
|
+
this.reject(result.error);
|
|
174
|
+
this.finishClose();
|
|
175
|
+
}
|
|
176
|
+
else this.openChild(result.child);
|
|
177
|
+
return {
|
|
178
|
+
promise: this.promise,
|
|
179
|
+
finished: this.finished,
|
|
180
|
+
cancel: this.cancel.bind(this),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
openChild(child) {
|
|
185
|
+
this.child = child;
|
|
186
|
+
this.listen();
|
|
187
|
+
this.writeInput();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
listen() {
|
|
191
|
+
this.child.stdout.on('data', this.receiveStdout.bind(this));
|
|
192
|
+
this.child.stderr.on('data', this.receiveStderr.bind(this));
|
|
193
|
+
this.child.stdin.once('error', this.stdinError.bind(this));
|
|
194
|
+
this.child.once('error', this.childError.bind(this));
|
|
195
|
+
this.child.once('close', this.closeChild.bind(this));
|
|
196
|
+
this.signal?.addEventListener('abort', this.terminate.bind(this), { once: true });
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
writeInput() {
|
|
200
|
+
if (this.invocation.input === 'stdin') this.child.stdin.end(this.input);
|
|
201
|
+
else this.child.stdin.end();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
receiveStdout(chunk) {
|
|
205
|
+
this.receiveOutput(this.stdout, chunk);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
receiveStderr(chunk) {
|
|
209
|
+
this.receiveOutput(this.stderr, chunk);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
receiveOutput(chunks, chunk) {
|
|
213
|
+
const nextBytes = this.outputBytes + chunk.length;
|
|
214
|
+
if (nextBytes <= maximumProviderOutputBytes) {
|
|
215
|
+
this.outputBytes = nextBytes;
|
|
216
|
+
chunks.push(chunk);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
this.terminate();
|
|
220
|
+
this.reject(new Error(`${this.agent} returned too much chat output`));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
stdinError(error) {
|
|
224
|
+
if (error.code !== 'EPIPE') this.reject(error);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
childError(error) {
|
|
228
|
+
this.reject(error);
|
|
229
|
+
if (!this.running()) this.finishClose();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
running() {
|
|
233
|
+
return Number.isInteger(this.child?.pid) && this.child.exitCode === null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
sendSignal(signal) {
|
|
237
|
+
try {
|
|
238
|
+
this.child.kill(signal);
|
|
239
|
+
return true;
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
killChild() {
|
|
246
|
+
if (!this.running()) return;
|
|
247
|
+
this.sendSignal('SIGKILL');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
scheduleForceKill() {
|
|
251
|
+
if (this.forceKillTimer) return;
|
|
252
|
+
this.forceKillTimer = setTimeout(() => {
|
|
253
|
+
this.forceKillTimer = undefined;
|
|
254
|
+
this.killChild();
|
|
255
|
+
}, forcedChildKillDelayMs);
|
|
256
|
+
this.forceKillTimer.unref();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
terminate() {
|
|
260
|
+
if (!this.running()) return;
|
|
261
|
+
if (!this.sendSignal('SIGTERM')) return;
|
|
262
|
+
this.scheduleForceKill();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
clearForceKill() {
|
|
266
|
+
if (!this.forceKillTimer) return;
|
|
267
|
+
clearTimeout(this.forceKillTimer);
|
|
268
|
+
this.forceKillTimer = undefined;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
settle(callback, value) {
|
|
272
|
+
if (this.settled) return;
|
|
273
|
+
this.settled = true;
|
|
274
|
+
callback(value);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
finishClose() {
|
|
278
|
+
if (this.closed) return;
|
|
279
|
+
this.closed = true;
|
|
280
|
+
this.clearForceKill();
|
|
281
|
+
removeTemporary(this.temporary);
|
|
282
|
+
this.resolveFinished();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
resolve(value) {
|
|
286
|
+
this.settle(this.resolvePromise, value);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
reject(error) {
|
|
290
|
+
this.settle(this.rejectPromise, error);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
parseOutput() {
|
|
294
|
+
try {
|
|
295
|
+
this.resolve(parseAgentResponse(this.agent, childOutput(this.stdout)));
|
|
296
|
+
} catch (error) {
|
|
297
|
+
this.reject(error);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
closeChild(status, signal) {
|
|
302
|
+
this.clearForceKill();
|
|
303
|
+
if (!this.settled) {
|
|
304
|
+
const error = closeError(this, status, signal);
|
|
305
|
+
if (error) this.reject(error);
|
|
306
|
+
else this.parseOutput();
|
|
307
|
+
}
|
|
308
|
+
this.finishClose();
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
cancel() {
|
|
312
|
+
if (this.settled) return;
|
|
313
|
+
this.terminate();
|
|
314
|
+
this.reject(cancelledError());
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function providerChild(options) {
|
|
319
|
+
return new ChildExecution(options).open();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function trackExecution(executions, execution) {
|
|
323
|
+
executions.add(execution);
|
|
324
|
+
execution.finished.finally(() => executions.delete(execution)).catch(noChange);
|
|
325
|
+
return execution;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function runRequest(options, executions, request) {
|
|
329
|
+
const prepared = preparedProviderRequest(options, request);
|
|
330
|
+
const controller = new AbortController();
|
|
331
|
+
const execution = providerChild({
|
|
332
|
+
invocation: prepared.invocation,
|
|
333
|
+
input: JSON.stringify(request),
|
|
334
|
+
agent: options.agent,
|
|
335
|
+
signal: controller.signal,
|
|
336
|
+
temporary: prepared.temporary,
|
|
337
|
+
});
|
|
338
|
+
const tracked = trackExecution(executions, execution);
|
|
339
|
+
return {
|
|
340
|
+
promise: tracked.promise,
|
|
341
|
+
cancel() {
|
|
342
|
+
controller.abort();
|
|
343
|
+
tracked.cancel();
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function closeExecutions(executions) {
|
|
349
|
+
for (const execution of executions) execution.cancel();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function createCodingAgentChatProvider(options = {}) {
|
|
353
|
+
const configured = providerOptions(options);
|
|
354
|
+
const executions = new Set();
|
|
355
|
+
return {
|
|
356
|
+
run(request) {
|
|
357
|
+
return runRequest(configured, executions, request);
|
|
358
|
+
},
|
|
359
|
+
close() {
|
|
360
|
+
closeExecutions(executions);
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReviewChatController } from './review-chat-controller.mjs';
|
|
2
|
+
|
|
3
|
+
export { ReviewChatError } from './review-chat-context.mjs';
|
|
4
|
+
export { createCodingAgentChatProvider } from './review-chat-provider.mjs';
|
|
5
|
+
|
|
6
|
+
export function createReviewChat(options) {
|
|
7
|
+
return new ReviewChatController(options).api();
|
|
8
|
+
}
|