Repository navigation
feat(workspace): close a chat from its tab, unread count on tabs, first-click star fix (ent#841, #3356) - #3358
Conversation
… a star that sticks on the first click (Abilityai/trinity-enterprise#841, #3356) #3356 — the first star click looked lost because a chat-state read that was already in flight (the 20 s poll, a turn finishing) answered with the pre-click state and `refreshThreads` overwrote the optimistic star. The server had the star; the screen did not; the second click re-sent the same PUT after the stale read had gone by. Local star writes are now held over any read issued before they settled (`createWriteGuard`). A starred, never-used Main is also listed in the sidebar, so the header star on a fresh agent has a Starred row to show. ent#841 — every chat tab but Main gets an × that ARCHIVES the chat (never deletes): PUT/DELETE .../sessions/{id}/archive, one click, an Undo toast, an InlineError under the strip on refusal. One archive rule (operator, 2026-10-08): any archived chat, Reset's retired Main included, leaves the tab strip and the sidebar's active groups and is listed under a collapsed Archived group; opening it there reopens it. This reverses the ent#523 "becomes the newest tab" ruling. The open chat's × is inert while its reply is in flight. Rooms are excluded: the strip lists one agent's 1:1 chats, so a room has no tab. No schema change. Also: a background chat with unread replies shows the sidebar row's blue count on its tab (and in the "N more" menu); the strip is fixed-width, so nothing moves. Fixes #3356 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-button hover ground (+2 gray, Abilityai/trinity-enterprise#841) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…widen to 192px (Abilityai/trinity-enterprise#841) OverflowTabs gains an opt-in `starred` glyph (visible row, menu and mirror, in the tab's own ink — no new colour). FIXED_TAB_WIDTH goes w-40 -> w-48 so the star, the unread count and the close × fit beside the label. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6518ab2 to
450d727
Compare
…-train, #3358) Every close shows the same words, so the toast's timer, restarted only by a watch on the message text, never restarted for a second close: chat B's Undo disappeared on chat A's timer. The restart is now keyed on a per-close sequence number set where closeChat assigns undoClose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
merge-train: one mechanical fix pushed, A second close now restarts the Undo toast's clock. New spec Body: added Approved at the batch gate by the operator: the two-class gray growth on Left as is, for follow-up: unread on an archived chat has no visible mark on the collapsed Archived group; no HTTP-level test of the two archive routes, the refused-close path or the busy-inert close button; the toast is a new component beside |
…son rebuilt, all entries kept Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
Three Workspace changes in one PR.
1. Starring a chat works on the first click — Fixes #3356
Root cause.
refreshThreadsreplaces the whole chat-state map with whatGET /chat-statereturns. A read already in flight when the star is clicked (the 20 s poll, a turn finishing) answers with the pre-click state and overwrites the optimistic star. The server has the star and the screen does not; the second click "works" because it re-sends the same PUT after the stale read has gone by.Fix. Local star writes are held over any read issued before they settled (
portalUtils.createWriteGuard). Only a read that started after the write settled retires the override.Second defect found on the way: starring a never-used Main from the header filled the header star, but the sidebar filters an unused Main out, so nothing appeared under Starred. A starred unused Main is now listed.
2. Close a chat with an × on its tab — abilityai/trinity-enterprise#841
sm:up, always drawn on touch, keyboard reachable, and also on the rows of the "N more" menu. One click, no confirmation.PUT/DELETE /api/enterprise/client-portal/agents/{name}/sessions/{id}/archive. Roster- then session-scoped, uniform 404, idempotent, 60/min. The live Main is a named 409. No schema change.InlineErrorunder the strip.OverflowTabsgains an opt-inclosabletab. A strip with no closable tab renders the same DOM as before.Decisions recorded (asked of the operator, 2026-10-08):
archived_atReset's retired Main carries, and every archived chat leaves the tab strip and the sidebar's active groups for a collapsed Archived · N group. Opening a chat there reopens it. This reverses the ent#523 ruling that a Reset archive "becomes the newest tab". The chat on screen keeps its tab even when archived.3. Unread count on the tab
A chat with unread replies that is not on screen shows the sidebar row's count on its tab in the same solid blue (
badgeVariant: 'primary'), and in the "N more" menu. The strip is fixed-width, so the count shortens that tab's label and moves nothing beside it.4. The star on the tab, and wider tabs
A starred chat's tab draws a filled star before its label, in the tab's own ink (no new colour), in the strip and in the "N more" menu.
FIXED_TAB_WIDTHgoes fromw-40(160px) tow-48(192px) so the star, the unread count and the × fit beside the label.Not in this PR
abilityai/trinity-enterprise#842 (a star in the composer row) is not implemented: the operator decided to keep the existing header star and add no new control.
Tests
tests/unit/test_ent841_close_chat.py— 8 passed. Wider portal/workspace backend unit set: 876 passed.vitest run): 293 files, 5007 tests passed. New:portalStarRace,portalChatTabsClose,overflowTabsClosable.mount.@smoke: 103 passed, 7 skipped. New hermetic specs:workspace-star-first-click.spec.jsholds a/chat-stateread open across the click. All 3 cases fail on the base commit and pass here.workspace-close-chat.spec.jscovers close → neighbour → Archived → Undo, reopen from Archived, and the tab unread count with equal tab widths.Not run: the new archive routes against a live backend. The local dev stack serves a different checkout, so they are covered by the service-level unit tests and the hermetic e2e fake.
The raw-colour baseline is re-frozen in its own commit:
OverflowTabs.vue+2 gray for the ×'s hover ground.Docs
requirements §5.41 (new) and the superseded line in §5.23,
architecture/workspace.md, two feature flows,tests/registry.json.Fixes #3356
Fixes abilityai/trinity-enterprise#841
🤖 Generated with Claude Code