feat(agents): chat-history UI (hooks + components) - #578
Draft
MarioCadenas wants to merge 5 commits into
Draft
Conversation
Additive, non-breaking option to resume an existing thread: seeds threadId so the first send() continues that thread instead of creating a new one; changing it re-seeds (switch conversations) without clobbering a server-assigned id. This is the internal seam useAgentThread uses to resume persisted threads. Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Sibling hooks for agent chat history, exported from @databricks/appkit-ui/react/beta:
- useAgentThreads: lists thread summaries (GET {basePath}/threads), with
optimistic deleteThread/renameThread; plain-fetch, revives Dates. Owns the
list, not the active conversation.
- useAgentThread(threadId?): owns one conversation's transcript — loads history
(GET /threads/:id), streams turns via useAgentChat (using its initialThreadId
seam to resume), commits each completed turn, surfaces the server-assigned id
on a new thread, optional URL persistence (default off).
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
…beta) Drop-in components over the two hooks, exported from @databricks/appkit-ui/react/beta: - ThreadList: history sidebar (owns useAgentThreads); controlled selection via activeThreadId/onSelect; per-row dropdown with inline Rename and alert-dialog-confirmed Delete; built on item/scroll-area/dropdown-menu. - AgentThread: one conversation's transcript + composer (owns useAgentThread); resolves the default agent from the plugin client config; onThreadCreated / onTurnComplete callbacks let the page refresh the list (no shared provider). Plain-text messages for v1. Includes a light ThreadList render test. Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Adds the /agent-history route composing <ThreadList> + <AgentThread>, its nav entry, and the chat-history-UI section of the agents plugin doc. Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Re-selecting a thread no longer refetches GET /threads/:id. useAgentThread keeps a per-hook Map<threadId, messages> cache: served on switch when present, written through as turns are sent/streamed so a cached entry stays current (no explicit invalidation). The playground history route also drops the per-select remount so the cache survives — switching threads is now instant and quiet. Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
MarioCadenas
added this pull request to stack #579
September 9, 2026 15:14
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.
What
The client layer for persistent agent chat history: hooks and drop-in components for a conversation sidebar, in
@databricks/appkit-ui/react/beta.Stacked on #576 (backend). Base branch is
feat/agent-persistent-threads; this PR is UI-only (packages/appkit-ui+apps/dev-playground). Review/merge #576 first.How it works
Sibling design (the list and the active conversation are separate lifecycles — CopilotKit-style, not one god hook):
useAgentThreads— lists thread summaries; optimisticdeleteThread/renameThread;refetch.useAgentThread(threadId?)— one conversation's transcript: loads history, streams turns (built onuseAgentChatvia a new additiveinitialThreadIdseam to resume), commits each turn, surfaces the server-assigned id for a new thread. Caches transcripts per thread (write-through) so re-selecting doesn't refetch.<ThreadList>— history sidebar overuseAgentThreads: controlled selection (activeThreadId/onSelect), per-row rename + delete,refetchSignalto refresh from a parent.<AgentThread>— transcript + composer overuseAgentThread; resolves the default agent from the plugin client config;onThreadCreated/onTurnCompletecallbacks let the page refresh the list (no shared provider).Compose them at the page level (the page holds the active thread id). See the dev-playground
Agent Historyroute (/agent-history) for a working example.Verification
useAgentChatseam,<ThreadList>, and the transcript cache), typecheck clean,check:fix/build/docs:buildpass.NOT verified
<ThreadList>/<AgentThread>were not eyeballed in a browser in-loop.Notes
<AgentThread>renders plain-text messages in v1 (markdown + tool-call chips are a planned enhancement).main(dropping the merged backend commits) + force-push. Commits are unsigned — re-sign before merge.Draft.