Commit graph

652 commits

Author SHA1 Message Date
Naiyuan Qing
6ef58a0cab refactor: restructure to monorepo architecture
- Move core agent engine to packages/core/
- Add packages/types/ for shared TypeScript types
- Add packages/utils/ for utility functions
- Add apps/cli/ for command-line interface
- Add apps/gateway/ for NestJS WebSocket gateway
- Add apps/server/ for REST API server
- Restructure desktop app (electron/ → src/main/, src/preload/)
- Update pnpm workspace configuration
- Remove legacy src/ directory

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 18:00:23 +08:00
yushen
5ba8c87744 fix(gateway): use esbuild to bundle workspace packages in Docker
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>
2026-02-10 17:34:40 +08:00
yushen
01f64ff1ec fix(gateway): include workspace packages in Docker build
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>
2026-02-10 17:31:51 +08:00
yushen
31f38bb0ec fix(gateway): update Dockerfile pnpm version and add pnpm-workspace.yaml
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>
2026-02-10 17:23:26 +08:00
LinYushen
cdff06d488
Merge pull request #118 from multica-ai/fix/gateway-pino-deadlock
chore(telegram): add webhook setup script
2026-02-10 17:09:12 +08:00
yushen
e9d934a384 chore(telegram): add webhook setup script
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 17:07:45 +08:00
LinYushen
187199d389
Merge pull request #117 from multica-ai/fix/gateway-pino-deadlock
feat(gateway): Telegram channel integration with connection link verification
2026-02-10 17:00:18 +08:00
yushen
d367e77c0a feat(device): add clientName to DeviceMeta for multi-client display
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>
2026-02-10 16:43:44 +08:00
yushen
a94b6e8b1c fix(telegram): use DeviceMeta interface for verify RPC meta parameter
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>
2026-02-10 16:19:08 +08:00
yushen
c9836d60d4 chore: move SQL schema to src/gateway/migrations/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 16:11:47 +08:00
yushen
bc78dcdca9 chore: move SQL schema to migrations/ directory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 16:10:29 +08:00
yushen
1547da3279 refactor(telegram): remove auto table creation, add SQL script for ops
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>
2026-02-10 16:08:52 +08:00
yushen
6284ffd74a fix(telegram): drop and recreate telegram_users table for schema change
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>
2026-02-10 16:06:58 +08:00
yushen
483f4a2f59 fix(gateway): graceful degradation when MySQL is unavailable
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>
2026-02-10 16:04:47 +08:00
yushen
dc60cb754d feat(telegram): replace Hub URL binding with connection link verification
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>
2026-02-10 16:04:35 +08:00
yushen
604d74d984 fix(gateway): route messages to virtual devices in handleSend()
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>
2026-02-10 16:04:10 +08:00
Naiyuan Qing
bfa96d87af
Merge pull request #116 from multica-ai/fix/remove-accidental-config
fix: remove accidentally committed ~/.super-multica config
2026-02-10 09:50:50 +08:00
Naiyuan Qing
cedb8f9138 revert: undo unintended .gitignore change
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:39:01 +08:00
Naiyuan Qing
6becd791ae fix: remove accidentally committed ~/.super-multica config
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>
2026-02-10 09:35:50 +08:00
Jiayuan Zhang
86bd01b8c6
Merge pull request #115 from multica-ai/forrestchang/agent-design-review
docs: add Multica product memo and vision
2026-02-10 03:21:54 +08:00
Jiayuan Zhang
d05b592fd5 docs: add Multica product memo and update README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:16:42 +08:00
Jiayuan Zhang
7d49fa8d06
Merge pull request #114 from multica-ai/forrestchang/list-agent-tools
chore: remove commit and code-review skills, add cleanup
2026-02-10 02:25:42 +08:00
Jiayuan Zhang
c165783e05 feat(skills): clean up removed bundled skills on update
Track bundled skill IDs in a .bundled-manifest.json file. On each
initialization, remove managed skills that were previously bundled
but are no longer present in the bundle directory. User-installed
skills are not affected since they are never recorded in the manifest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 02:18:00 +08:00
Jiayuan Zhang
8a69eb19f8 chore(skills): remove commit and code-review skills
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 02:12:23 +08:00
Bohan Jiang
b9300f3328
Merge pull request #113 from multica-ai/Bohan-J/dual-track-user-display-content-20260209
feat(desktop): model switching UI & pi-ai 0.52.9 upgrade
2026-02-09 19:59:34 +08:00
Jiang Bohan
368012bd66 chore(providers): remove Mistral from provider registry
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 19:20:21 +08:00
Jiang Bohan
a61e29469e fix(desktop): add overflow-y scroll to provider dropdown
The provider & model dropdown now scrolls internally instead of
causing the whole page to scroll when content exceeds viewport.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 19:20:16 +08:00
Jiang Bohan
5380b146b3 chore(deps): upgrade pi-ai and pi-agent-core to 0.52.9
Upgrade @mariozechner/pi-ai and @mariozechner/pi-agent-core from 0.50.3
to 0.52.9 to support latest models (claude-opus-4-6, o3, o3-mini).

Breaking type changes addressed:
- exactOptionalPropertyTypes: use conditional spread or `| undefined`
- TOOL_PROFILES removed: strip all profile references from CLI
- AgentMessage union requires timestamp: cast test fixtures
- AsyncAgent.id → sessionId
- Add explicit callback parameter types for SDK event handlers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 19:13:38 +08:00
Naiyuan Qing
f7ddcec78d
Merge pull request #112 from multica-ai/NevilleQingNY/telegram-msg-issue
fix(channels): correct reply routing, ack lifecycle, and whisper detection
2026-02-09 18:31:58 +08:00
Naiyuan Qing
7b885673da docs(skills): update whisper skill with correct transcription priority
Clarify that local whisper is the primary provider (free, offline),
OpenAI API is the fallback, and the skill only activates when both
are unavailable. Add setup instructions noting no restart is required.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:28:03 +08:00
Naiyuan Qing
1bd25c5aec fix(media): don't cache whisper binary detection failure
Only cache successful whisper binary lookups. When whisper is not found,
leave the cache empty so subsequent calls re-check PATH. This allows
the app to detect a newly installed whisper without requiring a restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:27:06 +08:00
Naiyuan Qing
c27f4e66b5 docs(channels): update README with route queue pattern and ack lifecycle
Document the new channel system design: FIFO pendingRoutes queue,
activeRoute/activeAcks state, agent_start/agent_end lifecycle,
InboundDebouncer, typing/reaction lifecycle, and UI metadata stripping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:27:06 +08:00
Naiyuan Qing
ec67dd6706 fix(ui): strip channel metadata prefixes from user messages in display
Add stripUserMetadata() to remove timestamp envelopes and media type
labels ([Voice Message] Transcript:, [Image] Description:, etc.) that
are injected for LLM context but should not appear in the desktop UI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:27:06 +08:00
Naiyuan Qing
f9d1e5c809 fix(channels): correct reply routing and ack lifecycle for rapid-fire messages
Replace global lastRoute-based reply targeting with a FIFO route queue
(pendingRoutes) that snapshots route + ack targets at each debouncer flush.
Use agent_start/agent_end lifecycle instead of message_end to ensure stable
routing across multi-turn runs. Track per-message 👀 acks in ackBuffer →
activeAcks for precise cleanup. Two-gate typing stop: only stop when all
queued runs complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:27:06 +08:00
Jiang Bohan
28a14a4beb chore(providers): update model registry with latest valid models
Update model lists against pi-ai 0.50.3 getModel() validation:
- Anthropic: add claude-opus-4-1, claude-sonnet-4-0
- OpenAI: add gpt-5.2, gpt-5-mini, gpt-4.1, gpt-4.1-mini
- Google: update to gemini-2.5-pro/flash/2.0-flash
- xAI: add grok-4 as default
- Groq: remove invalid mixtral-8x7b-32768
- OpenRouter: update to claude-sonnet-4-5

Note: pi-ai upgrade to 0.52.9 (for claude-opus-4-6, o3 etc.)
requires separate effort due to breaking type changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:58:03 +08:00
Bohan Jiang
4a3a9101c2
Merge pull request #111 from multica-ai/Bohan-J/dual-track-user-display-content-20260209
fix(channels): suppress heartbeat ack in outbound replies
2026-02-09 16:57:55 +08:00
Jiang Bohan
2349868e8e feat(desktop): add model switching to provider dropdown
Add model selector section below the provider grid in the dropdown.
Shows available models for the current provider with active model
indicator. Clicking a model calls setProvider with the modelId.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 16:56:25 +08:00
Jiang Bohan
96f83c0bc6 fix(channels): suppress heartbeat ack in outbound replies 2026-02-09 16:53:41 +08:00
Bohan Jiang
be312cd3e0
Merge pull request #110 from multica-ai/Bohan-J/dual-track-user-display-content-20260209
fix(agent): separate display content from agent user turns
2026-02-09 16:41:31 +08:00
Jiang Bohan
d5090441da fix(agent): use user message content type for displayContent 2026-02-09 16:37:33 +08:00
Jiang Bohan
ff0694175e Merge branch 'main' of https://github.com/multica-ai/super-multica 2026-02-09 16:25:30 +08:00
Bohan Jiang
a12907df86
Merge pull request #109 from multica-ai/Bohan-J/fix-chat-error-catch
fix(agent): only emit agent_error for LLM provider 401
2026-02-09 16:07:13 +08:00
Jiang Bohan
a8e7a803c9 fix(agent): separate display content from agent user turns 2026-02-09 15:54:10 +08:00
Jiang Bohan
7294e76929 fix(agent): only emit agent_error for auth issues, not runtime 400 errors
Previously all agent errors (including 400 invalid_request_error) were
emitted as agent_error events, triggering the UI error banner and
interrupting the chat flow. Now only auth-related errors (401, no API key)
emit agent_error so the "Configure" banner appears. Runtime errors like
400 are still shown as chat messages but don't block the agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:53:41 +08:00
Jiang Bohan
2fa8c383fb fix(agent): save original provider ID instead of alias in session meta
setProvider() was saving the alias-resolved provider (e.g. "anthropic"
instead of "claude-code") to session metadata. On restart, this caused
the wrong provider to be selected. Now saves the original providerId
so the exact user selection is preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:45:11 +08:00
Jiang Bohan
15f6604a16 fix(agent): persist provider selection across restarts
Move session metadata loading before provider resolution so that
the stored provider from a previous setProvider() call is used
in the fallback chain (options > session meta > credentials > default)
instead of always falling back to "kimi-coding".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:41:56 +08:00
Jiang Bohan
5c7d913128 fix(desktop): externalize grammy in Vite Electron build
grammy was not in rollupOptions.external, causing the channels IPC
handlers to fail at runtime with 'No handler registered'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:08:11 +08:00
Jiang Bohan
19fed71f09 fix(heartbeat): bypass empty-file check for cron-triggered wakes
Cron reminders were silently skipped when heartbeat.md had no actionable
content. Now cron: and exec-event reasons both bypass the empty-file
guard so scheduled reminders always reach the agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:08:04 +08:00
Jiang Bohan
d6993000ca Merge branch 'main' of https://github.com/multica-ai/super-multica
# Conflicts:
#	apps/desktop/electron/electron-env.d.ts
2026-02-09 14:34:48 +08:00
Bohan Jiang
94d6e15117
Merge pull request #101 from multica-ai/fix/credentials-reload
fix(agent): reload credentials dynamically
2026-02-09 14:33:40 +08:00