feat(channels): stream agent turns into threads, read Activity per mention - #3534
feat(channels): stream agent turns into threads, read Activity per mention#3534adamleithp wants to merge 3 commits into
Conversation
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
Reviews (1): Last reviewed commit: "feat(channels): stream agent turns into ..." | Re-trigger Greptile |
| const threadChannelId = threadTaskId | ||
| ? folderChannelIdFor( | ||
| items.find((item) => item.taskId === threadTaskId)?.channelName ?? null, | ||
| ) |
There was a problem hiding this comment.
Selected Mention Loses Its Channel
When the same task has mentions in multiple channels, this lookup takes the channel from the first matching feed item rather than the mention that opened the panel. Clicking another mention can therefore give ThreadSidebar the wrong channel ID and make “Open full” navigate to the wrong channel.
| storage: electronStorage, | ||
| // Sets don't survive JSON; store the ids as an array and rebuild on load. |
There was a problem hiding this comment.
If a mention is opened before the asynchronous persisted state finishes loading, electronStorage drops writes during that first-read window and hydration can replace the in-memory set with the saved IDs. The sidebar updates for the current session, but the mention becomes unread again after restart.
…ntion Agent turns and permission asks now land in a channel thread as messages, and Activity marks a mention read when you open its thread rather than when you open the page. Thread messages: - Render agent rows from `author_kind`/`event`/`payload` instead of `author`, which is null by design on agent rows and read as "Unknown". - Drop the durable `turn_complete` copy of a run the viewer is already watching stream, so the live turn doesn't get swapped at the end. - Break an agent's turn into paragraphs at tool-call boundaries instead of gluing every chunk into one clump. - Frame long bodies in a capped, bordered scroll window that opens on the last line and, while streaming, follows the output. Activity: - Open a mention's thread beside the list instead of navigating to the task. - Track read per mention, so the badge survives a glance at the page. - Highlight the row whose thread is open. - Count a task's thread as "being viewed" when its panel is open, so a notification doesn't announce what's already on screen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The committed lockfile was generated without pnpm-workspace.yaml's overrides applied, so it dropped the top-level overrides:/patchedDependencies: blocks and resolved overridden deps to their un-overridden versions (plain vite instead of rolldown-vite, undici 6.27.0 instead of the pinned 8.4.1, node-abi 4.33.0 instead of 3.92.0). pnpm install --frozen-lockfile rejected this with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH, failing every CI job at the install step. Regenerated with pnpm install --lockfile-only so the lockfile matches the workspace config again. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LakkSu5zcYbTzMKwurvBD4
a2eaa7d to
03b212e
Compare
#3380 landed on main after this branch was cut and already renders agent thread rows (author_kind on TaskThreadMessage, robot avatar + "Agent" label, no hover menu) inside ThreadMessageRow. Remove this branch's parallel copy: the duplicated TaskThreadMessage fields the rebase glued in, the separate AgentThreadRow component, and isAgentThreadMessage, whose only consumer was that branch. Keep the TaskThreadMessageEvent union and point the existing event field at it — the one piece #3380 didn't cover. Generated-By: PostHog Code Task-Id: a0f85df1-4a8f-4467-8051-e471b5e95009
|
Rebased onto
Typecheck, biome, host boundaries, and core/ui tests all green after the trim. |
Agent turns and permission asks now land in a channel thread as messages you can read in place, and Activity treats a mention as read when you open its thread — not when you glance at the page.
Thread messages
turn_complete/permission_requestare typed. Added aTaskThreadMessageEventunion and pointedTaskThreadMessage.eventat it, so agent rows render from a stable key rather than a freeform string.turn_completerow keyed bypayload.run_id.visibleThreadMessagesdrops that copy for a run the viewer is already streaming — the streamed turn is the one they watched arrive, and swapping it for the server's copy at the end made the message jump. A row with no run id is kept: a possible duplicate beats dropping the only copy.ThreadScrollBody, built on quill'sChatStream): capped height, scrolled for the rest, so one essay doesn't push the next row off screen. It follows live output while streaming, and opens on the last line once finished. The border lives on the wrapper, not the stream —ChatStream's mask would otherwise eat a border on its own element exactly when there's more to read.Activity
isMentionUnread/countUnreadMentionsreplace the global watermark;lastSeenAtstays as a read-only historical watermark so the switch doesn't resurface old mentions as unread.bg-fill-selected). Keyed on the mention, not the task — the panel tracks a task, and a task can be mentioned in several rows, so keying on it alone lit all of them for one click.Setdoesn't round-trip through JSON, so it's stored as an array and rebuilt on load.Notifications
activeNotificationTargetnow considers the panel — a collapsed panel is a rail with nothing legible in it, so it doesn't count. The host'sgetActiveTargetis thin glue over it.Notes
@posthog/quill0.3.0-beta.24→0.3.0-beta.25forChatStream.permission_requestrows render as text; their Approve/Deny actions aren't wired yet.TaskMentionDTOcarries noevent/payload/author_kind(Render agent thread updates: markdown links and agent-authored messages #3380 only added them toTaskThreadMessage), which is also why an agent's mention still shows as "Unknown" in the list. Needs a../posthogchange; not in this PR.main, unrelated and untouched here:@posthog/gitdetectDefaultBranch > prefers remote HEAD over local detection.Testing
pnpm typecheck,pnpm lint,node scripts/check-host-boundaries.mjs(no new violations) all clean.pnpm test: green except the pre-existing@posthog/gitfailure above.visibleThreadMessages(threadTimeline),isMentionUnread/countUnreadMentions(mentionActivity), tool-call turn breaks (threadAgentTurns),activeNotificationTarget.🤖 Generated with Claude Code