Skip to content

Feat/conversation UI assistant UI - #265

Merged
MiniMax-AI-Dev merged 4 commits into
mainfrom
feat/conversation-ui-assistant-ui
Aug 26, 2026
Merged

Feat/conversation UI assistant UI#265
MiniMax-AI-Dev merged 4 commits into
mainfrom
feat/conversation-ui-assistant-ui

Conversation

@liyangbing

Copy link
Copy Markdown
Collaborator

What & why

Migrate the conversation UI from a hand-rolled ChatStream/MessageRow/ComposerForm (~800 LOC) to @assistant-ui/react's ExternalStoreRuntime, achieving Claude/Codex-grade streaming chat UX. Also fixes the marketplace tab showing MCP directory data incorrectly, adds proper markdown typography, and sorts agents by newest-first.

How

Conversation UI (core change):

  • New parsar-chat-runtime.ts: bridges existing timeline REST API + SSE stream into assistant-ui's useExternalStoreRuntime. Handles message conversion, SSE lifecycle (delta/tool/thinking/permission/done/error), smart error suppression (completed-before-subscribe, user-cancelled, late-error).
  • New ParsarThread.tsx: Claude-style layout using ThreadPrimitive + MessagePrimitive.GroupedParts for chain-of-thought grouping, inline composer with Send/Stop toggle via ComposerPrimitive.
  • New ParsarChatView.tsx: orchestrator replacing ChatStream — wires runtime, interaction cards, working steps, queued run indicators.
  • New ParsarToolCallCard.tsx: expandable tool call card with icon dispatch, args summary, elapsed time.
  • Removed ~800 lines of old streaming code from ConversationsPage.tsx and api-conversations.ts.

Backend zero changes for conversation streaming — all existing SSE/REST APIs consumed as-is.

Additional fixes:

  • MarketplaceTab.tsx: default to PublishedMarketplaceTab instead of MCPDirectory when no item selected.
  • AgentsPage.tsx + store.sql: sort agents by created_at DESC (newest first).
  • style.css: add @tailwindcss/typography plugin for proper prose markdown rendering.

Trade-offs:

  • Runtime error metadata tunneled via null-byte sentinel in text content (documented in code; fragile but functional until assistant-ui adds native metadata support).
  • "View run →" link on failed messages not yet ported (documented as TODO).
  • Tool call elapsed time from useToolCallElapsed returns undefined for persisted messages (streaming WorkingSteps still works correctly).

Verification

  • pnpm typecheck — 0 errors
  • eslint — 0 errors
  • vite build — passes (367ms)
  • go build ./server/... — passes
  • make sqlc-generate — regenerated
  • Manual smoke: streaming conversation (verified per-token delta with Claude Code 2.1.246), send/stop/cancel, conversation switching, marketplace tab filter, agents sort order

Notes for reviewers

  • The @tailwindcss/typography addition is required for markdown prose classes to render — without it all prose styling is no-op.
  • useAgentRunStream was intentionally deleted from api-conversations.ts — its logic now lives inside parsar-chat-runtime.ts.
  • Claude Code CLI must be ≥2.1.x for per-token streaming (--include-partial-messages flag); older versions emit a single delta with the full response.
  • Follow-up PR planned: full Codex-style UI theming (navigation, fonts, spacing) — deliberately out of scope here.

…pliance plugin

Plugin SDK: ctx.hooks.on(eventName, handler) for registering hook handlers.
Plugin-host MCP transport: hooks/list + hooks/invoke JSON-RPC methods
with 5s per-handler timeout and first-wins semantics.

Go server: pluginhook.Invoker spawns plugin-host, calls hooks/invoke via
JSON-RPC. Integrated into run_stream.go event loop — intercepts
EventPermissionRequest before persistence. Auto-deny/allow decisions
skip interaction creation and auto-submit back to the daemon.

New event kinds: permission.auto_denied, permission.auto_allowed —
persisted with hook_reason/hook_plugin metadata.

SSE wire: permission events carry hook_decision field so the frontend
can skip the approval card for auto-decided requests.

Frontend: RunsPage timeline shows ShieldAlert/ShieldCheck icons for
auto-decided permissions. i18n keys added (en-US + zh-CN).

Example: @internal/compliance-approval plugin demonstrates:
- rm -rf, DROP TABLE → auto-deny
- kubectl delete, curl|bash → OA escalation + ask_human
- ls, cat, git status → auto-allow
- default → ask_human (normal flow)

Verified: make check passes, end-to-end JSON-RPC test confirms all
decision paths produce correct results.
Replace the hand-rolled ChatStream/MessageRow/ComposerForm (~800 LOC)
with assistant-ui's ExternalStoreRuntime backed by a custom adapter.

New architecture:
- parsar-chat-runtime.ts: bridges timeline API + SSE into assistant-ui
- ParsarChatView.tsx: orchestrator (header, runtime provider, interactions)
- ParsarThread.tsx: Claude-style thread (grouped reasoning, tool calls,
  inline composer with Send/Stop toggle, auto-scroll)
- ParsarToolCallCard.tsx: collapsible tool call card

Key improvements:
- Streaming markdown rendering (react-markdown via assistant-ui)
- Smart auto-scroll with detach on manual scroll-up
- Per-message rendering isolation (no full-tree re-render per token)
- Chain-of-thought grouping for reasoning + tool calls
- Proper SSE error handling (completed-before-subscribe, user-cancelled,
  late-error-with-content all collapse silently)
- Timeline polling paused during active streaming
- Conversation switch properly resets stream state

Backend: zero changes. All existing SSE/REST APIs consumed as-is.

Dependencies added:
- @assistant-ui/react ^0.15.16
- @assistant-ui/react-markdown ^0.14.12
- fix(capabilities): marketplace tab now shows PublishedMarketplaceTab
  instead of MCPDirectory when no item is selected. Switching to the
  marketplace tab with mcp filter no longer incorrectly displays the
  MCP directory catalog.

- fix(agents): sort agents list by created_at descending (newest first)
  both in the SQL query and as a frontend fallback sort.

- feat(web): add @tailwindcss/typography plugin so prose classes render
  proper markdown formatting (paragraph spacing, list bullets, code
  blocks, headings) in the conversation thread.
@MiniMax-AI-Dev
MiniMax-AI-Dev merged commit 8d26b61 into main Aug 26, 2026
13 checks passed
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.

2 participants