@@ -593,9 +593,9 @@ func (api *API) tasksList(rw http.ResponseWriter, r *http.Request) {
593593// @Security CoderSessionToken
594594// @Tags Experimental
595595// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
596- // @Paramid path string true "Task ID" format(uuid)
596+ // @Paramtask path string true "Task ID" format(uuid)
597597// @Success 200 {object} codersdk.Task
598- // @Router /api/experimental/tasks/{user}/{id } [get]
598+ // @Router /api/experimental/tasks/{user}/{task } [get]
599599//
600600// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
601601// taskGet is an experimental endpoint to fetch a single AI task by ID
@@ -605,7 +605,7 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
605605ctx := r .Context ()
606606apiKey := httpmw .APIKey (r )
607607
608- idStr := chi .URLParam (r ,"id " )
608+ idStr := chi .URLParam (r ,"task " )
609609taskID ,err := uuid .Parse (idStr )
610610if err != nil {
611611httpapi .Write (ctx ,rw ,http .StatusBadRequest , codersdk.Response {
@@ -710,83 +710,71 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
710710// @Security CoderSessionToken
711711// @Tags Experimental
712712// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
713- // @Paramid path string true "Task ID" format(uuid)
713+ // @Paramtask path string true "Task ID" format(uuid)
714714// @Success 202 "Task deletion initiated"
715- // @Router /api/experimental/tasks/{user}/{id } [delete]
715+ // @Router /api/experimental/tasks/{user}/{task } [delete]
716716//
717717// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
718- // taskDelete is an experimental endpoint to delete a task by ID (workspace ID) .
718+ // taskDelete is an experimental endpoint to delete a task by ID.
719719// It creates a delete workspace build and returns 202 Accepted if the build was
720720// created.
721721func (api * API )taskDelete (rw http.ResponseWriter ,r * http.Request ) {
722722ctx := r .Context ()
723723apiKey := httpmw .APIKey (r )
724+ task := httpmw .TaskParam (r )
724725
725- idStr := chi .URLParam (r ,"id" )
726- taskID ,err := uuid .Parse (idStr )
727- if err != nil {
728- httpapi .Write (ctx ,rw ,http .StatusBadRequest , codersdk.Response {
729- Message :fmt .Sprintf ("Invalid UUID %q for task ID." ,idStr ),
730- })
731- return
732- }
726+ now := api .Clock .Now ()
733727
734- // For now, taskID = workspaceID, once we have a task data model in
735- // the DB, we can change this lookup.
736- workspaceID := taskID
737- workspace ,err := api .Database .GetWorkspaceByID (ctx ,workspaceID )
738- if httpapi .Is404Error (err ) {
739- httpapi .ResourceNotFound (rw )
740- return
741- }
742- if err != nil {
743- httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
744- Message :"Internal error fetching workspace." ,
745- Detail :err .Error (),
746- })
747- return
728+ if task .WorkspaceID .Valid {
729+ workspace ,err := api .Database .GetWorkspaceByID (ctx ,task .WorkspaceID .UUID )
730+ if err != nil {
731+ if httpapi .Is404Error (err ) {
732+ httpapi .ResourceNotFound (rw )
733+ return
734+ }
735+ httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
736+ Message :"Internal error fetching task workspace before deleting task." ,
737+ Detail :err .Error (),
738+ })
739+ return
740+ }
741+
742+ // Construct a request to the workspace build creation handler to
743+ // initiate deletion.
744+ buildReq := codersdk.CreateWorkspaceBuildRequest {
745+ Transition :codersdk .WorkspaceTransitionDelete ,
746+ Reason :"Deleted via tasks API" ,
747+ }
748+
749+ _ ,err = api .postWorkspaceBuildsInternal (
750+ ctx ,
751+ apiKey ,
752+ workspace ,
753+ buildReq ,
754+ func (action policy.Action ,object rbac.Objecter )bool {
755+ return api .Authorize (r ,action ,object )
756+ },
757+ audit .WorkspaceBuildBaggageFromRequest (r ),
758+ )
759+ if err != nil {
760+ httperror .WriteWorkspaceBuildError (ctx ,rw ,err )
761+ return
762+ }
748763}
749764
750- data ,err := api .workspaceData (ctx , []database.Workspace {workspace })
765+ _ ,err := api .Database .DeleteTask (ctx , database.DeleteTaskParams {
766+ ID :task .ID ,
767+ DeletedAt :dbtime .Time (now ),
768+ })
751769if err != nil {
752770httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
753- Message :"Internal error fetching workspace resources. " ,
771+ Message :"Failed to delete task " ,
754772Detail :err .Error (),
755773})
756774return
757775}
758- if len (data .builds )== 0 || len (data .templates )== 0 {
759- httpapi .ResourceNotFound (rw )
760- return
761- }
762- if data .builds [0 ].HasAITask == nil || ! * data .builds [0 ].HasAITask {
763- httpapi .ResourceNotFound (rw )
764- return
765- }
766-
767- // Construct a request to the workspace build creation handler to
768- // initiate deletion.
769- buildReq := codersdk.CreateWorkspaceBuildRequest {
770- Transition :codersdk .WorkspaceTransitionDelete ,
771- Reason :"Deleted via tasks API" ,
772- }
773-
774- _ ,err = api .postWorkspaceBuildsInternal (
775- ctx ,
776- apiKey ,
777- workspace ,
778- buildReq ,
779- func (action policy.Action ,object rbac.Objecter )bool {
780- return api .Authorize (r ,action ,object )
781- },
782- audit .WorkspaceBuildBaggageFromRequest (r ),
783- )
784- if err != nil {
785- httperror .WriteWorkspaceBuildError (ctx ,rw ,err )
786- return
787- }
788776
789- //Delete build created successfully.
777+ //Task deleted and delete build created successfully.
790778rw .WriteHeader (http .StatusAccepted )
791779}
792780
@@ -796,10 +784,10 @@ func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
796784// @Security CoderSessionToken
797785// @Tags Experimental
798786// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
799- // @Paramid path string true "Task ID" format(uuid)
787+ // @Paramtask path string true "Task ID" format(uuid)
800788// @Param request body codersdk.TaskSendRequest true "Task input request"
801789// @Success 204 "Input sent successfully"
802- // @Router /api/experimental/tasks/{user}/{id }/send [post]
790+ // @Router /api/experimental/tasks/{user}/{task }/send [post]
803791//
804792// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
805793// taskSend submits task input to the tasks sidebar app by dialing the agent
@@ -808,7 +796,7 @@ func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
808796func (api * API )taskSend (rw http.ResponseWriter ,r * http.Request ) {
809797ctx := r .Context ()
810798
811- idStr := chi .URLParam (r ,"id " )
799+ idStr := chi .URLParam (r ,"task " )
812800taskID ,err := uuid .Parse (idStr )
813801if err != nil {
814802httpapi .Write (ctx ,rw ,http .StatusBadRequest , codersdk.Response {
@@ -878,17 +866,17 @@ func (api *API) taskSend(rw http.ResponseWriter, r *http.Request) {
878866// @Security CoderSessionToken
879867// @Tags Experimental
880868// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
881- // @Paramid path string true "Task ID" format(uuid)
869+ // @Paramtask path string true "Task ID" format(uuid)
882870// @Success 200 {object} codersdk.TaskLogsResponse
883- // @Router /api/experimental/tasks/{user}/{id }/logs [get]
871+ // @Router /api/experimental/tasks/{user}/{task }/logs [get]
884872//
885873// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
886874// taskLogs reads task output by dialing the agent directly over the tailnet.
887875// We enforce ApplicationConnect RBAC on the workspace and validate the sidebar app health.
888876func (api * API )taskLogs (rw http.ResponseWriter ,r * http.Request ) {
889877ctx := r .Context ()
890878
891- idStr := chi .URLParam (r ,"id " )
879+ idStr := chi .URLParam (r ,"task " )
892880taskID ,err := uuid .Parse (idStr )
893881if err != nil {
894882httpapi .Write (ctx ,rw ,http .StatusBadRequest , codersdk.Response {