Commit graph

441 commits

Author SHA1 Message Date
Naiyuan Qing
f5c6f05295 fix(web): replace PWA icons with full-bleed versions to fix iOS white border
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>
2026-02-05 14:46:30 +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
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
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
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
Jiang Bohan
4086fa6985 feat(agent): add subscribe method for multiple event consumers
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>
2026-02-04 16:46:28 +08:00
LinYushen
c70dd338c2
Merge pull request #84 from multica-ai/reasoning-mode-support
feat(agent): add reasoning mode for thinking content display
2026-02-04 16:15:20 +08:00
LinYushen
b85a186139
Merge pull request #81 from multica-ai/system-prompt-engine
feat(agent): add system prompt engineering module
2026-02-04 16:14:42 +08:00
yushen
f649792118 fix(agent): allow output reinit 2026-02-04 16:09:36 +08:00
yushen
8fe2b5f010 fix(agent): resolve reasoningMode from profile config and session meta
- Read reasoningMode from profile config and storedMeta when not
  explicitly set via options (matching thinkingLevel pattern)
- Skip extractThinking() call when reasoningMode is "off"
- Clean up redundant ?? undefined casts in CLI entry points

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:00:53 +08:00
yushen
f585882a06 fix(agent): keep skills prompt without profile 2026-02-04 15:57:06 +08:00
Naiyuan Qing
caee37c631 chore: init tool call styles branch 2026-02-04 15:54:17 +08:00
yushen
953a29672a feat(agent): implement reasoning mode in engine and CLI
Wire reasoningMode through Agent runner, CLI output, and all CLI
entry points (run, interactive, non-interactive). In stream mode,
thinking content is printed to stderr in real-time. In on mode,
thinking is shown after message completion. Default is stream.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:50:47 +08:00