@@ -74,6 +74,7 @@ export class TasksPanel
7474 TasksApi . resumeTask . method ,
7575 TasksApi . deleteTask . method ,
7676 TasksApi . downloadLogs . method ,
77+ TasksApi . sendTaskMessage . method ,
7778 ] ) ;
7879
7980 private view ?: vscode . WebviewView ;
@@ -337,7 +338,7 @@ export class TasksPanel
337338
338339 await this . client . stopWorkspace ( task . workspace_id ) ;
339340
340- await this . refreshAndNotifyTasks ( ) ;
341+ await this . refreshAndNotifyTask ( taskId ) ;
341342 vscode . window . showInformationMessage ( `Task "${ taskName } " paused` ) ;
342343 }
343344
@@ -355,10 +356,44 @@ export class TasksPanel
355356 task . template_version_id ,
356357 ) ;
357358
358- await this . refreshAndNotifyTasks ( ) ;
359+ await this . refreshAndNotifyTask ( taskId ) ;
359360 vscode . window . showInformationMessage ( `Task "${ taskName } " resumed` ) ;
360361 }
361362
363+ private async handleSendMessage (
364+ taskId : string ,
365+ message : string ,
366+ ) : Promise < void > {
367+ const task = await this . client . getTask ( "me" , taskId ) ;
368+
369+ if ( task . status === "paused" ) {
370+ if ( ! task . workspace_id ) {
371+ throw new Error ( "Task has no workspace" ) ;
372+ }
373+ await this . client . startWorkspace (
374+ task . workspace_id ,
375+ task . template_version_id ,
376+ ) ;
377+ }
378+
379+ try {
380+ await this . client . sendTaskInput ( "me" , taskId , message ) ;
381+ } catch ( err ) {
382+ if (
383+ isAxiosError ( err ) &&
384+ ( err . response ?. status === 409 || err . response ?. status === 400 )
385+ ) {
386+ throw new Error ( "Task is not ready to receive messages" ) ;
387+ }
388+ throw err ;
389+ }
390+
391+ await this . refreshAndNotifyTask ( taskId ) ;
392+ vscode . window . showInformationMessage (
393+ `Message sent to "${ getTaskLabel ( task ) } "` ,
394+ ) ;
395+ }
396+
362397 private async handleViewInCoder ( taskId : string ) : Promise < void > {
363398 const baseUrl = this . client . getHost ( ) ;
364399 if ( ! baseUrl ) return ;
@@ -409,18 +444,6 @@ export class TasksPanel
409444 }
410445 }
411446
412- /**
413- * Placeholder handler for sending follow-up messages to a task.
414- * The Coder API does not yet support this feature.
415- */
416- private handleSendMessage ( taskId : string , message : string ) : Promise < void > {
417- this . logger . info ( `Sending message to task ${ taskId } : ${ message } ` ) ;
418- vscode . window . showInformationMessage (
419- "Follow-up messages are not yet supported by the API" ,
420- ) ;
421- return Promise . resolve ( ) ;
422- }
423-
424447 private async fetchTasksWithStatus ( ) : Promise < {
425448 tasks : readonly Task [ ] ;
426449 supported : boolean ;
@@ -452,6 +475,18 @@ export class TasksPanel
452475 }
453476 }
454477
478+ private async refreshAndNotifyTask ( taskId : string ) : Promise < void > {
479+ try {
480+ const task = await this . client . getTask ( "me" , taskId ) ;
481+ this . sendNotification ( {
482+ type : TasksApi . taskUpdated . method ,
483+ data : task ,
484+ } ) ;
485+ } catch ( err ) {
486+ this . logger . warn ( "Failed to refresh task after action" , err ) ;
487+ }
488+ }
489+
455490 private async fetchTemplates ( ) : Promise < TaskTemplate [ ] > {
456491 if ( ! this . client . getHost ( ) ) {
457492 return [ ] ;
@@ -529,10 +564,7 @@ export class TasksPanel
529564 const logs = await this . client . getTaskLogs ( "me" , taskId ) ;
530565 return { logs, status : "ok" } ;
531566 } catch ( err ) {
532- if (
533- isAxiosError ( err ) &&
534- ( err . response ?. status === 400 || err . response ?. status === 409 )
535- ) {
567+ if ( isAxiosError ( err ) && err . response ?. status === 409 ) {
536568 return { logs : [ ] , status : "not_available" } ;
537569 }
538570 this . logger . warn ( "Failed to fetch task logs" , err ) ;
0 commit comments