|
1 | 1 | package coderd |
2 | 2 |
|
3 | 3 | import ( |
| 4 | +"context" |
4 | 5 | "database/sql" |
5 | 6 | "errors" |
6 | 7 | "fmt" |
@@ -190,49 +191,60 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) { |
190 | 191 | createWorkspace(ctx,aReq,apiKey.UserID,api,owner,createReq,rw,r) |
191 | 192 | } |
192 | 193 |
|
193 | | -// tasksListResponse wraps a list of experimental tasks. |
194 | | -// |
195 | | -// Experimental: Response shape is experimental and may change. |
196 | | -typetasksListResponsestruct { |
197 | | -Tasks []codersdk.Task`json:"tasks"` |
198 | | -Countint`json:"count"` |
199 | | -} |
200 | | - |
201 | | -funcmapTaskStatus(ws codersdk.Workspace) codersdk.TaskStatus { |
202 | | -switchws.LatestBuild.Status { |
203 | | -casecodersdk.WorkspaceStatusPending: |
204 | | -returncodersdk.TaskStatusPending |
205 | | - |
206 | | -casecodersdk.WorkspaceStatusStarting: |
207 | | -returncodersdk.TaskStatusStarting |
| 194 | +// tasksFromWorkspaces converts a slice of API workspaces into tasks, fetching |
| 195 | +// prompts and mapping status/state. |
| 196 | +func (api*API)tasksFromWorkspaces(ctx context.Context,apiWorkspaces []codersdk.Workspace) ([]codersdk.Task,error) { |
| 197 | +// Fetch prompts for each workspace build and map by build ID. |
| 198 | +buildIDs:=make([]uuid.UUID,0,len(apiWorkspaces)) |
| 199 | +for_,ws:=rangeapiWorkspaces { |
| 200 | +buildIDs=append(buildIDs,ws.LatestBuild.ID) |
| 201 | +} |
| 202 | +parameters,err:=api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx,buildIDs) |
| 203 | +iferr!=nil { |
| 204 | +returnnil,err |
| 205 | +} |
| 206 | +promptsByBuildID:=make(map[uuid.UUID]string,len(parameters)) |
| 207 | +for_,p:=rangeparameters { |
| 208 | +ifp.Name==codersdk.AITaskPromptParameterName { |
| 209 | +promptsByBuildID[p.WorkspaceBuildID]=p.Value |
| 210 | +} |
| 211 | +} |
208 | 212 |
|
209 | | -casecodersdk.WorkspaceStatusRunning: |
| 213 | +tasks:=make([]codersdk.Task,0,len(apiWorkspaces)) |
| 214 | +for_,ws:=rangeapiWorkspaces { |
| 215 | +varcurrentState*codersdk.TaskStateEntry |
210 | 216 | ifws.LatestAppStatus!=nil { |
211 | | -switchws.LatestAppStatus.State { |
212 | | -casecodersdk.WorkspaceAppStatusStateWorking: |
213 | | -returncodersdk.TaskStatusWorking |
214 | | -casecodersdk.WorkspaceAppStatusStateIdle: |
215 | | -returncodersdk.TaskStatusIdle |
216 | | -casecodersdk.WorkspaceAppStatusStateComplete: |
217 | | -returncodersdk.TaskStatusCompleted |
218 | | -casecodersdk.WorkspaceAppStatusStateFailure: |
219 | | -returncodersdk.TaskStatusFailed |
| 217 | +currentState=&codersdk.TaskStateEntry{ |
| 218 | +Timestamp:ws.LatestAppStatus.CreatedAt, |
| 219 | +State:codersdk.TaskState(ws.LatestAppStatus.State), |
| 220 | +Message:ws.LatestAppStatus.Message, |
| 221 | +URI:ws.LatestAppStatus.URI, |
220 | 222 | } |
221 | 223 | } |
222 | | -returncodersdk.TaskStatusStarting |
223 | | - |
224 | | -casecodersdk.WorkspaceStatusStopping,codersdk.WorkspaceStatusStopped: |
225 | | -returncodersdk.TaskStatusStopping |
226 | | - |
227 | | -casecodersdk.WorkspaceStatusDeleting,codersdk.WorkspaceStatusDeleted: |
228 | | -returncodersdk.TaskStatusDeleting |
| 224 | +tasks=append(tasks, codersdk.Task{ |
| 225 | +ID:ws.ID, |
| 226 | +OrganizationID:ws.OrganizationID, |
| 227 | +OwnerID:ws.OwnerID, |
| 228 | +Name:ws.Name, |
| 229 | +TemplateID:ws.TemplateID, |
| 230 | +WorkspaceID: uuid.NullUUID{Valid:true,UUID:ws.ID}, |
| 231 | +CreatedAt:ws.CreatedAt, |
| 232 | +UpdatedAt:ws.UpdatedAt, |
| 233 | +Prompt:promptsByBuildID[ws.LatestBuild.ID], |
| 234 | +Status:ws.LatestBuild.Status, |
| 235 | +CurrentState:currentState, |
| 236 | +}) |
| 237 | +} |
229 | 238 |
|
230 | | -casecodersdk.WorkspaceStatusFailed,codersdk.WorkspaceStatusCanceling,codersdk.WorkspaceStatusCanceled: |
231 | | -returncodersdk.TaskStatusFailed |
| 239 | +returntasks,nil |
| 240 | +} |
232 | 241 |
|
233 | | -default: |
234 | | -returncodersdk.TaskStatusPending |
235 | | -} |
| 242 | +// tasksListResponse wraps a list of experimental tasks. |
| 243 | +// |
| 244 | +// Experimental: Response shape is experimental and may change. |
| 245 | +typetasksListResponsestruct { |
| 246 | +Tasks []codersdk.Task`json:"tasks"` |
| 247 | +Countint`json:"count"` |
236 | 248 | } |
237 | 249 |
|
238 | 250 | // tasksList is an experimental endpoint to list AI tasks by mapping |
@@ -323,41 +335,14 @@ func (api *API) tasksList(rw http.ResponseWriter, r *http.Request) { |
323 | 335 | return |
324 | 336 | } |
325 | 337 |
|
326 | | -// Fetch prompts for each workspace build and map by build ID. |
327 | | -buildIDs:=make([]uuid.UUID,0,len(apiWorkspaces)) |
328 | | -for_,ws:=rangeapiWorkspaces { |
329 | | -buildIDs=append(buildIDs,ws.LatestBuild.ID) |
330 | | -} |
331 | | -parameters,err:=api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx,buildIDs) |
| 338 | +tasks,err:=api.tasksFromWorkspaces(ctx,apiWorkspaces) |
332 | 339 | iferr!=nil { |
333 | 340 | httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{ |
334 | | -Message:"Internal error fetching task prompts.", |
| 341 | +Message:"Internal error fetching task prompts and states.", |
335 | 342 | Detail:err.Error(), |
336 | 343 | }) |
337 | 344 | return |
338 | 345 | } |
339 | | -promptsByBuildID:=make(map[uuid.UUID]string,len(parameters)) |
340 | | -for_,p:=rangeparameters { |
341 | | -ifp.Name==codersdk.AITaskPromptParameterName { |
342 | | -promptsByBuildID[p.WorkspaceBuildID]=p.Value |
343 | | -} |
344 | | -} |
345 | | - |
346 | | -tasks:=make([]codersdk.Task,0,len(apiWorkspaces)) |
347 | | -for_,ws:=rangeapiWorkspaces { |
348 | | -tasks=append(tasks, codersdk.Task{ |
349 | | -ID:ws.ID, |
350 | | -OrganizationID:ws.OrganizationID, |
351 | | -OwnerID:ws.OwnerID, |
352 | | -Name:ws.Name, |
353 | | -TemplateID:ws.TemplateID, |
354 | | -WorkspaceID: uuid.NullUUID{Valid:true,UUID:ws.ID}, |
355 | | -Prompt:promptsByBuildID[ws.LatestBuild.ID], |
356 | | -Status:mapTaskStatus(ws), |
357 | | -CreatedAt:ws.CreatedAt, |
358 | | -UpdatedAt:ws.UpdatedAt, |
359 | | -}) |
360 | | -} |
361 | 346 |
|
362 | 347 | httpapi.Write(ctx,rw,http.StatusOK,tasksListResponse{ |
363 | 348 | Tasks:tasks, |
@@ -432,35 +417,14 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) { |
432 | 417 | return |
433 | 418 | } |
434 | 419 |
|
435 | | -// Fetch the AI prompt from the build parameters. |
436 | | -params,err:=api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx, []uuid.UUID{ws.LatestBuild.ID}) |
| 420 | +tasks,err:=api.tasksFromWorkspaces(ctx, []codersdk.Workspace{ws}) |
437 | 421 | iferr!=nil { |
438 | 422 | httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{ |
439 | | -Message:"Internal error fetching task prompt.", |
| 423 | +Message:"Internal error fetching task prompt and state.", |
440 | 424 | Detail:err.Error(), |
441 | 425 | }) |
442 | 426 | return |
443 | 427 | } |
444 | | -prompt:="" |
445 | | -for_,p:=rangeparams { |
446 | | -ifp.Name==codersdk.AITaskPromptParameterName { |
447 | | -prompt=p.Value |
448 | | -break |
449 | | -} |
450 | | -} |
451 | | - |
452 | | -resp:= codersdk.Task{ |
453 | | -ID:ws.ID, |
454 | | -OrganizationID:ws.OrganizationID, |
455 | | -OwnerID:ws.OwnerID, |
456 | | -Name:ws.Name, |
457 | | -TemplateID:ws.TemplateID, |
458 | | -WorkspaceID: uuid.NullUUID{Valid:true,UUID:ws.ID}, |
459 | | -Prompt:prompt, |
460 | | -Status:mapTaskStatus(ws), |
461 | | -CreatedAt:ws.CreatedAt, |
462 | | -UpdatedAt:ws.UpdatedAt, |
463 | | -} |
464 | 428 |
|
465 | | -httpapi.Write(ctx,rw,http.StatusOK,resp) |
| 429 | +httpapi.Write(ctx,rw,http.StatusOK,tasks[0]) |
466 | 430 | } |