@@ -75,6 +75,7 @@ import { openBrowser } from "@plannotator/server/browser";
7575import { cleanupDaemonState , discoverDaemon } from "@plannotator/server/daemon/client" ;
7676import { startDaemonRuntime } from "@plannotator/server/daemon/runtime" ;
7777import { createDaemonSessionFactory } from "@plannotator/server/daemon/session-factory" ;
78+ import { getDaemonStartCommand } from "@plannotator/server/daemon/start-command" ;
7879import { formatRemoteShareNotice } from "@plannotator/server/share-url" ;
7980import { hostnameOrFallback } from "@plannotator/shared/project" ;
8081import { readImprovementHook } from "@plannotator/shared/improvement-hooks" ;
@@ -438,15 +439,6 @@ function resolvePluginCwd(request: Partial<PluginBaseRequest>): string {
438439 return cwd ;
439440}
440441
441- function getDaemonStartCommand ( ) : string [ ] {
442- const executable = process . argv [ 0 ] ;
443- const entry = process . argv [ 1 ] ;
444- if ( entry && / \. (?: [ c m ] ? [ j t ] s ) $ / . test ( entry ) ) {
445- return [ executable , entry , "daemon" , "start" , "--foreground" ] ;
446- }
447- return [ executable , "daemon" , "start" , "--foreground" ] ;
448- }
449-
450442async function ensureDaemonClient ( options : { pluginError ?: boolean } = { } ) {
451443 const fail = options . pluginError ? emitPluginError : emitCommandError ;
452444 const existing = await discoverDaemon ( ) ;
@@ -479,6 +471,23 @@ async function runDaemonSessionRequest(request: PluginRequest): Promise<{
479471 result : PluginActionResult ;
480472 session : PluginSessionInfo ;
481473} > ;
474+ function registerDaemonSessionInterruptCleanup ( cancelSession : ( ) => Promise < void > ) : ( ) => void {
475+ let cancelling = false ;
476+ const handleSignal = ( exitCode : number ) => {
477+ if ( cancelling ) return ;
478+ cancelling = true ;
479+ void cancelSession ( ) . finally ( ( ) => process . exit ( exitCode ) ) ;
480+ } ;
481+ const onSigint = ( ) => handleSignal ( 130 ) ;
482+ const onSigterm = ( ) => handleSignal ( 143 ) ;
483+ process . once ( "SIGINT" , onSigint ) ;
484+ process . once ( "SIGTERM" , onSigterm ) ;
485+ return ( ) => {
486+ process . off ( "SIGINT" , onSigint ) ;
487+ process . off ( "SIGTERM" , onSigterm ) ;
488+ } ;
489+ }
490+
482491async function runDaemonSessionRequest ( request : PluginRequest , options : { pluginError ?: boolean } = { } ) : Promise < {
483492 result : PluginActionResult ;
484493 session : PluginSessionInfo ;
@@ -490,6 +499,11 @@ async function runDaemonSessionRequest(request: PluginRequest, options: { plugin
490499 fail ( created . error . code , created . error . message ) ;
491500 }
492501
502+ const cancelCreatedSession = async ( ) => {
503+ await daemon . cancelSession ( created . session . id ) . catch ( ( ) => undefined ) ;
504+ } ;
505+ const unregisterInterruptCleanup = registerDaemonSessionInterruptCleanup ( cancelCreatedSession ) ;
506+
493507 const sessionUrl = new URL ( created . session . url ) ;
494508 const sessionPort = Number ( sessionUrl . port ) ;
495509 const session : PluginSessionInfo = {
@@ -505,29 +519,37 @@ async function runDaemonSessionRequest(request: PluginRequest, options: { plugin
505519 emitPluginSessionReady ( session ) ;
506520 }
507521
508- if ( request . action === "review" ) {
509- await handleReviewServerReady ( created . session . url , daemon . state . isRemote , sessionPort ) ;
510- } else if ( request . action === "annotate" || request . action === "annotate-last" ) {
511- await handleAnnotateServerReady ( created . session . url , daemon . state . isRemote , sessionPort ) ;
512- } else {
513- await handleServerReady ( created . session . url , daemon . state . isRemote , sessionPort ) ;
514- }
522+ try {
523+ if ( request . action === "review" ) {
524+ await handleReviewServerReady ( created . session . url , daemon . state . isRemote , sessionPort ) ;
525+ } else if ( request . action === "annotate" || request . action === "annotate-last" ) {
526+ await handleAnnotateServerReady ( created . session . url , daemon . state . isRemote , sessionPort ) ;
527+ } else {
528+ await handleServerReady ( created . session . url , daemon . state . isRemote , sessionPort ) ;
529+ }
515530
516- const completed = await daemon . waitForResult < PluginActionResult > ( created . session . id ) ;
517- if ( completed . ok !== true ) {
518- fail ( completed . error . code , completed . error . message ) ;
519- }
520- if ( completed . session . status !== "completed" ) {
521- fail (
522- completed . session . status ,
523- completed . session . error ?? `Plannotator session ${ completed . session . id } ended with status ${ completed . session . status } .` ,
524- ) ;
525- }
531+ const completed = await daemon . waitForResult < PluginActionResult > ( created . session . id ) ;
532+ if ( completed . ok !== true ) {
533+ await cancelCreatedSession ( ) ;
534+ fail ( completed . error . code , completed . error . message ) ;
535+ }
536+ if ( completed . session . status !== "completed" ) {
537+ fail (
538+ completed . session . status ,
539+ completed . session . error ?? `Plannotator session ${ completed . session . id } ended with status ${ completed . session . status } .` ,
540+ ) ;
541+ }
526542
527- return {
528- result : completed . result ,
529- session,
530- } ;
543+ unregisterInterruptCleanup ( ) ;
544+ return {
545+ result : completed . result ,
546+ session,
547+ } ;
548+ } catch ( err ) {
549+ unregisterInterruptCleanup ( ) ;
550+ await cancelCreatedSession ( ) ;
551+ throw err ;
552+ }
531553}
532554
533555async function runDaemonBackedPluginRequest ( request : PluginRequest ) : Promise < void > {
0 commit comments