Commit graph

911 commits

Author SHA1 Message Date
Jiayuan Zhang
a7629db01e fix(gateway): enable CORS for HTTP endpoints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:42:29 +08:00
Jiayuan Zhang
005908710e chore: add local dev script for Gateway + Desktop with Telegram bot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:39:43 +08:00
Jiayuan Zhang
b39a0dd2ac feat(desktop): add Telegram QR code to Clients page and Onboarding
- Create TelegramConnectQR component (fetches short code from Gateway)
- Export reusable hooks/components from qr-code.tsx
- Update ChannelsTab with Telegram QR card
- Rewrite ConnectStep for QR-based flow (replaces BotFather token input)
- Re-add ConnectStep to onboarding: Privacy → Provider → Channels → Start

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:30:10 +08:00
Jiayuan Zhang
d75a24714d feat(gateway): add Telegram QR deep link connection flow
Add short code store, bot commands (/start, /status, /help), and
POST /telegram/connect-code endpoint for Desktop to create QR codes.
Users scan a QR → Telegram opens → /start {code} → auto-connects.

- ShortCodeStore: in-memory Map with TTL for connection info
- Bot commands registered via setMyCommands
- Refactor handleConnectionLink into shared connectUser method
- Fetch bot username via getMe() for deep link URL

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:30:01 +08:00
Jiayuan Zhang
5010d87284 feat(gateway): add long-polling fallback for local Telegram development
When TELEGRAM_WEBHOOK_URL is not set, the bot automatically starts in
long-polling mode (bot.start()) instead of waiting for webhook calls.
This allows local development without ngrok or a public URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:05:19 +08:00
Jiayuan Zhang
4cb8b93f93 refactor(desktop): hide manual Telegram bot creation, use official Gateway bot only
Remove the user-facing ability to create custom Telegram bots via BotFather.
Non-technical users should only need to message @multica_bot on Telegram.
- Disable telegramChannel plugin registration in initChannels()
- Remove ConnectStep from onboarding flow (Privacy → Provider → Start)
- Replace TelegramCard with simple text pointing to @multica_bot

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:20:39 +08:00
Jiayuan Zhang
38181ab4db refactor(gateway): remove group chat support from Telegram bot
Group chats have unresolved issues in the Gateway context:
- Per-user deviceId causes context overwrites across groups
- Reply chains across users route to wrong Hubs
- Welcome messages are noisy in groups

Restrict to private chats only until a proper group model is designed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:12:26 +08:00
Jiayuan Zhang
9646b08306 feat(gateway): port Desktop Telegram channel features to Gateway webhook bot
Port all 7 features from the Desktop long-polling Telegram channel plugin
to the Gateway webhook-based Telegram bot:

- Markdown → Telegram HTML formatting with parse-error fallback
- Text chunking for messages >4096 chars (paragraph-boundary split)
- Reply-to original message + 👀 ack reaction lifecycle
- Group chat support (mention/reply filtering, @mention stripping)
- Per-chat message serialization (prevents race conditions)
- Inbound media handling (voice/audio/photo/video/document)
  with transcription (Whisper) and description (Vision API)
- Outbound file captions with HTML formatting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:06:43 +08:00
Jiayuan Zhang
13e5492993
Merge pull request #171 from multica-ai/forrestchang/markdown-accept
feat(web): add Accept: text/markdown header for Cloudflare Markdown for Agents
2026-02-13 21:00:08 +08:00
yushen
8881ae8f4b chore: bump version to 0.1.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 20:00:25 +08:00
Jiayuan Zhang
27c3ba5682 feat(web): add Accept: text/markdown header for Cloudflare Markdown for Agents
Prefer markdown responses from servers that support Cloudflare's Markdown
for Agents feature, reducing token usage by ~80% when available. Non-supporting
servers fall back to HTML as before.

- Update Accept header to prefer text/markdown in web_fetch requests
- Add text/markdown content-type handling to skip HTML parsing pipeline
- Capture x-markdown-tokens response header in WebFetchResult
- Add extractMarkdownTitle() helper for native markdown title extraction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:47:17 +08:00
yushen
faecc32aff chore(desktop): fix electron-builder config for releases
- Fix publish repo from "multica" to "super-multica"
- Add zip to mac targets (required for electron-updater auto-updates)
- Enable hardenedRuntime (required for notarization)
- Add notarize config with teamId placeholder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:46:30 +08:00
LinYushen
882dc8592b
Merge pull request #157 from multica-ai/feat/improve-compaction
feat(compaction): improve summary mode with fallback, split-turn, and metadata
2026-02-13 19:15:38 +08:00
LinYushen
77aff992c1
Merge pull request #170 from multica-ai/feat/desktop-api-client
feat(core): add auth-store and shared API client for desktop auth
2026-02-13 19:12:00 +08:00
yushen
882e34c491 fix(core): preserve context-specific auth error messages
Add optional context parameter to getAuthHeaders() so callers can
provide feature-specific suffixes (e.g. "to use web search") in the
not-logged-in error message, restoring the original behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:58:27 +08:00
yushen
53cffe923b refactor(tools): use shared api-client for auth headers
Replace duplicated getLocalAuth() + manual header construction in
finance/api.ts and web-search.ts with the shared getAuthHeaders()
and API_BASE_URL from hub/api-client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:56:26 +08:00
yushen
f76312511d feat(core): add shared api-client module for auth headers
Extract API_BASE_URL and getAuthHeaders() into a reusable module
so that tools don't duplicate base URL and auth header construction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:56:20 +08:00
yushen
77953a611d feat(finance): replace API key auth with auth headers
Route all financial data requests through api-dev.copilothub.ai/api/v1/financial
proxy and authenticate via sid/device-id/os-type headers instead of X-API-KEY.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:52:46 +08:00
Naiyuan Qing
4b6f42cc21
Merge pull request #169 from multica-ai/fix/google-oauth-client-id
fix(web): update Google OAuth Client ID
2026-02-13 18:39:05 +08:00
Naiyuan Qing
7b581b4e39 fix(web): update Google OAuth Client ID
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 18:38:12 +08:00
yushen
92a137414d feat(web-search): replace HMAC signing with auth headers
Migrate web_search tool from HMAC-SHA256 reqId signing to
sid/device-id/os-type auth headers, matching the desktop API client
pattern. Update endpoint to /api/v1/web-search.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:25:43 +08:00
yushen
ec413effb9 feat(core): add auth-store module to read local auth data
Reads sid and deviceId from ~/.super-multica/auth.json for use by
tools that need authenticated API access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:25:37 +08:00
yushen
5ee08e9368 Merge remote-tracking branch 'origin/main' into feat/desktop-api-client 2026-02-13 17:57:19 +08:00
Naiyuan Qing
9e3169e034
Merge pull request #168 from multica-ai/docs/desktop-build-guide
docs(desktop): add build commands and configuration guide
2026-02-13 17:56:42 +08:00
Naiyuan Qing
5c5ac76693 docs(desktop): add build commands and configuration guide to .env.example
- Add build commands section with dev/staging/production options
- Add build output section explaining release directory structure
- Add configuration guide for production builds
- Add variable naming convention explanation
- Improve environment variables documentation with examples

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 17:55:44 +08:00
Naiyuan Qing
9877a4f97e
Merge pull request #167 from multica-ai/feat/desktop-device-id
feat: unify encrypted Device ID across all platforms
2026-02-13 17:47:54 +08:00
Naiyuan Qing
0c748f563f
Merge pull request #166 from multica-ai/NevilleQingNY/login-drag-region
fix(desktop): enable window dragging on login page
2026-02-13 17:34:23 +08:00
Naiyuan Qing
242be23876 feat(utils): unify encrypted Device ID across all platforms
- Add common generateEncryptedId() utility in @multica/utils
- All Device IDs now use same encryption algorithm (40 hex chars)
- Web: store encrypted format directly in localStorage
- Desktop: use shared utility, accept encrypted ID from Web
- Hub: use shared utility for hub-id generation
- Telegram: use shared utility for device ID generation
- Gateway hook: use encrypted format for client connections

Algorithm: sha256(sha256(uuid).slice(0,32)).slice(0,8) + sha256(uuid).slice(0,32)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 17:34:23 +08:00
Naiyuan Qing
8dfd4bc388 fix(desktop): enable window dragging on login page
Add WebkitAppRegion drag to login page background areas so the window
can be dragged on macOS. Mark the sign-in button as no-drag to keep it
clickable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:28:38 +08:00
Naiyuan Qing
052c7ac040
Merge pull request #163 from multica-ai/feat/desktop-device-id
fix(web): add API_URL to turbo.json globalEnv
2026-02-13 17:16:11 +08:00
Jiayuan Zhang
fe6fdd4ddc
Merge pull request #165 from multica-ai/forrestchang/analyze-run-logs
feat(session): optimize image storage with externalization and resize
2026-02-13 17:13:40 +08:00
Naiyuan Qing
911ed5ae36
Merge pull request #164 from multica-ai/NevilleQingNY/persist-chat-tabs
fix(desktop): persist chat state across tab navigation
2026-02-13 17:10:54 +08:00
Naiyuan Qing
298299d88e fix(desktop): persist chat state across tab navigation
Keep LocalChat mounted at the Layout level with CSS visibility toggle
instead of unmounting on route change, preserving messages, streaming
state, and IPC subscriptions when switching sidebar tabs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:04:15 +08:00
Naiyuan Qing
8fcc14ceb1 fix(web): add API_URL to turbo.json globalEnv
Turborepo was not passing the API_URL environment variable to the build
process, causing Next.js rewrites to fall back to the default test API
instead of the production API configured in Vercel.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 16:59:18 +08:00
yushen
9026c27f21 Merge remote-tracking branch 'origin/main' into feat/desktop-api-client 2026-02-13 16:57:42 +08:00
Naiyuan Qing
adfff8366f
Merge pull request #162 from multica-ai/feat/desktop-device-id
feat(auth): Desktop Device ID from Web login
2026-02-13 16:55:53 +08:00
Naiyuan Qing
003bde460d fix(web): remove auth guard from home page
Home page (QR code scanning) does not require authentication.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 16:53:22 +08:00
Naiyuan Qing
0d11318618 fix(desktop): prevent duplicate welcome toast on login
- Move auth callback listener setup before async operations
- Add unique ID to welcome toast to prevent duplicates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 16:53:17 +08:00
Naiyuan Qing
f13509e12a feat(auth): pass encrypted Device ID from Web to Desktop
- Web stores raw UUID, encrypts when transmitting (consistent with copilot-search)
- Desktop receives encrypted Device ID from Web login callback
- Desktop stores encrypted 40-char format in auth.json
- Update IPC types to include deviceId in auth callback

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 16:53:13 +08:00
yushen
309c27b4dd feat(desktop): add API client with auth headers
Add fetch wrapper for desktop renderer to call Multica backend REST API.
Attaches sid, device-id, and os-type headers automatically using
useAuthStore and electronAPI.auth.getDeviceIdHeader().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 16:31:43 +08:00
Naiyuan Qing
68e262810c fix(desktop): store encrypted Device ID directly (40 hex chars)
- Change from storing raw UUID to storing encrypted format
- Consistent with devv-sdk and Web implementation
- Auto-migrate old UUID format to new encrypted format
- Validate device ID format (40 hex characters)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 16:00:16 +08:00
Naiyuan Qing
c79e87e000
Merge pull request #161 from multica-ai/feat/desktop-device-id
feat(desktop): add persistent Device ID with encryption
2026-02-13 15:43:01 +08:00
Naiyuan Qing
f0c9c43678 feat(web): add desktop callback API route
Server-side redirect to deep link for production builds.
More reliable than client-side window.location.href.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 15:37:08 +08:00
Naiyuan Qing
57cb99dbba feat(desktop): add persistent Device ID with encryption
- Generate UUID-based Device ID on first launch
- Store deviceId in auth.json (persists across logins/logouts)
- Add double SHA-256 encryption (consistent with Web)
- Expose getDeviceId and getDeviceIdHeader IPC methods
- Fix callback path to only accept /callback (prevent duplicate toasts)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 15:35:59 +08:00
Jiayuan Zhang
7ac90a2ce7 feat(tools): add image resize wrapper for read tool
Wraps the read tool from pi-coding-agent to automatically downscale
oversized images (>1MB or >2000px) before they enter the session.
Uses macOS sips for resize with no extra dependencies, following the
same pattern as OpenClaw. Falls back gracefully on non-macOS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:12:37 +08:00
Jiayuan Zhang
278334474f feat(session): externalize base64 images from session JSONL
Session JSONL files were bloated because base64 image data was stored
inline (a real session had 6.7MB of images in a 9.8MB file). Images
are now extracted to per-session media/ directories as binary files,
with compact $ref references stored in the JSONL. Images are restored
transparently on read. Old sessions with inline base64 remain
backward compatible and auto-migrate on next compaction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:12:30 +08:00
Bohan Jiang
ae3fee93da
Merge pull request #160 from multica-ai/fix/codex-provider-api
fix(providers): use dedicated openai-codex provider
2026-02-13 15:10:19 +08:00
Jiang Bohan
13fbeaf4d2 fix(providers): use dedicated openai-codex provider instead of aliasing to openai
Codex OAuth tokens use the ChatGPT backend API (chatgpt.com), not the
standard OpenAI API (api.openai.com). pi-ai already has a dedicated
openai-codex provider with the correct API format (openai-codex-responses)
and base URL. Remove the alias that was incorrectly mapping openai-codex
to openai, which caused 401 errors due to missing scopes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:01:57 +08:00
Naiyuan Qing
7578946990
Merge pull request #159 from multica-ai/refactor/login-ui-consistency
refactor(ui): unify login page styling across web and desktop
2026-02-13 14:57:16 +08:00
Naiyuan Qing
a2cabb550f refactor(ui): unify login page styling across web and desktop
- Use bordered icon with consistent size on both platforms
- Adjust font size to match icon proportions
- Simplify desktop tagline for cleaner presentation
- Streamline web login header to [icon] Sign In format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 14:56:16 +08:00