mirror of
https://github.com/coder/coder.git
synced 2026-10-16 14:48:56 +08:00
- Experiment, behind `chat-projects` (off by default). First of three stacked PRs: #29301 (memory), #29583 (UI). This PR is API only; the screenshots below are from the UI in #29583. - CRUD under `/api/experimental/organizations/{organization}/chats/projects/{project}`. `GET /api/experimental/chats/projects` lists the caller's projects across all organizations. - `project_id` on chat create and as a chat list filter. A chat joins a project only at creation; there is no move. - Projects are identified by ID. Names are display labels (64 characters, description 1024) with no uniqueness constraint. An optional `icon` URL (usually an emoji image under `/emojis`) is capped at 256 characters and audited. - A user can own at most 100 projects across all organizations; creating another answers 409. Creates count and insert under a per-owner advisory lock so concurrent requests cannot overshoot. - Projects are private to their `owner_id`. Members may only create their own, and a chat can only be bound to a project its owner owns. An unreadable or foreign project on chat create answers 404 so IDs cannot be probed; a project from another organization answers 400. - Permissions ride on the `agents-access` role next to chats (after #30004), so whoever can use Coder Agents can use projects. Owners and org admins reach every project. ### Examples Create a project in an organization: ```http POST /api/experimental/organizations/{organization}/chats/projects {"name": "Platform", "description": "Infra and deploy work", "icon": "/emojis/1f680.png"} ``` ```json { "id": "7c0e4a3e-5b1f-4f7d-9a51-2f3c8f6d2b10", "organization_id": "bb640d07-ca8a-4869-b6bc-ae61ebb2fda1", "owner_id": "0ed9befc-4911-4ccf-a8e2-559bf72daa94", "name": "Platform", "description": "Infra and deploy work", "icon": "/emojis/1f680.png", "created_at": "2026-09-30T15:04:05Z", "updated_at": "2026-09-30T15:04:05Z" } ``` List the caller's projects across organizations with `GET /api/experimental/chats/projects` (an array of the object above). Update with `PATCH .../chats/projects/{project}` and any of `name`, `description`, `icon`; delete with `DELETE`, which detaches its chats. Create a chat in the project, and list only its chats: ```http POST /api/v2/chats {"organization_id": "bb640d07-…", "project_id": "7c0e4a3e-…", "content": [{"type": "text", "text": "Plan the deploy"}]} GET /api/v2/chats?project_id=7c0e4a3e-… ``` At the limit: ```json 409 {"message": "You can have at most 100 chat projects. Delete a project to create another."} ``` <details> <summary>Screenshots (UI from #29583)</summary>      </details> --- Generated with Coder Agents on behalf of @f0ssel. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
42 lines
923 B
SQL
42 lines
923 B
SQL
-- name: InsertChatProject :one
|
|
INSERT INTO chat_projects (id, organization_id, owner_id, name, description, icon)
|
|
VALUES (
|
|
COALESCE(sqlc.narg('id')::uuid, gen_random_uuid()),
|
|
@organization_id::uuid,
|
|
@owner_id::uuid,
|
|
@name::text,
|
|
@description::text,
|
|
@icon::text
|
|
)
|
|
RETURNING *;
|
|
|
|
-- name: GetChatProjectByID :one
|
|
SELECT *
|
|
FROM chat_projects
|
|
WHERE id = @id::uuid;
|
|
|
|
-- name: GetChatProjectsByOwnerID :many
|
|
SELECT *
|
|
FROM chat_projects
|
|
WHERE owner_id = @owner_id::uuid
|
|
ORDER BY lower(name), id;
|
|
|
|
-- name: UpdateChatProjectByID :one
|
|
UPDATE chat_projects
|
|
SET
|
|
name = @name::text,
|
|
description = @description::text,
|
|
icon = @icon::text,
|
|
updated_at = now()
|
|
WHERE id = @id::uuid
|
|
RETURNING *;
|
|
|
|
-- name: DeleteChatProjectByID :exec
|
|
DELETE FROM chat_projects
|
|
WHERE id = @id::uuid;
|
|
|
|
-- name: CountChatProjectsByOwnerID :one
|
|
SELECT COUNT(*)::bigint
|
|
FROM chat_projects
|
|
WHERE owner_id = @owner_id::uuid;
|