feat(web): chat timeline overlay + zero-brain Get Online + unified activity log#565
Merged
feat(web): chat timeline overlay + zero-brain Get Online + unified activity log#565
Conversation
Disables monaco typescript semantic validation on beforeMount so files opened in the ide tab no longer render every import as a red "cannot find module" squiggle — the in-browser tsserver has no project graph so its semantic diagnostics were pure noise. Syntax errors are still surfaced; only unresolved-symbol noise is hidden. Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Adds server-derived user-turn grouping to the application chat plus static publish/deploy activity bubbles, so the thread stays compact and every long-running operation has a visible home in the conversation. - new GetChatTurnGroupsUseCase walks persisted messages server-side, returns completed turn groups (collapsed by default) and the latest in-flight turn as currentTurn (expanded by default), with hiddenMessageIds so the flat thread skips anything the cards own - unit tests cover empty feed, step-tagged skipping, live turn promotion, chronological ordering, long-message truncation, and orphan assistant messages - new /api/interactive/chat/:featureId/turn-groups thin route delegates to the use case - TurnGroupCard renders completed cards with an emerald check and an in-progress card with a fuchsia gradient spinner, pinned "working on your request..." title, non-collapsible while live - TurnGroupList hydrates cards from the main chat cache and renders the streaming indicator inline inside the in-progress card - useChatRuntime accepts hiddenMessageIds and suppressStreamingIndicator options, exposes rawMessages and streamingState for the host - ChatTab wires everything through a new applicationId prop so application chats get the full experience while repo and global chats are untouched - OperationBubble polls existing operation_log_entries endpoints and renders a static chronological card per publish or deploy, shown after the thread so users see the full history in place Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Turns the "Get online" state into a fully autonomous pipeline and ships a single chronological log surface for every long-running operation the button can trigger. - new SmartDeployLogsDrawer merges GitRemoteCreate, CloudDeploy, and RepoSync log entries into one timeline sorted by createdAt, each row tagged with a coloured kind chip (github sky, cloud fuchsia, sync emerald) so the source of every line stays obvious - SmartDeployButton gets a persistent scroll-icon segment after the chevron that opens the unified drawer, always visible so users never have to hunt for a per-op log affordance - handleGetOnline in SmartDeployCluster runs the full best-effort pipeline on a single click: ensure owners, create github remote with the default owner plus slugified name, refresh git status, auto-select the first connected cloud provider, initiate deploy - the drawer auto-opens the moment any primary action fires and polls every 1.5s while running so the pipeline is never silent; toasts surface the exact reason when no github owner or no connected provider is available instead of reverting the button - rocket tone plus gradient icon chip on the "Get online" button so it pops as the primary call to action; workingSource gains a getOnline variant that pins the label on "Getting online..." through the entire pipeline to kill intermediate state flicker - oneClickRunning flag in useSmartDeployState dominates every other branch so the button cannot flash through deploy or save while the github create and cloud deploy trade batons - top-bar buttons and tabs switch from h-9 inside an h-12 bar to an explicit h-12 so the row sits flush top-to-bottom with no outer padding band; explicit height avoids h-full-in-flex-items-center resolution quirks Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Drops the cards from rounded-2xl (16px) and rounded-xl (14px) to rounded-sm (2px) on both the live ApplicationCard and the new application placeholder so every tile on the dashboard has the same sharp vs-code-tab edge. Fixes a visual mismatch where the placeholder stayed rounded after the main card was tightened. Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Unifies the application chat around a single chronological timeline driven by the three-layer model documented in features/chat/CLAUDE.md: raw events (Layer 1) flow through a pure synchronous grouping layer (Layer 2) that produces high-level friendly cards (Layer 3). Default view shows only the user request plus a high-level activity indicator — every raw tool event is hidden behind a progressive-disclosure chevron. - new CLAUDE.md in features/chat/ codifies the three-layer rules with explicit do/don't guidance, file responsibilities, and anti-patterns so future edits cannot break the flow - client-side computeTurnGroupsFromMessages replaces the stale server query for the web view, runs synchronously on every render via useTurnGroupsView so the overlay updates in the same tick as SSE deltas arrive - in-progress card is demoted to completed when status.isRunning goes false, so finished conversations never leave a permanent "Working on your request..." card pretending work is still in flight - useChatRuntime gains hideAllMessages option — when true the flat assistant-ui thread returns an empty message list and the overlay owns the entire visible surface, closing the last gap where raw bubbles could leak - TurnGroupCard splits into a condensed slot (user request plus friendly streaming indicator, default visible) and a details slot (raw thinking / read / output bubbles, revealed on chevron click); the user message never renders twice - new CondensedStreamingIndicator shows only a spinner plus a high-level activity line (tool status, "Thinking...", "Working ...") — never the raw assistant stream text, so the layer rule holds through the whole pipeline - ErrorRecoveryBanner surfaces effectiveStatus failures at the top of the chat pane with a prominent Try again button wired to onResumeWorkflow, replacing the silent red pill dead end - old InitialRequestBubble removed; the CurrentTurnCard is now the single anchor for every user request, pinned in its chronological position rather than at the top - chronological ordering enforced: error banner -> StepTracker -> completed turn cards (oldest first) -> in-progress turn -> operation bubbles -> pending interaction Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Finalises the one-click "Get online" pipeline, detaches the activity log button from the split, and hardens the unified logs drawer against hung requests. - handleGetOnline is fully zero-brain: ensure owners, create the github remote with the default owner plus slugified name, pick the first connected cloud provider, fire deploy. The ONLY stop conditions are missing tokens — github connect goes to the PublishToGitHub modal, missing cloud provider opens the ConnectProviderModal on the first enabled provider. No toasts, no panel side-trips, one click equals one specific next action - activity log icon button is detached from the SmartDeployButton split, rendered as a standalone 28x28 muted icon next to the primary action so it reads as a neighbour, not a welded third segment - SmartDeployLogsDrawer gains AbortController per-request timeouts (6s), splits hasLoadedOnce from background polling so the "Loading logs..." spinner only appears on first fetch, adds a manual Refresh button, and surfaces per-scope errors as a soft banner while still rendering the entries that did come back — no more stuck-on-loading drawer - Drawer empty state distinguishes "could not load" from "no activity yet" so the user knows whether to retry or just wait - configure state kind removed from use-smart-deploy-state — the button stays "Get online" in every pre-live state, the pipeline itself handles the token gates inline Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Eliminates the last two client-side polling paths in the application page (refetchInterval on the loader query, setInterval in the activity drawer) and replaces them with typed, backend-owned SSE deltas. The server remains the sole poller; the client patches state in-place as typed events arrive. Backend: - New NotificationEventType values ApplicationUpdated + OperationLogAppended with scoped payload models, plumbed through TypeSpec codegen. - New IOperationLogEventBus port + in-memory adapter. The SQLite operation-log repo publishes after each successful INSERT so clients see every appended log line within a tick, not on a 2s poll. - StreamAgentEventsUseCase diffs applications rows per poll and re-emits bus publishes as notifications. Per-connection cache seeds silently on reconnect. Client: - useApplicationUpdate + useOperationLogAppend selector hooks on the shared agent-events context. - ApplicationPageLoader patches the React Query cache in-place on event, zero HTTP refetch. Removes the prior invalidate-on-any-event hack. - SmartDeployLogsDrawer appends new entries with dedup by id. Initial hydration fetch on open is preserved; setInterval is gone. Also bundles prior chat-timeline / smart-deploy polish on the branch: scaffold stdout streaming to operation logs (enables the ApplicationSetup kind to populate the drawer), bubbled chat-timeline groupings, and AppTopBar / SmartDeployButton / SmartDeployCluster layout polish. Spec: specs/090-application-sse-deltas/ Invariants: DB is source of truth; SSE is a hint. Missing an event is never fatal — next read rehydrates from the row. No client timers. Tests: 20 new spec-scoped unit tests. Full suite green (6604 unit + 763 integration). typecheck + lint + tsp + storybook clean. Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Contributor
blackpc
pushed a commit
that referenced
this pull request
Apr 20, 2026
# [1.189.0](v1.188.0...v1.189.0) (2026-04-20) ### Features * **web:** chat timeline overlay + zero-brain Get Online + unified activity log ([#565](#565)) ([b48e643](b48e643)), closes [Hi#level](https://github.com/Hi/issues/level) [hi#level](https://github.com/hi/issues/level) Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two large UX upgrades to the application page, ready to replace the current
chaotic flat thread + the half-working Get Online button.
Three-layer chat timeline (no raw bubbles by default)
codifies the strict three-layer model: Raw events → Overlay grouping layer → High-level UI.
Every rule is spelled out (single chronological column, no direct Layer 1 rendering,
pure synchronous grouping, default collapsed friendly titles, optimistic rendering,
extensible raw feed for system/debug events, no competing rendering paths) so future
edits can't re-introduce chaos.
on every render — zero stale-query windows, zero race flicker.
`CondensedStreamingIndicator` ("Using tool: Bash", "Thinking…", "Working…"),
never the raw assistant stream. Chevron expands to full raw history.
finished conversations don't leave a stale "Working on your request…" card pinned.
returns an empty message list and the overlay owns the entire visible surface.
"Try again" button wired to `onResumeWorkflow`, replacing the silent red pill dead end.
every user request, pinned in its chronological position rather than at the top.
long-message truncation / empty-message fallback / orphan assistant).
Zero-brain Get Online pipeline + unified activity log
(slug + private) → pick first connected cloud provider → fire deploy. The ONLY stop
conditions are missing tokens — GitHub connect goes to `PublishToGitHubModal`,
missing provider opens `ConnectProviderModal` on the first enabled provider.
No toasts, no panel side-trips, one click equals one specific next action.
flicker as git-create and cloud-deploy trade batons.
visibly pops as the primary call to action.
entries into a single chronological timeline; each row wears a coloured kind chip
(GitHub sky, Cloud fuchsia, Sync emerald).
flashes back to "Loading logs…" once data is on screen.
still rendering entries that did come back.
muted icon next to the primary action. Always visible, not welded to the deploy.
`h-12` so the row sits flush top-to-bottom with no outer padding band.
Miscellaneous
TypeScript files no longer show "Cannot find module" red squigglies for every
import. Syntax errors stay visible.
"New application" placeholder — matched to the dashboard tile family.
Commits
Test plan
as: in-progress turn card (only user request visible) → StepTracker → completed
setup card, no raw `Thinking`/`Read`/`Output` bubbles leaking into the thread.
emerald card and a new in-progress fuchsia card appears chronologically after it.
the user message.
shows entries from all three operation scopes (GitHub / Cloud / Sync) merged
by timestamp with coloured kind chips.
each click opens the right inline connect modal (no panel side-trips).
pipeline runs end-to-end with the button pinned on "Getting online…" throughout.
squigglies on imports, syntax errors still visible.
error recovery banner appears at the top of the chat with a working "Try again"
button.
🤖 Generated with Claude Code