@x-apidocgen {"skip": true}
(rw http.ResponseWriter, r *http.Request)
| 2482 | |
| 2483 | // @x-apidocgen {"skip": true} |
| 2484 | func (api *API) workspaceAgentAddChatContext(rw http.ResponseWriter, r *http.Request) { |
| 2485 | ctx := r.Context() |
| 2486 | workspaceAgent := httpmw.WorkspaceAgent(r) |
| 2487 | |
| 2488 | var req agentsdk.AddChatContextRequest |
| 2489 | if !readChatContextBody(ctx, rw, r, &req, false) { |
| 2490 | return |
| 2491 | } |
| 2492 | |
| 2493 | if len(req.Parts) == 0 { |
| 2494 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2495 | Message: "No context parts provided.", |
| 2496 | }) |
| 2497 | return |
| 2498 | } |
| 2499 | |
| 2500 | if len(req.Parts) > maxChatContextParts { |
| 2501 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2502 | Message: fmt.Sprintf("Too many context parts (%d). Maximum is %d.", len(req.Parts), maxChatContextParts), |
| 2503 | }) |
| 2504 | return |
| 2505 | } |
| 2506 | |
| 2507 | // Filter to only non-empty context-file and skill parts. |
| 2508 | filtered := chatd.FilterContextParts(req.Parts, false) |
| 2509 | if len(filtered) == 0 { |
| 2510 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2511 | Message: "No context-file or skill parts provided.", |
| 2512 | }) |
| 2513 | return |
| 2514 | } |
| 2515 | req.Parts = filtered |
| 2516 | responsePartCount := 0 |
| 2517 | |
| 2518 | // Use system context for chat operations since the |
| 2519 | // workspace agent scope does not include chat resources. |
| 2520 | // We verify agent-to-chat ownership explicitly below. |
| 2521 | //nolint:gocritic // Agent needs system access to read/write chat resources. |
| 2522 | sysCtx := dbauthz.AsSystemRestricted(ctx) |
| 2523 | workspace, err := api.Database.GetWorkspaceByAgentID(sysCtx, workspaceAgent.ID) |
| 2524 | if err != nil { |
| 2525 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 2526 | Message: "Failed to determine workspace from agent token.", |
| 2527 | Detail: err.Error(), |
| 2528 | }) |
| 2529 | return |
| 2530 | } |
| 2531 | |
| 2532 | chat, err := resolveAgentChat(sysCtx, api.Database, workspaceAgent.ID, workspace.OwnerID, req.ChatID) |
| 2533 | if err != nil { |
| 2534 | writeAgentChatError(ctx, rw, err) |
| 2535 | return |
| 2536 | } |
| 2537 | |
| 2538 | // Stamp each persisted part with the agent identity. Context-file |
| 2539 | // parts also get server-authoritative workspace metadata. |
| 2540 | directory := workspaceAgent.ExpandedDirectory |
| 2541 | if directory == "" { |
nothing calls this directly
no test coverage detected