Commit Graph

2977 Commits

Author SHA1 Message Date
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
Naiyuan Qing
736df03a4f Merge pull request #156 from multica-ai/feat/desktop-auth
feat: add desktop authentication with Web login
2026-02-13 14:49:38 +08:00
Naiyuan Qing
09562776d4 fix(web): avoid setState in useEffect in AuthGuard 2026-02-13 14:43:52 +08:00
Naiyuan Qing
e0f80b0054 merge: resolve conflict with main (keep both auth and subagents handlers) 2026-02-13 14:41:15 +08:00
Naiyuan Qing
450257035f fix: add missing comma in package.json 2026-02-13 14:39:38 +08:00
Bohan Jiang
b2e4f08424 Merge pull request #158 from multica-ai/feat/subagent-dashboard
feat(desktop): subagent dashboard
2026-02-13 14:37:55 +08:00
Naiyuan Qing
7faf421996 merge: resolve conflict with main branch (build scripts) 2026-02-13 14:36:42 +08:00
Naiyuan Qing
e3c24fc10b chore(desktop): add deep link protocol and build scripts
- Add multica:// protocol for macOS and Windows (production login)
- Add build:staging and build:production scripts
- Update env vars: remove MULTICA_URL, add WEB_URL
- Update README with environment configuration docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 14:33:48 +08:00
Naiyuan Qing
ae86bba599 feat(web): add client-side auth with session storage and route protection
- Add lib/auth.ts for cookie-based session storage
- Add AuthGuard component for route protection
- Update request.ts to include sid in Authorization header
- Update login-form.tsx to save session and redirect if authenticated
- Wrap ChatPage with AuthGuard

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 14:31:02 +08:00
Naiyuan Qing
683182e3ac fix(web): fix login page prerender error
Split login page into Server Component + Client Form to properly
handle useSearchParams with force-dynamic rendering.

Reference: CAP project pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 14:25:38 +08:00
Naiyuan Qing
2a6e10496a feat(desktop): improve login page and add auth toasts
- Add tagline and animation to login page
- Add toast notification on login success
- Add toast notification on logout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 14:19:53 +08:00
Jiang Bohan
499c573544 feat(desktop): add subagent dashboard with real-time status tracking
Adds a status bar and slide-out dashboard panel to the chat view that
shows subagent progress in real-time. Polls at 2s when active, 10s when
idle. Completed runs auto-hide after 5 minutes. Includes dismiss button
and 30s auto-dismiss for the status bar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:46:58 +08:00
yushen
d7e85d0c25 fix(compaction): prevent double-counting in split-turn detection
- detectSplitTurn now returns adjustedToSummarize (truncated at
  assistantIndex) so split prefix messages are not summarized twice
  and removedCount is not inflated
- Remove unused contextWindow parameter from computeAdaptiveChunkRatio
- Remove duplicated single-chunk fast path in compactMessagesWithChunkedSummary
  (the multi-chunk loop handles 1 chunk naturally)
- Fix triple-newline formatting in buildPlainTextFallback by concatenating
  metadata sections directly instead of joining through parts array

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:33:31 +08:00
yushen
9e7907a814 feat(compaction): switch default to summary mode with split-turn and adaptive chunking
- Default compaction mode changed from "tokens" to "summary" (LLM-based)
- Split turn detection: handles orphaned tool_result messages at compaction
  boundary by summarizing the split turn prefix separately
- Adaptive chunk sizing: dynamically adjusts chunk ratio (0.15-0.4) based on
  average message token count instead of fixed 50k tokens
- Fallback chain: summary compaction wraps in try/catch, falling back to
  tokens mode on complete failure; summarizeWithFallback provides 3-level
  degradation within summary mode itself
- Metadata appended to summaries: file operations + tool failures sections
- CompactionResult extended with fileOperations and toolFailures fields
- CompactionEndEvent gains optional summary field
- API key resolution improved: reuses agent's own key for summary generation

Backward compatible: explicit "count" or "tokens" mode behaves identically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:26:34 +08:00
yushen
ba44de89b7 feat(compaction): add metadata extraction and multi-level summary fallback
New modules for improved compaction:
- compaction-metadata.ts: extracts file operations (read/modified) and tool
  failures from compacted messages, appended to summaries for context retention
- summary-fallback.ts: 3-level degradation chain (full LLM summary → filtered
  summary excluding oversized messages → plain-text fallback with metadata)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:26:22 +08:00
Naiyuan Qing
31c8b1babc refactor(web): replace devd proxy with Next.js rewrites
- Add rewrites in next.config.ts to proxy /api/* to api-dev.copilothub.ai
- Update docs to reflect new local dev workflow (no devd needed)
- Fix web port number in CLAUDE.md (3001 → 3000)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 13:25:08 +08:00
Naiyuan Qing
6e3ba38df6 docs(auth): clarify storage location for SID and user data
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:39:16 +08:00
Naiyuan Qing
2eb7ff6847 chore: update pnpm-lock.yaml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:25:12 +08:00
Naiyuan Qing
bef3a5b3cb docs: add desktop auth integration guide
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:25:08 +08:00
Naiyuan Qing
108cf7ffb0 feat(web): add login page for desktop auth callback
- Add email/code login with verification
- Add Google OAuth login
- Add desktop callback API route
- Add request service with device ID handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:25:03 +08:00
Naiyuan Qing
2577475ba6 feat(desktop): add authentication flow with Web login
- Add auth IPC handlers (main process)
- Add auth store with Zustand (renderer)
- Add login page with branded UI
- Add AuthGuard for protected routes
- Add user dropdown menu in sidebar footer
- Support deep link (multica://) for production
- Support local HTTP callback for development

Reference: https://github.com/CapSoftware/Cap

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:24:57 +08:00
Naiyuan Qing
ca1c260735 feat(ui): add size prop to MulticaIcon bordered variant
Supports sm, md, lg sizes for flexible usage in different contexts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:24:48 +08:00
Naiyuan Qing
35ab158775 feat(types): add AuthUser type for auth integration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 12:24:43 +08:00
Bohan Jiang
7acf4cc4a5 Merge pull request #155 from multica-ai/fix/codex-oauth-expiry
fix(oauth): don't expire credentials with refresh_token
2026-02-13 11:56:49 +08:00
Jiang Bohan
a490c737cc feat(providers): add gpt-5.3-codex and update OpenAI model lists
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 11:55:16 +08:00
Jiang Bohan
16c325c808 fix(oauth): don't expire OAuth credentials that have refresh_token
Codex and Claude Code OAuth tokens with refresh_token can auto-renew,
so they should not be considered expired based on last_refresh time or
file mtime. Previously, credentials were hardcoded to expire after 1
hour, causing valid Codex sessions to show as unconfigured.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 11:42:24 +08:00
Bohan Jiang
065b686960 Merge pull request #154 from multica-ai/fix/desktop-ci-publish
fix(desktop): prevent electron-builder auto-publish in CI
2026-02-13 11:31:05 +08:00
Jiang Bohan
d641c1a30c fix(desktop): prevent electron-builder auto-publish in CI
electron-builder detects CI and implicitly triggers publishing to GitHub
Releases, which fails without GH_TOKEN. Adding --publish never to the
build script so CI only builds without attempting to publish.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 11:30:26 +08:00
Naiyuan Qing
0ae17d6082 Merge pull request #153 from multica-ai/docs/monorepo-dev-workflow
docs: add monorepo development workflow
2026-02-13 09:29:51 +08:00
Naiyuan Qing
e87e39f13b docs: add monorepo development workflow documentation
- Update root dev script to build packages before watching
- Add --no-dts flag to package dev scripts to avoid DTS race conditions
- Document monorepo development workflow in README

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 09:21:47 +08:00
Naiyuan Qing
c728a80a9b Merge pull request #152 from multica-ai/fix/markdown-strikethrough-parsing
fix(ui): remove math plugins and disable single-tilde strikethrough
2026-02-13 08:51:37 +08:00
Naiyuan Qing
374ce68b84 fix(ui): remove math plugins and disable single-tilde strikethrough
- Remove remarkMath and rehypeKatex plugins that caused text wrapping
  issues by interpreting $ signs as LaTeX delimiters
- Configure remarkGfm with singleTilde: false to prevent single ~ from
  being parsed as strikethrough (e.g., ~1000 should not become <del>)
- Only double tilde ~~text~~ now renders as strikethrough

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 08:33:56 +08:00
Jiayuan Zhang
ad26eec7d2 Merge pull request #151 from multica-ai/forrestchang/telegram-file-send
feat(gateway): handle send_file action in Telegram service
2026-02-13 04:28:56 +08:00
Jiayuan Zhang
0c6cdb0d3a fix(hub): initialize channelManager before restoreAgents
Move channel plugin initialization (initChannels + ChannelManager
constructor) before restoreAgents() to prevent TypeError when
createAgent() calls channelManager.listChannelInfos() during restore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 01:40:16 +08:00
Jiayuan Zhang
f5ac4b85e8 feat(gateway): handle send_file action in Telegram service
Add sendFileToTelegram method that decodes base64 file data and sends
it via grammy's InputFile API. Handle send_file RoutedMessage action
in the virtual device sendCallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 01:37:41 +08:00