Commit graph

1406 commits

Author SHA1 Message Date
Jiayuan
5b2c61cfab feat(agent): add instructions field for agent persona/identity
Add an `instructions` text field to the agent model, allowing users to
define each agent's role, expertise, and working style. Instructions are
injected into CLAUDE.md as an "Agent Identity" section so the agent
knows who it is on every task execution.

- Migration 021: add instructions column to agent table
- Backend: create/update/get agent handlers support instructions
- ClaimTask response includes instructions for daemon injection
- execenv: inject instructions into CLAUDE.md meta-skill
- Frontend: add Instructions tab to agent detail panel
2026-03-29 17:01:07 +08:00
Jiayuan
ffda18c809 feat(agent): add per-task session persistence for Claude Code resumption
Store the Claude Code session ID and working directory when a task
completes. On the next task for the same (agent, issue) pair, look up
the prior session and pass --resume <session_id> to Claude Code so
the agent retains conversation context across multiple tasks on the
same issue.

Changes:
- Migration 020: add session_id and work_dir columns to agent_task_queue
- CompleteAgentTask stores session_id and work_dir on completion
- GetLastTaskSession query retrieves prior session for (agent, issue)
- ClaimTaskByRuntime handler populates prior_session_id in response
- Daemon passes ResumeSessionID through to Claude backend Execute()
- Claude backend adds --resume flag when ResumeSessionID is set
2026-03-29 16:53:28 +08:00
Jiayuan Zhang
42f72371bd
Merge pull request #165 from multica-ai/forrestchang/feature-audit
feat(runtimes): add usage charts, activity heatmap, and hourly distribution
2026-03-29 15:46:39 +08:00
Jiayuan
36798b1d76 feat(runtimes): add usage charts, activity heatmap, and hourly distribution
Add comprehensive data visualization to the runtime detail page:
- Daily token usage stacked area chart and daily cost bar chart
- Model distribution donut chart with cost breakdown
- GitHub-style activity heatmap (13 weeks of daily token usage)
- Hourly task distribution bar chart with new backend endpoint
- Responsive 2-column grid layout for charts on wide screens

Backend: new GET /api/runtimes/{runtimeId}/activity endpoint
returning hourly task counts from agent_task_queue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 15:44:10 +08:00
Jiayuan Zhang
c5fed182e3
Merge pull request #163 from multica-ai/forrestchang/test-agent-review
Remove auto-init issue on agent creation
2026-03-29 14:24:14 +08:00
Jiayuan Zhang
6871163b0b
Merge pull request #164 from multica-ai/forrestchang/fix-runtime-status
fix(runtime): add server-side sweeper to detect stale runtimes
2026-03-29 14:24:05 +08:00
Jiayuan
b3bbf92a1d fix(runtime): add server-side sweeper to detect stale runtimes
The only path to marking a runtime offline was the daemon's deregister
call on graceful shutdown. If the daemon crashed, was killed, or lost
network, the status stayed "online" forever. Add a background goroutine
that sweeps every 30s and marks runtimes offline after 45s without a
heartbeat (3 missed intervals).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 14:22:12 +08:00
Jiayuan
01ac0a81a9 refactor(agent): remove auto-init issue on agent creation
The createAgentInitIssue flow created a boilerplate "Initialize environment"
issue every time an agent was created, polluting the issue list with low-value
tasks. Agents naturally learn the project context when executing real work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 14:21:49 +08:00
Naiyuan Qing
586c3bf470
Merge pull request #162 from multica-ai/naiyuan/realtime-sync-refactor
feat(realtime): WS invalidation + refetch pattern
2026-03-29 13:51:22 +08:00
Naiyuan Qing
9236674667 feat(realtime): WS invalidation + refetch pattern, inbox bugfixes, UI polish
Refactor real-time sync from per-event precise mutations to WS-as-invalidation-signal + debounced refetch.

Backend:
- Add SubscribeAll to Event Bus — auto-broadcasts ALL events, eliminates manual 25-item allEvents list
- Add skill event constants to protocol, fix skill handler string literals
- Add title_changed activity tracking

Frontend:
- WSClient: add onAny() method for wildcard event subscription
- useRealtimeSync: rewrite to refreshMap + prefix routing + 100ms debounce
- Precise handlers only for side effects: workspace:deleted, member:removed, member:added (self-check)
- Reconnect now refetches all stores (fixes missing members/skills/workspace refresh)
- Stale-while-revalidate: fetch() only shows loading spinner on initial load, not on refetch
- Remove redundant useWSEvent in agents/page.tsx and skills-page.tsx
- WSClient.disconnect() now clears all handler registrations

Inbox bugfixes:
- Unify sidebar badge count with page count via dedupedItems + unreadCount in store
- Sort by time DESC (removed severity-first ordering)
- Ellipsis on truncated detail labels

UI:
- Status/Priority pickers: replace RadioGroup with MenuItem for auto-close on selection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:49:40 +08:00
Jiayuan Zhang
26318f6afd
Merge pull request #161 from multica-ai/forrestchang/explore-cli-cmds
feat(cli): restructure CLI commands for better UX
2026-03-29 01:49:17 +08:00
Jiayuan
38d595d81d feat(cli): restructure CLI commands for better UX
- Add top-level `multica login` that combines auth + workspace auto-discovery
- Restructure daemon into subcommands: start, stop, status, logs
- Add background daemon mode with PID management
- Add daemon deregistration on shutdown (new API endpoint + SQL query)
- Remove unused commands: runtime list, status, agent get/delete/stop
- Make `config` show config directly instead of requiring `config show`
- Update README to reflect new CLI structure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 01:43:45 +08:00
Naiyuan Qing
19810363eb
Merge pull request #160 from multica-ai/naiyuan/activity-log
feat: unified activity timeline, comment replies, and inbox notifications
2026-03-29 00:24:11 +08:00
Naiyuan Qing
e72f5f0801 feat(inbox): add priority/due_date notifications, structured details, and hover card
- Add missing notifications for priority_changed and due_date_changed events
- Publish priority_changed and due_date_changed flags from UpdateIssue handler
- Add details JSONB column to inbox_item (migration 019) for structured change data
- Store from/to values in details for status, priority, assignee, and due_date changes
- Notification titles now use plain issue title; details carry structured context
- Add human-readable label maps (statusLabels, priorityLabels) in notification listeners
- Update inbox handler responses to include details field
- Frontend: InboxDetailLabel renders rich subtitles per notification type
  - Status: "Set status to ● In Progress" with StatusIcon
  - Priority: "Set priority to ◆ High" with PriorityIcon
  - Assigned: "Assigned to Bob" with resolved actor name
  - Due date: "Set due date to Apr 20"
  - Comment: truncated comment body preview
- Frontend: HoverCard on inbox items shows issue title + description context
- Add due_date_changed to InboxItemType and typeLabels
- Add tests for priority_changed and due_date_changed notifications

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:22:17 +08:00
Naiyuan Qing
b2ee151306 fix(activity): address code review feedback and improve timeline UX
- Extract shared timeAgo utility, remove duplicates from comment-card and issue-detail
- Remove unused replies prop from CommentCard
- Fix recursive delete to remove all descendant replies, not just direct children
- Improve formatActivity with human-readable status/priority labels and actor names
- Validate parent comment exists and belongs to same issue before creating reply
- Add priority_changed activity recording in activity listeners
- Fix activity SQL query to sort ASC (was DESC, then re-sorted in handler)
- Fix reply-input layout alignment and test submit button selector
- Minor: .gitignore additions, button dark mode aria-expanded fix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:21:46 +08:00
Naiyuan Qing
5d2e62ccde fix(comments): fix padding, separate CommentInput from ReplyInput
- Remove Card double padding (Card py-4 + inner px-4 was too much, override with !py-0)
- Use lighter border-border/50 for reply separators inside Card
- Create CommentInput component for bottom "Leave a comment" — no avatar, full
  width editor, submit button in footer row below editor
- ReplyInput stays for in-card "Leave a reply" — has avatar, compact inline layout
- Two different components for two different use cases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:13:03 +08:00
Naiyuan Qing
0c8738676c refactor(comments): flat thread layout in one Card (Linear-style)
Replace recursive Card-in-Card with flat thread layout:
- One Card per comment thread, parent + all replies flat inside
- Replies separated by border-t, not nested Cards
- CommentRow component handles each individual comment (header + content + edit)
- Three-dot menu shows active state when open (data-[popup-open])
- ReplyInput simplified: avatar + editor + submit button, no extra border container
- Nested replies collected recursively but rendered flat

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:39:02 +08:00
Naiyuan Qing
56c06ec13b refactor(timeline): use avatar for activity entries, remove filter, allow nested replies
- Activity entries now show ActorAvatar instead of a small dot (consistent with comments)
- Remove All/Comments/Activity filter toggle (comments are just a type of activity)
- Remove one-level reply restriction in backend (allow nested threading)
- Remove unused Circle import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:13:23 +08:00
Naiyuan Qing
6cc8f7586a fix(comments): cascade delete replies in DB when parent comment is deleted
Change parent_id FK from ON DELETE SET NULL to ON DELETE CASCADE.
Deleting a parent comment now deletes all its replies at the DB level.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:04:35 +08:00
Naiyuan Qing
8a9ae0102d fix(comments): cascade delete replies when parent comment is deleted
When a parent comment is deleted, remove all its replies from the timeline
instead of promoting them to top-level (orphaned replies have no context).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:03:46 +08:00
Naiyuan Qing
ba3c8e1b3f fix(activity): address code review feedback
- Fix activity:created WS payload to match frontend expectations
  (issue_id at top level, entry as TimelineEntry object)
- Promote child comments to top-level when parent is deleted
  (both in handleDeleteComment and WS comment:deleted handler)
- Enforce one-level reply nesting: reject replies to replies with 400

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:02:25 +08:00
Naiyuan Qing
e7fe6ea79b feat(activity): unified activity timeline with comment reply support
Replace the comment-only list with a Linear-style unified timeline that
interleaves field changes and comments chronologically.

Backend:
- activity_listeners.go: records field changes (status, assignee, description,
  task completed/failed) to activity_log table on domain events
- Timeline API: GET /api/issues/{id}/timeline merges activity_log + comments
  sorted by created_at
- Comment reply: parent_id column + handler support for threading

Frontend:
- Unified timeline replaces comment list: activity entries as compact muted
  lines, comments as Card components with reply threading
- Filter toggle (All / Comments / Activity)
- Reply UI: inline editor under comments with Cancel/Reply buttons
- Real-time sync for activity:created + comment events
- 10 new Go tests, all passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:53:08 +08:00
Naiyuan Qing
3bb79564ed
Merge pull request #159 from multica-ai/naiyuan/subscriber-notifications
feat(notifications): subscriber-driven notification system
2026-03-28 21:17:42 +08:00
Naiyuan Qing
c2e8071c64 fix(subscribers): remove all reason labels from subscriber popover
Clean list — just checkbox, avatar, and name. No Creator/Assignee labels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:14:58 +08:00
Naiyuan Qing
89c617b39e fix(subscribers): only show Creator and Assignee labels in subscriber popover
Remove commenter/mentioned/manual reason labels — users only need to see
who created and who is assigned. Other reasons add noise without value.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:11:09 +08:00
Naiyuan Qing
2ec3e4eb89 fix(subscribers): use composite key (user_id + user_type) in subscriber:removed WS handler
Consistent with subscriber:added handler. Prevents removing a member subscriber
when an agent with the same UUID is unsubscribed (or vice versa).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:07:48 +08:00
Naiyuan Qing
f410799ab5 fix(subscribers): prevent duplicate subscriber entries from optimistic update + WS race
When subscribing, both the optimistic setSubscribers and the WS subscriber:added
event could add the same entry. Now both paths check for existing entries using
(user_id + user_type) composite key before appending.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:59:35 +08:00
Naiyuan Qing
8a96aa698c fix(subscribers): deduplicate members list in subscriber popover
Members array from workspace store can contain duplicate user_ids (e.g. user
added to workspace twice). Filter by unique user_id before rendering to prevent
React duplicate key warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:57:41 +08:00
Naiyuan Qing
b8fa71462a fix(subscribers): pass user_type to subscribe/unsubscribe API for correct agent handling
Root cause: backend hardcoded UserType="member" in subscribe/unsubscribe handlers,
so unsubscribing an agent actually tried to delete a member record (no-op), and
the WS event broadcast wrong user_type causing other subscribers' UI to break.

- Backend: accept optional user_type in subscribe/unsubscribe request body
- Frontend: pass userType through API client to backend
- Fixes: clicking agent checkbox no longer affects member subscriptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:56:37 +08:00
Naiyuan Qing
df6f6584c3 fix(subscribers): fix duplicate key error, add agents to subscriber popover
- Fix duplicate React key by using composite key (type-id) for avatars and command items
- Add Agents section to subscriber Command popover (members + agents both selectable)
- Fix subscriber matching to use both user_type and user_id (prevents cross-type collisions)
- Add max-h-64 to CommandList to prevent overflow
- toggleSubscriber now accepts userType parameter for proper agent support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:51:50 +08:00
Naiyuan Qing
05c0471945 feat(subscribers): interactive subscriber management with AvatarGroup + Command popover
- Backend: subscribe/unsubscribe API now accepts optional user_id to manage other users
- Frontend: replace manual avatar stacking with shadcn AvatarGroup component
- Frontend: replace disabled-checkbox Popover with Command+Popover combo (Linear-style)
  - Search/filter workspace members
  - Click to toggle subscription (checkbox)
  - Shows reason badge (Assignee, Creator, etc.) for auto-subscribed users
- Clean up duplicate status_change type (keep only status_changed)
- All tests pass (Go + TypeScript)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:48:20 +08:00
Naiyuan Qing
ec188a36c9 refactor(issues): move subscribers UI from sidebar to Activity header (Linear-style)
Move subscriber controls from right sidebar to Activity section header:
- Left: "Activity" title, Right: "Subscribe/Unsubscribe" button + avatar stack
- Click avatar stack opens Popover showing all subscribers with checkboxes
- Non-subscribers shown dimmed in the popover list
- Stacked avatar display (overlapping, max 5 + count badge)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:36:50 +08:00
Naiyuan Qing
6a09714041 fix(inbox): add missing notification type labels for subscriber-driven notifications
Add new_comment, unassigned, assignee_changed, priority_changed, status_changed
to InboxItemType and typeLabels so inbox renders proper labels instead of raw
type strings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:29:26 +08:00
Naiyuan Qing
5b9241b74f fix(notifications): address code review feedback
- Add comment explaining subscriber→notification listener registration order in main.go
- Add issue_status field to notifySubscribers and notifyDirect (fixes missing StatusIcon in inbox)
- Backfill existing commenters as subscribers in migration 016
- Add TODO comment for @mention duplicate notification prevention (deferred until @mention feature is enabled)
- Add context.Background() usage note for future bus-level timeout improvements
- Add toast error feedback on subscribe/unsubscribe failure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 20:24:07 +08:00
Naiyuan Qing
bfe9498def feat(notifications): replace hardcoded inbox notifications with subscriber-driven model
Replace inbox_listeners.go with a subscriber-driven notification system:

- Add issue_subscriber table with auto-subscribe on create/assign/comment
- New subscriber_listeners.go: maintains subscriber data on domain events
- New notification_listeners.go: notifySubscribers (fanout to all subscribers
  minus actor) and notifyDirect (targeted, punches through unsubscribe)
- Subscriber API: list/subscribe/unsubscribe endpoints
- Frontend: subscribers section in issue detail sidebar with real-time sync
- Frontend: inbox notification grouping by (issue_id, type, actor_id)
- Remove createInboxForIssueCreator from task.go (unified through event bus)
- 21 new Go tests, all passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 19:33:20 +08:00
Naiyuan Qing
5fc03c61fe
Merge pull request #158 from multica-ai/forrestchang/theme-card-selector
feat(settings): visual theme preview card selector
2026-03-28 16:27:12 +08:00
Naiyuan Qing
6b93e3ba9c fix(tests): update issue page tests for new header and view store shape
- Add missing view-store mock fields (sortBy, sortDirection, cardProperties,
  listCollapsedStatuses, toggleListCollapsed) and exported constants
- Add SortableContext mock to @dnd-kit/sortable
- Fix filter button assertions (Status/Priority: All → Filter/Display)
- Fix issue detail test: use getAllByText for duplicate title text
- Fix breadcrumb test: workspace name shown instead of "Issues"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:25:20 +08:00
Naiyuan Qing
572d033b95 feat(ui): comprehensive UI consistency fixes and list view accordion redesign
- Runtime page: add ResizablePanelGroup with persistent layout, fix scroll
- Agents page: replace hand-rolled dropdowns with shadcn Popover/DropdownMenu,
  remove redundant wrapper div, fix header height to h-12
- Skills page: widen create dialog to sm:max-w-md, stabilize tab height
- Settings: use variant="destructive" on AlertDialogAction instead of hardcoded className
- Issues list view: rewrite with base-ui Accordion grouped by status,
  show all statuses (including empty), add per-group create button,
  persist expand/collapse state, apply sort settings
- Issues header: show filtered issue count next to New Issue button
- Extract shared sortIssues utility from board-column for reuse
- Remove redundant StatusIcon from ListRow (already grouped by status)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:18:42 +08:00
Naiyuan Qing
1d08057dd8 feat(settings): replace theme buttons with visual preview card selector
Replace simple text buttons with macOS-style window preview cards for
Light/Dark/System theme selection, using pure CSS miniature window mockups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:03:47 +08:00
Jiayuan Zhang
fd9d2e2290
Merge pull request #157 from multica-ai/forrestchang/kanban-redesign
feat(issues): redesign kanban board with drag sorting and display settings
2026-03-28 01:14:39 +08:00
Jiayuan
f050ab1ae2 feat(issues): add inline property editing on kanban cards and calendar date picker
- Add inline pickers on board cards for priority, assignee, and due date
- Add custom trigger prop to PriorityPicker, AssigneePicker, DueDatePicker for styling control
- Replace due date quick options with Calendar-based DueDatePicker in issue detail sidebar
- Use PickerWrapper to stop event propagation from pickers to Link/drag handlers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 01:13:18 +08:00
Jiayuan Zhang
14ae1b9aff
Merge pull request #156 from multica-ai/forrestchang/agent-issue-flow
feat(daemon): inject skills into agent-native directories
2026-03-28 00:52:32 +08:00
Jiayuan
7cd9110628 feat(issues): redesign kanban board with drag sorting, filters, and display settings
- Redesign card layout: priority label, description line, subtle shadow, configurable properties
- Wider columns (280px) with rounded background, count badge, and card spacing
- Add SortableContext for within-column drag reordering with fractional position indexing
- Fix collision detection to prefer card targets over column droppables for reliable down-drag
- Add hidden columns panel on right side with show/hide toggle
- Consolidate header into Filter popover (status + priority) and Display popover (ordering + card properties)
- Auto-switch to manual sort when cards are dragged to preserve drag ordering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 00:50:29 +08:00
Jiayuan
46144646c5 feat(daemon): inject skills into agent-native directories
Write skills to provider-native paths so agents discover them
automatically instead of relying on manual path references in
CLAUDE.md/AGENTS.md.

- Claude: write to {workDir}/.claude/skills/ (native discovery)
- Codex: write to per-task CODEX_HOME/skills/ with auth/config
  seeded from ~/.codex/ (symlink auth.json, copy config files)
- Fallback: keep .agent_context/skills/ for unknown providers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 00:47:00 +08:00
Jiayuan Zhang
1b505c3a21
Merge pull request #155 from multica-ai/forrestchang/codex-token-parse
fix(daemon): fix Codex token usage parsing from session logs
2026-03-28 00:04:40 +08:00
Jiayuan
241acb3eac fix(daemon): fix Codex token usage parsing from session logs
The parser read `payload.msg` but Codex JSONL files store token data at
`payload.info`. Also adds model tracking from `turn_context` events,
`last_token_usage` fallback, and `cache_read_input_tokens` field support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 00:03:47 +08:00
Jiayuan Zhang
e860691124
Merge pull request #154 from multica-ai/forrestchang/skills-tree-view
feat(skills): file-browser tree view with markdown preview
2026-03-27 23:57:28 +08:00
Jiayuan
8de700620d feat(skills): replace skill detail with file-browser tree view
Redesign the skill detail panel to use a directory tree + file viewer
layout, similar to a file browser. SKILL.md and supporting files are
shown in a collapsible tree on the left; selecting a file renders its
content on the right with markdown preview (including YAML frontmatter
parsing) and an edit toggle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 23:54:32 +08:00
Jiayuan Zhang
88294fada6
Merge pull request #153 from multica-ai/forrestchang/skill-add-ux-review
feat(skills): improve import skill UX with source cards
2026-03-27 23:44:26 +08:00
Jiayuan
f4ff01210b feat(skills): improve import skill UX with source cards
Replace the subtle inline badge with two always-visible source cards
that show URL formats for ClawHub and Skills.sh, highlighting the
detected source as the user types. Import button now shows
source-specific loading text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 23:42:08 +08:00