Commit graph

44 commits

Author SHA1 Message Date
Jiang Bohan
dafbf856ac merge: resolve conflicts with main branch
- Merge auth-profiles feature from main into runner.ts
- Merge closeCallbacks feature from main into async-agent.ts
- Regenerate pnpm-lock.yaml with new dependencies

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:57:05 +08:00
Jiang Bohan
03bcd853d3 feat(desktop): add UI components for Tools and Skills management
- Create tool-list.tsx with collapsible groups and toggle switches
- Create skill-list.tsx with status badges and action dialogs
- Create qr-code.tsx for connection QR code display
- Add dialog.tsx component to @multica/ui

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:25:30 +08:00
Naiyuan Qing
54ee2f3b00 feat(ui): add streaming indicator to StreamingMarkdown
Show a spinner with "Generating..." label while assistant messages are
being streamed. The indicator appears immediately when content is empty
and persists below the content until streaming completes.

Also fix duplicate React key warning by including block index in the key
to handle blocks with identical content.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 17:56:22 +08:00
Naiyuan Qing
d5b31eeddb fix(sdk,store): align frontend streaming protocol with new AgentEvent format
Backend Hub now sends raw AgentEvent in stream payloads instead of the
old delta/final/error state machine. Update StreamPayload type to use
event field, add extractTextFromEvent helper, and rewrite gateway store
handler to dispatch on event.type (message_start/update/end).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 16:54:34 +08:00
Naiyuan Qing
a8143735e9 feat(desktop): initialize electron app with routing and cleanup
Remove template boilerplate (sample SVGs, test IPC message, comments),
add react-router-dom v7 with createHashRouter, scaffold home and chat
pages using @multica/ui components, and add READMEs for desktop, ui,
and store packages documenting import conventions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 14:17:31 +08:00
Naiyuan Qing
86d00bb134 feat(ui): render AI messages with streaming markdown
Messages store gains streamingIds set and startStream/appendStream/
endStream actions. Gateway store routes stream action payloads to
these new actions. Chat component switches to StreamingMarkdown
for in-progress messages, providing incremental block-level rendering.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 17:18:35 +08:00
Naiyuan Qing
d04bed8175 feat(agent): add streaming support for AI message generation
AsyncAgent now subscribes to pi-agent-core events (message_start,
message_update, message_end) and forwards incremental text deltas
through a stream callback. Hub registers the callback and sends
stream payloads to the requesting client via Gateway.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 17:18:10 +08:00
Naiyuan Qing
441c2059a8 fix(sdk): point exports to source and remove .js import suffixes
- Change package exports from dist/ to src/ (consistent with @multica/store and @multica/ui)
- Add private: true since SDK is an internal monorepo package
- Switch tsconfig from NodeNext to bundler moduleResolution
- Remove .js suffixes from all internal imports for Turbopack compatibility

Eliminates the need to build SDK before running dev server or Next.js build.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:58:23 +08:00
Naiyuan Qing
a62ac2e075 chore: remove @multica/fetch package
No consumers remain after migrating to pure WebSocket RPC.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:29:27 +08:00
Naiyuan Qing
e491949749 refactor(store): remove @multica/fetch dependency
- Move gatewayUrl into gateway store state with setGatewayUrl action
- layout.tsx uses useGatewayStore.getState().setGatewayUrl() directly
- Remove @multica/fetch from store and web package.json dependencies

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:23:06 +08:00
Naiyuan Qing
a1c28b3d04 feat(ui): add auto-scroll to bottom for chat messages
- Add useAutoScroll hook using ResizeObserver + MutationObserver
- Observes content children for size changes (streaming, images)
- Watches for new DOM nodes (new messages, history load)
- Respects user scroll position: no force-scroll when reading above
- Integrate in Chat component alongside existing useScrollFade

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:14:18 +08:00
Naiyuan Qing
4d6d57187c feat(store): load agent message history via RPC
- Add typed AgentMessageItem to SDK with proper content block types
- Add fetchAgentMessages action to hub store using getAgentMessages RPC
- Extract text from complex content blocks (user string, assistant array)
- Auto-load history when selecting an agent with no local messages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:13:59 +08:00
Naiyuan Qing
3622f82a7b feat(gateway): add auto-connect, hub discovery via list-devices
- Add LIST_DEVICES event and "hub" device type to SDK
- Add listDevices() method to GatewayClient
- Add handleListDevices handler in Gateway
- Change Hub deviceType from "client" to "hub"
- Refactor gateway store: auto-connect WS, separate hubId selection
- Hub-init: auto-connect on mount, discover hubs on registered
- Hub-sidebar: show discovered hubs list with connect/disconnect UI

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:13:40 +08:00
Naiyuan Qing
150c87a496 refactor(frontend): replace HTTP API with pure WebSocket RPC
- gateway store: add hubId state and request() RPC method
- hub store: replace consoleApi calls with gateway.request() RPC
- hub-init: simplify to react on gwState === "registered"
- hub-sidebar: add hub-id input + connect/disconnect flow
- chat: use gateway hubId for message routing
- layout: remove consoleUrl config (no longer needed)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 15:27:07 +08:00
Naiyuan Qing
1f22c3e578 feat(hub): register RPC handlers for hub, agent, and gateway operations
Add 5 new RPC methods (getHubInfo, listAgents, createAgent, deleteAgent,
updateGateway) mirroring the existing Console HTTP API, enabling pure
WebSocket communication from the frontend.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 15:27:07 +08:00
yushen
2541745152 feat(sdk): add RPC request method and types to GatewayClient
Add request<T>() method that handles full request/response lifecycle
with auto-generated requestId, timeout handling, and pending request
cleanup on disconnect. Also add GetAgentMessagesParams and
GetAgentMessagesResult type definitions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 14:10:00 +08:00
Naiyuan Qing
3d7b13555f refactor(sdk): unify gateway-sdk into @multica/sdk package
Sync latest code from src/shared/gateway-sdk/ into packages/sdk/,
update all backend imports to use @multica/sdk, and remove the
duplicate src/shared/gateway-sdk/ directory.

- Translate Chinese comments to English in SDK source
- Fix package.json exports with default condition
- Add @multica/sdk as workspace dependency for backend
- Update imports in gateway, test-client, and hub

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:43:52 +08:00
Naiyuan Qing
4a7a9800f2 fix(frontend): apply code review fixes across store and UI
- Move setConfig() after imports in layout.tsx
- Add gateway disconnect cleanup in hub-init useEffect
- Replace silent catches with toast error notifications in hub store
- Optimize chat selectors with useMemo and useCallback/getState()
- Remove unused getMessagesByAgent from messages store
- Add clipboard try/catch with error toast
- Add skeleton loading states for hub sidebar and chat header

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 11:52:42 +08:00
Naiyuan Qing
eef26d8675 refactor(frontend): complete migration of all hooks and components to packages
- Create gateway store in @multica/store (WS connection independent of components)
- Gateway auto-connects when hub is ready, messages handled internally
- Move scroll-fade hook to @multica/ui/hooks
- Move Chat component to @multica/ui/components
- Add setConfig() call in web layout for URL injection
- Delete all web-local hooks, components, and lib/config
- Web app is now a pure shell: layout.tsx + page.tsx

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 11:07:57 +08:00
Naiyuan Qing
97fce5b113 refactor(store): migrate messages hook to Zustand store
- Move useMessages from apps/web to packages/store/src/messages.ts
- Convert useState to Zustand store for global message persistence
- Add reserved interfaces: updateMessage, loadMessages, getMessagesByAgent
- Update chat.tsx imports to use @multica/store

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 10:49:52 +08:00
Naiyuan Qing
5275bc55fc refactor(store): migrate device-id hook to @multica/store
- Move useDeviceId from apps/web to packages/store/src/device-id.ts
- Update imports in chat.tsx and use-gateway.ts to use @multica/store
- Add uuid dependency to @multica/store

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 10:45:20 +08:00
Naiyuan Qing
63861d03c6 refactor(frontend): extract shared stores and components into packages
- Create @multica/fetch package for HTTP client and URL config
- Migrate hub store and hub-init hook to @multica/store
- Move HubSidebar component to @multica/ui for web/desktop reuse
- Update web app imports to use shared packages
- Remove counter store example and its component-example usage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 10:37:17 +08:00
Naiyuan Qing
bcaf14464a fix(ui): improve disabled state cursor and no-agent empty state
- Add cursor-not-allowed and reduced opacity to ChatInput when disabled
- Show user icon in empty state when no agent is selected
- Pass contextual placeholder text based on agent selection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:45:53 +08:00
Naiyuan Qing
7e5bc7b7ae fix(ui): prevent chat submit during IME composition
Check e.nativeEvent.isComposing so pressing Enter to confirm
CJK input does not accidentally submit the message.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:42:54 +08:00
Naiyuan Qing
4ff227685e feat(ui): add onSubmit/disabled props to ChatInput, convert AppSidebar to children slot
ChatInput now accepts onSubmit callback and disabled state.
AppSidebar uses children instead of items prop for flexible content injection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:40:56 +08:00
Naiyuan Qing
cdcce47141 feat(ui): add brand icon and artistic font to sidebar header
- Display Multica icon alongside brand name in sidebar header
- Use Playfair Display serif font for an artistic brand feel
- Expose --font-brand CSS variable from layout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:35:48 +08:00
Naiyuan Qing
8018290fba fix(ui): add semantic colors to sonner toast icons
success → emerald-500, info → blue-500, warning → amber-500,
error → red-500, loading → muted-foreground.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:22:27 +08:00
Naiyuan Qing
9af889a9bb fix(web): import toast from @multica/ui instead of bare sonner
sonner is a dependency of @multica/ui, not web. Re-export toast from
the ui sonner module and update the import path in chat.tsx.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:21:24 +08:00
Naiyuan Qing
5f367fb6b7 fix(web): replace Zustand device store with local useDeviceId hook
Move device ID logic from @multica/store (Zustand persist) into a
simple useDeviceId hook in the web app. SSR returns empty string,
client reads/writes localStorage directly — no hydration mismatch,
no suppressHydrationWarning needed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:16:54 +08:00
Naiyuan Qing
7d326695c1 feat(web): add scroll fade hint effect to chat message list
Use CSS mask-image gradients to hint at scrollable overflow in the chat
area. Adds useScrollFade hook that dynamically applies top/bottom fade
based on scroll position via scroll events and ResizeObserver.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:14:19 +08:00
Naiyuan Qing
047de2b431 fix(web): suppress deviceId hydration mismatch warning
Zustand persist generates a new deviceId on the server (no localStorage),
then hydrates a different value from localStorage on the client. Add
suppressHydrationWarning to the deviceId span since this mismatch is expected.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:04:57 +08:00
Naiyuan Qing
905e8c8ae3 fix(ui): remove Shiki span background-color causing unwanted highlights
The dual-theme CSS applied background-color to .shiki span elements,
which picked up token-level bg variables from github-dark/light themes
and created visible purple/blue highlights on code lines.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:48:29 +08:00
Naiyuan Qing
88d2e9340b feat(ui): add light/dark theme toggle in sidebar
Add next-themes integration with a ThemeProvider wrapper and a
ThemeToggle dropdown (Light / Dark / System) in the sidebar footer.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:21:31 +08:00
Naiyuan Qing
ffaed12048 feat(ui): add global scrollbar styling with light/dark support
Thin 6px scrollbars with transparent tracks and themed thumbs using
CSS standard properties + WebKit pseudo-elements for max compatibility.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:09:05 +08:00
Naiyuan Qing
f348d91c18 feat(ui): add Spinner component from multica
Port the SpinKit Grid 3x3 spinner as a shared UI component.
Uses currentColor and em sizing for flexible theming and scaling.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:01:48 +08:00
Naiyuan Qing
01790a57d2 refactor(ui): extract AppSidebar into shared UI component
Move sidebar markup from page.tsx into a reusable AppSidebar component
in packages/ui for cross-app reuse.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 20:57:57 +08:00
Naiyuan Qing
4036463d6c feat(web): add sidebar layout
Wrap layout in SidebarProvider, restructure page into left
sidebar navigation + right SidebarInset content area.
Add use-mobile hook via shadcn for responsive behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 20:40:35 +08:00
Naiyuan Qing
9b87cd789e feat(ui): add Markdown rendering components
Add CodeBlock, Markdown, StreamingMarkdown components with
Shiki syntax highlighting, GFM support, and linkify utility.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 20:40:27 +08:00
Naiyuan Qing
d7d2861a79 feat(store): add shared Zustand store package with counter example
- Create packages/store with @multica/store package
- Add zustand to pnpm catalog for version consistency
- Add counter store as cross-platform state example
- Integrate counter into ComponentExample for verification
- Add tsconfig path mappings for web and desktop
- Add @multica/store to Next.js transpilePackages
- Add @multica/store dependency to packages/ui

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:34:09 +08:00
Naiyuan Qing
eb5c388a80 refactor(ui): reorganize components into ui/ subdirectory and share layout
- Move shadcn components from src/components/ to src/components/ui/
- Move component-example and example from apps/web to packages/ui
- Update package.json exports with separate components/* and components/ui/* paths
- Update components.json ui alias in both packages/ui and apps/web
- Add missing @import "shadcn/tailwind.css" to globals.css
- Add new UI components: sheet, sidebar, skeleton, switch
- Update apps/web and apps/desktop to use shared ComponentExample

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:34:09 +08:00
Naiyuan Qing
6431829b0c chore: unify shared deps with pnpm catalogs
Add catalog section to pnpm-workspace.yaml for react, react-dom,
@types/react, @types/react-dom, @types/node, and typescript.
Update all package.json files to use catalog: protocol.
Upgrade desktop from React 18 to 19. Rename to @multica/desktop.
Add dev:desktop script to root.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:34:09 +08:00
Naiyuan Qing
c1129ff37d feat(ui): extract components, utils, and styles from apps/web
Move 13 shadcn UI components, cn() utility, and theme CSS variables
to packages/ui for cross-platform reuse. Add @source directives for
Tailwind v4 content scanning.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:34:05 +08:00
Naiyuan Qing
e1443720eb feat(ui): create @multica/ui package skeleton
Shared UI package for web, electron, and mobile. Uses subpath exports
following the official shadcn monorepo template pattern.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:34:05 +08:00
Naiyuan Qing
84fe9d99f5 Add monorepo setup with Turborepo and Web client
- Add pnpm workspace and Turborepo configuration
- Extract Gateway SDK to packages/sdk as independent package
- Add Next.js + shadcn Web client in apps/web
- Update root package.json with turbo scripts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 16:33:35 +08:00