Composes the Phase 9 assistant primitives at /assistant: full-bleed chat
canvas with a 760px centered column, AssistantHomeGreeting for the no-
conversation state, AssistantInputBar + ActionStrip anchored at the
bottom, and HistorySheet / MemorySheet slide-overs. Drops the 160px
inner conversation-list column and the custom MessageBubble, delegating
thread rendering to the shared ChatMessageList and streaming to the
shared useStreamingChat hook. Adds a ?prompt= query-param fallback for
Studio → Assistant hand-offs, preserves the existing assistantHandoff
call as the Promote action, and syncs the selected conversation id with
the shared ChatPanelContext so HistorySheet stays in lockstep.
Also fixes typecheck fallout from the rewrite: switches toast tones to
the documented info|success|warn|error set, narrows the stale-project
filter to use archivedAt (ProjectStatus never had "archived"), and
tightens the MemorySheet test render helper to JSX.Element.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a minimal pending-gate indicator hook for Phase 11. Reads
the existing approvals endpoint and exposes {hasPendingGates, count,
loading, error} for the IconRail Assistant dot overlay. The rename
from "Approvals" to "Gates" is display-only — approvalsApi and the
underlying /api/approvals endpoint are untouched.
Ships the hook + tests only; the IconRail wiring is deferred to the
controller post-Wave 2 (IconRail is a Phase 8 file).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Aggregates active agents, pending gates, recent completions, and stale
projects from the existing agents, approvals, activity, and projects
APIs into a single shape consumed by AssistantHomeGreeting. The pure
`composeHomeStatus` helper drives the tests; the hook wires it to
react-query and degrades each slice to empty on fetch error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The usePiperTts hook imported a non-existent 'tts' namespace from
@mintplex-labs/piper-tts-web@1.0.4. The package exports named
functions (stored, download, predict, etc.) at the top level, not
under a tts namespace. The failing named-import threw at module-link
time, which crashed the lazy chunk for PersonalAssistant.tsx and
left /NEX/assistant blank with only a React error boundary fallback.
Two fixes in one file:
1. Import as namespace:
import * as tts from "@mintplex-labs/piper-tts-web"
ESM namespace imports synthesize a 'tts' object whose members are
the package's named exports, so the existing tts.stored() /
tts.download() / tts.predict() call sites bind to real functions
without touching the hook body.
2. Wrap predict() Blob result in URL.createObjectURL() before passing
to new Audio(). predict() returns Promise<Blob>, not a URL string,
and Audio() cannot accept a Blob directly. Added a shared cleanup
callback that revokes the object URL on onended/onerror and in the
catch path so we don't leak blob URLs on every speak invocation.
Bug 1 was the page-blanking crash at module load. Bug 2 was a latent
runtime crash behind the speak button click handler, surfaced while
the file was already being edited.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- postMessageAndStream data type extended with optional voiceMode field
- startStream signature updated: (userMessage, agentId?, voiceMode?)
- voiceMode forwarded into fetch body via postMessageAndStream call
- useMediaQuery: SSR-safe hook with addEventListener for live breakpoint updates
- usePullToRefresh: touch gesture hook with 64px threshold, haptic feedback via navigator.vibrate
- PullToRefresh: visual wrapper with Loader2 spinner, pull/release text indicators
- Add uploadFile method to chatApi using XHR for progress tracking
- Add ChatFileUploadResponse to shared type imports
- Create useChatFileUpload hook with PendingFile lifecycle management
- Hook manages uploading/done/error states with progress callbacks
- ChatTaskCreatedBadge renders loading state and resolved badge with View task link
- ChatStatusUpdateBadge renders CheckCircle2 + agent completion text with task link
- useBrainstormerDefault returns general role agent ID with React Query deduplication
- Fix ChatMessageList synthetic streaming entry to include messageType: null
- Add postMessageAndStream and savePartialMessage to chatApi (fetch ReadableStream for POST SSE)
- Create useStreamingChat hook with startStream, stop, streamingContent, isStreaming
- startTransition wraps token updates to avoid blocking user input (PERF-02)
- AbortController used for stop functionality (CHAT-12)
- stop() saves partial content with [stopped] suffix to DB
- Add @testing-library/react devDependency to enable renderHook testing
- 5 passing unit tests: token accumulation, lifecycle, stop/abort, error, null guard
- Add Search/X icons and Input to ChatConversationList with 300ms debounce
- Listen for nexus:focus-chat-search event to focus search input
- Add onSearch handler to useKeyboardShortcuts (fires before input guard)
- Wire Layout Cmd+K to open chat panel and dispatch focus event
- Add ilike import and search/agentId conditions in chatService.listConversations
- Extract search and agentId from req.query in GET /conversations route
- Extend chatApi.listConversations opts with search and agentId params
- Update useChatConversations to accept opts.search and include in queryKey
j/k navigate up/down, a to archive, U to mark unread, r to mark read,
Enter to open. Includes server-side DELETE /issues/:id/read endpoint
for mark-unread support on issues.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Approvals, failed runs, and join requests now have the same
unread dot + archive X pattern as issues in the Mine tab:
- Click the blue dot to mark as read, then X appears on hover
- Desktop: animated dismiss with scale/slide transition
- Mobile: swipe-to-archive via SwipeToArchive wrapper
- Dismissed items are filtered out of Mine tab
- Badge count excludes dismissed approvals and join requests
- localStorage-backed read/dismiss state for non-issue items
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- add company existence check on quota-windows route to guard against
sentinel and forged company IDs (was a no-op assertCompanyAccess)
- fix useDateRange minuteTick memo frozen at mount; realign interval to
next calendar minute boundary via setTimeout + intervalRef pattern
- fix midnight timer in Costs.tsx to use stable [] dep and
self-scheduling todayTimerRef to avoid StrictMode double-invoke
- return null for rolling window rows with no DB data instead of
rendering $0.00 / 0 tok false zeros
- fix secondsToWindowLabel to handle windows >168h with actual day count
instead of silently falling back to 7d
- fix byProvider.get(p) non-null assertion to use ?? [] fallback
merge Usage page into Costs as two tabs ('Spend' and 'Providers'),
extract shared date-range logic to useDateRange() hook, delete /usage
route and sidebar entry, fix quota-windows bugs from prior review
Resolve conflicts by keeping the issue-documents work alongside upstream heartbeat-context, worktree branding, and adapter runtime updates.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This shortcut interfered with browser tab-switching (Cmd+1..9) and
produced a black screen when used. Removes the handler, the Layout
callback, and the design-guide documentation entry.
Closes RUS-56
Rename all workspace packages from @paperclip/* to @paperclipai/* and
the CLI binary from `paperclip` to `paperclipai` in preparation for
npm publishing. Bump CLI version to 0.1.0 and add package metadata
(description, keywords, license, repository, files). Update all
imports, documentation, user-facing messages, and tests accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add drag-and-drop reordering to sidebar project list using dnd-kit,
persisted per-user via localStorage. Use consistent project order in
issue properties, new issue dialog, and issue detail mention options.
Move projects section below Work section in sidebar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When switching companies via the sidebar rail, dropdown, or keyboard
shortcuts, the app now navigates to the last page visited for that
company instead of staying on the current (now irrelevant) page.
Falls back to /dashboard if no previous page exists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Auth sign-in/sign-up page and InviteLanding page for invite acceptance.
Add CloudAccessGate that checks deployment mode and redirects to /auth when
session is required. Add CompanyRail with drag-and-drop company switching.
Add MarkdownBody prose renderer. Redesign Inbox with category filters and
inline join-request approval. Refactor AgentDetail to overview/configure/runs
views with claude-login support. Replace navigate() anti-patterns with <Link>
components in Dashboard and MetricCard. Add live-run indicators in sidebar
agents. Fix LiveUpdatesProvider cache key resolution for issue identifiers.
Add auth, health, and access API clients.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace custom useApi/useAgents hooks with @tanstack/react-query.
Add LiveUpdatesProvider for WebSocket-driven cache invalidation.
Add queryKeys module for centralized cache key management. Rework
all pages and dialogs to use React Query mutations and queries.
Improve CompanyContext with query-based data fetching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>