- Replace phased roadmap with simple future tools list
- Add Chinese README (README.zh-CN.md)
- Add language switching links between EN/CN docs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use spread operator to conditionally add description property
instead of assigning undefined to optional fields.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use `validation.valid === false` instead of `!validation.valid`
to properly narrow the discriminated union type.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update createAllTools to accept options object with profileId
- Add memory tools when profileId is provided
- Add group:memory tool group for memory tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add architecture diagram showing Hub-Agent-Client relationship and
document how Profile config.json integrates with tools configuration.
Mark Phase 2 as complete.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add mergeToolsConfig function to combine Profile tools config with
CLI options. Profile config serves as base, CLI options override.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ProfileConfig interface with tools, provider, model, and
thinkingLevel settings. ProfileManager now exposes getToolsConfig()
and getProfileConfig() methods.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the 4-layer policy filter system, tool groups, profiles,
and usage examples for both CLI and programmatic interfaces.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Handle undefined values correctly in optional object properties
for TypeScript strict mode compatibility.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New CLI commands:
- pnpm tools:cli list - list available tools with optional filtering
- pnpm tools:cli groups - show all tool groups
- pnpm tools:cli profiles - show all profiles
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --tools-profile, --tools-allow, and --tools-deny CLI options
to configure tool policy from command line.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ToolsConfig to AgentOptions for policy configuration
- Add isSubagent flag for subagent tool restrictions
- Refactor resolveTools to apply 4-layer policy filtering
- Add createAllTools and getAllToolNames utility functions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplified handleSend function in Chat component by removing unnecessary useCallback.
- Refactored useDeviceId hook to utilize useSyncExternalStore for better state management and removed useState and useEffect for device ID retrieval.
- Updated useGateway hook to ensure onMessageRef is set correctly on options change.
- Enhanced useScrollFade hook to properly cancel animation frames on cleanup.
Replace useState-based useHub hook and separate useActiveAgent store
with a single useHubStore (Zustand). This fixes the bug where
HubSidebar and Chat held independent state copies, causing stale data
and duplicate 30s polling. Agent create/delete logic now lives in the
store with automatic activeAgentId management.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Re-add deviceId (full UUID) with copy-to-clipboard button next to the
SidebarTrigger, matching the original behavior from commit 0975510.
Both deviceId and agentId now have independent copy states.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Re-add the copy-to-clipboard button that was lost when chat.tsx was
rewritten for hub/agent support. Clicking copies the full agentId,
shows a checkmark icon for 2s, and triggers a toast confirmation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Align with sidebar component library convention: use Tailwind v4 native
data-active: instead of data-[active]:, and add missing
text-sidebar-accent-foreground for active state.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace SidebarMenuButton with a custom flex row div that handles hover
and active states on the entire item, not just the text area. Delete
button uses stopPropagation to avoid triggering selection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SidebarMenuButton applies truncate via [&>span:last-child]:truncate,
so the text must be in a <span> rather than a bare text node to get
overflow-hidden + text-ellipsis + whitespace-nowrap.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Drop SidebarMenuAction (absolute positioning) in favor of a flex row:
left side (SidebarMenuButton) gets flex-1 min-w-0 for natural truncation,
right side (delete button) sits as a normal flex child with hover reveal.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
Use CSS truncation for agent/hub IDs instead of JS slicing, show delete
button only on hover via showOnHover prop, and reduce contrast on status
dots, labels, and placeholder text for a more subtle appearance.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- hub-sidebar: displays Hub connection status, agent list with create/delete
- chat: sends messages via Gateway to Hub, receives agent responses, filters by active agent
- layout: passes HubSidebar as children to AppSidebar, removes static NAV_ITEMS
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- use-gateway: GatewayClient WebSocket lifecycle with auto-connect/disconnect
- use-hub: REST polling for Hub status and agent CRUD operations
- use-active-agent: Zustand store for cross-component selected agent state
- use-messages: replace mock data with real addUser/addAssistant/clear API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds gateway and console URL configuration in app/lib/config.ts,
centralizing endpoint URLs with env var overrides.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
- Copy brand icon from gateway to web app/icon.png and public/icon.png
- Remove default favicon.ico and placeholder SVGs
- Update metadata title and description
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Display full UUID instead of truncated 8-char slice. Add ghost button
with copy icon that writes deviceId to clipboard, switches to checkmark
for 2s, and shows a sonner toast confirmation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
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>
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>