Commit graph

507 commits

Author SHA1 Message Date
yushen
ec6dbff61c Merge remote-tracking branch 'origin/main' into copilothub-web-search 2026-02-06 11:43:40 +08:00
Naiyuan Qing
1e6da205df feat(ui): spin MulticaIcon on hover
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 20:22:29 +08:00
Naiyuan Qing
5e174b8fef fix(ui): responsive horizontal padding on message list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 20:15:19 +08:00
Naiyuan Qing
21312abd01 feat: chat input padding 2026-02-05 19:02:38 +08:00
Naiyuan Qing
039a625dbd
Merge pull request #96 from multica-ai/feat/message-return
feat(chat): add message history pagination with scroll-up loading
2026-02-05 18:48:56 +08:00
Naiyuan Qing
02f3534f2e chore(chat): set DEFAULT_MESSAGES_LIMIT to 200 for production
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 18:45:15 +08:00
Naiyuan Qing
f7950066bc
Merge pull request #97 from multica-ai/cleanup/remove-old-chat-files
Remove unused Zustand stores from @multica/store
2026-02-05 18:44:48 +08:00
Naiyuan Qing
1fe27a59d0 chore(store): remove unused Zustand stores and slim down package
After the chat refactoring moved state management to @multica/hooks,
the Zustand stores (useConnectionStore, useMessagesStore, useAutoConnect)
are no longer imported by any application code. This removes them along
with their unused dependencies (zustand, uuid, react).

- Delete connection-store.ts, messages.ts, use-auto-connect.ts
- Extract Message/ToolStatus types into types.ts (preserves UI imports)
- Remove saveConnection/loadConnection/clearConnection from connection.ts
- Drop zustand, uuid, react deps from package.json

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 18:41:31 +08:00
Naiyuan Qing
65c2fea1b6 feat(chat): add message history pagination with scroll-up loading
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>
2026-02-05 18:40:15 +08:00
Naiyuan Qing
c2b5ada2ef
Merge pull request #86 from multica-ai/exec-approvals
feat(agent): add exec approval system for command execution
2026-02-05 17:59:43 +08:00
Naiyuan Qing
669cbc791b fix(desktop): resolve eslint exhaustive-deps warnings in useLocalChat
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>
2026-02-05 17:56:54 +08:00
Naiyuan Qing
9bcb0993b1 Merge remote-tracking branch 'origin/main' into exec-approvals
# Conflicts:
#	apps/desktop/src/hooks/use-local-chat.ts
2026-02-05 17:54:19 +08:00
Naiyuan Qing
bece8f0545 refactor(web): adapt chat page for extracted shared hooks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:51:12 +08:00
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
Naiyuan Qing
607adeb667 feat(desktop): implement local chat with direct IPC and mode switching
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>
2026-02-05 17:50:55 +08:00
Naiyuan Qing
7a21686505 refactor(hooks,ui): extract useGatewayChat hook and update shared components
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>
2026-02-05 17:50:47 +08:00
Naiyuan Qing
874de766ec feat(hub): add local exec approval routing for desktop IPC chat
Add localApprovalHandlers map so exec approval requests can be routed
to the Electron renderer via IPC instead of requiring a Gateway
connection. Expose setLocalApprovalHandler/removeLocalApprovalHandler
and resolveExecApproval on Hub for the IPC layer to use.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:50:41 +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
Naiyuan Qing
056b9abff6 refactor(ui): deduplicate device-pairing with StatusWrapper and PairingHeader
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>
2026-02-05 17:07:45 +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
Naiyuan Qing
22bd392cb0 refactor(desktop): reuse shared ChatView, DevicePairing, and hooks in chat page
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>
2026-02-05 15:43:39 +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
Naiyuan Qing
b896ac402a refactor(ui): self-contain Loading/Spinner styles and clarify usage semantics
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>
2026-02-05 15:38:39 +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
Naiyuan Qing
53c350ea33 refactor(ui,hooks): extract shared ChatView and DevicePairing to packages
- 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>
2026-02-05 15:28:44 +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
Naiyuan Qing
7fdbf24c4e feat(ui): add exec approval card and refine tool/thinking expand style
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>
2026-02-05 14:44:16 +08:00
Naiyuan Qing
0a6e930c2b feat(ui): render thinking content blocks in message list
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>
2026-02-05 14:44:09 +08:00
Naiyuan Qing
348b12b532 fix(ui): prevent long unbreakable strings from overflowing markdown
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>
2026-02-05 14:44:04 +08:00
Naiyuan Qing
7cb9788bed feat(web): add ChatPage with DevicePairing and ChatView
New page architecture: ChatPage composes useGatewayConnection + DevicePairing
(QR scan/paste with connection status) + ChatView (messages, error banner,
input). Decoupled from Zustand stores, fully props-driven.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:43:59 +08:00