Skip to content

feat(agents): chat-history UI (hooks + components) - #578

Draft
MarioCadenas wants to merge 5 commits into
feat/agent-persistent-threadsfrom
feat/agent-thread-history-ui
Draft

feat(agents): chat-history UI (hooks + components)#578
MarioCadenas wants to merge 5 commits into
feat/agent-persistent-threadsfrom
feat/agent-thread-history-ui

Conversation

@MarioCadenas

Copy link
Copy Markdown
Collaborator

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; optimistic deleteThread / renameThread; refetch.
  • useAgentThread(threadId?) — one conversation's transcript: loads history, streams turns (built on useAgentChat via a new additive initialThreadId seam 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 over useAgentThreads: controlled selection (activeThreadId / onSelect), per-row rename + delete, refetchSignal to refresh from a parent.
  • <AgentThread> — transcript + composer over useAgentThread; resolves the default agent from the plugin client config; onThreadCreated / onTurnComplete callbacks 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 History route (/agent-history) for a working example.

Verification

  • 33 unit tests (both hooks, the useAgentChat seam, <ThreadList>, and the transcript cache), typecheck clean, check:fix / build / docs:build pass.
  • Backend endpoints this consumes were live-tested against a real Lakebase (see feat(agents): persistent Lakebase thread store #576).

NOT verified

  • UI visual render — the route serves and every endpoint it uses is verified, but the rendered <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).
  • Squash-merge repo: after feat(agents): persistent Lakebase thread store #576 merges, this branch needs a rebase onto main (dropping the merged backend commits) + force-push. Commits are unsigned — re-sign before merge.

Draft.

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
MarioCadenas added this pull request to stack #579 September 9, 2026 15:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant