GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||
GeezerVison is showing github.com — feat(site/src): move chats between projects from the chat menu by ibetitsmike · Pull Request #30895 · coder/coder Conversation
|
| Move to project submenu | Move is off while the chat runs | Project page after the move |
|---|---|---|
![]() |
![]() |
![]() |
Pixel: new ChatTopBar submenu stories, ProjectPage ChatMovedToAnotherProject, and the ChatsSidebar menus without Move to project (archived, shared, subagent) and MoveToProjectOffWhileSubagentRuns, which focuses the blocked item. The open CompactProjectSelector stories lose the hint.
make pre-commit passes. Vitest passes on the 5 touched specs (437 tests), and the Storybook tests of the 4 touched story files pass (134).AgentsPageLayout.test.tsx ends on the older project when two moves arrive in reverse order and it does not refetch. The resetUnloadedChatLists tests fail when the project list family or the unloaded-only check is removed.disabled or the open guard is removed.aria-current on the current project, which site/AGENTS.md leaves to the stories.Xum opened this PR on behalf of @ibetitsmike.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
chatd gains MoveChatToProject, which sets the project of a root chat. Its subagent chats follow because they use the project of the root. The chatstate machine gets a SetProject transition, allowed only from W, E0 and E1, like SetArchived. SetFamilyProject locks the root row before its subagents, in the same order as archiving, so a busy family gets ErrTransitionNotAllowed and a move never overlaps a step. A move to the project the chat is already in changes nothing, even while the chat runs. After the commit, chatd publishes a project_change watch event for each chat of the family. A root chat outside a project now has an empty memory index, so a chat that leaves its project, or whose project is deleted, gets the memories it saw removed at its next turn start.
PATCH /api/v2/chats/{chat} now accepts project_id. A UUID moves an idle
root chat into a project of its owner and organization; uuid.Nil removes
it from its project. The project checks are the ones of chat creation,
now shared by validateChatProjectSelection.
A project that the chat's owner does not own gives 404 even for an
admin, so an admin cannot put a member's chat into another user's
project and expose its memory. A child chat, an archived chat or a
disabled experiment gives 400, and a busy family gives 409. The move is
the last write of the request, so a refused move keeps the earlier
writes, as a refused archive does.
The chat menu (sidebar, top bar, project page) gets a Move to project submenu with the projects of the chat's organization, a check mark and aria-current on the current one, and Remove from project. It shows only for the owner of a root chat that is not archived, with the chat-projects experiment, and it is off with the Archive agent hint while the chat or a subagent runs. moveChatToProject updates the cached chat lists and the chat entity optimistically, and its rollback restores only project_id. Other tabs follow project_change watch events: a move keeps updated_at, so project_id is taken only from that kind, and the open chat refetches. The project page drops a chat that moved away. The composer's project picker no longer says "Can't move to a project later".
There was an error while loading. Please reload this page.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Here are some automated review suggestions for this pull request.
Reviewed commit: eab509f362
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
…ject item keyboard reachable Radix keeps disabled menu items out of keyboard focus, so while the chat or a subagent ran, keyboard and screen reader users could not reach "Move to project" or the hint its aria-describedby names. The trigger now only looks disabled and its submenu refuses to open while blocked.
|
@codex review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Here are some automated review suggestions for this pull request.
Reviewed commit: 96bcfd3375
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
@codex review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
…oject menu The menu reads one organization's projects, so a filter in the component replaces the grouping selector and its lodash import.
Add the SetProject transition to the transition list and the execution state diagram, note that a root chat's project can change after creation, and describe how a moved chat's memory index is brought up to date at its next turn.
The PATCH /api/v2/chats/{chat} section said the endpoint emits no state
transitions unless the request changes archived. A project_id change now
applies SetProject to the chat family, so list its supported states and
refusals.
Brings in origin/main through mike/move-chats-chatd. Chat creation on main now checks project access with chatd.ChatProjectUsableBy, so validateChatProjectSelection uses that check for both creation and moves.
A move accepts the same projects as chat creation, which now include projects shared with the chat's owner. Extend the owner-check test to share the project and move the chat, and describe the rule on UpdateChatRequest.ProjectID.
chatd can now move a root chat, together with its subagent chats, into a project, to another project, or out of its project. Nothing calls this yet. #30894 adds the API. **Stack** (moving chats between projects, bottom first): 1. **This PR**: the move in chatd 2. #30894: `PATCH /api/v2/chats/{chat}` takes `project_id` 3. #30895: **Move to project** in the chat menu 4. #30795: drag a chat onto a project folder in the sidebar **Why:** today a chat keeps the project it was created with. A move must follow the family rules of archiving, because a step that runs during a move would still have the memory tools of the old project. - `chatstate.Tx.SetProject` runs only from W, E0 and E1, like `SetArchived`. `SetFamilyProject()` locks the root row before its subagents, in the same order as archiving, so a busy family gets `ErrTransitionNotAllowed` and nothing changes. - A move to the project the chat is already in changes nothing, even while the chat runs. The check reads the locked root row, so it waits for a move that is still in flight. - Only the root row stores `project_id`, and subagents use the project of the root. After the commit, chatd publishes a new `project_change` watch event for each chat of the family. The move keeps `updated_at`, so lists keep their order. - A root chat outside a project now has an empty memory index. When a chat leaves its project, or its project is deleted, its next turn start commits one memory index update that removes the memories the model saw there. **What to scrutinize:** the lock order and the same-project check under the lock in `SetFamilyProject()` (`chatstate/family.go`), the turn-start condition in `memoryIndexMessage()` (`memory.go`), and whether the `ARCHITECTURE.md` text matches them. **Generated** (`make gen`): `queries.sql.go`, `querier.go`, `dbmock` and `dbmetrics` come from `queries/chats.sql`. `coderd/apidoc`, `docs/reference/api/schemas.md` and `typesGenerated.ts` come from the new watch event kind, which is also why two `chats.test.ts` fixtures gain `project_change: false`. **Architecture doc:** `coderd/x/chatd/ARCHITECTURE.md` lists `SetProject` among the transitions and in the execution state diagram (W, E0 and E1 back to themselves). It also says that a root chat's project can change after creation, and that a moved chat's next turn starts with a memory index update from the old project to the new one. ## Testing - `make pre-commit` passes. `go test` passes for `coderd/x/chatd/chatstate`, `coderd/database/dbauthz` (`TestMethodTestSuite`) and the chatd memory tests. - `TestSetFamilyProjectLocksRootFirst` fails with 55P03 when a subagent row is locked first. `TestSetFamilyProjectKeepsTheCurrentProject` covers the same-project move during a run. The transition matrix test gains `SetProject` cases for W, E0 and E1. - `TestMovedChatUsesNewProject` runs two real turns around a move: the second turn uses the instructions and memories of the new project, and `OutOfProject` fails without the memory index removal. > Xum opened this PR on behalf of @ibetitsmike.
`PATCH /api/v2/chats/{chat}` now takes `project_id`. A project ID moves
the chat into that project, and `uuid.Nil` removes it from its project.
**Stack** (moving chats between projects, bottom first):
1. #30893: the move in chatd
2. **This PR**: the chat update API takes `project_id`
3. #30895: **Move to project** in the chat menu
4. #30795: drag a chat onto a project folder in the sidebar
**Why:** #30893 can move a chat family, and the UI layers above need an
endpoint to call.
- A move accepts the same projects as chat creation, through
`validateChatProjectSelection()`, which this PR extracts from
`postChats()` without a change in behavior.
- A project that the chat's owner cannot use gives 404, even for an
admin. The owner must own the project or hold a grant on it
(`chatd.ChatProjectUsableBy`, the check that chat creation uses since
#30439). So an admin cannot put a member's chat into a project that the
member has no access to and expose its memory.
- A child chat, an archived chat or a disabled `chat-projects`
experiment gives 400. A family that is not idle gives 409 ("Cannot move
an active chat. Interrupt or wait for the chat to finish first."). A
project deleted between the check and the move gives 404.
- The move is the last write in `patchChat()`, so a refused move keeps
the earlier writes of the same request, as a refused archive does.
**What to scrutinize:** the access check in
`validateChatProjectSelection()` and the order of the refusals in
`patchChat()` (`coderd/exp_chats.go`).
**Architecture doc:** the `PATCH /api/v2/chats/{chat}` section of
`coderd/x/chatd/ARCHITECTURE.md` lists the `SetProject` states of a move
and its refusals, and no longer says that only an `archived` change
emits transitions.
**Generated** (`make gen`): `coderd/apidoc`,
`docs/reference/api/chats.md`, `docs/reference/api/schemas.md` and
`typesGenerated.ts` come from `UpdateChatRequest.ProjectID` in
`codersdk/chats.go`.
## Testing
- `make pre-commit` passes, and so does `go test ./coderd -run
TestPatchChatProject` (14 subtests).
- `TestPatchChatProject/AnotherOwnersProject` gets 404 for another
user's project, then moves the chat after the project is shared with the
chat's owner. It fails without the access check, and also with an
owner-only check. `MoveBackWaitsForAPendingMove` ends in the wrong
project when the handler skips the move before the lock.
`ActiveFamilyReturnsConflict` checks the 409 for a running, interrupting
or action-waiting root and for a running subagent.
`PublishesProjectChange` and `AuditsTheMove` cover the watch event and
the audit entry.
- Untested: the 404 when the project is deleted between the check and
the move.
> Xum opened this PR on behalf of @ibetitsmike.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.