Use chatRef to hold stable reference to useChat return value, avoiding
stale closure issues and satisfying react-hooks/exhaustive-deps rule.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add LocalChat component using useLocalChat hook that communicates with
the Hub via IPC (no Gateway required). Fix streamId extraction to use
event.message.id matching Hub behavior. Fix history to return raw
AgentMessageItem[] instead of flattened strings. Add exec approval
forwarding over IPC. Use conditional rendering for LocalChat to prevent
event leaking from remote sessions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace Zustand-based message/connection stores with local state hooks.
useLocalChat now returns UseChatReturn shape with internal agentId discovery,
tool execution events, and error handling. Remote mode uses shared
useGatewayConnection + useChat + DevicePairing from packages.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Widen the LocalChatEvent.event.type union to include compaction_start
and compaction_end, fixing TS2367 comparison errors in use-local-chat.
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>
- Wrap maybeCompact() in try/catch to ensure compaction_end always fires
- Widen multicaListeners type to match subscribeAll() callback signature
- Import CompactionEndEvent from SDK instead of inline type casts
- Add doc comment explaining reason field type difference (agent vs SDK)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements a simple memory_search tool for searching memory files:
- Searches memory.md and memory/*.md files by keyword
- Returns matching lines with context (2 lines before/after)
- Supports case-sensitive/insensitive search
- Respects maxResults limit
Tool is only available when a profile is active (has profileDir).
System prompt includes memory usage guidance when tool is present.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Forward compaction_start/compaction_end events through Hub (Gateway path)
and Desktop IPC (local path) to the Zustand messages store. Adds
CompactionEvent types to the SDK, compacting/lastCompaction state to
useMessagesStore, and event routing in both connection-store and
use-local-chat.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The original icon PNGs had pre-baked rounded corners and transparent
backgrounds. When iOS applies its own superellipse mask on Add to Home
Screen, the transparent corners were filled with white, creating a
visible white border around the icon.
Changes:
- Regenerate all icon PNGs as full-bleed (no rounded corners, opaque
background filling entire canvas) from the existing logo SVG
- Add dedicated apple-touch-icon.png at 180x180 (iOS standard size)
- Add favicon.ico for universal browser fallback
- Replace oversized app/icon.png (540x540) with 192x192 full-bleed
- Update layout.tsx to reference apple-touch-icon.png
- Add explicit purpose: "any" to 192x192 manifest entry
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace Zustand global stores with hook-local state for the web app.
useGatewayConnection handles client lifecycle, identity persistence,
reconnection, and keyed reset. useChat handles message history, streaming
events, tool execution, Hub error action, and exec approval requests.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Memory is now managed through profile files (memory.md, memory/*.md) using
standard read/edit tools, following OpenClaw's file-first approach.
Changes:
- Remove memory/ folder with KV-based memory tools
- Remove group:memory from tool groups
- Update system prompt to remove memory tool references
- Update README docs to reflect file-based memory approach
Agents use workspace.md instructions to manage memory via file operations.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sessions_spawn tool was not showing in the desktop tools UI because
TOOL_GROUPS and ALL_KNOWN_TOOLS were missing the subagent group.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Message.content changed from string to ContentBlock[] — update desktop's
local chat hook to match: extractContentFromAgentEvent returns ContentBlock[],
and history messages are normalized from string to ContentBlock[].
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add useProvider hook for provider state management
- Add ApiKeyDialog for configuring API key providers
- Add OAuthDialog for importing OAuth credentials from CLI tools
- Update home page with provider dropdown selector
- Support switching providers mid-conversation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add provider.ts with handlers for list, current, set, saveApiKey, importOAuth
- Import OAuth credentials from CLI tools (Claude Code, Codex)
- Register provider handlers in IPC index
- Expose provider API in preload.ts with TypeScript types
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused AgentEvent import from hub.ts
- Change @typescript-eslint/no-unused-vars to warn instead of error
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add getMessages() to Agent and AsyncAgent for retrieving session history
- Fix type annotations in hub.ts for AgentMessage handling
- Remove duplicate type export in preload.ts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the dual-mode chat architecture showing how IPC and Gateway
paths share the same UI components, Store, and Agent layer.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Chat page now supports two modes:
- Local: Direct IPC to agent in same Electron process
- Remote: WebSocket via Gateway to external Hub
Both modes reuse the same UI components and useMessagesStore.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add IPC handlers for direct local agent communication:
- localChat:subscribe - Subscribe to agent events
- localChat:unsubscribe - Unsubscribe from events
- localChat:send - Send message to local agent
- localChat:getHistory - Get message history
This enables chat without Gateway connection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add AsyncAgent.subscribe() that allows multiple subscribers to receive
the same agent events, enabling local IPC chat to coexist with other
event consumers.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add IPC handlers for profile:getStyle and profile:setStyle
- Add style dropdown with 6 preset options in agent settings UI
- Display style descriptions to help users choose
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Radix UI version in this project doesn't support asChild on
AlertDialogDescription. Use inline spans with block display instead.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The import was redundant since it's already re-exported directly.
Fixes eslint no-unused-vars error in CI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merge remote main branch, keeping both device verification (ws-auth-handshake)
and agent settings/profile features from main.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 60s timeout to pending device confirms to prevent Promise leaks
when client disconnects before user responds
- Add offDeviceConfirmRequest to preload and clean up IPC listener on
component unmount to prevent duplicate listener accumulation
- Extract duplicated parseUserAgent into shared lib/parse-user-agent.ts
- Clean up expired tokens in DeviceStore.registerToken to prevent
memory accumulation from unscanned QR codes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add DeviceList component on home page showing verified devices with
parsed User-Agent info (browser, OS) and relative time. Add useDevices
hook with listDevices/revokeDevice IPC. Update DeviceConfirmDialog to
show human-readable device info (e.g. "Chrome on macOS") instead of
raw device ID.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add DeviceConfirmDialog component that shows an AlertDialog when a new
device requests connection, letting the user Allow or Reject. Wire up
Electron IPC for token registration and device confirmation flow between
main process and renderer. Register QR code tokens with Hub on generate
and refresh.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add reloadSystemPrompt call after profile updates
- Add error handling and logging for Hub initialization
- Clean up debug logs from agent IPC handlers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add UI for editing agent name and user preferences:
- AgentSettingsDialog component with name input and user.md textarea
- Agent Settings section on Home page with Edit button
- Auto-reload agent info when settings are saved
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add IPC handlers for profile management:
- profile:get - Get profile name and user content
- profile:updateName - Update agent display name
- profile:updateUser - Update user.md content
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add logo.svg as the new brand logo
- Generate logo-192x192.png and logo-512x512.png from SVG for PWA
- Update app-header, manifest, and layout to reference new logo files
- Remove old icon.png, icon-192x192.png, icon-512x512.png
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- desktop layout.tsx: remove connection logic, keep header + tabs + outlet
- web app-header.tsx: remove connection logic, keep logo + theme toggle
Connection lifecycle is now owned by the shared Chat component.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>