* refactor(views): reuse AssigneePicker in CreateIssueModal
Replace the hand-rolled inline assignee Popover in CreateIssueModal with
the shared AssigneePicker component. This fixes missing features (private
agent permission checks, lock icon, disabled state, selection checkmark)
and ensures consistent behavior across all assignee dropdowns.
* refactor(views): consolidate all picker components across the codebase
Enhance shared pickers (StatusPicker, PriorityPicker, DueDatePicker,
ProjectPicker) with triggerRender, controlled open/onOpenChange, and
align props — matching the AssigneePicker API.
Replace inline implementations in:
- create-issue.tsx: Status, Priority, DueDate, Project (4 pickers)
- issue-detail.tsx sidebar: Status, Priority (2 pickers)
- batch-action-toolbar.tsx: Status, Priority (2 pickers)
StatusPicker now has its first consumer (was defined but unused).
Removes ~200 lines of duplicated picker code.
* feat(sidebar): redesign sidebar layout for better space usage and grouping
- Split header into two rows: workspace switcher (full width) + search bar with new issue button
- Regroup navigation: Personal (Inbox, My Issues) + Workspace with label (Issues, Projects, Agents, Runtimes, Skills)
- Move Settings to SidebarFooter (like Linear)
- Search now renders as a full-width input-style button with ⌘K hint
Closes MUL-441
* fix(sidebar): style ⌘K shortcut as bordered badge matching project conventions
Use bordered kbd badge (bg-muted, border, font-mono) consistent with
search-command.tsx pattern. Render ⌘ symbol slightly larger for readability.
* feat(sidebar): add user profile info to footer
Show user avatar, name and email at the bottom of the sidebar
with a dropdown menu for logout, similar to the Lumis reference design.
* refactor(sidebar): move Settings back to Workspace nav, footer shows only user info
Settings is a navigable page that belongs with other nav items.
Footer now cleanly separates identity (user profile) from navigation.
* refactor(sidebar): split Workspace into Workspace + Configure groups
Split 6-item Workspace group into two cleaner groups:
- Workspace: Issues, Projects, Agents (core collaboration)
- Configure: Runtimes, Skills, Settings (infrastructure/admin)
* fix(sidebar): align search bar with nav items
Remove extra px-2 from search container and change button px-2.5 to px-2
so the search icon aligns at the same left offset as nav item icons.
* refactor(sidebar): make search and new issue regular menu items
Replace bordered input-style search bar and icon button with
SidebarMenuButton components so they share the same visual weight,
padding, and hover behavior as all other nav items.
Add a HighlightText component that highlights the search query in both
issue titles and comment snippets using case-insensitive matching with
yellow highlight styling for light and dark modes.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(landing): add OpenClaw and OpenCode to landing page
The landing page hero "Works with" section and i18n text only listed
Claude Code and Codex. Updated to include all four supported runtimes:
Claude Code, Codex, OpenClaw, and OpenCode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(landing): remove X (Twitter) button from header nav
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /ws endpoint only accepted JWT tokens while REST /api/* routes
accepted both JWTs and PATs (mul_*). Add PATResolver interface and
wire it into HandleWebSocket so PAT holders can use WebSocket streaming.
Also update README (en + zh-CN) to list OpenClaw and OpenCode as
supported agent runtimes alongside Claude Code and Codex.
Previously, runtimes could never be deleted once an agent was created
because agents can only be archived (not deleted) and the count check
included archived agents. Now the check only counts active agents, and
archived agents are cleaned up before runtime deletion.
Add a visible search trigger button next to the create-issue button in
the sidebar header, improving search discoverability (previously only
accessible via ⌘K). Search dialog open state is shared via a Zustand
store so both the button and keyboard shortcut work.
Also restores turbo.json globalEnv config (FRONTEND_PORT, etc.) that was
accidentally dropped during the monorepo extraction, fixing worktree
port conflicts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
subscribe/onReconnect used wsRef (a ref) with empty useCallback deps,
so the function identity never changed when the WSClient was recreated.
Consumers' effects never re-ran, leaving handlers registered on the
old (disconnected) client.
Switch to wsClient state so the callback identity updates on reconnect,
causing all useEffect consumers to re-subscribe on the new client.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move setPendingTask() before invalidateQueries() so that
pendingTaskRef is set earlier, reducing the window where incoming
WS task:message events would be dropped.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- README.md / README.zh-CN.md: add X link to top navigation
- layout.tsx: add twitter site/creator metadata (@multica_hq)
- Landing header: add X icon button next to GitHub
- Landing footer: add X and GitHub social icons
- Footer i18n: replace Community link with X (Twitter) in en/zh
- shared.tsx: add twitterUrl constant and XMark icon component
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- 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>
- 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>
* 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>
* 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
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.
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.
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.
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.
- 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.
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>
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
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>
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>
- 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>
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
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>
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>
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>