diffsplain 0.8.3 → 0.9.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 +10 -5
- package/dist/assets/{angular-html-e4D_THVy.js → angular-html-m_m91ZYB.js} +1 -1
- package/dist/assets/{angular-ts-Cx3870JF.js → angular-ts-CO5Z--Rb.js} +1 -1
- package/dist/assets/{apl-DZuu22Wh.js → apl-ogYYgLUu.js} +1 -1
- package/dist/assets/{astro-K-NemFAk.js → astro-DAfY3cNR.js} +1 -1
- package/dist/assets/{blade-ConbVu3U.js → blade-E6RzsLUV.js} +1 -1
- package/dist/assets/{c-DtmaBqln.js → c-kKdxhtHF.js} +1 -1
- package/dist/assets/{cobol-BMHoPOfB.js → cobol-3oDDyFNf.js} +1 -1
- package/dist/assets/{coffee-DfweJ19Y.js → coffee-dsiILuWe.js} +1 -1
- package/dist/assets/{cpp-CPh_zIOW.js → cpp-DYyNFq__.js} +1 -1
- package/dist/assets/{crystal-CAEX7C1J.js → crystal-B7dVp9TF.js} +1 -1
- package/dist/assets/{css-C8ihGqCA.js → css-DlxJ0aex.js} +1 -1
- package/dist/assets/{edge-DVZPwQ9j.js → edge-BjEVphkC.js} +1 -1
- package/dist/assets/{elixir-D03TKulP.js → elixir-0xTOtMcM.js} +1 -1
- package/dist/assets/{elm-JUX-2xVV.js → elm-iQk_Wrxq.js} +1 -1
- package/dist/assets/{erb-HbktAFZJ.js → erb-BO74ztiE.js} +1 -1
- package/dist/assets/{git-rebase-Ccd_ELAP.js → git-rebase-BN667QRY.js} +1 -1
- package/dist/assets/{glimmer-js-BcinUfi2.js → glimmer-js-DTGUIHeS.js} +1 -1
- package/dist/assets/{glimmer-ts-DuN2UkN9.js → glimmer-ts-BU3oQn2d.js} +1 -1
- package/dist/assets/{glsl-BWmCEPsR.js → glsl-KLiqLJi2.js} +1 -1
- package/dist/assets/{graphql-DJGYoBFW.js → graphql-D_idcsoJ.js} +1 -1
- package/dist/assets/{hack-ZPqBE9w3.js → hack-BXlsgPIr.js} +1 -1
- package/dist/assets/{haml-CZDZk6Gw.js → haml-fP0aUg4-.js} +1 -1
- package/dist/assets/{handlebars-d23PDS0n.js → handlebars-C1ZEaot-.js} +1 -1
- package/dist/assets/{html-BgzX2DyB.js → html-D04qIuup.js} +1 -1
- package/dist/assets/{html-derivative-Bq6M-ZFw.js → html-derivative-C6ai-9QL.js} +1 -1
- package/dist/assets/{http-DVhMl_cW.js → http-C7bz3ZvQ.js} +1 -1
- package/dist/assets/{hurl-CbspBAqF.js → hurl-jL6B6Ahr.js} +1 -1
- package/dist/assets/index-BPaJGi-m.js +1574 -0
- package/dist/assets/index-VAyBpb3u.css +2 -0
- package/dist/assets/{java--YZbq0z2.js → java-BVzvLCON.js} +1 -1
- package/dist/assets/{javascript-cvRuifRJ.js → javascript-UDbZHxCI.js} +1 -1
- package/dist/assets/{jinja-BeZmr3LP.js → jinja-DB-QKo2A.js} +1 -1
- package/dist/assets/{jison-qrpGZaxs.js → jison-B1ZbR2FF.js} +1 -1
- package/dist/assets/{json-4xUzsNJn.js → json-DV4WwJzT.js} +1 -1
- package/dist/assets/{jsx-BlXrTlSg.js → jsx-DS6_VTvW.js} +1 -1
- package/dist/assets/{julia-IN3jzmBc.js → julia-C4tevET0.js} +1 -1
- package/dist/assets/{just-C_50nLQH.js → just-CWMjefzB.js} +1 -1
- package/dist/assets/{latex-Cd-_2IS1.js → latex-tyEFf_Af.js} +1 -1
- package/dist/assets/{liquid-CEJf6Xg5.js → liquid-C3d1X1rL.js} +1 -1
- package/dist/assets/{lua-BlaV_n8i.js → lua-sXvrzLQY.js} +1 -1
- package/dist/assets/{marko-Cb-NPdc_.js → marko-CQweucif.js} +1 -1
- package/dist/assets/{mdc-Dt4ywVAS.js → mdc-TrxLWF7s.js} +1 -1
- package/dist/assets/{nginx-C_6SKViP.js → nginx-ChE2nSNJ.js} +1 -1
- package/dist/assets/{nim-BbkBjoeZ.js → nim-BY1CTRfx.js} +1 -1
- package/dist/assets/{perl-CYPU6TVa.js → perl-Cvj2PQQH.js} +1 -1
- package/dist/assets/{php-B6Oqilrc.js → php-CGmHp8HW.js} +1 -1
- package/dist/assets/{pug-C9Poo2KU.js → pug-DM4S0bRr.js} +1 -1
- package/dist/assets/{qml-DkMURMPv.js → qml-DI89Al9K.js} +1 -1
- package/dist/assets/{r-Bm-Gfi0p.js → r-Bs5_4yYh.js} +1 -1
- package/dist/assets/{razor-B0LqOok3.js → razor-DimzayhZ.js} +1 -1
- package/dist/assets/{regexp-jAbMHzwe.js → regexp-BLACz0cx.js} +1 -1
- package/dist/assets/{rst-BlWHfg8c.js → rst-DcWzxQh2.js} +1 -1
- package/dist/assets/{ruby-Bt5lKwPL.js → ruby-Dlat5E8d.js} +1 -1
- package/dist/assets/{sas-TuY2-8EF.js → sas-CCDmMaBY.js} +1 -1
- package/dist/assets/{scss-Dh1SsWlK.js → scss-BPiU2nu6.js} +1 -1
- package/dist/assets/{shellscript-CThiwmnp.js → shellscript-CKinVNrN.js} +1 -1
- package/dist/assets/{shellsession-DQ5iRUWd.js → shellsession-Cea8Pu5d.js} +1 -1
- package/dist/assets/{soy-BfM-BrZG.js → soy--BRAPY4-.js} +1 -1
- package/dist/assets/{sql-F617W1uN.js → sql-DjKiCyWK.js} +1 -1
- package/dist/assets/{stata-Ctov3ki2.js → stata-CDvo3J6y.js} +1 -1
- package/dist/assets/{surrealql-C-i2bJGB.js → surrealql-C7b7E5sh.js} +1 -1
- package/dist/assets/{svelte-oZT41pTl.js → svelte-DO0tKtiK.js} +1 -1
- package/dist/assets/{templ-CxX9Hf3e.js → templ-DhhmR_rv.js} +1 -1
- package/dist/assets/{tex-GyzJq8GJ.js → tex-Cn_V-Gg4.js} +1 -1
- package/dist/assets/{ts-tags-BugzKu0x.js → ts-tags-B6c-FTmA.js} +1 -1
- package/dist/assets/{tsx-DLqwDEUq.js → tsx-Cvtt2sJ-.js} +1 -1
- package/dist/assets/{twig-DADiR9Vq.js → twig-B7ZbCUmB.js} +1 -1
- package/dist/assets/{typescript-BlDIG_FO.js → typescript-i3C6um2B.js} +1 -1
- package/dist/assets/{vue-COXmmg2A.js → vue-DyPX0Vum.js} +1 -1
- package/dist/assets/{vue-html-Cy_3KYj1.js → vue-html-D362KpK3.js} +1 -1
- package/dist/assets/{vue-vine-CUqOY8dY.js → vue-vine-D34cBbwO.js} +1 -1
- package/dist/assets/{xml-C9JY7Wf6.js → xml-DJEk7u4n.js} +1 -1
- package/dist/assets/{xsl-DBCl8hSu.js → xsl-CoTtf90f.js} +1 -1
- package/dist/assets/{yaml-BbMebKkS.js → yaml-Cv5epQ4-.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +11 -3
- 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 +36 -9
- package/scripts/coding-agents.mjs +206 -79
- package/scripts/generate-summaries.mjs +864 -425
- package/scripts/local-target.mjs +106 -0
- package/scripts/present.mjs +205 -72
- package/scripts/review-chat-context.mjs +510 -0
- package/scripts/review-chat-controller.mjs +568 -0
- package/scripts/review-chat-provider.mjs +352 -0
- package/scripts/review-chat.mjs +8 -0
- package/scripts/serve-built.mjs +206 -24
- 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,106 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
export function isBaseWorktreeTarget({
|
|
4
|
+
base,
|
|
5
|
+
branch,
|
|
6
|
+
checkout,
|
|
7
|
+
head,
|
|
8
|
+
pullRequest,
|
|
9
|
+
worktree,
|
|
10
|
+
}) {
|
|
11
|
+
return Boolean(base) && [branch, checkout, head, pullRequest, worktree]
|
|
12
|
+
.every((value) => !value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const checkoutTargetKinds = new Set([
|
|
16
|
+
'checkout',
|
|
17
|
+
'worktree',
|
|
18
|
+
'base-worktree',
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
function localTargetKind({ checkout, worktree }) {
|
|
22
|
+
if (checkout) return 'checkout';
|
|
23
|
+
if (worktree) return 'worktree';
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function remoteTargetKind({ branch, pullRequest }) {
|
|
28
|
+
if (pullRequest) return 'pr';
|
|
29
|
+
if (branch) return 'branch';
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function hasRangeTarget({ base, head, range }) {
|
|
34
|
+
return Boolean(range || base || head);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function gitTargetKind(options) {
|
|
38
|
+
const { base, branch, checkout, head, pullRequest, worktree } = options;
|
|
39
|
+
if (isBaseWorktreeTarget({
|
|
40
|
+
base,
|
|
41
|
+
branch,
|
|
42
|
+
checkout,
|
|
43
|
+
head,
|
|
44
|
+
pullRequest,
|
|
45
|
+
worktree,
|
|
46
|
+
})) return 'base-worktree';
|
|
47
|
+
if (hasRangeTarget(options)) return 'range';
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function explicitTargetKind(options) {
|
|
52
|
+
return localTargetKind(options) ||
|
|
53
|
+
remoteTargetKind(options) ||
|
|
54
|
+
gitTargetKind(options);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function resolvedTargetKind(options) {
|
|
58
|
+
const explicit = explicitTargetKind(options);
|
|
59
|
+
if (explicit) return explicit;
|
|
60
|
+
if (options.snapshotSupplied) return undefined;
|
|
61
|
+
return 'worktree';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function reviewAccessMode({
|
|
65
|
+
repo,
|
|
66
|
+
base,
|
|
67
|
+
branch,
|
|
68
|
+
checkout,
|
|
69
|
+
head,
|
|
70
|
+
noCheckoutAccess = false,
|
|
71
|
+
pullRequest,
|
|
72
|
+
range,
|
|
73
|
+
snapshotSupplied = false,
|
|
74
|
+
worktree,
|
|
75
|
+
}) {
|
|
76
|
+
if (noCheckoutAccess) {
|
|
77
|
+
return { mode: 'snapshot-only', reason: 'disabled' };
|
|
78
|
+
}
|
|
79
|
+
const targetKind = resolvedTargetKind({
|
|
80
|
+
base,
|
|
81
|
+
branch,
|
|
82
|
+
checkout,
|
|
83
|
+
head,
|
|
84
|
+
pullRequest,
|
|
85
|
+
range,
|
|
86
|
+
snapshotSupplied,
|
|
87
|
+
worktree,
|
|
88
|
+
});
|
|
89
|
+
if (checkoutTargetKinds.has(targetKind)) {
|
|
90
|
+
return { mode: 'checkout-read-only', root: repo };
|
|
91
|
+
}
|
|
92
|
+
return { mode: 'snapshot-only', reason: 'target-mismatch' };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function resolveBaseWorktreeCommit(repo, base) {
|
|
96
|
+
const result = spawnSync(
|
|
97
|
+
'git',
|
|
98
|
+
['-C', repo, 'rev-parse', '--verify', `${base}^{commit}`],
|
|
99
|
+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] },
|
|
100
|
+
);
|
|
101
|
+
const oid = result.status === 0 ? result.stdout.trim() : '';
|
|
102
|
+
if (!oid) {
|
|
103
|
+
throw new Error(`Could not resolve base ref "${base}" to a commit.`);
|
|
104
|
+
}
|
|
105
|
+
return oid;
|
|
106
|
+
}
|
package/scripts/present.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
mkdirSync,
|
|
8
8
|
mkdtempSync,
|
|
9
9
|
readFileSync,
|
|
10
|
+
renameSync,
|
|
10
11
|
rmSync,
|
|
11
12
|
statSync,
|
|
12
13
|
writeFileSync,
|
|
@@ -17,11 +18,17 @@ import { createInterface } from 'node:readline';
|
|
|
17
18
|
import { fileURLToPath } from 'node:url';
|
|
18
19
|
import { helpText, parseCliArgs } from './cli-args.mjs';
|
|
19
20
|
import {
|
|
21
|
+
agentReadOnlyWarning,
|
|
20
22
|
assertReasoningSupported,
|
|
21
23
|
codingAgentAvailability,
|
|
22
24
|
codingAgentBinary,
|
|
23
25
|
selectCodingAgent,
|
|
24
26
|
} from './coding-agents.mjs';
|
|
27
|
+
import {
|
|
28
|
+
isBaseWorktreeTarget,
|
|
29
|
+
reviewAccessMode,
|
|
30
|
+
resolveBaseWorktreeCommit,
|
|
31
|
+
} from './local-target.mjs';
|
|
25
32
|
import { doctorReport } from './doctor.mjs';
|
|
26
33
|
import { accessTokenDirectory } from './access-token.mjs';
|
|
27
34
|
import { cacheStatus, clearCache, formatCacheStatus, pruneCache } from './cache.mjs';
|
|
@@ -178,31 +185,83 @@ function emitSupportRecord(code = 1) {
|
|
|
178
185
|
}
|
|
179
186
|
}
|
|
180
187
|
|
|
188
|
+
function targetOption(args, name) {
|
|
189
|
+
const index = args.indexOf(name);
|
|
190
|
+
return index === -1 ? undefined : args[index + 1];
|
|
191
|
+
}
|
|
192
|
+
|
|
181
193
|
const { agentEnabled, browserEnabled, host, port } = cli;
|
|
182
194
|
const feedArgs = [...cli.feedArgs];
|
|
183
195
|
const agentArgs = [...cli.agentArgs];
|
|
196
|
+
const base = targetOption(feedArgs, '--base');
|
|
197
|
+
const head = targetOption(feedArgs, '--head');
|
|
198
|
+
const branch = targetOption(feedArgs, '--branch');
|
|
199
|
+
const checkout = feedArgs.includes('--checkout');
|
|
200
|
+
const reviewRepo = targetOption(feedArgs, '--repo');
|
|
201
|
+
const accessMode = reviewAccessMode({
|
|
202
|
+
repo: reviewRepo,
|
|
203
|
+
base,
|
|
204
|
+
branch,
|
|
205
|
+
checkout,
|
|
206
|
+
head,
|
|
207
|
+
noCheckoutAccess: cli.noCheckoutAccess,
|
|
208
|
+
pullRequest: targetOption(feedArgs, '--pr'),
|
|
209
|
+
worktree: feedArgs.includes('--worktree'),
|
|
210
|
+
});
|
|
211
|
+
if (isBaseWorktreeTarget({
|
|
212
|
+
base,
|
|
213
|
+
branch,
|
|
214
|
+
checkout,
|
|
215
|
+
head,
|
|
216
|
+
pullRequest: targetOption(feedArgs, '--pr'),
|
|
217
|
+
worktree: feedArgs.includes('--worktree'),
|
|
218
|
+
})) {
|
|
219
|
+
try {
|
|
220
|
+
resolveBaseWorktreeCommit(targetOption(feedArgs, '--repo'), base);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error(error.message);
|
|
223
|
+
process.exit(2);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
184
226
|
let selectedAgent;
|
|
227
|
+
let selectedAgentBinary;
|
|
185
228
|
beginSupportRecord();
|
|
186
229
|
if (agentEnabled) {
|
|
187
230
|
const selectionStarted = performance.now();
|
|
188
231
|
try {
|
|
189
232
|
selectedAgent = await selectCodingAgent(
|
|
190
233
|
cli.agent,
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
234
|
+
{
|
|
235
|
+
available: (agent) =>
|
|
236
|
+
codingAgentAvailability(agent, {
|
|
237
|
+
binary: codingAgentBinary(agent, { codexBin: cli.codexBin }),
|
|
238
|
+
}),
|
|
239
|
+
},
|
|
195
240
|
);
|
|
196
241
|
assertReasoningSupported(selectedAgent, cli.reasoning);
|
|
197
|
-
|
|
242
|
+
selectedAgentBinary = codingAgentBinary(selectedAgent, {
|
|
198
243
|
codexBin: cli.codexBin,
|
|
199
244
|
});
|
|
200
|
-
recordSelectedProvider(selectedAgent,
|
|
245
|
+
recordSelectedProvider(selectedAgent, selectedAgentBinary);
|
|
201
246
|
supportRecorder?.addStage(
|
|
202
247
|
'agent',
|
|
203
248
|
performance.now() - selectionStarted,
|
|
204
249
|
);
|
|
205
250
|
agentArgs.push('--agent', selectedAgent);
|
|
251
|
+
if (
|
|
252
|
+
accessMode.mode === 'snapshot-only' &&
|
|
253
|
+
accessMode.reason === 'target-mismatch'
|
|
254
|
+
) {
|
|
255
|
+
console.log(
|
|
256
|
+
'Warning: This target does not map to the live checkout. Agent notes will use the supplied snapshot only.',
|
|
257
|
+
);
|
|
258
|
+
agentArgs.push('--access-warning-emitted');
|
|
259
|
+
}
|
|
260
|
+
const readOnlyWarning = agentReadOnlyWarning(selectedAgent, accessMode);
|
|
261
|
+
if (readOnlyWarning) {
|
|
262
|
+
console.log(readOnlyWarning);
|
|
263
|
+
agentArgs.push('--provider-read-only-warning-emitted');
|
|
264
|
+
}
|
|
206
265
|
} catch (error) {
|
|
207
266
|
recordSelectedProvider(cli.agent || 'unknown');
|
|
208
267
|
supportRecorder?.addStage(
|
|
@@ -217,6 +276,12 @@ if (agentEnabled) {
|
|
|
217
276
|
} else {
|
|
218
277
|
feedArgs.push('--no-summaries');
|
|
219
278
|
}
|
|
279
|
+
if (agentEnabled) {
|
|
280
|
+
agentArgs.push('--access-mode', accessMode.mode);
|
|
281
|
+
if (accessMode.mode === 'snapshot-only') {
|
|
282
|
+
agentArgs.push('--access-reason', accessMode.reason);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
220
285
|
const outputIndex = feedArgs.indexOf('--output');
|
|
221
286
|
let runtimeDirectory;
|
|
222
287
|
|
|
@@ -226,16 +291,27 @@ if (outputIndex === -1) {
|
|
|
226
291
|
feedArgs.push('--output', liveOutput);
|
|
227
292
|
agentArgs.push('--output', liveOutput);
|
|
228
293
|
}
|
|
294
|
+
const outputPath = resolve(
|
|
295
|
+
callerDirectory,
|
|
296
|
+
feedArgs[feedArgs.indexOf('--output') + 1],
|
|
297
|
+
);
|
|
298
|
+
let rawSnapshotPath = outputPath;
|
|
299
|
+
if (agentEnabled) {
|
|
300
|
+
if (!runtimeDirectory) {
|
|
301
|
+
runtimeDirectory = mkdtempSync(join(tmpdir(), 'diffsplain-live-'));
|
|
302
|
+
}
|
|
303
|
+
rawSnapshotPath = resolve(runtimeDirectory, 'raw-diff-data.json');
|
|
304
|
+
const feedOutputIndex = feedArgs.indexOf('--output');
|
|
305
|
+
feedArgs[feedOutputIndex + 1] = rawSnapshotPath;
|
|
306
|
+
feedArgs.push('--exclude-output', outputPath);
|
|
307
|
+
}
|
|
308
|
+
const reviewSnapshotPath = agentEnabled ? rawSnapshotPath : outputPath;
|
|
229
309
|
process.on('exit', () => {
|
|
230
310
|
if (runtimeDirectory) {
|
|
231
311
|
rmSync(runtimeDirectory, { recursive: true, force: true });
|
|
232
312
|
}
|
|
233
313
|
});
|
|
234
314
|
if (!feedArgs.includes('--watch')) feedArgs.push('--watch');
|
|
235
|
-
const outputPath = resolve(
|
|
236
|
-
callerDirectory,
|
|
237
|
-
feedArgs[feedArgs.indexOf('--output') + 1],
|
|
238
|
-
);
|
|
239
315
|
const repoIndex = feedArgs.indexOf('--repo');
|
|
240
316
|
const remoteIndex = feedArgs.indexOf('--remote');
|
|
241
317
|
const projectKey = createHash('sha256')
|
|
@@ -262,7 +338,9 @@ writeFileSync(accessPath, access, { mode: 0o600 });
|
|
|
262
338
|
chmodSync(accessPath, 0o600);
|
|
263
339
|
if (agentEnabled) {
|
|
264
340
|
feedArgs.push('--ignore-summary-watch');
|
|
265
|
-
|
|
341
|
+
if (accessMode.mode === 'snapshot-only') {
|
|
342
|
+
agentArgs.push('--snapshot', rawSnapshotPath);
|
|
343
|
+
}
|
|
266
344
|
}
|
|
267
345
|
|
|
268
346
|
const snapshotStarted = performance.now();
|
|
@@ -334,73 +412,107 @@ function scheduleBrowserOpen(match) {
|
|
|
334
412
|
}, 750);
|
|
335
413
|
}
|
|
336
414
|
|
|
415
|
+
function optionalSiteArgument(flag, value) {
|
|
416
|
+
return value ? [flag, value] : [];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function chatAccessArguments() {
|
|
420
|
+
if (accessMode.mode !== 'checkout-read-only') return [];
|
|
421
|
+
return ['--chat-access-root', accessMode.root];
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function chatAgentArguments() {
|
|
425
|
+
if (!agentEnabled) return [];
|
|
426
|
+
return [
|
|
427
|
+
'--chat-agent',
|
|
428
|
+
selectedAgent,
|
|
429
|
+
'--chat-binary',
|
|
430
|
+
selectedAgentBinary,
|
|
431
|
+
'--chat-access-mode',
|
|
432
|
+
accessMode.mode,
|
|
433
|
+
...chatAccessArguments(),
|
|
434
|
+
...optionalSiteArgument('--chat-model', cli.model),
|
|
435
|
+
...optionalSiteArgument('--chat-reasoning', cli.reasoning),
|
|
436
|
+
];
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function siteArguments() {
|
|
440
|
+
return [
|
|
441
|
+
resolve(root, 'scripts/serve-built.mjs'),
|
|
442
|
+
'--output',
|
|
443
|
+
outputPath,
|
|
444
|
+
'--port',
|
|
445
|
+
String(port),
|
|
446
|
+
'--host',
|
|
447
|
+
host,
|
|
448
|
+
'--project',
|
|
449
|
+
projectKey,
|
|
450
|
+
'--access',
|
|
451
|
+
access,
|
|
452
|
+
...optionalSiteArgument('--previous-access', previousAccess),
|
|
453
|
+
'--chat-snapshot',
|
|
454
|
+
outputPath,
|
|
455
|
+
...chatAgentArguments(),
|
|
456
|
+
...(!cli.portWasPassed ? ['--increment-port'] : []),
|
|
457
|
+
];
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function handleSiteLine(line) {
|
|
461
|
+
if (handleConnectedTab(line)) return;
|
|
462
|
+
console.log(line);
|
|
463
|
+
const match = line.match(/^Diffsplain: (http:\/\/\S+)$/);
|
|
464
|
+
markSiteReady(match);
|
|
465
|
+
scheduleBrowserOpen(match);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function listenForSiteLines(child) {
|
|
469
|
+
if (!child.stdout) return;
|
|
470
|
+
createInterface({ input: child.stdout }).on('line', handleSiteLine);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function siteFailed(code, signal) {
|
|
474
|
+
return Boolean(code || signal);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function recordSiteFailure(code) {
|
|
478
|
+
supportRecorder?.addStage('serve', performance.now() - siteStarted, 'failed');
|
|
479
|
+
emitSupportRecord(code || 1);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function handleSiteExit(code, signal) {
|
|
483
|
+
if (closing) return;
|
|
484
|
+
if (siteFailed(code, signal)) recordSiteFailure(code);
|
|
485
|
+
stop(code || (signal ? 1 : 0));
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function handleSiteError(error) {
|
|
489
|
+
if (closing) return;
|
|
490
|
+
supportRecorder?.addStage('serve', performance.now() - siteStarted, 'failed');
|
|
491
|
+
console.error(`Could not start the local page: ${error.message}`);
|
|
492
|
+
emitSupportRecord();
|
|
493
|
+
stop(1);
|
|
494
|
+
}
|
|
495
|
+
|
|
337
496
|
function startSite() {
|
|
338
497
|
if (closing || site) return;
|
|
339
498
|
siteStarted = performance.now();
|
|
340
|
-
const child = spawn(
|
|
341
|
-
|
|
342
|
-
[
|
|
343
|
-
resolve(root, 'scripts/serve-built.mjs'),
|
|
344
|
-
'--output',
|
|
345
|
-
outputPath,
|
|
346
|
-
'--port',
|
|
347
|
-
String(port),
|
|
348
|
-
'--host',
|
|
349
|
-
host,
|
|
350
|
-
'--project',
|
|
351
|
-
projectKey,
|
|
352
|
-
'--access',
|
|
353
|
-
access,
|
|
354
|
-
...(previousAccess ? ['--previous-access', previousAccess] : []),
|
|
355
|
-
...(!cli.portWasPassed ? ['--increment-port'] : []),
|
|
356
|
-
],
|
|
357
|
-
{ cwd: root, stdio: ['ignore', 'pipe', 'inherit'] },
|
|
358
|
-
);
|
|
359
|
-
site = child;
|
|
360
|
-
|
|
361
|
-
if (child.stdout) {
|
|
362
|
-
const siteLines = createInterface({ input: child.stdout });
|
|
363
|
-
siteLines.on('line', (line) => {
|
|
364
|
-
if (handleConnectedTab(line)) return;
|
|
365
|
-
console.log(line);
|
|
366
|
-
const match = line.match(/^Diffsplain: (http:\/\/\S+)$/);
|
|
367
|
-
markSiteReady(match);
|
|
368
|
-
scheduleBrowserOpen(match);
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
child.on('exit', (code, signal) => {
|
|
373
|
-
if (!closing) {
|
|
374
|
-
if (code || signal) {
|
|
375
|
-
supportRecorder?.addStage(
|
|
376
|
-
'serve',
|
|
377
|
-
performance.now() - siteStarted,
|
|
378
|
-
'failed',
|
|
379
|
-
);
|
|
380
|
-
emitSupportRecord(code || 1);
|
|
381
|
-
}
|
|
382
|
-
stop(code || (signal ? 1 : 0));
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
child.on('error', (error) => {
|
|
386
|
-
if (!closing) {
|
|
387
|
-
supportRecorder?.addStage(
|
|
388
|
-
'serve',
|
|
389
|
-
performance.now() - siteStarted,
|
|
390
|
-
'failed',
|
|
391
|
-
);
|
|
392
|
-
console.error(`Could not start the local page: ${error.message}`);
|
|
393
|
-
emitSupportRecord();
|
|
394
|
-
stop(1);
|
|
395
|
-
}
|
|
499
|
+
const child = spawn(process.execPath, siteArguments(), {
|
|
500
|
+
cwd: root,
|
|
501
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
396
502
|
});
|
|
503
|
+
site = child;
|
|
504
|
+
listenForSiteLines(child);
|
|
505
|
+
child.on('exit', handleSiteExit);
|
|
506
|
+
child.on('error', handleSiteError);
|
|
397
507
|
}
|
|
398
508
|
|
|
399
509
|
function snapshotState() {
|
|
400
510
|
try {
|
|
401
|
-
const snapshot = JSON.parse(readFileSync(
|
|
511
|
+
const snapshot = JSON.parse(readFileSync(reviewSnapshotPath, 'utf8'));
|
|
402
512
|
if (snapshot.notes?.reviewFingerprint) {
|
|
403
|
-
const fingerprint =
|
|
513
|
+
const fingerprint =
|
|
514
|
+
snapshot.notes.agentReviewFingerprint ||
|
|
515
|
+
snapshot.notes.reviewFingerprint;
|
|
404
516
|
const emptyReview =
|
|
405
517
|
Array.isArray(snapshot.files) && snapshot.files.length === 0;
|
|
406
518
|
return {
|
|
@@ -409,6 +521,7 @@ function snapshotState() {
|
|
|
409
521
|
snapshot.notes.complete &&
|
|
410
522
|
snapshot.notes.fresh &&
|
|
411
523
|
snapshot.notes.generatedFor === fingerprint &&
|
|
524
|
+
snapshot.notes.accessMode === accessMode.mode &&
|
|
412
525
|
(emptyReview ||
|
|
413
526
|
(snapshot.notes.agent === selectedAgent &&
|
|
414
527
|
(snapshot.notes.model || null) === (cli.model || null) &&
|
|
@@ -599,7 +712,7 @@ function markSnapshotReady() {
|
|
|
599
712
|
if (snapshotReady) return;
|
|
600
713
|
snapshotReady = true;
|
|
601
714
|
try {
|
|
602
|
-
supportRecorder?.addBytes('snapshot', statSync(
|
|
715
|
+
supportRecorder?.addBytes('snapshot', statSync(reviewSnapshotPath).size);
|
|
603
716
|
} catch {}
|
|
604
717
|
supportRecorder?.addStage(
|
|
605
718
|
'snapshot',
|
|
@@ -607,11 +720,29 @@ function markSnapshotReady() {
|
|
|
607
720
|
);
|
|
608
721
|
}
|
|
609
722
|
|
|
723
|
+
function seedPresentationSnapshot() {
|
|
724
|
+
const raw = readFileSync(rawSnapshotPath);
|
|
725
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
726
|
+
const pendingOutput = `${outputPath}.${process.pid}.${randomBytes(8).toString('hex')}.tmp`;
|
|
727
|
+
writeFileSync(pendingOutput, raw);
|
|
728
|
+
renameSync(pendingOutput, outputPath);
|
|
729
|
+
}
|
|
730
|
+
|
|
610
731
|
function isSnapshotLine(line) {
|
|
611
732
|
return line.startsWith('Wrote ') || line === 'No diff-data changes';
|
|
612
733
|
}
|
|
613
734
|
|
|
614
|
-
function startSnapshotDependents() {
|
|
735
|
+
function startSnapshotDependents({ rawSnapshotWritten = false } = {}) {
|
|
736
|
+
if (agentEnabled && rawSnapshotWritten) {
|
|
737
|
+
try {
|
|
738
|
+
seedPresentationSnapshot();
|
|
739
|
+
} catch (error) {
|
|
740
|
+
console.error(`Could not publish the live snapshot: ${error.message}`);
|
|
741
|
+
emitSupportRecord();
|
|
742
|
+
stop(1);
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
615
746
|
markSnapshotReady();
|
|
616
747
|
startSite();
|
|
617
748
|
if (agentEnabled) scheduleAgent();
|
|
@@ -622,7 +753,9 @@ function shouldPrintFeedLine(line) {
|
|
|
622
753
|
}
|
|
623
754
|
|
|
624
755
|
function handleFeedLine(line) {
|
|
625
|
-
if (isSnapshotLine(line))
|
|
756
|
+
if (isSnapshotLine(line)) {
|
|
757
|
+
startSnapshotDependents({ rawSnapshotWritten: line.startsWith('Wrote ') });
|
|
758
|
+
}
|
|
626
759
|
if (shouldPrintFeedLine(line)) console.log(line);
|
|
627
760
|
}
|
|
628
761
|
|