Agent trace logs are now stored in-memory (pilotRunStore) and broadcast
through the existing /ws/crm-updates WebSocket channel. When a client
reconnects, it receives a pilot.catchup with all accumulated logs so the
user sees agent progress even after page reload. Three new WS event
types: pilot.trace, pilot.finished, pilot.catchup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a context scope is picked via the pipette, the picker mode now
turns off automatically since the selection is done and shows as a chip.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After hiding a contact inbox, the contacts list now refetches immediately
so the hidden contact disappears reactively. When the current contact is
removed from the list, the selection jumps to the most recently active
contact (by lastContactAt) instead of the first item in the current sort.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clear old timeline items immediately on thread switch and display a centered
loader until the new conversation loads, instead of showing stale messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Function was used in CrmWorkspaceApp template but not exported/destructured,
causing TypeError at runtime.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ContactThreadRead model to track when users last viewed each contact thread.
Contacts with messages newer than the last read time show a blue dot in the sidebar.
Opening a thread automatically marks it as read via markThreadRead mutation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- WebSocket now detects new ContactMessages and broadcasts
message.new events with contactId, text, channel, direction
- Frontend handles message.new: refreshes timeline for open chat,
refreshes contacts for sidebar preview update
- dashboard.changed still fires for non-message changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove bulk CommunicationsQuery from useContacts (was loading ALL
messages for ALL contacts on init)
- Rebuild commThreads from contacts + contactInboxes using the new
lastMessageText field from Phase 1
- Per-contact messages now load on-demand via getClientTimeline
- Remove commItems from useWorkspaceRouting, use clientTimelineItems
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The refactoring in a4d8d81 moved calendar logic into useCalendar.ts but
used the old CSS-transform animation code instead of the GSAP-based
flying rect + flying label implementation. This restores:
- GSAP-based animateCalendarZoomIntoSource and animateCalendarFlipTransition
- Flying label that animates from card title → toolbar on zoom-in and back
- Clone-and-swap pattern with skeleton content in fly-rect (no text)
- Fly-rect/fly-label refs and setters now live in the composable
- isoWeekNumber() and weekNumber field on monthRows
- Sibling card titles and week numbers faded during zoom
- Removed old CSS-transform camera state and calendarSceneTransformStyle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add refetchChatMessages + refetchChatConversations to
refetchAllCrmQueries so WebSocket dashboard.changed events
cover pilot chat updates
- Reduce background polling from 2s to 30s (fallback only)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each composable now owns its types and exports them. Other composables
import types from the owning composable. Deleted centralized crm-types.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the 6000+ line monolithic component into modular composables:
- crm-types.ts: shared types and utility functions
- useAuth, useContacts, useContactInboxes, useCalendar, useDeals,
useDocuments, useFeed, useTimeline, usePilotChat, useCallAudio,
usePins, useChangeReview, useCrmRealtime, useWorkspaceRouting
CrmWorkspaceApp.vue is now a thin orchestrator (~2500 lines) that
wires composables together with glue code, keeping template and
styles intact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>