Use Zustand persist middleware with localStorage to remember onboarding
completion across app restarts. Only the completed flag is persisted;
transient UI state resets each launch. Add --force-onboarding CLI flag
to re-show onboarding even when already completed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove Combobox component and use a plain text input for model name,
allowing users to enter any model identifier manually.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Save & Test flow: saves API key, then sends a minimal prompt to verify
the provider is reachable. Shows phase-based status (saving/testing/
success/error) with auto-close on success.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Queued through the serialization queue to safely switch provider,
send a minimal test prompt, and restore the previous provider.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace plain text input with Combobox for model selection. Users can
search and select from the provider's model list via dropdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace bg-muted/30 with border-l for a clean separator between the
prompt list and ChatView panels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed check from availableProviders.length > 0 to current?.available,
so Continue is only enabled when a provider is both configured and
selected as the active default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace simple prompts with ones that demonstrate real agent
capabilities: web search, project analysis, and shell execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Continue button is now disabled until the bot status is 'running'.
Skip remains available when no token has been entered.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fake sample prompts with real agent interaction. Clicking a
prompt sends it via localChat and shows the live ChatView on the right
panel with streaming responses.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenRouter requires both API key and model name. Adds optional model
input field to ApiKeyDialog, enabled via showModelInput prop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents pre-selecting an unconfigured provider and enabling Continue
when no provider is configured. Also passes modelId through on success.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add complete onboarding wizard: Permissions > Provider > Connect > Try it
Step 1 (Permissions): Privacy & Trust acknowledgements with toggles for
file system, shell execution, LLM requests, and local storage access.
Step 2 (Provider): LLM provider setup with 4 supported providers
(Kimi Code, Claude Code OAuth, Codex OAuth, OpenRouter), default
provider selection via radio indicator, and contextual setup tutorials
in the right panel that change on hover.
Step 3 (Connect): Optional Telegram bot connection with token input and
BotFather tutorial. Reuses existing useChannels() hook.
Step 4 (Try it): Sample prompts and completion.
Includes OnboardingGuard, Zustand store (no persist - resets on launch),
breadcrumb stepper with progress bar, and left-right split layout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add titleBarStyle hiddenInset and trafficLightPosition to BrowserWindow.
Add drag region to main layout header with no-drag on interactive elements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change primary from custom purple oklch(0.51 0.23 277) to shadcn
default neutral near-black/near-white. Also reset chart and sidebar
primary colors to shadcn defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move renderer files to src/renderer/src/ (electron-vite standard)
- Move index.html to src/renderer/
- Remove root: '.' config that broke HMR
- Use ELECTRON_RENDERER_URL instead of VITE_DEV_SERVER_URL
- Update tsconfig paths for new structure
This fixes hot module replacement not working after the monorepo
restructure. The previous non-standard directory layout with root: '.'
caused electron-vite's HMR to fail silently.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wire registry and sessions_spawn through the lane-based queue so
sub-agents respect max concurrency. Add resolveSubagentTimeoutMs()
with defaults (10 min), 0 = no timeout, and safe clamping.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a command queue system adapted from OpenClaw to prevent
unbounded sub-agent spawning. Default max concurrency: 10.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace tsc with esbuild for building @multica/sdk and @multica/store
in the Docker builder stage. esbuild resolves extensionless imports
that Node.js ESM cannot handle at runtime, producing self-contained
bundles for each workspace package.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy @multica/sdk and @multica/store workspace packages into both builder
and production stages. Build them with tsc in the builder stage, then
patch their package.json exports to point from ./src/*.ts to ./dist/*.js
for Node.js runtime compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update pnpm from 10.16.1 to 10.28.2 to match project packageManager,
and copy pnpm-workspace.yaml into both build stages so pnpm can resolve
the catalog configuration recorded in the lockfile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clientName field to DeviceMeta so non-browser clients (Telegram,
Discord, etc.) can provide a human-readable label instead of relying on
userAgent parsing. Desktop UI now prioritizes clientName over parsed UA
string, fixing "Unknown on Unknown" display for Telegram connections.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pack Telegram user info (userId, username, firstName) into the
userAgent field instead of passing custom fields that don't conform
to the SDK's DeviceMeta interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move table DDL to scripts/telegram-users.sql for manual execution by
ops. Remove OnModuleInit and ensureTable() from TelegramUserStore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The old table had hub_url column; new schema uses hub_id + agent_id.
CREATE TABLE IF NOT EXISTS won't alter existing tables, so drop first.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of throwing and crashing the gateway when MySQL connection
fails, close the broken pool and continue with pool=null so the
isAvailable() guard handles it gracefully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the two-step Hub URL binding flow with a multica://connect
connection link flow that uses the same verify RPC handshake as the
SDK/web clients.
Changes:
- types.ts: replace hubUrl with hubId + agentId fields
- telegram-user.store.ts: update DB schema (hub_id, agent_id columns),
accept explicit deviceId in upsert
- telegram.service.ts: rewrite with parseConnectionCode validation,
verify RPC via routeFromVirtualDevice, pending request map for
RPC promise tracking, smart sendCallback for stream/message/RPC
- package.json: add @multica/store workspace dependency
Flow: user pastes multica://connect link -> parse & validate ->
check Hub online -> register virtual device -> verify RPC to Hub ->
Desktop approval -> save to DB -> route messages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handleSend() only checked socket-based devices (deviceToSocket map),
causing DEVICE_NOT_FOUND errors when Hub sends responses to virtual
devices like Telegram. Now checks virtualDevices map as fallback.
Also adds routeFromVirtualDevice() to allow virtual devices to
initiate messages (e.g., verify RPC, chat messages) through the
Gateway routing infrastructure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The empty ~/.super-multica/channels.json5 file was accidentally added
during a merge conflict resolution. Remove it and add ~/.super-multica/
to .gitignore to prevent future accidents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>