Commit Graph

71 Commits

Author SHA1 Message Date
Naiyuan Qing
fe358feff0 Reapply "feat: workspace URL refactor v2 + rollback-safe compat layer (#1138)" (#1139) (#1141)
This reverts commit b30fd98605.
2026-04-16 13:16:35 +08:00
Naiyuan Qing
b30fd98605 Revert "feat: workspace URL refactor v2 + rollback-safe compat layer (#1138)" (#1139)
This reverts commit 75d12c26c5.
2026-04-16 12:26:40 +08:00
Naiyuan Qing
75d12c26c5 feat: workspace URL refactor v2 + rollback-safe compat layer (#1138)
* Reapply "feat: workspace URL refactor + slug-first API identity (#1131)" (#1137)

This reverts commit 9b94914bc8.

* compat: legacy URL redirect + localStorage double-write for safe rollback

The first attempt at this refactor (#1131) was reverted because existing
users on old URLs (/issues, /projects, etc.) hit 404 immediately after
deploy, and rolling back left them with empty dashboards — the legacy
code reads localStorage["multica_workspace_id"] to attach a workspace
to API requests, but the new code had stopped writing that key.

Two compat layers added on top of the restored refactor:

1. proxy.ts now intercepts legacy route prefixes (/issues/*, /projects/*,
   /agents/*, /inbox/*, /my-issues/*, /autopilots/*, /runtimes/*,
   /skills/*, /settings/*). Logged-in users with a last_workspace_slug
   cookie are 302'd to /{slug}/{rest}, preserving their deep link. Users
   without the cookie bounce through / where the landing page picks a
   workspace client-side. Unauthenticated users go to /login.

2. Both layouts now double-write the workspace id to the legacy
   localStorage key on every workspace entry. New code ignores this key
   — it exists solely so that if this PR ever gets reverted again, the
   legacy build reading the key would still find the correct workspace
   and avoid the empty-dashboard symptom users saw during the rollback.

Net effect: any direction of deploy ↔ rollback is now cache-compatible,
and any direction of old bookmark → new route resolves without 404.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(platform): defer rehydrateAllWorkspaceStores to a microtask

Same React 19 render-phase restriction that forced setCurrentWorkspace
to defer its subscriber notifications. rehydrateAllWorkspaceStores
synchronously calls each persist store's rehydrate, which setState()s
the store, which schedules updates on any subscribed component. When
the workspace layout's render-phase ref guard invoked this, React
complained that SearchCommand (a store subscriber) couldn't be
re-rendered while WorkspaceLayout was still rendering.

Fix: queueMicrotask the rehydrate loop and add a pending-flag guard so
rapid workspace switches coalesce into one rehydrate on the final slug.
Persist stores tolerate one microtask of staleness — they hold UI
preferences, not correctness-critical state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:23:41 +08:00
Naiyuan Qing
9b94914bc8 Revert "feat: workspace URL refactor + slug-first API identity (#1131)" (#1137)
This reverts commit 59ace95a1e.
2026-04-16 11:56:15 +08:00
Naiyuan Qing
59ace95a1e feat: workspace URL refactor + slug-first API identity (#1131)
* feat: workspace URL refactor + slug-first API identity

Make the URL the single source of truth for workspace identity.
All workspace-scoped URLs now carry the workspace slug as the first
path segment (/{slug}/issues, /{slug}/projects, etc.), matching the
industry standard (Linear, Notion, Vercel, GitHub).

## Key architectural changes

**URL-driven workspace identity:**
- Web routes moved under app/[workspaceSlug]/(dashboard)/
- Desktop routes nested under /:workspaceSlug
- paths.ts builder centralises all URL construction
- reserved-slugs validation (backend + frontend + DB migration audit)

**Slug-first API contract:**
- Frontend sends X-Workspace-Slug header (from URL) instead of X-Workspace-ID (UUID)
- Backend middleware resolves slug → UUID via GetWorkspaceBySlug, falls back to
  X-Workspace-ID for CLI/daemon backwards compatibility
- WebSocket auth accepts ?workspace_slug query param with SlugResolver callback

**State cleanup:**
- Deleted: useWorkspaceStore (Zustand mirror), switchWorkspace/hydrateWorkspace/
  clearWorkspace, localStorage["multica_workspace_id"], api._workspaceId
- useCurrentWorkspace() derives from URL slug + React Query workspace list
- useWorkspaceId() is now a bridge hook (no Context, derives from useCurrentWorkspace)
- WorkspaceIdProvider removed from DashboardGuard
- Paired module vars (slug + UUID) in workspace-storage.ts for non-React consumers

**Layout simplified:**
- Render-phase ref guard sets workspace context synchronously (no async gate)
- DashboardGuard handles auth redirect, loading state, and workspace resolution
- Subscriber notifications deferred via queueMicrotask (React 19 compat)
- persist namespace uses slug (immutable) instead of UUID

## Issues resolved

MUL-43 (share links), MUL-509 (mobile workspace switch), MUL-723 (workspace in URL),
MUL-727 (create workspace flash), MUL-728 (delete workspace no-navigate),
MUL-820 (sidebar Join not switching)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve code review C3/C4/C5/C6 — desktop deadlock + hardcoded paths

C3: Desktop OnboardingGate was calling useCurrentWorkspace() outside
WorkspaceSlugProvider → always null → permanent onboarding deadlock.
Rewrite to use useQuery(workspaceListOptions()) which reads React Query
cache directly without slug context. Remove DashboardGuard from
DesktopShell (auth gating handled by AppContent, workspace routing by
WorkspaceRouteLayout per-tab).

C4: Landing page "Dashboard" links hardcoded /issues (no longer valid).
Changed to / — proxy handles redirect to /{lastSlug}/issues.

C5: autopilots-page.tsx had one hardcoded /autopilots/${id} link.
Changed to wsPaths.autopilotDetail(id).

C6: inbox-page.tsx hardcoded /inbox paths. Changed to wsPaths.inbox().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(desktop): wrap shell in WorkspaceSlugProvider from module var

AppSidebar calls useWorkspacePaths() → useRequiredWorkspaceSlug() which
throws outside WorkspaceSlugProvider. In the desktop shell, the sidebar
renders at the shell level (outside any tab's WorkspaceRouteLayout).

Fix: DesktopShell reads the current slug via useSyncExternalStore on
the workspace-storage singleton. When slug is available, wraps the
entire shell in WorkspaceSlugProvider. When null (first mount before
any tab's WorkspaceRouteLayout sets it), shows a loading spinner.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(desktop): migrate old tab paths + fix shell slug deadlock

Tab store rehydration: old-format paths like "/issues/abc" (missing
workspace slug prefix) are reset to "/" so IndexRedirect picks the
correct workspace. Detection: if the first segment is a known route
name (issues, projects, etc.) rather than a workspace slug, it's an
old-format path.

Desktop shell: TabContent must always render (not gated behind slug
check) so WorkspaceRouteLayout can mount and call setCurrentWorkspace.
Only sidebar and shell-level UI (chat, modals, search) gate on slug
being present.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:53:09 +08:00
Naiyuan Qing
70e4f44860 style(fonts): add text-autospace for CJK+Latin auto-spacing and sync design doc
- packages/ui/styles/base.css: add `text-autospace: ideograph-alpha
  ideograph-numeric` to html. Native CSS feature (Chrome 119+,
  Electron recent) that auto-inserts 1/4em space between CJK ideographs
  and Latin letters/numerals. Progressive enhancement — older browsers
  ignore the rule silently.
- docs/design.md: update font family table to reflect Inter + CJK system
  fallback. Reword font-bold ban rationale to be font-agnostic
  (information density / layout rhythm), not Geist-specific.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 08:45:23 +08:00
Naiyuan Qing
a8c3137f3b Merge remote-tracking branch 'origin/main' into feat/desktop-app
# Conflicts:
#	apps/web/app/(dashboard)/layout.tsx
#	apps/web/app/globals.css
#	apps/web/app/layout.tsx
#	apps/web/core/chat/mutations.ts
#	apps/web/core/chat/queries.ts
#	apps/web/features/chat/components/chat-message-list.tsx
#	apps/web/features/chat/components/chat-window.tsx
#	apps/web/features/landing/components/landing-footer.tsx
#	packages/core/package.json
#	packages/views/layout/app-sidebar.tsx
2026-04-10 08:01:19 +08:00
Naiyuan Qing
d911cdf5ac refactor: extract all shared logic to packages — apps are now thin routing shells
- Add CoreProvider to @multica/core/platform — single component for API/stores/WS/QueryClient init
- Delete 13 platform files across web (6) and desktop (7), each app keeps only navigation.tsx
- Extract AppSidebar + DashboardLayout to @multica/views/layout
- Extract LoginPage to @multica/views/auth
- Extract AgentsPage (1,279 lines) to @multica/views/agents (11 files)
- Extract InboxPage (468 lines) to @multica/views/inbox (5 files)
- Extract SettingsPage + 6 tabs (1,277 lines) to @multica/views/settings (9 files)
- Fix AppLink to use forwardRef for Base UI render prop compatibility
- Fix Tailwind @source to scan .ts files (status config with bg-info/bg-warning)
- Suppress next-themes React 19 script tag warning
- Add WebProviders wrapper for Server→Client function passing
- Wire all desktop routes to shared views, remove PlaceholderPage
- Net: +106 / -4,094 lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:45:41 +08:00
Naiyuan Qing
870d9d9465 docs: add implementation plan for upload/attachment fixes (MUL-410)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:33:19 +08:00
Naiyuan Qing
f41a0cf423 feat(views): extract packages/views — shared business UI + navigation adapter
- Create NavigationAdapter interface (push, replace, back, pathname, searchParams)
- Create AppLink component replacing next/link in 4 files
- Replace useRouter → useNavigation in 3 files (issue-detail, create-issue, create-workspace)
- Create WebNavigationProvider wrapping Next.js useRouter/usePathname/useSearchParams
- Move ~85 feature UI files (issues, editor, modals, my-issues, skills, runtimes) to packages/views/
- Add store singleton registration pattern (registerAuthStore, registerWorkspaceStore)
- Create data-aware wrappers in packages/views/common/ (ActorAvatar, Markdown)
- Update all app-layer imports to @multica/views/*
- Add @source directive for Tailwind to scan views package
- packages/views/ has zero next/* imports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:49:55 +08:00
Naiyuan Qing
19a1bbba4a feat(editor): drag-and-drop file upload with file card display
- Add drag-and-drop overlay with brand color visual feedback
- Images: inline rendering with blob preview → real URL replacement
- Non-images: file card node (spinner → filename card with download button)
- File card markdown roundtrip: [name](url) ↔ fileCard node via preprocessor
- Fix: double-upload on drag (check defaultPrevented)
- Fix: drop overlay not clearing (global drop/dragend listener)
- Fix: drop replacing existing content (use posAtCoords for drop position)
- Fix: multi-file drop position drift (only first file uses drop pos)
- Fix: same-name file upload conflict (use uploadId instead of filename)
- Fix: image upload descendants traversal not stopping (add found flag)
- Fix: parent comment edit missing onUploadFile prop
- Remove: attachment section UI (files live in markdown)
- Remove: file type whitelist (accept all types like Linear)
- Remove: console.log perf logs from production code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 09:26:12 +08:00
Naiyuan Qing
862b85e064 fix(web): DnD local-state overlay, onSettled list invalidation, WS self-event filter
- Board DnD: use local pendingMove state for instant card placement,
  bypassing TQ's async setQueryData notification delay
- useUpdateIssue: add list invalidation to onSettled (was only detail)
- use-realtime-sync: add isSelf check to specific issue WS handlers
  (prevents redundant cache writes for own mutations)
- Clean up debug console.logs from board-view, issues-page, mutations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:25:35 +08:00
Naiyuan Qing
5fe1ec806d docs: add TanStack Query migration plan
Phase 0-5 plan for migrating server state from Zustand to TanStack Query,
extracting headless business logic to core/ directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:20:43 +08:00
Jiayuan
c4a24c1a86 docs: refine README layout per feedback
- Move banner image to very top, remove feature background images
- Move product screenshot into "What is Multica?" section
- Fix logo SVG: use icon-only (no text) for reliable GitHub rendering
- Use markdown heading for "Multica" text instead of SVG text element
- Clean up features into a single bullet list
2026-04-02 01:09:38 +08:00
Jiayuan
479d69305d docs: redesign README with landing page content and images
- Add centered header with logo (dark/light mode), badges, and nav links
- Use landing page headline "Your next 10 hires won't be human."
- Add hero banner illustration and product screenshot from landing page
- Feature sections with inline images (teammates, runtimes)
- Rewrite feature descriptions to match landing page messaging
- Add architecture table alongside diagram
- Create logo SVGs in docs/assets/
- All links verified against main branch (CLI_AND_DAEMON.md, CONTRIBUTING.md, etc.)
2026-04-02 00:46:02 +08:00
Jiayuan Zhang
d4f5c5b16f feat: pivot to AI-native task management platform (#232)
Replace the agent framework codebase with a new monorepo structure
for an AI-native Linear-like product where agents are first-class citizens.

New architecture:
- server/ — Go backend (Chi + gorilla/websocket + sqlc)
  - API server with REST routes for issues, agents, inbox, workspaces
  - WebSocket hub for real-time updates
  - Local daemon entry point for agent runtime connection
  - PostgreSQL migration with 13 tables (issue, agent, inbox, etc.)
  - WebSocket protocol types for server<->daemon communication
- apps/web/ — Next.js 16 frontend
  - Dashboard layout with sidebar navigation
  - Route skeleton: inbox, issues, agents, board, settings
- packages/ui/ — Preserved shadcn/ui design system (26+ components)
- packages/types/ — Full API contract types (Issue, Agent, Workspace, Inbox, Events)
- packages/sdk/ — REST ApiClient + WebSocket WSClient
- packages/store/ — Zustand stores (issue, agent, inbox, auth)
- packages/hooks/ — React hooks (useIssues, useAgents, useInbox, useRealtime)
- packages/utils/ — Shared utilities

Removed: apps/cli, apps/desktop, apps/mobile, apps/gateway,
packages/core, skills/, and all agent-framework code.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 17:55:49 +08:00
Jiayuan Zhang
0f5bd5fff1 refactor(agent): remove legacy memory subsystem 2026-02-17 15:33:39 +08:00
Jiayuan Zhang
218e6da544 refactor(apps): adopt conversation-first IPC and API surfaces 2026-02-17 09:42:13 +08:00
Jiayuan Zhang
c4d9f0273a docs: clarify channel route key conversation binding 2026-02-17 09:39:25 +08:00
Jiayuan Zhang
f0f6055031 feat(platform): align conversation semantics across surfaces 2026-02-17 09:39:25 +08:00
Jiayuan Zhang
8e245e77ca refactor(clients): adopt conversation rpc with legacy fallback 2026-02-17 09:39:25 +08:00
Jiayuan Zhang
708116afb1 feat(gateway): support telegram active conversation sessions 2026-02-17 09:39:25 +08:00
Jiayuan Zhang
62feefb07d Merge pull request #219 from multica-ai/codex/web-policy-hybrid-roadmap
docs(agent): add web tools policy optimization roadmap
2026-02-17 02:47:02 +08:00
Jiayuan Zhang
276e30626a docs(agent): add web tools policy optimization roadmap 2026-02-17 02:43:55 +08:00
Jiayuan Zhang
8a2b3e10f3 test(e2e): add natural Notion gap-discovery benchmark case 2026-02-17 02:37:29 +08:00
Jiayuan Zhang
50407918b9 test(e2e): add spotify capability-gap ux benchmark case 2026-02-17 02:37:29 +08:00
Jiayuan Zhang
2074aac49e feat(e2e): add clawhub skills benchmark suite 2026-02-17 02:37:29 +08:00
Jiayuan Zhang
2447230ca7 docs: keep only workflow testing and process guidance 2026-02-17 01:15:22 +08:00
Jiayuan Zhang
88582fe050 docs(development): restore dev-local workflow docs 2026-02-17 01:11:21 +08:00
Jiayuan Zhang
0ed46510ee docs: regenerate prioritized core documentation 2026-02-17 00:53:37 +08:00
Jiayuan Zhang
ecb0cd392e chore(docs): remove non-e2e documentation 2026-02-17 00:46:36 +08:00
Jiayuan Zhang
c38a576b8f feat(benchmark): parallelize finance e2e runs 2026-02-16 02:15:55 +08:00
Jiayuan Zhang
edc55390cf feat(benchmark): add finance e2e case suite 2026-02-16 01:29:24 +08:00
Jiayuan Zhang
10c57c0f7a docs: add SWE-bench runner guide
Covers the full pipeline: dataset download, agent execution,
result analysis, and official Docker evaluation. Includes
runner options, output format, known limitations, and initial
benchmark results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:30:58 +08:00
Jiayuan Zhang
75fac3a2d7 fix(auth): fallback to dev auth.json for E2E tests
web_search and data tools authenticate via auth.json (sid + deviceId).
When SMC_DATA_DIR is set (e.g. for E2E tests), the auth file may not
exist in the custom dir. Now getLocalAuth() falls back to
~/.super-multica-dev/auth.json, which is created by pnpm dev:local
Desktop login and valid for the dev backend (api-dev.copilothub.ai).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:37:26 +08:00
Jiayuan Zhang
1ffa8b1389 docs: add SMC_DATA_DIR isolation for E2E test sessions
E2E tests now use ~/.super-multica-e2e to avoid polluting dev
(~/.super-multica-dev) or production (~/.super-multica) session data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:29:39 +08:00
Jiayuan Zhang
a823e391b9 docs: add E2E testing workflow to CLAUDE.md and update guide with MULTICA_API_URL
Add agent-driven E2E testing section to CLAUDE.md so all team members'
Coding Agents automatically know how to run and analyze E2E tests.
Update guide with MULTICA_API_URL requirement discovered during testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:23:37 +08:00
Jiayuan Zhang
496eda82d7 docs: add agent-driven E2E testing guide for Coding Agents
Comprehensive guide teaching Coding Agents how to perform automated E2E
testing by running the agent CLI with --run-log and analyzing structured
run-log events. Includes feature test playbooks, event reference, and
analysis patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:03:47 +08:00
Jiayuan Zhang
0678431a7d docs: update credential docs for per-skill .env files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:34:51 +08:00
Jiayuan Zhang
358fcb3c0e Merge pull request #197 from multica-ai/forrestchang/create-pr
feat(report): add code stats report generator
2026-02-15 13:09:52 +08:00
yushen
4dba1cfdf0 refactor: unify API URL env var to MULTICA_API_URL
Replace scattered API_URL, MAIN_VITE_API_URL, and RENDERER_VITE_API_URL
with a single MULTICA_API_URL across all apps and packages.

- Desktop: use envPrefix to expose MULTICA_* to main process, rename
  RENDERER_VITE_API_URL → RENDERER_VITE_MULTICA_API_URL, remove
  MAIN_VITE_API_URL (now read directly via MULTICA_API_URL)
- Web: add .env.development with MULTICA_API_URL, enforce required check
  in next.config.ts, update .gitignore to allow .env.development
- Core: make MULTICA_API_URL required in api-client (no silent fallback)
- Scripts: pass MULTICA_API_URL in dev-local.sh for web process
- Turbo: update globalEnv from API_URL to MULTICA_API_URL
- Docs: update references to the new env var name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 06:31:00 +08:00
Jiayuan Zhang
a7c1b42b31 feat(report): add code stats report generator 2026-02-15 04:32:30 +08:00
Jiayuan Zhang
00aa2d26ef docs: remove obsolete design proposals and plans
Delete auto-memory-refresh, cron-job-tool, and dashboard-design
docs that were never implemented. Remove Design Proposals section
from README.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 03:32:47 +08:00
Jiayuan Zhang
a91e6b7a08 docs: remove openclaw research notes and add doc index to README
Delete docs/channel/openclaw-research.md (1187-line research dump,
insights already absorbed into implementation). Expand README
documentation section with categorized links to all docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 03:26:51 +08:00
Jiayuan Zhang
18a6996c97 docs: slim down README and split into topic-specific docs
Add local full-stack development section (pnpm dev:local) and
move detailed content (credentials, CLI, skills/tools, time
injection, development guide) into separate docs/ files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 03:23:54 +08:00
Jiayuan Zhang
1bfd206217 docs: add architecture and module diagram (draw.io) (#180)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 01:09:26 +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
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
901f5ba804 docs: add dashboard design plan
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 17:04:07 +08:00