Commit graph

449 commits

Author SHA1 Message Date
Naiyuan Qing
3c303df8f1 Merge branch 'main' into exec-approvals 2026-02-05 11:06:52 +08:00
Naiyuan Qing
e8012a5580 feat(ui): use default font size for messages and larger send button
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 11:04:21 +08:00
Naiyuan Qing
f1dff1e93b
Merge pull request #91 from multica-ai/feat/mobile-pwa-optimization-2
feat(connection): add device verification status feedback
2026-02-05 10:48:33 +08:00
Naiyuan Qing
22c957ee76 chore(web): enable experimental HTTPS and fix scanner active states
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 10:44:29 +08:00
Naiyuan Qing
037908cf8d feat(connection): add device verification status feedback for collaborators
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>
2026-02-05 10:44:15 +08:00
Naiyuan Qing
963bb6c0f9
Merge pull request #90 from multica-ai/feat/mobile-pwa-optimization
feat: mobile PWA optimization with improved onboarding UX
2026-02-05 09:55:17 +08:00
Naiyuan Qing
cff9c004db feat(ui): add paste mode success/error feedback with state-based rendering
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>
2026-02-05 09:53:09 +08:00
Naiyuan Qing
544425ae40 feat(ui): improve mobile onboarding copy and chat input sizing
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>
2026-02-05 09:23:53 +08:00
Naiyuan Qing
8e8a0d58d1 feat(ui): redesign connect prompt with scan/paste tabs and fullscreen QR
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>
2026-02-05 09:23:46 +08:00
Naiyuan Qing
21efbf943a chore(web): update PWA logo assets
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 09:23:41 +08:00
Naiyuan Qing
05ff0aa6ad docs: add product capabilities reference document
Comprehensive single-source-of-truth document covering all product
modules, features, and technical details. Serves as the foundation
for subsequent UI design, copywriting, and user journey documents.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 08:49:28 +08:00
Naiyuan Qing
845e503899 feat(ui): redesign QR scanner with state machine and mobile sheet
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>
2026-02-05 08:22:49 +08:00
Naiyuan Qing
d0681ef46d feat(ui): extend QR scanner hook with lifecycle control and flash API
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>
2026-02-05 08:22:42 +08:00
Naiyuan Qing
b74a5ea1a7 feat(ui): replace ChatInput textarea with Tiptap editor
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>
2026-02-05 07:56:11 +08:00
Jiang Bohan
fc6c3e30b3 chore(desktop): remove coming soon label from remote agent button
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 04:01:30 +08:00
Jiang Bohan
71cc8aee40 fix(desktop): add sessions_spawn to tool groups
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>
2026-02-05 03:41:45 +08:00
Bohan Jiang
a985009801
Merge pull request #89 from multica-ai/Bohan-J/profile-progressive-load
refactor(profile): progressive disclosure + simplify tool policy
2026-02-05 03:36:24 +08:00
Jiang Bohan
cdc64f9c83 feat(profile): enforce file-based memory with stronger guidance
Update workspace.md template to prevent agents from claiming to
"remember" things without actually editing files. The new guidance:

- Uses "No Mental Notes!" as a strong warning
- Lists specific trigger phrases (记住, Remember, I prefer, etc.)
- Maps each trigger to the appropriate file to edit
- Explicitly forbids saying "I'll remember" without file edits

This addresses the issue where agents would acknowledge user
preferences verbally but not persist them to profile files.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 03:32:53 +08:00
Jiang Bohan
a3e639f8f5 refactor(cli): make desktop app the default dev target
- Change `multica dev` default from gateway+console+web to desktop app
- Remove console from dev command options (use embedded Hub in desktop)
- Update package.json scripts to reflect new defaults
- Update README.md and CLAUDE.md architecture documentation

The desktop app has an embedded Hub, so no separate console/gateway is
needed for local development. Gateway is now optional, only needed for
remote client access.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 03:14:44 +08:00
Jiang Bohan
087d1a8653 refactor(tools): remove tool profile layer from policy system
Simplify 4-layer policy to 3-layer:
- Layer 1: Global allow/deny (user config)
- Layer 2: Provider-specific rules
- Layer 3: Subagent restrictions

Removed:
- ToolProfileId type (minimal/coding/web/full)
- TOOL_PROFILES constant
- getProfilePolicy function
- profile field from ToolsConfig

Users can achieve the same effect using allow/deny with group:* syntax.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 02:58:15 +08:00
Jiang Bohan
9b16001e0e feat(subagent): pass tools to subagent system prompt
Resolve tools before building subagent system prompt so the
"## Tooling" section is included, matching OpenClaw's pattern.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 02:58:08 +08:00
Jiang Bohan
5cdc6974f7 refactor(profile): implement progressive disclosure for profile loading
- Only inject workspace.md into system prompt (not soul, user, memory)
- Add profile directory path to workspace section for on-demand file access
- Agent now reads soul.md, user.md, memory.md on first session using tools
- Reduces system prompt size and improves token efficiency
- Aligns with workspace.md template instructions ("Read soul.md first")

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 02:41:29 +08:00
Naiyuan Qing
bef2e901cb
Merge pull request #83 from multica-ai/feat/issue-82-render-tool-call-styles
feat: tool call rendering and error handling
2026-02-04 18:54:30 +08:00
Naiyuan Qing
c412e44f10 fix(desktop): update use-local-chat to use ContentBlock[] instead of string
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>
2026-02-04 18:50:44 +08:00
Bohan Jiang
bd1778440a
Merge pull request #87 from multica-ai/Bohan-J/athens
feat(desktop): add provider selection and credential management
2026-02-04 18:47:27 +08:00
Naiyuan Qing
83e1210ec0 merge: resolve conflicts with main, keep pi-ai types + add extractThinkingFromEvent
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:44:23 +08:00
Naiyuan Qing
e4f1d51453 feat(store,ui): handle Hub error messages and display error banner
- Handle `action: "error"` messages in connection-store (e.g. UNAUTHORIZED)
- Widen lastError type to `{code, message}` to support all error codes
- Display dismissible error banner in Chat with role="alert" and aria-live
- Add accessible close button with focus-visible ring

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:39:32 +08:00
Jiang Bohan
e4ce3349f8 docs(desktop): update TODO list in README
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:25:26 +08:00
Jiang Bohan
197b77e043 feat(desktop): add provider selection UI
- 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>
2026-02-04 18:25:20 +08:00
Jiang Bohan
48245be52d feat(desktop): add provider IPC handlers
- 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>
2026-02-04 18:25:13 +08:00
Jiang Bohan
d7eb0da49b feat(agent): add provider switching and OAuth credential support
- Add getProviderInfo() and setProvider() methods to Agent class
- Expose provider methods via AsyncAgent
- Add setLlmProviderOAuthToken() for storing OAuth credentials
- Extend ProviderConfig type with OAuth fields (oauthToken, oauthRefreshToken, oauthExpiresAt)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:25:06 +08:00
Naiyuan Qing
1f7951df1b fix(ui): render tool calls immediately from assistant toolCall blocks
Tools were only visible after tool_execution_end because the UI relied
solely on toolResult messages (created at tool_execution_start, ~8ms
before end). Now MessageList detects toolCall blocks in the streaming
assistant message and renders them as "running" ToolCallItems immediately.
Once a real toolResult message arrives, the synthetic one is replaced.

- Add resolvedToolCallIds set to deduplicate assistant vs toolResult renders
- Extract getTextContent to shared utils to avoid duplication
- Wrap MessageList and ToolCallItem in memo for performance
- Add accessible region/tabIndex to expanded result panel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:12:34 +08:00
Naiyuan Qing
cfd46ee602 refactor(sdk,store): clean up SDK exports and scope tool interruption
- Remove backward-compatible aliases (TextBlock, ThinkingBlock, ToolCallBlock)
  and extractTextFromEvent from SDK — unused after prior refactors
- Add explicit ContentBlock doc comment explaining the wider union tradeoff
- Scope endStream tool interruption to the same agentId (prevents
  cross-agent interference in multi-agent scenarios)
- Handle tool_execution_update event (no-op for now, avoids unhandled case)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:12:24 +08:00
yushen
8e8ba0edb6 docs: add exec approval WebSocket protocol documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:32:04 +08:00
Naiyuan Qing
703c4686d9 feat(ui): improve tool-call-item with status dots, smart subtitles, and accessibility
- Replace hugeicons status icons with CSS colored dots + glow-pulse
  animation for running state (honors prefers-reduced-motion)
- Add smart subtitles from toolArgs: file basename, command preview,
  search pattern, URL hostname
- Add right-aligned stats: line count, match count, file count
- Add hover chevron for expand/collapse affordance
- Fix accessibility: aria-label, aria-expanded, focus-visible ring
- Store toolArgs in Message (was received but discarded)
- Extract toolArgs from assistant ToolCall blocks during fetchHistory
- Add --tool-running/success/error CSS variables with dark mode support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:30:46 +08:00
Naiyuan Qing
583242baba feat(store,ui): add tool execution lifecycle and ContentBlock rendering
- Message.content is now ContentBlock[] (was string), supporting
  text, thinking, toolCall, and image blocks
- Add toolResult role with toolCallId, toolName, toolStatus, isError
- Add startToolExecution/endToolExecution to MessagesStore
- MessageList renders toolResult messages via ToolCallItem
- Extract text from ContentBlock[] for markdown rendering

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:30:37 +08:00
yushen
abc48e5152 fix(hub): honor exec approval timeout fallback 2026-02-04 17:23:11 +08:00
yushen
b85138d32d Merge remote-tracking branch 'origin/main' into exec-approvals 2026-02-04 17:22:02 +08:00
Naiyuan Qing
ef4e57ffdd refactor(sdk): unify message types with pi-ai source of truth
Replace hand-written message/content types in @multica/sdk with
`import type` from @mariozechner/pi-ai and @mariozechner/pi-agent-core.
This ensures compile-time correctness and eliminates type drift between
backend and frontend (e.g. "tool_use" vs "toolCall", "tool_result" vs
"toolResult").

- stream.ts: re-export TextContent, ThinkingContent, ToolCall,
  ImageContent from pi-ai; use AgentEvent from pi-agent-core
- rpc.ts: AgentMessageItem = pi-ai Message (no more manual mirroring)
- connection-store.ts: use SDK types instead of inline hand-written ones
- ContentBlock now includes ImageContent to match backend reality

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:13:01 +08:00
yushen
8406a1f5d3 fix(hub): use sessionId instead of profileId for exec approval routing
The createExecApprovalCallback was using profileId as the agentId for
approval requests, but agentSenders map is keyed by agent.sessionId.
This caused sendToClient lookups to fail, silently denying all Hub-mode
approvals. Now generates sessionId upfront and passes it separately
from profileId to the callback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:12:21 +08:00
yushen
d930040258 feat(sdk): add exec approval action types for client integration
- ExecApprovalRequestAction: Hub-to-Client approval request payload
- ResolveExecApprovalParams/Result: Client-to-Hub RPC types
- ApprovalDecision type: allow-once, allow-always, deny
- Export from SDK actions index for frontend consumption

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:07:22 +08:00
yushen
d742e668d7 feat(hub): integrate exec approval manager with Hub and Gateway
- ExecApprovalManager: tracks pending approvals, sends to clients via
  Gateway, resolves on RPC response, auto-denies on timeout (fail-closed)
- RPC handler: resolveExecApproval for client decision delivery
- Hub integration: creates approval callback per agent, injects into
  AsyncAgent, registers RPC handler, cancels pending on agent close
- Reads/writes exec approval config and allowlist from agent profile
- Test coverage for manager: request/resolve, timeout, cancel, errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:07:16 +08:00
yushen
89089ef866 feat(agent): wire exec approval callback into tool execution pipeline
- Add optional onApprovalNeeded callback to exec tool (backward compatible)
- Thread callback through CreateToolsOptions → AgentOptions → resolveTools
- Add ExecApprovalConfig to ProfileConfig for per-profile configuration
- Create CLI terminal approval callback (readline-based) for non-Hub mode
- Export all exec approval types and functions from tools index

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:07:07 +08:00
yushen
e67682cfa0 feat(agent): add exec approval type definitions and safety evaluation engine
Introduces the core exec approval system with:
- Type definitions: ExecSecurity, ExecAsk, ApprovalDecision, ExecApprovalConfig
- Command safety evaluation: shell syntax analysis, safe binary detection,
  dangerous pattern detection, allowlist matching
- Persistent allowlist management: glob pattern matching, dedup, usage tracking
- Comprehensive test coverage (76 tests)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:06:58 +08:00
Bohan Jiang
1db8b21a83
Merge pull request #85 from multica-ai/feat/local-chat-ipc
feat(desktop): add local chat mode with direct IPC
2026-02-04 17:00:33 +08:00
Jiang Bohan
2cf13511b7 fix(desktop): fix lint errors and relax unused-vars rule
- 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>
2026-02-04 16:57:41 +08:00
Jiang Bohan
a098a78942 fix(agent): add getMessages method and fix TypeScript errors
- 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>
2026-02-04 16:51:07 +08:00
Jiang Bohan
fbe55ab11e docs(desktop): add data flow architecture for Local/Remote modes
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>
2026-02-04 16:46:41 +08:00
Jiang Bohan
26df74738f feat(desktop): add dual-mode chat page (Local/Remote)
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>
2026-02-04 16:46:37 +08:00
Jiang Bohan
4a986b1d9a feat(desktop): add local chat IPC handlers
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>
2026-02-04 16:46:33 +08:00