- Add AppState module in core for managing app state persistence
- Add app-state IPC handlers for reading/writing onboarding state
- Hydrate onboarding state from file system on app startup
- Prevent flash by showing blank screen during hydration
- Update onboarding store to sync with file system
- Improve MulticaIcon with enhanced animation states
- Minor UI fixes in chat and device list components
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace @hugeicons/react with lucide-react across all packages
- Update all components to use Lucide icon components
- Add silent option to store refresh methods to control toast display
- Simplify icon usage with direct component imports
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Scroll cursor into view on content changes (e.g., Shift+Enter)
- Add scroll threshold and margin for better edge handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add remark-math + rehype-katex plugins to render inline ($...$) and
display ($$...$$) math expressions. Includes dark mode CSS overrides,
streaming block splitting for math fences, and math range exclusion
in link preprocessing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace ring-[3px] with ring-3 in button and input
- Use data-horizontal/data-vertical in separator
- Fix sidebar data attributes and RTL support
- Simplify tooltip provider nesting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Separate entrance animation from hover animation
- Use state to track entrance completion
- Hover spin only activates after entrance is done
- Shorten entrance animation to 0.6s
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add radio button style indicators for provider selection
- Add HoverCard component for provider setup help
- Add Link component for external URLs
- Add Popover component (dependency for HoverCard)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Display the label (or truncated task) as subtitle for SpawnSession tool
calls, so users can see what each spawned session is working on.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add chart icon, smart subtitle (shows action + ticker, e.g. "price_snapshot AAPL"),
and running state label for the data tool in the tool call UI component.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Simplify permissions step to single centered column
- Replace per-item switches with single "I understand" checkbox
- Add capabilities info card with clean dividers
- Add trust note section for privacy messaging
- Rename step from "Permissions" to "Privacy" for clarity
- Add fade-in animation for step transitions
- Add shadcn checkbox component
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Font unification:
- Add @fontsource packages for Geist Sans, Geist Mono, Playfair Display
- Create fonts.ts for centralized font imports
- Import fonts in both web (layout.tsx) and desktop (main.tsx)
- Register --font-brand in Tailwind @theme inline block
- Fix font-brand class usage (replace arbitrary value syntax)
Design system documentation:
- Add comprehensive design philosophy comments to globals.css
- Document typography choices (why Geist, why Playfair for brand)
- Document color system approach (neutral grays, semantic colors only)
- Explain component library customizations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Welcome step before the 4-step onboarding flow
- Welcome page introduces Multica with brand title (Playfair Display font)
- Display three core principles: Your AI, Your Machine, Your Control
- Add entrance spin animation to MulticaIcon component
- Welcome page has no stepper, only shown after clicking "Start Exploring"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change primary from custom purple oklch(0.51 0.23 277) to shadcn
default neutral near-black/near-white. Also reset chart and sidebar
primary colors to shadcn defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the new channel system design: FIFO pendingRoutes queue,
activeRoute/activeAcks state, agent_start/agent_end lifecycle,
InboundDebouncer, typing/reaction lifecycle, and UI metadata stripping.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add stripUserMetadata() to remove timestamp envelopes and media type
labels ([Voice Message] Transcript:, [Image] Description:, etc.) that
are injected for LLM context but should not appear in the desktop UI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the agent fails due to missing API key, the error banner now
shows a "Configure" button that opens the same ApiKeyDialog (or
OAuthDialog) used on the home page. After successful configuration
the error clears and the user can immediately start chatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the agent encounters an error (e.g. no API key configured),
the Chat UI now shows an error banner instead of silently hanging.
The user can still type and retry after fixing their configuration.
- Add AgentErrorEvent to SDK stream types
- Forward agent_error events through IPC to renderer
- Handle error events in useLocalChat hook
- Keep chat input enabled for AGENT_ERROR (retriable)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Return latest messages by default instead of oldest. Support paginated
loading of older messages when scrolling up via IntersectionObserver,
with scrollHeight compensation to preserve scroll position.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move gateway-specific chat logic into dedicated useGatewayChat hook.
useChat remains a pure state hook with no IO. Update ChatView props,
remove legacy chat.tsx and connect-prompt.tsx.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract StatusWrapper to replace duplicated fullscreen/inline wrapper in
ConnectionStatus and RejectedStatus. Extract PairingHeader to replace
repeated title+description blocks in mobile and desktop views. Make
desktop container mb responsive (mb-14 sm:mb-28).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move all CSS out of globals.css into inline styles within each component.
Loading (Apple-style radiating lines) for passive waiting states;
Spinner (3x3 grid pulse) for active processing/execution states.
Switch device-pairing ConnectionStatus from Loading to Spinner.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract ChatView from web chat-page into packages/ui as a prop-driven
component (accepts UseChatReturn shape, no transport dependency)
- Move DevicePairing from apps/web to packages/ui with locally defined
ConnectionIdentity type (no @multica/hooks dependency)
- Create @multica/hooks package with useGatewayConnection and useChat
(moved from apps/web/hooks)
- Add isLoadingHistory state to useChat with skeleton loading in ChatView
- Add MulticaIcon (pure CSS asterisk via clip-path, adapts to theme)
- Slim web chat-page.tsx from 188 to 65 lines (just wires hooks to UI)
Desktop can now reuse ChatView and DevicePairing directly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ExecApprovalItem for human-in-the-loop command approval with uniform
outline buttons (Allow/Always/Deny), countdown timer, and command display.
Refine ToolCallItem and ThinkingItem: transparent by default, unified
bg-muted/30 wrapper on expand with seamless button+content integration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ThinkingItem component for displaying LLM extended thinking. Renders
as a collapsible row (matching ToolCallItem style) with expand to reveal
thinking text. MessageList now extracts and renders ThinkingContent blocks
before text content, matching the LLM output order.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add break-words to markdown-content wrapper so URLs and file paths in
<p>, <li>, <a> etc. wrap at container boundary instead of overflowing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add @utility container (w-full max-w-4xl mx-auto) to globals.css and
create a reusable Loading spinner component for consistent loading states.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a "verifying" connection state between "connected" and "registered"
so collaborators see clear feedback while waiting for the device owner
to approve their connection on Desktop.
Changes across the stack:
- Hub: verify RPC returns isNewDevice flag to distinguish new vs whitelisted
- SDK: emit "verifying" state before verify RPC, pass isNewDevice through
- Store: capture isNewDevice via onVerified, capture rejection via onError
- UI: ConnectionStatus (waiting), RejectedStatus (declined), and
verify success overlay (approved) replace the stuck scanner screen
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace overlay approach with conditional rendering for paste validation
states. Success shows checkmark icon with 600ms delay before connecting,
error shows alert with message and auto-resets after 2s. Improves
Connecting text visibility.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rewrite user-facing text to be source-agnostic and result-focused:
- Connect prompt: "Scan to start" / "Scan a QR code to use an Agent"
- Empty chat: "Your Agent is ready"
- Input placeholder: "Ask your Agent..." / "Scan QR code to get started"
- Bump chat input font to text-base for mobile readability
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace sheet-based scanner with inline QrScannerView, add scan/paste
mode toggle for desktop, and fullscreen camera overlay for mobile.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rewrite QrScannerView with full state machine (idle/requesting/scanning/
detected/success/error), corner bracket animations snapping to QR
cornerPoints, flash toggle, and haptic feedback.
Add QrScannerSheet as bottom sheet wrapper for mobile. Simplify
ConnectPrompt to use useIsMobile() — mobile shows scan button + sheet,
desktop shows paste-only UI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add cornerPoints, hasFlash/toggleFlash, and manual start/stop/pause
to useQrScanner. Change enabled default to false for click-to-start.
Add scoped CSS animations for scanner bracket breathing and error shake.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Swap the plain <textarea> for a minimal Tiptap (ProseMirror) editor
with IME-safe Enter-to-submit, Shift+Enter newline, placeholder
support, and an optional imperative ref (getText/setText/focus/clear).
All rich-text extensions are disabled — only plain text is allowed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>