@@ -102,6 +102,7 @@ export class TaskService {
102102 if ( task . taskStatus === "running" ) {
103103 void this . resumeTaskWorkspace ( task ) . catch ( ( error : unknown ) => {
104104 log . error ( "Failed to resume agent task workspace" , { workspaceId : task . id , error } ) ;
105+ void this . handleTaskStartFailure ( task . id , error ) ;
105106 } ) ;
106107 }
107108
@@ -119,6 +120,75 @@ export class TaskService {
119120 await this . queueScheduling ( ) ;
120121 }
121122
123+ private formatErrorForReport ( error : unknown ) : string {
124+ if ( error instanceof Error ) {
125+ return error . message ;
126+ }
127+
128+ if ( typeof error === "string" ) {
129+ return error ;
130+ }
131+
132+ try {
133+ return JSON . stringify ( error ) ;
134+ } catch {
135+ return String ( error ) ;
136+ }
137+ }
138+
139+ private async handleTaskStartFailure ( workspaceId : string , error : unknown ) : Promise < void > {
140+ const workspaceConfig = this . config . getWorkspaceConfig ( workspaceId ) ;
141+ if ( ! workspaceConfig ) {
142+ log . error ( "Failed to handle agent task start failure: unknown workspace" , {
143+ workspaceId,
144+ error,
145+ } ) ;
146+ return ;
147+ }
148+
149+ const agentType = workspaceConfig . workspace . agentType ?? "unknown" ;
150+ const model = workspaceConfig . workspace . taskModel ?? DEFAULT_MODEL ;
151+
152+ const reportMarkdown = [
153+ "Mux failed to start this agent task workspace." ,
154+ "" ,
155+ `- Agent preset: \`${ agentType } \`` ,
156+ `- Model: \`${ model } \`` ,
157+ "" ,
158+ "Error:" ,
159+ "```" ,
160+ this . formatErrorForReport ( error ) ,
161+ "```" ,
162+ "" ,
163+ "Suggested next steps:" ,
164+ "- Verify the model string is supported by the selected provider." ,
165+ "- Verify you have an API key set for that provider." ,
166+ ] . join ( "\n" ) ;
167+
168+ // If this isn't a properly-parented task workspace, at least mark it complete so it doesn't
169+ // consume a scheduler slot indefinitely.
170+ if ( ! workspaceConfig . workspace . parentWorkspaceId ) {
171+ await this . updateTaskWorkspace ( workspaceId , { taskStatus : "reported" } ) ;
172+ await this . maybeCleanupReportedWorkspace ( workspaceId ) ;
173+ await this . queueScheduling ( ) ;
174+ return ;
175+ }
176+
177+ try {
178+ await this . handleAgentReport ( workspaceId , { reportMarkdown } ) ;
179+ } catch ( reportError : unknown ) {
180+ // Ensure a failed report doesn't leave the queue stuck.
181+ log . error ( "Failed to forward agent task start failure report" , {
182+ workspaceId,
183+ error : reportError ,
184+ } ) ;
185+
186+ await this . updateTaskWorkspace ( workspaceId , { taskStatus : "reported" } ) ;
187+ await this . maybeCleanupReportedWorkspace ( workspaceId ) ;
188+ await this . queueScheduling ( ) ;
189+ }
190+ }
191+
122192 async createAgentTask ( params : CreateAgentTaskParams ) : Promise < { childWorkspaceId : string } > {
123193 const preset = getAgentPreset ( params . agentType ) ;
124194
@@ -770,9 +840,11 @@ export class TaskService {
770840 }
771841
772842 private async resumeTaskWorkspace ( workspace : AgentTaskWorkspace ) : Promise < void > {
773- const preset = workspace . agentType ? getAgentPreset ( workspace . agentType ) : undefined ;
843+ assert ( workspace . agentType , "resumeTaskWorkspace requires agentType" ) ;
844+
845+ const preset = getAgentPreset ( workspace . agentType ) ;
774846 if ( ! preset ) {
775- return ;
847+ throw new Error ( `Unknown agent preset: ${ workspace . agentType } ` ) ;
776848 }
777849
778850 await this . ensureTaskPromptSeeded ( workspace ) ;
@@ -836,8 +908,10 @@ export class TaskService {
836908
837909 for ( const workspace of queued ) {
838910 await this . updateTaskWorkspace ( workspace . id , { taskStatus : "running" } ) ;
911+
839912 void this . resumeTaskWorkspace ( workspace ) . catch ( ( error : unknown ) => {
840913 log . error ( "Failed to start queued agent task" , { workspaceId : workspace . id , error } ) ;
914+ void this . handleTaskStartFailure ( workspace . id , error ) ;
841915 } ) ;
842916 }
843917 }
0 commit comments