11#!/usr/bin/env node
22
3- import { spawn , spawnSync } from 'node:child_process' ;
3+ import { spawn } from 'node:child_process' ;
44import { createHash } from 'node:crypto' ;
55import {
6- existsSync ,
76 mkdtempSync ,
87 readFileSync ,
98 rmSync ,
@@ -19,6 +18,7 @@ import {
1918 selectCodingAgent ,
2019} from './coding-agents.mjs' ;
2120import { doctorReport } from './doctor.mjs' ;
21+ import { ensureBuiltAssets , openBrowser } from './presenter-runtime.mjs' ;
2222
2323const root = resolve ( dirname ( fileURLToPath ( import . meta. url ) ) , '..' ) ;
2424const callerDirectory = process . cwd ( ) ;
@@ -100,18 +100,11 @@ if (agentEnabled) {
100100 agentArgs . push ( '--snapshot' , outputPath ) ;
101101}
102102
103- const builtPage = resolve ( root , 'dist/index.html' ) ;
104- if ( ! existsSync ( builtPage ) ) {
105- const result = spawnSync (
106- process . platform === 'win32' ? 'npm.cmd' : 'npm' ,
107- [ 'run' , 'build' ] ,
108- { cwd : root , stdio : 'inherit' } ,
109- ) ;
110- if ( result . error ) {
111- console . error ( `Could not build the local page: ${ result . error . message } ` ) ;
112- process . exit ( 1 ) ;
113- }
114- if ( result . status !== 0 ) process . exit ( result . status || 1 ) ;
103+ try {
104+ ensureBuiltAssets ( { root } ) ;
105+ } catch ( error ) {
106+ console . error ( error . message ) ;
107+ process . exit ( 1 ) ;
115108}
116109
117110const feed = spawn (
@@ -127,37 +120,11 @@ let site;
127120let agent ;
128121let agentTimer ;
129122let agentFingerprint ;
123+ let failedAgentFingerprint ;
130124let queuedFingerprint ;
131125let browserOpened = false ;
132126let browserOpenTimer ;
133127
134- function openBrowser ( url ) {
135- let command ;
136- let args ;
137- if ( process . env . BROWSER ) {
138- command = process . env . BROWSER ;
139- args = [ url ] ;
140- } else if ( process . platform === 'darwin' ) {
141- command = 'open' ;
142- args = [ url ] ;
143- } else if ( process . platform === 'win32' ) {
144- command = 'cmd.exe' ;
145- args = [ '/d' , '/s' , '/c' , 'start' , '' , url ] ;
146- } else {
147- command = 'xdg-open' ;
148- args = [ url ] ;
149- }
150-
151- const opener = spawn ( command , args , {
152- detached : true ,
153- stdio : 'ignore' ,
154- } ) ;
155- opener . once ( 'error' , ( error ) => {
156- console . error ( `Could not open the browser: ${ error . message } ` ) ;
157- } ) ;
158- opener . unref ( ) ;
159- }
160-
161128function startSite ( ) {
162129 if ( closing || site ) return ;
163130 const child = spawn (
@@ -196,7 +163,10 @@ function startSite() {
196163 browserOpenTimer = setTimeout ( ( ) => {
197164 browserOpenTimer = undefined ;
198165 browserOpened = true ;
199- openBrowser ( match [ 1 ] ) ;
166+ openBrowser ( match [ 1 ] , {
167+ onError : ( error ) =>
168+ console . error ( `Could not open the browser: ${ error . message } ` ) ,
169+ } ) ;
200170 } , 750 ) ;
201171 }
202172 } ) ;
@@ -287,11 +257,14 @@ function runAgent(fingerprint) {
287257 settled = true ;
288258 const finishedFingerprint = agentFingerprint ;
289259 if ( agent === child ) agent = undefined ;
290- agentFingerprint = finishedFingerprint ;
291- if ( ! closing && ( error || code || signal ) ) {
260+ agentFingerprint = undefined ;
261+ const superseded =
262+ queuedFingerprint && queuedFingerprint !== finishedFingerprint ;
263+ if ( ! closing && ( error || code || signal ) && ! superseded ) {
264+ failedAgentFingerprint = finishedFingerprint ;
292265 if ( error ) console . error ( error . message ) ;
293266 console . error (
294- 'The coding agent could not write notes. The diff page will stay open .' ,
267+ 'The coding agent could not write notes. It will retry after the diff changes or Diffsplain restarts .' ,
295268 ) ;
296269 }
297270 const latest = queuedFingerprint || snapshotFingerprint ( ) ;
@@ -311,10 +284,15 @@ function scheduleAgent(fingerprint) {
311284 state ?. hasCurrentAgentNotes &&
312285 selectedFingerprint === state . fingerprint
313286 ) {
314- agentFingerprint = selectedFingerprint ;
315287 return ;
316288 }
317- if ( ! selectedFingerprint || selectedFingerprint === agentFingerprint ) return ;
289+ if (
290+ ! selectedFingerprint ||
291+ selectedFingerprint === agentFingerprint ||
292+ selectedFingerprint === failedAgentFingerprint
293+ ) {
294+ return ;
295+ }
318296 if ( agent ) {
319297 if ( selectedFingerprint !== agentFingerprint ) {
320298 queuedFingerprint = selectedFingerprint ;
0 commit comments