mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-27 21:33:41 +02:00
fix/transcript-virtual-scroll
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fcb4798f12 |
fix(issues): stop cold-load render loop on the Issues route (MUL-4985) (#5643)
Board and Swimlane crashed with "Maximum update depth exceeded" on first paint of the Issues route. During cold load the member/agent/squad directory queries are unresolved, so useActorName's `= []` defaults allocated a fresh array every render and its `getActorName` memo changed identity each render. BoardView's `groups` (and SwimLaneView's `laneGroups`) list `getActorName` as a dep, so they churned every render and re-fired the column-resync effect without end; react-virtuoso escalated the loop into the reported crash. This predates MUL-4797 — it was exposed when board/swimlane columns were virtualized with a real <Virtuoso>. - Share stable empty references for the loading directory snapshot so getActorName is referentially stable across cold-load renders (root cause). - Equality-guard the shared column setter in useDragSettle so a content-equal rebuild returns the previous reference and cannot spin the resync effect (defense-in-depth). Regression coverage: useActorName stability during cold load; the column-setter equality guard; and Board (40 cards) + Swimlane rendered with the REAL react-virtuoso under pending directories, which reproduce "Maximum update depth exceeded" without the fix and pass with it. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
002ea0d879 |
MUL-4797: add configurable issue table view (#5454)
* feat(issues): add configurable table view Co-authored-by: multica-agent <github@multica.ai> * test(issues): cover table columns in page fixture Co-authored-by: multica-agent <github@multica.ai> * fix(issues): make table column picker interactive Co-authored-by: multica-agent <github@multica.ai> * fix(issues): repair quick create and virtualize table rows Co-authored-by: multica-agent <github@multica.ai> * fix(issues): keep pinned table cells opaque Co-authored-by: multica-agent <github@multica.ai> * fix(issues): anchor full-width table rows Co-authored-by: multica-agent <github@multica.ai> * fix(issues): consolidate table controls Co-authored-by: multica-agent <github@multica.ai> * fix(issues): harden table pagination and export Co-authored-by: multica-agent <github@multica.ai> * feat(issues): add table quick search Co-authored-by: multica-agent <github@multica.ai> * fix(issues): make table window filters, selection, and export authoritative Round-2 review fixes for the issues table (MUL-4797): - Send the agents-working filter as a server ids facet so matches on unfetched pages surface and total/pagination/export agree; a present- but-empty id list yields an empty window instead of an unfiltered one. - Reset surface selection when the membership window changes and act on selection ∩ visible rows in the batch toolbar, so batch actions, Export selected, and the count all share one authoritative set. - Materialize the full flat window while table grouping is active, and suspend hierarchy nesting / parent-based grouping until the window is complete so structure cannot reshuffle as pages arrive; suppress header facet-count badges while the table window is partial. - Resolve actor directories and the property catalog at export time and fail the export instead of writing Unknown* actors or dropping configured property columns on cold/errored lookups. - Append a unique id tie-break to the list/grouped ORDER BY and mirror it in compareIssuesForSort so offset pages are stable across same-timestamp ties. Co-authored-by: multica-agent <github@multica.ai> * fix(issues): bound table structure window and align chip/transport/selection Round-3 review fixes for the issues table (MUL-4797): - Cap whole-window materialization at TABLE_STRUCTURE_MAX_WINDOW (1000): below it the remaining pages load automatically — hierarchy applies without scrolling to the last page — and above it grouping/hierarchy suspend with an explicit toolbar notice instead of triggering an unbounded workspace download from a persisted view option. - Give the agents-working chip the authoritative in-window running set (the ids-facet window query, shared key with the filter-on state) so its badge can no longer say 0 while the filter would find matches on unfetched pages; falls back to loaded-row scoping elsewhere. - Route ids-facet windows through a new POST /api/issues/query twin — hundreds of running-issue UUIDs overflow the ~8 KB GET request-line budget of common proxies. The body carries the same key/value pairs; the handler rebuilds the query string and delegates to ListIssues. - Reset surface selection during render (key-change pattern) instead of a post-commit effect, so no frame ever pairs new membership with the old selection. Co-authored-by: multica-agent <github@multica.ai> * fix(issues): harden table auto-pagination against errors and stale totals Round-4 review fixes for the issues table (MUL-4797): - Stop the structure materialization loop (and the scroll sentinel) when the window query is in error state — a persistently failing page left hasNextPage true and isFetchingNextPage false after every attempt, so the ungated effect refired forever. Resuming is an explicit toolbar Retry. The advancement decision now lives in a pure, tested shouldAutoLoadNextStructurePage helper. - Make the structure ceiling a hard stop: the ceiling check reads the LATEST page's total (pagination already advances on it, so a stale small page-1 total could re-open unbounded materialization), and the loop additionally halts on loaded count >= ceiling regardless of any reported total. - Drive the working (ids-facet) window to completion — it is inherently bounded by the running set — and treat it as the chip's authoritative scope only when complete, so >100 running issues no longer under-count as a single page. Co-authored-by: multica-agent <github@multica.ai> * fix(issues): make working-window pagination capped and unknown-aware Round-5 (final) review fixes for the issues table (MUL-4797): - The working (ids-facet) window now advances through the same shouldAutoLoadNextWindowPage gates as the structure loop — it shares the main table's cache key while the agents-working filter is on, so an uncapped chip-driven loop re-opened the very ceiling the table just enforced. An over-ceiling window stops after page one. - A cold-load failure of the flat window is an ERROR state, not an empty workspace: isEmpty only claims empty on a successful zero-result fetch, and the surface renders a dedicated failed-to-load state with a reachable Retry (the in-table Retry never mounted without data). - The chip scope is now tri-state honest: a COMPLETE window (or an empty running set) yields a precise count, keepPreviousData carries the last-known-complete set across re-keys, and everything else — cold resolving, failed, over the ceiling — presents as an explicit unknown ('Agents working: —') instead of a number derived from whichever incomplete window happened to be loaded. Co-authored-by: multica-agent <github@multica.ai> * fix(issues): single pagination owner and placeholder-honest chip scope Round-6 review fixes for the issues table (MUL-4797): - Exclude placeholder data from the working-window completeness gate: on a re-key (running set or facet change) keepPreviousData leaves the OLD key's rows visible, and pairing them with the new task snapshot published a precise-looking number for a scope nobody fetched. The scope now reads unknown until the new key resolves. - Make the shared table query single-owner while the agents-working filter is on: the chip's background loop no longer answers the same render snapshot as TableView's structure loop, and every auto caller (structure loop, working loop, scroll sentinel, retry) now uses fetchNextPage({cancelRefetch: false}) so a concurrent responder no-ops instead of cancel/restarting a fetch whose HTTP request is not abortable — which had been duplicating every offset. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Lambda <lambda@multica.ai> Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
746c0c4456 |
MUL-2746 fix(avatar): normalize relative avatar urls in desktop/web (#3100)
* fix(avatar): normalize relative avatar urls in desktop/web Co-authored-by: multica-agent <github@multica.ai> * fix: test Co-authored-by: multica-agent <github@multica.ai> * fix(avatar): normalize avatar url in AvatarPicker preview MUL-2746. The picker is used by create-agent and create-squad, and also prefills from a template's `avatar_url` when duplicating an agent. The upload result / template URL is root-relative in local-storage setups, so on Desktop (file:// runtime) the preview <img> resolves against the local filesystem and the avatar fails to render. Route the value through `resolvePublicFileUrl` for rendering only; the stored URL stays raw so the parent's create call still posts what the backend expects. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: multica-agent <github@multica.ai> Co-authored-by: J (Multica agent) <agents@multica.ai> |
||
|
|
8e88156356 | Add assignee grouping for issue boards (#2693) | ||
|
|
29082f7cfe |
feat: implement Squad feature MVP (#2505)
* feat: implement Squad feature MVP
- Add migration 084_squad: squad, squad_member, squad_activity_log tables
- Extend issue.assignee_type to support 'squad'
- Add sqlc queries for squad CRUD, member management, activity logs
- Add Go handler with full Squad API (CRUD, members, activity log)
- Register routes: /api/squads/*, /api/issues/{id}/squad-activity, /api/squad-activity
- Add Squad trigger logic:
- Assign Squad immediately triggers leader
- Every external comment on squad-assigned issue triggers leader
- Anti-loop: squad members' comments don't trigger leader
- Dedup: skip if leader already has pending task
- Add squad activity log API (方案 B) for leader no-op recording
- Add frontend TypeScript types (Squad, SquadMember, SquadActivityLog)
- Add protocol events: squad:created, squad:updated, squad:deleted
Co-authored-by: multica-agent <github@multica.ai>
* fix: address PR review blocking issues
1. validateAssigneePair now accepts 'squad' assignee_type
2. All squad endpoints validate workspace ownership via GetSquadInWorkspace
3. CreateSquadActivityLog restricted to squad leader agent only
4. AddSquadMember validates member exists in workspace
5. UpdateSquad auto-adds new leader to squad members
6. DeleteSquad transfers assigned issues to leader before deletion
7. IssueAssigneeType includes 'squad' in frontend types
Co-authored-by: multica-agent <github@multica.ai>
* feat: soft-delete squads via archive instead of hard delete
- Add migration 085: archived_at + archived_by columns on squad table
- ListSquads now excludes archived squads (ListAllSquads for admin)
- DeleteSquad → ArchiveSquad (sets archived_at, preserves all records)
- Transfer squad-assigned issues to leader before archiving
- SquadResponse includes archived_at/archived_by fields
- Frontend Squad type updated with nullable archived fields
Co-authored-by: multica-agent <github@multica.ai>
* feat: re-add Squads frontend entry (sidebar nav + pages)
Re-applies the frontend squad entry that was lost during a merge:
- Sidebar nav: Squads item with Users icon
- Paths: squads() and squadDetail() in workspace paths
- Routes: /squads and /squads/[id] pages
- Views: SquadsPage (list) and SquadDetailPage
- i18n: en 'Squads' / zh '小队'
- Reserved slug: 'squads'
Co-authored-by: multica-agent <github@multica.ai>
* fix: fix SquadsPage rendering - use PageHeader children pattern
PageHeader takes children, not title/actions props. The incorrect
usage caused a React rendering error. Now matches the pattern used
by autopilots and agents pages.
Co-authored-by: multica-agent <github@multica.ai>
* fix(squads): add API client methods and package export for squads pages
* feat: complete Squad frontend - create dialog, member management, API methods
- Add CreateSquadModal with name/description/leader selection
- Register 'create-squad' in modal registry
- Wire 'New Squad' button to open the modal
- Add full API client methods: createSquad, updateSquad, deleteSquad,
addSquadMember, removeSquadMember
- Rewrite SquadDetailPage with:
- Member list showing resolved names
- Add/remove member UI
- Archive squad button
- Back navigation to squads list
Co-authored-by: multica-agent <github@multica.ai>
* feat: improve Squad UI - match create agent dialog style
- CreateSquadModal: proper Dialog with Header/Description/Footer,
agent picker with avatars, textarea for description
- SquadDetailPage: centered max-w-2xl layout, ActorAvatar for members,
Crown badge for leader, textarea for member description,
improved spacing and visual hierarchy
- Renamed 'role' field label to 'Description' in add member form
(describes the member's responsibilities in the squad)
Co-authored-by: multica-agent <github@multica.ai>
* feat(squad): add avatar, instructions; drop unique-name constraint
- 086: add squad.avatar_url
- 087: drop unique constraint on squad.name (squads with the same
name are legitimate across teams; uniqueness was an accidental
product constraint)
- 088: add squad.instructions (text, default '')
- UpdateSquad now COALESCEs avatar_url + instructions
- handler exposes Instructions in SquadResponse and accepts it in
UpdateSquad
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): assignable + mention target; trigger leader on assign
- assignee picker and @mention suggestion list squads alongside
agents and members; renders squad avatar/icon
- creating or updating an issue with assignee_type=squad enqueues
a task for the squad's current leader (mirrors agent-assignee
parking-lot rule: skip backlog only)
- workspace queries/hooks expose squads where needed for the
pickers
- locales updated for new picker copy
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): agent-style detail page with members + instructions tabs
- restructure squad detail page to mirror the agent detail page:
320px inspector (creator, leader, created/updated) + tabbed
pane (Members | Instructions) with dirty-guard AlertDialog
- inline name + avatar editing on the inspector
- inline description editor (modal textarea)
- members tab: leader + member picker with role descriptions,
swap leader, edit member roles, remove
- instructions tab: ContentEditor + Save (mirrors agent pattern)
- squads list shows the squad avatar/icon
- core types + api.updateSquad accept avatar_url + instructions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): inject leader briefing on claim (protocol + roster + instructions)
When a squad's leader agent claims a task on a squad-assigned issue,
append a system-level briefing to the agent's Instructions composed of:
1. Squad Operating Protocol — hard-coded rules: leader is a
coordinator, dispatch via @mention, stop after dispatching,
resume on re-trigger, do not work outside the roster.
2. Squad Roster — leader self-row plus one row per non-archived
member with a literal mention markdown string ([@Name](mention://
agent|member/<UUID>)) the leader can paste verbatim. Round-trips
through util.ParseMentions, enforced by a contract test.
3. Squad Instructions — the user-defined squad.instructions block,
omitted entirely when empty so we do not leave a dangling heading.
Non-leader members claiming the same issue receive no briefing.
Tests cover: full squad with mixed agent/human members, lone leader,
archived agents skipped, empty user instructions, mention round-trip,
and the leader/non-leader claim-handler gate.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(squad): tell leader not to restate issue context in dispatch comment
After observing leaders padding their delegation comments with full
re-summaries of the issue body and prior discussion, make the
Operating Protocol explicit:
- assignees on Multica already have the full issue (title,
description, all comments, attachments) and workspace context;
- delegation comments should add only what cannot be inferred
(who is picked, why, extra constraints), aim for two or three
sentences;
- restating context is now an explicit hard rule violation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(squad): unify leader evaluation into activity_log, add CLI command
- Squad member comments now trigger leader (only leader self-excluded)
- Replace squad_activity_log with activity_log (action: squad_leader_evaluated)
- Add CLI: multica squad activity <issue-id> <outcome> --reason
- Add API: POST /api/issues/{id}/squad-evaluated
- Update squad operating protocol to require evaluation recording
- Remove squad_activity_log table from schema and generated code
* feat(cli): add squad list, get, member list commands
* fix(squad): address review findings (P1+P2)
P1 fixes:
- Add 'squads' to reserved_slugs.json (source of truth)
- Add 'create-squad' to ModalType union
- Remove unused leaderOpen/selectedLeader in create-squad modal
- Replace literal JSX strings with i18n selectors (en + zh-Hans)
P2 fixes:
- Add 'squad' to mention regex (MentionRe)
- Fix human member lookup in squad briefing (use GetUser directly)
- Add squads routes to desktop app
- Add squad:created/updated/deleted to WSEventType + invalidation
- Reject archived squads as issue assignees
* fix(squad): restore zh-Hans key, publish activity event, invalidate issues on archive
- Restore create_project.title in zh-Hans modals.json (dropped by prior edit)
- Publish activity:created WS event after squad leader evaluation
- Invalidate issue queries on squad:deleted (archive transfers assignees)
- Add creator info to squad list cards
* fix(squad): realtime sync, rerun support, leader validation
- Use workspaceKeys.squads prefix for detail/member queries (realtime invalidation)
- Publish squad:updated after add/remove/role-change member mutations
- Support rerun for squad-assigned issues (targets leader agent)
- Reject assignment to squads whose leader is archived
---------
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
||
|
|
e3e61c161c |
fix(inbox): show Multica logo for system-actor notifications (#2479)
Notifications from system actors (e.g. GitHub PR closed) were rendering with an "S" initials fallback. The avatar now shows the Multica icon when actor_type === "system", matching the platform's brand. Co-authored-by: multica-agent <github@multica.ai> |
||
|
|
a3eefcf2c4 |
Revert "feat: add online status indicator on agent & member avatars (#821)" (#837)
This reverts commit
|
||
|
|
1d64ea4ba6 |
feat: add online status indicator on agent & member avatars (#821)
* feat: add online status indicator dot on agent & member avatars
Backend:
- Track member presence via WebSocket connections in the Hub
- Broadcast member:online/offline events when users connect/disconnect
- Add GET /api/workspaces/{id}/members/online endpoint
- Add member:online and member:offline event type constants
Frontend:
- Add isOnline prop to ActorAvatar with a status dot at top-right corner
- Green dot = online, gray dot = offline, no dot = status unknown
- Fetch online member list via new query, update optimistically on WS events
- Derive agent online status from existing agent.status field
- Wire online status through ActorAvatar views wrapper (enabled by default)
* fix: address code review — fix hub tests and avatar rounding
1. Hub tests: consume the member:online presence event from the first
connection before asserting on broadcast messages.
2. ActorAvatar: use rounded-[inherit] on the inner wrapper so callers
can override rounding (e.g. rounded-lg for agent list items).
* fix: consume member:online presence event in integration test
Same fix as the hub unit tests — read and discard the member:online
event before asserting on issue:created in TestWebSocketIntegration.
|
||
|
|
e1e7f68330 |
feat: extract packages/core — Turborepo infrastructure + headless business logic
Phase 1: Monorepo infrastructure - Add Turborepo with turbo.json pipeline (build, dev, typecheck, test) - Update pnpm-workspace.yaml to include packages/* - Create shared TypeScript config (packages/tsconfig) Phase 2: Extract packages/core (zero react-dom, all-platform reuse) - Move domain types, API client, logger, utils → packages/core/ - Move TanStack Query modules (issues, inbox, workspace, runtimes) - Move Zustand stores (auth, workspace, issues, navigation, modals) - Move realtime sync (WSProvider, hooks, ws-updaters) - Refactor auth/workspace stores to factory pattern for DI - Refactor ApiClient with onUnauthorized callback - Refactor useWorkspaceId to React Context (WorkspaceIdProvider) - Refactor WSProvider to accept wsUrl + store props - Create apps/web/platform/ bridge layer (api singleton, store instances) - Update 91 import paths across apps/web/ - Fix 3 test files for new import paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |