Commit graph

472 commits

Author SHA1 Message Date
yushen
3817e2d8a2 feat(tools): add HMAC-SHA256 request signing to web search
Sign each search request with HMAC-SHA256 using Hub ID, a per-request
nonce (UUIDv7), and unix timestamp. The signed reqId is sent in the
request body to prevent unauthorized API usage.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:50:57 +08:00
yushen
51ba86a8eb refactor(tools): clean up web search naming and remove dead code
Rename CopilotHub references to Devv Search (constants, types, function
names, error message). Remove unused resolveTimeoutSeconds/resolveCacheTtlMs
imports and use constants directly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:31:53 +08:00
yushen
630f06eddb chore(tools): update web_search descriptions to Devv Search
Remove "requires API key" wording and rebrand to Devv Search across
tool definition, desktop UI, system prompt, and README.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:21:39 +08:00
yushen
8ea2f2a1bf feat(tools): replace web search with CopilotHub API
Remove Brave and Perplexity providers in favor of a single CopilotHub
search endpoint (api-dev.copilothub.ai/web-search). Simplifies schema
to query-only, removes credential dependencies, retains caching.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:19:12 +08:00
Bohan Jiang
363c65b392
Merge pull request #95 from multica-ai/Bohan-J/tool-result-pruning
feat(context): add tool result pruning for smarter context management
2026-02-05 16:28:41 +08:00
Jiang Bohan
6a21a51766 merge: resolve conflict with main branch
- Keep needsCompaction() method from compaction-feedback PR
- Keep tool result pruning from this branch
- Add "pruning" to CompactionEndEvent.reason type in events.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 16:26:11 +08:00
Jiang Bohan
d46d647cfb chore: trigger CI 2026-02-05 16:22:41 +08:00
Jiang Bohan
71e44bebc0 fix(session): add explicit return type to maybeCompact method
Adding explicit return type to help TypeScript resolve the type
correctly across different build configurations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 16:20:40 +08:00
Jiang Bohan
4e61155e5e chore(turbo): add src as global dependency for cache invalidation
The desktop app imports from the root src directory, but turbo wasn't
tracking those files for cache hash calculation. This caused CI builds
to use stale hashes when types changed in the root src directory.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 16:16:33 +08:00
Jiang Bohan
17fc77e44d chore: trigger CI rebuild 2026-02-05 16:11:35 +08:00
Jiang Bohan
d2827ae948 fix(session): add pruning to SessionEntry reason type
The CompactionResult type includes "pruning" as a reason but SessionEntry
did not, causing type errors when writing compaction entries.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 16:01:10 +08:00
Jiang Bohan
a7f1c56e09 fix(profile): resolve exactOptionalPropertyTypes type error in updateStyle 2026-02-05 15:55:30 +08:00
Jiang Bohan
3dd7ff52d6 feat(context): add tool result pruning for smarter context management
Two-phase pruning approach based on OpenClaw's microcompact-style:
- Soft Trim (30% utilization): Keep head 1500 + tail 1500 chars of large tool results
- Hard Clear (50% utilization): Replace old tool results with placeholder

Protections:
- Never prunes before first real user message (bootstrap protection)
- Protects last 3 assistant messages and their corresponding tool results
- Skips image-containing tool results
- Respects tool allow/deny lists

Enabled by default in tokens/summary compaction modes.
2026-02-05 15:50:58 +08:00
LinYushen
6ebd610ffe
Merge pull request #94 from multica-ai/compaction-feedback
feat: add compaction feedback events
2026-02-05 15:41:38 +08:00
yushen
d42cd8b2e1 docs: add client streaming protocol reference
Document how clients receive real-time events via WebSocket and IPC,
covering message lifecycle, tool execution, and compaction events with
full data structure definitions and routing pseudocode.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:39:21 +08:00
yushen
0421efb824 fix(desktop): add compaction event types to LocalChatEvent
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>
2026-02-05 15:35:51 +08:00
yushen
f0a359ba64 fix(agent): emit compaction events only when compacted 2026-02-05 15:32:41 +08:00
yushen
8f9dcbf7e5 fix(agent): address compaction feedback review findings
- 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>
2026-02-05 15:27:08 +08:00
Jiang Bohan
0b69c8f160 docs: simplify README and add development section 2026-02-05 15:21:15 +08:00
Jiang Bohan
79e1dc0acd refactor(prompt): update profile and memory sections
- Profile: add usage hint for base path
- Memory Recall: clear step-by-step instructions for search and update

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:14:09 +08:00
Jiang Bohan
7547e563fc refactor(prompt): simplify profile and memory sections
- Profile: concise directory path with single usage hint
- Memory Recall: one-liner instruction matching OpenClaw style

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:05:54 +08:00
Jiang Bohan
6bfe836559 feat(tools): add keyword-based memory_search tool
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>
2026-02-05 14:57:40 +08:00
yushen
1316d329ee feat(hub): propagate compaction events to all frontend transports
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>
2026-02-05 14:55:00 +08:00
yushen
70f3755552 feat(agent): emit compaction lifecycle events
Introduce MulticaEvent type system parallel to pi-agent-core's AgentEvent,
with compaction_start and compaction_end events. Agent.subscribeAll() merges
both event streams. maybeCompact() now emits events bracketing the compaction
work, gated by a new SessionManager.needsCompaction() pre-check.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:54:52 +08:00
Naiyuan Qing
be35dd4f7c
Merge pull request #93 from multica-ai/NevilleQingNY/fix-web-pwa-icons
fix(web): replace PWA icons with full-bleed versions to fix iOS white border
2026-02-05 14:49:20 +08:00
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
Jiang Bohan
1e1fa410c3 refactor(tools): remove KV memory tools in favor of file-based memory
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>
2026-02-05 14:41:23 +08:00
LinYushen
6e8f0a3c41
Merge pull request #92 from multica-ai/fix-session-mkdir-enoent
fix(session): resolve subagent empty result and ENOENT errors
2026-02-05 14:27:38 +08:00
yushen
e13bc30841 fix(agent): propagate session write errors 2026-02-05 14:24:24 +08:00
yushen
e23462dc72 fix(session): add error logging and remove TOCTOU in ensureSessionDir
- Log storage write errors in SessionManager.enqueue() instead of
  silently swallowing them
- Remove existsSync check in ensureSessionDir to avoid TOCTOU race;
  mkdirSync with recursive is idempotent when dir already exists

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:18:41 +08:00
yushen
2ec25cb32a fix(session): flush session writes before subagent result delivery
The subagent announce flow reads the child's session file to extract
results, but saveMessage() is fire-and-forget (void enqueue). When
agent.run() completes, pending appendEntry writes may not have flushed
to disk yet, causing readLatestAssistantReply() to find no entries.

Add SessionManager.flush() and call it in AsyncAgent.write() after
agent.run() returns. This ensures waitForIdle() won't resolve until
all session data is on disk, fixing the "no return content" issue.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:12:53 +08:00
yushen
3039e3b34c fix(session): handle transient ENOENT in session directory creation
The mkdir call with { recursive: true } can throw ENOENT on macOS APFS
due to filesystem race conditions. This caused SpawnSession child agents
to silently fail — the session data was never written, so the parent
read back empty results ("子任务完成了,但没有返回内容").

Two fixes:
- Add retry logic to mkdir calls in acquireSessionWriteLock and
  ensureSessionDir to handle transient ENOENT
- Add .catch() to SessionManager.enqueue() to prevent unhandled
  promise rejections from fire-and-forget storage operations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 13:52:47 +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