Commit Graph

2130 Commits

Author SHA1 Message Date
LinYushen
70aea76bf6 fix(views): remove background container from provider logos (#573)
Show provider logos directly without the green/gray rounded background
container in both runtime list and detail views.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 17:22:46 +08:00
yushen
fb475915c1 fix(chat): add workspace scoping, error logging, and query cleanup
- CancelTaskByUser: verify task belongs to current workspace for both
  chat and issue tasks, preventing cross-workspace cancellation
- Log errors for TouchChatSession and CreateChatMessage instead of
  silently discarding them
- Add ON DELETE CASCADE to chat_session.creator_id FK
- Add staleTime: Infinity to chat query options (project convention)
- Remove dead useSendChatMessage mutation (replaced by direct api call)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 17:18:14 +08:00
yushen
1f717c9059 feat(chat): add ownership checks, optimistic messages, and cleanup
- Add creator ownership verification on chat session endpoints (get, archive, send, list messages)
- Add CancelTaskByUser handler with ownership check instead of unrestricted CancelTask
- Show user messages optimistically before server response
- Remove unused streamingContent from chat store and sendMessage mutation import
- Make QueryProvider devtools flag a prop instead of reading process.env in core package
- Add proper FK constraint on chat_session.creator_id → user(id)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 17:13:14 +08:00
yushen
8a73251b15 Merge remote-tracking branch 'origin/main' into agent/cc-girl/16ef1984 2026-04-09 17:06:37 +08:00
LinYushen
c283288133 feat(web): display provider logos in runtime list (#571)
* feat(web): display provider-specific logos in runtime list

Replace generic monitor/cloud icons with distinctive SVG logos for each
agent CLI provider (Claude, Codex, OpenCode, OpenClaw) in the runtime
list and detail views.

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

* fix(web): use official provider logos from upstream sources

Replace hand-drawn SVG approximations with official logos:
- Claude: Anthropic mark from Bootstrap Icons (bi-claude)
- Codex: OpenAI mark from Bootstrap Icons (bi-openai)
- OpenCode: pixel-art "O" from anomalyco/opencode brand assets
- OpenClaw: pixel lobster mascot from openclaw/openclaw

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-09 17:05:18 +08:00
Bohan Jiang
c8f0f3dc9d feat(views): show sub-issue progress in list rows (#566)
* feat(views): show sub-issue progress indicator in issue list rows

When an issue has sub-issues, display a circular progress ring with
done/total count (e.g. "2/3") in the list row. Progress is computed
from the already-loaded issue list without additional API calls.

Extracts ProgressRing into a shared component reused by both
issue-detail and list-row.

* feat(views): refine sub-issue progress UI and add to board view

- Move progress badge right after issue title (not pushed to far right)
- Increase progress ring size from 11px to 14px for better visibility
- Add sub-issue progress indicator to board card view
- Thread childProgressMap through BoardView → BoardColumn → BoardCard
2026-04-09 16:52:12 +08:00
yushen
821b6ece57 merge: resolve conflicts with main (project feature)
Merge both chat and project types/events/routes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:49:55 +08:00
yushen
3ffebd097c feat(chat): improve chat UI, fix streaming, add stop/fullscreen/agent permissions
- Redesign chat UI: Linear-style FAB, agent selector, empty state, Markdown rendering
- Fix WS message broadcast for chat tasks (resolve workspaceID from chat_session)
- Fix streaming race condition using refs for pendingTaskId
- Save assistant replies to chat_message on task completion
- Add real-time timeline rendering (tool calls, results, thinking) with collapsible groups
- Add historical timeline loading for past assistant messages
- Persist activeSessionId in localStorage + auto-restore from server
- Add chat workspace context to agent prompt (CLI commands, repos, skills)
- Add stop button (cancel task) during agent execution
- Add fullscreen mode (right-side panel, 50% width)
- Filter agent selector by visibility permissions (same as assign picker)
- Add generic POST /api/tasks/{taskId}/cancel route for chat tasks
- Add new chat (+) button, remove duplicate close button
- Devtools toggle via NEXT_PUBLIC_DEVTOOLS env var

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:47:11 +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
Bohan Jiang
245beed829 feat(projects): add priority attribute to projects (#565)
Add priority field (urgent/high/medium/low/none) to projects, matching
the existing issue priority system. Includes database migration, API
support for create/update/list filtering, and UI for the create dialog,
project list table, and project detail page.
2026-04-09 16:31:05 +08:00
Bohan Jiang
741247c5cc fix(projects): add distinct colored dots for each project status (#564)
Each project status now displays a unique colored dot indicator in both
the status dropdown trigger and menu items. Previously all statuses
showed the same color, making them indistinguishable.
2026-04-09 16:23:17 +08:00
Naiyuan Qing
ef11bcd2d1 Merge pull request #536 from multica-ai/agent/naiyuan-agent/66842ca3
fix: upload content-type, disposition, attachment sync, and list API optimization (MUL-410)
2026-04-09 16:23:15 +08:00
Bohan Jiang
9da6a911cd fix(views): resolve nested button hydration error in agent live card (#563)
Change inner <button> to <span role="button"> inside CollapsibleTrigger
to fix "button cannot be a descendant of button" hydration error.
2026-04-09 16:16:01 +08:00
Bohan Jiang
b669b1c3a6 Merge pull request #562 from multica-ai/agent/j/4fbf073a
feat(cli): add project commands and --project flag for issues
2026-04-09 16:05:05 +08:00
Bohan Jiang
8c51614cfa Merge pull request #561 from multica-ai/feat/create-issue-project-picker
feat(issues): add project picker to create issue modal + fix IssuesHeader store
2026-04-09 16:04:46 +08:00
Jiang Bohan
1b7c3d7d94 fix(projects): remove issue count from Issues tab and align tab bar with header 2026-04-09 16:02:53 +08:00
Jiang Bohan
b7ffba4d2f fix(issues): wrap IssuesHeader inside ViewStoreProvider
IssuesHeader was rendered outside ViewStoreProvider in IssuesPage,
causing "useViewStore must be used within ViewStoreProvider" crash
after switching IssuesHeader to context-based store. Moved the
provider boundary up to include IssuesHeader.
2026-04-09 15:59:39 +08:00
Jiang Bohan
072ccc90aa feat(cli): add project commands and --project flag for issues
Add `multica project` CLI commands (list, get, create, update, delete,
status) so agents can manage projects. Also add --project flag to
`issue create` and `issue update` for associating issues with projects.
2026-04-09 15:57:05 +08:00
Jiang Bohan
8cf27af3b2 feat(issues): add project picker to create issue modal + fix IssuesHeader view store
- Add a Project pill to the create issue modal property toolbar,
  allowing users to assign a project at creation time. Uses the
  existing projectListOptions query and passes project_id in the
  create request. Supports selecting, changing, and clearing project.
- Fix IssuesHeader to use context-based useViewStore instead of the
  global useIssueViewStore singleton, so filters/sort/view toggle
  work correctly when mounted inside a project-scoped ViewStoreProvider.
2026-04-09 15:52:36 +08:00
Naiyuan Qing
0696532a99 fix(issues): skip list cache as initialData when description is missing
The list API no longer returns description. ContentEditor reads
defaultValue on mount only and ignores subsequent prop changes in
editable mode. Seeding initialData from list cache (description=null)
caused the editor to mount with empty content permanently.

Only use list cache as initialData when description is present;
otherwise let the loading state show until the detail query resolves.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:45:25 +08:00
Bohan Jiang
0ff9e2ba39 Merge pull request #558 from multica-ai/feat/project-ui-redesign
feat(projects): redesign project UI to match Linear
2026-04-09 15:38:56 +08:00
Bohan Jiang
3916a0ed1d Merge pull request #557 from multica-ai/agent/j/e8ad55f1
fix(cli): show actionable error when workspace_id is missing
2026-04-09 15:35:48 +08:00
Jiang Bohan
b6c369ef17 feat(projects): redesign project UI to match Linear and align with issue patterns
Create Project dialog:
- Match Create Issue modal layout (custom shell, TitleEditor,
  ContentEditor, property toolbar with pill buttons)
- Add status picker, lead picker, and emoji icon chooser
- Expandable dialog (compact ↔ expanded)

Projects list page:
- Replace card layout with Linear-style table (column headers,
  dense rows with icon, name, status badge, lead avatar, created date)

Project detail page:
- Linear-style breadcrumb header with ... menu (copy link, delete)
  and copy link icon on the right
- Tab bar: Overview + Issues
- Overview: clickable emoji icon picker, TitleEditor, inline property
  pills (status + lead), ContentEditor for description
- Issues tab: reuses existing BoardView/ListView/IssuesHeader/
  BatchActionToolbar with a project-scoped view store and client-side
  project_id filtering
- Remove summary stats section
2026-04-09 15:35:32 +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
fee8f41ea5 perf(api): omit description from list issues response
Change ListIssues and ListOpenIssues SQL queries to select specific
columns (excluding description, acceptance_criteria, context_refs).
Reduces list API payload size, especially for issues with embedded images.

Frontend handles null description gracefully — board card short-circuits,
issue detail fetches full data via its own query.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:33:15 +08:00
Naiyuan Qing
80afd1cc00 fix(editor): decouple description uploads from attachment records
Description editor uploads no longer pass issueId to the upload API.
This avoids stale attachment records when users delete images from
the editor — the URL already lives in the markdown content.

Comment/reply uploads continue linking to the issue for agent discovery.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:33:08 +08:00
Naiyuan Qing
8526f013da fix(upload): SVG content-type fallback and Content-Disposition for non-media files
- Add extension-based content-type override after http.DetectContentType()
  to fix SVG files getting text/xml instead of image/svg+xml
- Use Content-Disposition: attachment for non-media files so browsers
  download CSV/PDF instead of displaying inline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:33:02 +08:00
Jiang Bohan
3046f51300 fix(cli): show actionable error when workspace_id is missing
When a user has multiple workspaces but no default configured,
`agent list` and `issue list` would fail with a cryptic server-side
"workspace_id is required" error. Now the CLI validates early and
suggests using --workspace-id, MULTICA_WORKSPACE_ID env, or
`multica config set workspace_id`.

Closes #532
2026-04-09 15:31:54 +08:00
LinYushen
d5f18c23cb fix(runtime): remove redundant provider from list item subtitle (#555)
The runtime name already includes the provider (e.g., "Codex (mini.local)"),
so showing provider again in the subtitle was redundant. Now the subtitle
shows only the owner avatar + name, falling back to runtime_mode if no owner.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:17:22 +08:00
Bohan Jiang
dab9c7cf9b Merge pull request #553 from gyh1621/gyh
fix(daemon/repocache): unstick stale cache from initial snapshot
2026-04-09 15:05:48 +08:00
Naiyuan Qing
83769c4780 fix(desktop): add type=submit to login buttons
base-ui Button defaults to type="button", which doesn't trigger form
onSubmit. Explicit type="submit" fixes the click-to-submit flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:01:23 +08:00
Bohan Jiang
68e2a14ba2 feat(projects): add Project entity with full-stack CRUD support (#552)
Implements the Project concept as a higher-level grouping for issues.
Hierarchy: workspace → project → issue → sub-issue.

Backend:
- Migration 034: project table + issue.project_id FK
- sqlc queries for project CRUD
- Project handler with list/get/create/update/delete
- Issue handler updated to support project_id in create/update
- Routes at /api/projects, WebSocket event constants

Frontend (new monorepo structure):
- @multica/core: Project types, API client methods, queries/mutations,
  status config, realtime sync
- @multica/views: Projects list page, detail page (overview + issues
  tabs), project picker for issue detail panel
- apps/web: Route pages, sidebar navigation entry

All TypeScript type checks and tests pass.
2026-04-09 14:59:16 +08:00
Naiyuan Qing
848d79df11 fix(desktop): remove type:module — Electron main/preload are CJS
Root cause: "type": "module" made Node.js treat all .js as ESM, but
Electron loads preload via require() (CJS). Removing it makes .js
default to CJS, which is what Electron expects. No rollup overrides needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:44 +08:00
Naiyuan Qing
1caa7f6324 fix(desktop): preload .cjs output for ESM package + CORS for electron dev
- Preload output as .cjs so Node.js treats it as CJS regardless of
  "type": "module" in package.json
- Add electron-vite dev server ports (5173, 5174) to default CORS origins

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:53:15 +08:00
yushen
f9a430e100 merge: resolve conflicts with main branch monorepo extraction
Update chat feature imports to use new package paths:
- @/shared/types → @multica/core/types
- @/shared/api → @/platform/api
- @core/* → @multica/core/*
- @/features/realtime → @multica/core/realtime
- @/components/ui/* → @multica/ui/components/ui/*

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:49:47 +08:00
Bohan Jiang
d7a37f60b5 fix(web): resolve CSS token import and WorkspaceIdProvider crash after monorepo extraction (#551)
- globals.css: use relative path for @multica/ui/styles/tokens.css
  since Tailwind v4's @import resolver doesn't follow pnpm workspace
  symlinks + package.json#exports
- globals.css: widen @source globs from *.tsx to *.{ts,tsx} so
  Tailwind scans .ts config files — fixes bg-info being purged
  (Done badge invisible in light mode)
- layout.tsx: hoist WorkspaceIdProvider above SidebarProvider so
  AppSidebar (which now calls useWorkspaceId via useMyRuntimesNeedUpdate
  from #533) doesn't throw on mount
2026-04-09 14:48:48 +08:00
Naiyuan Qing
0e0c5f4cdb fix(desktop): force preload CJS output and fix CSS @source paths
- Preload must be CJS (Electron loads it via require), force format: "cjs"
  and entryFileNames: "[name].js" so output matches main's reference
- @source paths were 4 levels up but need 5 (src/renderer/src/ to root)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:47:46 +08:00
Naiyuan Qing
bea274492c fix(desktop): use localStorage instead of electron-store
Electron renderer IS a browser — localStorage works natively, no need
for electron-store in preload. Removes the preload module loading issue
and eliminates an unnecessary dependency + IPC bridge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:46:00 +08:00
Naiyuan Qing
f7c1ae4d77 fix(desktop): move AuthInitializer to App root to prevent init deadlock
AuthInitializer was inside DashboardShell which has an isLoading early
return — the initializer never rendered, so isLoading never became false.
Moved to App.tsx (same as web's root layout) so it always executes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:43:00 +08:00
Naiyuan Qing
784111a498 fix(desktop): fix tsconfig path alias and AppLink children type error
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:37:33 +08:00
Naiyuan Qing
77f48d9f26 feat(desktop): add CSS, router, pages, and app entry with provider nesting
- globals.css with Tailwind + design tokens from @multica/ui
- Hash router with dashboard shell, issues, my-issues, runtimes, skills pages
- Login page with email OTP flow (no Google OAuth)
- IssueDetailPage wrapper extracting route param for IssueDetail
- App.tsx with ThemeProvider > QueryProvider > RouterProvider nesting
- main.tsx without StrictMode to avoid Zustand double-render issues

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:35:51 +08:00
gyh1621
6e475b9521 fix(daemon/repocache): unstick stale cache from initial snapshot
The bare cache used a mirror-style fetch refspec
(+refs/heads/*:refs/heads/*) which collided with worktree-locked
refs/heads/agent/<task> branches once those branches were pushed
back to origin as PRs. git fetch aborted with "refusing to fetch
into branch ... checked out at ...", the error was swallowed as a
warning, and every subsequent checkout reused the snapshot from
the original clone.

Fix:
- Clone / migrate bare caches to a remote-tracking layout
  (+refs/heads/*:refs/remotes/origin/*) so fetched heads never
  land in refs/heads/*.
- Resolve the base ref from refs/remotes/origin/HEAD with a
  5-level fallback (verified origin/HEAD symref to origin/main
  or origin/master to the bare HEAD bridged into origin/<same>
  to single-entry origin/* scan to bare HEAD for legacy caches).
- Refuse to guess when refs/remotes/origin/* has multiple
  candidates and none match a known fallback, so CreateWorktree
  fails loudly instead of basing work on an arbitrary branch.
- Refresh refs/remotes/origin/HEAD after every successful fetch,
  not just on the legacy migration path, so a cache that was
  already modern picks up an upstream default-branch change.
- Verify the primary symref target actually exists so a phantom
  refs/remotes/origin/HEAD from a broken set-head does not
  surface a deleted branch.
- Detect legacy caches on the fly and rewrite refspec +
  refs/remotes/origin/* + refs/remotes/origin/HEAD in place so
  existing clones self-heal on next use.
- Serialize per-bare-repo mutation (both Sync and CreateWorktree)
  with sync.Map-backed mutexes so concurrent fetch and worktree
  add on the same repo cannot race on git's own lockfiles.
- Narrow the already-exists retry to actual branch-collision
  errors so a path-collision no longer silently leaks a branch
  into the bare repo.
2026-04-09 14:34:51 +08:00
Naiyuan Qing
dafd51e327 feat(desktop): add title bar, dashboard shell, sidebar, and shared components
- multica-icon: copied from web, zero platform-specific deps
- theme-provider: next-themes + TooltipProvider wrapper
- title-bar: draggable frameless title bar with macOS traffic light inset
- app-sidebar: adapted from web — uses @multica/views/navigation instead of next/link
- dashboard-shell: root layout with auth guard, sidebar, outlet, and workspace provider

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:33:20 +08:00
Naiyuan Qing
f9eeafb568 feat(desktop): add renderer platform layer — storage, api, auth, ws, navigation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:30:12 +08:00
Naiyuan Qing
4585306bfc feat(desktop): frameless window with hiddenInset title bar and electron-store preload bridge
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:28:18 +08:00
LinYushen
0c4f1027e8 fix(runtime): redesign filter bar with segmented control and owner dropdown (#548)
Replace cluttered inline owner pills with a clean two-part filter bar:
- Left: Mine/All segmented control with proper bg-muted container
- Right: Owner DropdownMenu (only in All mode) with avatars and counts

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:27:36 +08:00
Naiyuan Qing
74cc1d488e chore(desktop): scaffold electron-vite desktop app with monorepo config
- Scaffold apps/desktop/ using electron-vite react-ts template
- Configure electron.vite.config.ts with externalizeDeps, React, Tailwind CSS v4
- Wire up @multica/core, @multica/ui, @multica/views workspace dependencies
- Configure electron-builder.yml for mac/linux/win packaging
- Add @tailwindcss/vite to pnpm catalog
- Add dev:desktop script and electron to onlyBuiltDependencies in root package.json
- Clean up generated boilerplate, keep minimal placeholder renderer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:26:30 +08:00
Bohan Jiang
a135c44838 fix(issues): add done issue pagination to list view (#545)
List view only showed the first 50 done issues without a total count or
load-more mechanism. Reuse the existing useLoadMoreDoneIssues hook and
extract InfiniteScrollSentinel into a shared component so both board and
list views paginate identically.
2026-04-09 14:21:15 +08:00
Bohan Jiang
ec2b48a616 feat(runtime): point-to-point update notifications via registered_by (#533)
* feat(runtime): proactive CLI update notifications with per-user filtering

- Add latestCliVersionOptions query (GitHub Releases API, 10-min TanStack cache)
- Add useMyRuntimesNeedUpdate / useUpdatableRuntimeIds hooks using owner_id
- Show red dot on sidebar Runtimes item when user's runtimes need updates
- Show update arrow icon alongside status dot in runtime list items

* fix(core): add runtimes/hooks to package.json exports
2026-04-09 14:20:54 +08:00
yushen
50f9e673e8 feat(chat): add agent chat feature (full stack)
Implement the Master Agent chat feature allowing users to chat with agents
directly from a floating window, separate from the issue-based workflow.

Backend:
- New chat_session and chat_message tables (migration 033)
- Make issue_id nullable on agent_task_queue for chat tasks
- REST API: create/list/get/archive sessions, send/list messages
- EnqueueChatTask in TaskService with session_id persistence
- WS events: chat:message, chat:done
- Daemon: chat task type with separate prompt builder
- ClaimTaskByRuntime populates chat context (session, message, repos)

Frontend:
- ChatSession/ChatMessage types + API client methods
- core/chat: TanStack Query options, mutations with optimistic updates, WS updaters
- features/chat: Zustand store, ChatFab (floating button), ChatWindow with
  real-time streaming via task:message events
- Mounted in dashboard layout (bottom-right corner)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:19:46 +08:00