Commit graph

948 commits

Author SHA1 Message Date
Nexus Dev
3d2117ee9f fix(nexus): auto-bootstrap invite and vite onnxruntime middleware
Zero-terminal first boot. Previously the bootstrap_ceo invite had to be
created via a CLI command (paperclipai auth bootstrap-ceo) and the UI
showed a code block instructing the user to run it. Nexus is meant to
be zero-terminal, so the server now auto-creates the invite on startup
when no instance admin exists and exposes its relative path through
/api/health. BootstrapPendingPage redirects straight to /invite/{token}.
The CLI command is left intact for headless/SSH-only setups.

Invite flow fixes that surfaced during testing:

  - InviteLanding's invite query had default React Query refetch
    behavior. After a successful bootstrap accept, the invite is marked
    accepted server-side, so the refetch returned "not available" and
    shadowed the success screen, making it look like the bootstrap had
    failed when it actually succeeded. Set staleTime: Infinity +
    refetchOnWindowFocus/Mount/Reconnect: false so the first fetch is a
    one-shot snapshot.

  - Reordered the render checks so result?.kind === "bootstrap" / "join"
    are evaluated before the invite-availability error check — defensive
    against any stray refetch that still leaks through.

  - On bootstrap success, window.location.replace("/") lands the new
    admin directly on the board; the "Bootstrap complete" confirmation
    screen is now an unreachable safety net.

Vite onnxruntime middleware replaces the earlier public/ dump. The
previous commit put ort-wasm-simd-threaded.{mjs,wasm} in ui/public/ so
VAD's onnxWASMBasePath: "/" would find them. That works at runtime but
trips vite's dep optimizer: it scans onnxruntime-web, resolves the
dynamic import string to the public asset, and errors with "files in
/public should not be imported from source code." Remove the files and
add a vite plugin (configureServer middleware) that serves the two URLs
straight from node_modules/.pnpm/onnxruntime-web@*/. Runtime keeps
working and the files never enter vite's module graph.

Production build caveat: the middleware only runs in dev. When building
a static dist for production, the wasm files will need a different
mechanism (e.g. generateBundle hook). Not addressed here.

Also bundled (load-bearing for LAN browser testing):

  - ui/src/lib/queryKeys.ts: add missing 'nexus' group. useNexusMode
    referenced queryKeys.nexus.settings since commit 7bb72a5a (Phase
    33-02) but the key was never added. Caused a blank screen crash on
    any page that mounts Sidebar.

  - ctl.sh: read PORT from .env instead of hardcoding 3100, and read it
    once at the top so every subcommand honors it. Fixes the Version /
    Mode showing '?' in status output after the port move to 6100.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 16:50:28 +00:00
Nexus Dev
8f6dd220aa fix(nexus): restore chat migrations, mount routes, add onnx assets
HEAD had 3 pairs of drizzle-generated migrations colliding on indices 46-48
(chat set vs doc/feedback/routines set) with a journal that only referenced
one of each pair. Migrations 0047-0055 (chat_conversations, chat_messages,
bookmarks, chat_files, push_subscriptions, etc.) were committed as files on
disk but never added to _journal.json, so drizzle never applied them.

Rename the three non-chat ghost migrations out of the conflict zone
(0046/0047/0048 -> 0056/0057/0058) and extend the journal with entries for
all 12 previously-orphaned migrations so drizzle applies them in order on
fresh DB init.

Also mount chatRoutes() in app.ts — the router was defined in routes/chat.ts
but never wired up, so /api/companies/:id/{conversations,bookmarks} 404'd
even when tables existed.

Ship ort-wasm-simd-threaded.mjs + .wasm in ui/public so VAD can load the
onnxruntime module at /ort-wasm-simd-threaded.mjs instead of getting the
SPA HTML fallback.

Bundles pre-existing LAN-testing hunks in app.ts: conditional COOP/COEP
headers (only on secure/localhost origins) and Vite HMR host fix for
0.0.0.0 binding so the HMR client connects back to whatever hostname the
browser used. These are load-bearing for LAN browser testing on plain HTTP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:44:43 +00:00
Nexus Dev
1c8a26dbb4 feat: Phase 45 — Content as Skills (9 SKILL.md files, Creative group, gap fixes) 2026-04-05 09:57:20 +00:00
Nexus Dev
d25d88d053 feat: Phase 44 — Video & Presentations (Remotion MP4, SSE progress) 2026-04-05 09:57:11 +00:00
Nexus Dev
e4165adefb feat: Phase 43 — Documents & Branding (PDF reports, brand kit ZIP) 2026-04-05 09:57:02 +00:00
Nexus Dev
0956c31384 feat: Phase 42 — Wallpapers, Social, Format Conversion & Voice (12 platforms, convert pipeline, offline badge) 2026-04-05 09:56:53 +00:00
Nexus Dev
fc55990fde feat: Phase 41 — Diagrams, Icons & Theme Engine (Mermaid, SVG icons, OKLCH palettes) 2026-04-05 09:56:37 +00:00
Nexus Dev
8f97e69184 feat(39-02): VoiceStep hardware-aware UI with conditional enable/skip
- Add VoiceCapability interface to ui/src/api/hardware.ts
- Export VoiceCapability type from useHardwareInfo.ts
- VoiceStep accepts voiceCapability prop, renders conditionally
- Insufficient hardware: shows capability note with skip-only button
- Binaries present: shows green checkmarks next to STT/TTS labels
- Missing binaries on sufficient hardware: shows install note, dimmed Enable
- NexusOnboardingWizard passes voiceCapability from hardware probe to VoiceStep
2026-04-04 03:55:50 +00:00
Nexus Dev
9dc00f3a88 feat(39-01): ChatVoicePlayer sentence-buffered streaming playback
- Add streaming prop (default true) to ChatVoicePlayerProps
- Connect to POST /api/synthesize/stream via fetch + ReadableStream
- Parse SSE lines manually from response body stream
- First sentence audio begins playing as soon as first chunk arrives
- Subsequent sentences auto-play in sequence from audioQueue
- Show 'Sentence N of M' progress indicator during streaming playback
- Dot progress bar shows completed vs pending sentences
- Falls back to full-fetch mode on stream error or streaming=false
- Clean up all object URLs on unmount or new text
2026-04-04 03:55:50 +00:00
Nexus Dev
ed21eb339c feat(38-03): insert TelegramStep as step 5 in NexusOnboardingWizard
- Import TelegramStep component
- Insert Telegram step at position 5 (between Voice and Root Directory)
- Shift Root Directory from step 5 → step 6
- Shift Summary from step 6 → step 7
- Update step indicator from 'of 5' to 'of 6'
- Update summary indicator from step===6 to step===7
- Update all setStep() navigation callbacks accordingly
- Update error message referencing step 6 for root directory
2026-04-04 03:55:50 +00:00
Nexus Dev
713e92be0f feat(38-03): create TelegramStep onboarding component
- BotFather numbered instructions (4-step setup guide)
- Token input with live validation via POST /api/telegram/token
- Success state showing connected bot username
- Error state with descriptive message
- Skip/Back/Next navigation; Next enabled only after validation
2026-04-04 03:55:50 +00:00
Nexus Dev
35be67d019 fix(37): pass voiceMode in ChatPanel handleEdit path + add verification 2026-04-04 03:55:50 +00:00
Nexus Dev
7d3820a84f feat(37-04): wire VoiceMicButton, VoiceModeToggle, ChatVoiceBadge, voiceMode into chat UI
- ChatInput: replace VoiceRecordButton with VoiceMicButton (VAD-powered)
- ChatInput: add VoiceModeToggle above input when enableVoiceInput=true
- ChatMessage: add ChatVoiceBadge render for voice_input and voice_full messageTypes
- ChatMessage: auto-play reads from localStorage nexus:voice:autoplay key
- ChatPanel: import and call useVoiceMode, extract mode as voiceMode
- ChatPanel: pass voiceMode as third arg to all startStream calls (5 call sites)
2026-04-04 03:55:50 +00:00
Nexus Dev
9435458033 feat(37-04): add voiceMode to chatApi.postMessageAndStream + useStreamingChat.startStream
- postMessageAndStream data type extended with optional voiceMode field
- startStream signature updated: (userMessage, agentId?, voiceMode?)
- voiceMode forwarded into fetch body via postMessageAndStream call
2026-04-04 03:55:50 +00:00
Nexus Dev
8bf2a65a0b feat(37-03): VoiceModeToggle three-pill component + useVoiceMode hook
- VoiceModeToggle: Text / Voice In / Full Voice pills with active/inactive styling
- Auto-play checkbox in full_voice mode, persists to nexus:voice:autoplay in localStorage
- useVoiceMode: reads/writes voiceMode via PATCH /api/nexus/settings with loading state
  (deviation Rule 3: created missing blocking dependency for VoiceModeToggle)
2026-04-04 03:55:50 +00:00
Nexus Dev
6b60f42a25 feat(37-03): ChatVoicePlayer + ChatVoiceBadge components
- ChatVoicePlayer: POST /api/synthesize, play/pause controls, autoPlay support, blob URL cleanup
- ChatVoiceBadge: Voice badge, SPOKEN/DETAILED parsing, collapsible full markdown for voice_full
2026-04-04 03:55:50 +00:00
Nexus Dev
21ecf23d9a feat(37-02): VoiceWaveform canvas component and VoiceMicButton
- VoiceWaveform: 80x32 canvas with Web Audio AnalyserNode (fftSize=64), 20 animated bars drawn from frequency data using --primary color
- VoiceMicButton: three visual states — idle (Mic icon), recording (VoiceWaveform + ring-2 ring-primary), processing (Loader2 animate-spin)
- All three states have correct aria-labels per UI spec copywriting contract
2026-04-04 03:55:50 +00:00
Nexus Dev
0d0b17c8a0 feat(37-02): encodeWav utility, useVadRecorder + useVoiceMode hooks
- encodeWav: 44-byte WAV header encoder (RIFF/WAVE/fmt/data), PCM mono 16-bit
- useVadRecorder: wraps useMicVAD with startOnLoad:false, auto-stop on speech end, POSTs to /api/transcribe
- useVoiceMode: reads/writes voiceMode from GET/PATCH /api/nexus/settings with optimistic update
2026-04-04 03:55:50 +00:00
Nexus Dev
de1287fba3 feat(37-01): install VAD library, copy ONNX assets, configure Vite COOP/COEP headers
- Add @ricky0123/vad-react dependency to ui/package.json
- Add copy-vad-assets npm script for reproducible asset copying
- Copy vad.worklet.bundle.min.js, silero_vad_legacy.onnx, silero_vad_v5.onnx to ui/public/
- Add COOP/COEP headers to Vite dev server config (SharedArrayBuffer support in dev)
- Update pnpm lockfile
2026-04-04 03:55:50 +00:00
Nexus Dev
c7974fa67c feat(34-02): voice onboarding step + PersonalAssistant voice wiring
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:49 +00:00
Nexus Dev
847f316319 feat(34-01): create usePiperTts hook and TtsButton component with piper-tts-web
- Install @mintplex-labs/piper-tts-web as UI dependency
- Create usePiperTts hook with prewarm/speak/stop/status/progress (VOICE-01, VOICE-02)
- tts.stored() checks IndexedDB cache to skip re-download
- tts.download() with progress callback for visible download progress
- tts.predict() returns WAV blob URL for CPU-safe WASM synthesis
- Create TtsButton component showing download progress during prewarm
- TtsButton shows Volume2/VolumeX icons for idle/speaking states
2026-04-04 03:55:49 +00:00
Nexus Dev
36746ed17b feat(34-01): register chatFileRoutes + nexusSettingsRoutes in app.ts, add voiceEnabled to nexus-settings
- Add chatFileRoutes(db, storageService) after assistantHandoffRoutes (inside boardMutationGuard)
- Add nexusSettingsRoutes() after chatFileRoutes
- Extend nexusSettingsSchema with voiceEnabled: z.boolean().default(false)
- Update default return values in nexusSettingsService.get() to include voiceEnabled: false
- Add voiceEnabled?: boolean to NexusSettings client interface in hardware.ts
2026-04-04 03:55:49 +00:00
Nexus Dev
222d00c57f feat(33-03): real AI streaming with memory injection + assistant handoff
Replace streamEcho with Puter proxy AI call, inject memory facts as
system message, append memory after each turn. Assistant-to-PM handoff
creates new conversation with context summary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:49 +00:00
Nexus Dev
7bb72a5a2f feat(33-01,33-02): memory service + sanitizer, personal assistant page
33-01: memory-sanitizer, assistant-memory service, REST routes, 17 tests
33-02: useNexusMode hook, PersonalAssistantPage, sidebar nav, route wiring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:49 +00:00
Nexus Dev
4032d4d88b feat(32-01): wire summary step, skip buttons, chat handoff in wizard
- Add OnboardingSummaryStep as step 5 of the wizard
- Add Skip buttons on step 1 (hardware) and step 2 (mode)
- Replace step 4 form submit with Review & finish -> step 5 flow
- Add Skip to summary on step 4
- Step indicator shows 'Summary' on step 5 instead of 'Step 5 of 4'
- Add deriveProviderLabel helper for provider display text
- Add handleStartChat that creates workspace then calls setChatOpen(true)
- Refactor shared workspace creation into createWorkspace() helper
2026-04-04 03:55:49 +00:00
Nexus Dev
1683e88b9f feat(32-01): create OnboardingSummaryStep component and tests
- Read-only summary card with hardware, mode, provider, root dir rows
- SummaryRow helper component with optional mono styling
- Start chatting CTA with spinner and disabled state
- 6 unit tests covering rendering, empty root dir, error, click, loading
2026-04-04 03:55:49 +00:00
Nexus Dev
d9c6d121f3 feat(31-03): add ProviderSelectionStep and wire 4-step onboarding wizard
- ProviderSelectionStep: three provider cards (Puter/Google/API key) with adapter badges
- Cards use border-primary bg-primary/5 when selected (matches ModeSelector pattern)
- PuterAuthButton/GoogleOAuthButton/ApiKeyEntryForm wired via callbacks
- NexusOnboardingWizard: step count 3→4, provider selection at step 3
- Parallel probe for hermes_local/claude_local/openclaw_gateway on wizard open
- Credentials stored after company creation (puterToken, googleOAuthStateId, apiKeyData)
- Skip always advances to step 4; Back from step 4 goes to step 3
2026-04-04 03:55:49 +00:00
Nexus Dev
f6db1f7882 feat(31-03): add puter-proxy API client and auth/key entry components
- puterProxyApi: storeToken, getAuthUrl, claimGoogleTokens, storeApiKey
- PuterAuthButton: loads Puter CDN script, triggers signIn popup, captures token
- GoogleOAuthButton: 3-second risk warning gate, opens OAuth popup, captures stateId
- ApiKeyEntryForm: provider dropdown (OpenAI/Anthropic/Groq) + password input
2026-04-04 03:55:49 +00:00
Nexus Dev
28a1d1aa5e feat(30-02): wire multi-step wizard in NexusOnboardingWizard
- Refactor to 3-step flow: hardware detection, mode selection, root directory
- Add step indicator 'Step N of 3'
- Add HardwareSummaryStep on step 1 with dynamic heading
- Add ModeSelector on step 2 with 'both' pre-selected
- Add Back buttons on steps 2 and 3
- Persist selected mode via updateNexusSettings on wizard completion
- Reset step and mode on wizard close
2026-04-04 03:55:49 +00:00
Nexus Dev
2a47c60057 feat(30-02): API client, hook, ModeSelector, and HardwareSummaryStep
- Add ui/src/api/hardware.ts with fetchHardwareInfo, fetchNexusSettings, updateNexusSettings
- Add ui/src/hooks/useHardwareInfo.ts with useQuery wrapper
- Add queryKeys.hardware.info to ui/src/lib/queryKeys.ts
- Add ModeSelector with three-card layout and selected state styling
- Add HardwareSummaryStep with skeleton loading, tier-appropriate labels, privacy frame
2026-04-04 03:55:49 +00:00
Nexus Dev
0fc748d2d4 feat(29-02): Hermes skill injection + default provider integration tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:49 +00:00
Nexus Dev
1ff3953c97 feat(29-01): adapter probe route, Hermes onboarding fallback, neutral templates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:49 +00:00
Nexus Dev
1cf1c1f038 feat(28-02,28-03): Ollama UI surface + Hermes runtime dashboard
28-02: ollamaApi client, model dropdown in config, skill badge
28-03: stateJson merge after heartbeat, HermesRuntimeCard in AgentOverview

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:49 +00:00
Nexus Dev
39327b7660 feat(28-03): merge Hermes runtime data into stateJson and add HermesRuntimeCard
- Add OllamaPsResponse interface and getOllamaMemoryUsage() to ollama.ts
- Import getOllamaMemoryUsage in heartbeat.ts
- Add hermes_local block in updateRuntimeState: COALESCE jsonb merge of hermesModel + hermesMemoryBytes
- Add HermesRuntimeCard component in AgentDetail.tsx
- Render HermesRuntimeCard in AgentOverview gated by adapterType === hermes_local
- Native skill count derived from agentsApi.skills entries with originLabel === Hermes skill
2026-04-04 03:55:49 +00:00
Nexus Dev
fbea338c23 feat(28-02): add Hermes skill badge and native skills section header in AgentSkillsTab
- Render purple "Hermes skill" badge for skills with originLabel === "Hermes skill"
- Section header shows "Hermes native skills & user-installed skills" for hermes_local agents
- Non-Hermes originLabel values continue to render as plain muted text
2026-04-04 03:55:49 +00:00
Nexus Dev
926b3a8763 feat(28-02): create ollamaApi client and Hermes Ollama model dropdown
- Add ui/src/api/ollama.ts with ollamaApi.status() and ollamaApi.models()
- Replace free-text Model input with hybrid dropdown/fallback in HermesLocalConfigFields
- Dropdown shows pulled Ollama models with * prefix for recommended entries
- Install callout shown when Ollama is absent (with link to installUrl)
- Edit mode: selecting an Ollama model atomically sets model + provider:custom + base_url
- Manual entry fallback via "Other (manual entry)..." option or when Ollama absent
- Uses useCompany() hook for companyId (consistent with AgentConfigForm pattern)
2026-04-04 03:55:48 +00:00
Nexus Dev
9ef04fd1de feat(27-01): close Hermes adapter integration gaps
- Add hermes_local to SESSIONED_LOCAL_ADAPTERS (HERM-03)
- Fix create-mode toolsets field guard (HERM-02)
- Add hermes session codec round-trip tests (HERM-04)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:48 +00:00
Nexus Dev
4b9d267f46 fix(v1.3): close 3 integration gaps from milestone audit
1. Push notifications: call sendPushToAll after streaming completes
2. Mobile offline: add useOfflineQueue + banners to MobileChatView
3. New conversation streaming: call startStream in Path 1 handleSend

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:48 +00:00
Nexus Dev
8235a607b7 fix(26): remove empty vendor-react chunk and mark PWA-02/PWA-08 complete
vendor-react manualChunks doesn't work with @vitejs/plugin-react JSX
runtime — react/react-dom stay in entry. Documented and removed.
PWA-02 and PWA-08 were implemented but not marked in REQUIREMENTS.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:48 +00:00
Nexus Dev
862cf7fef3 feat(26-04): create push API client, usePushNotifications hook, and NotificationPermissionPrompt
- Add ui/src/api/push.ts with getVapidPublicKey, subscribe, unsubscribe methods
- Add ui/src/hooks/usePushNotifications.ts with SW pushManager subscription flow
- urlBase64ToUint8Array utility converts VAPID key for applicationServerKey
- NotificationPermissionPrompt shows after 3rd agent response (engagement gate)
- Checks nexus.notifPromptDismissed localStorage key for dismiss state
- ChatPanel tracks agentResponseCount from assistant messages and renders prompt
- Install idb package (missing dependency from plan 26-00 prerequisites)
2026-04-04 03:55:48 +00:00
Nexus Dev
471a9daaa6 feat(26): merge worktree code from plans 26-00, 26-01, 26-03
SW cache-first rewrite, React.lazy code splitting, PWA types/test stubs,
install prompt, offline banner, offline queue, ChatPanel wiring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:48 +00:00
Nexus Dev
6b7e54bbf9 feat(26-02): create MobileChatView and wire ChatPanel for responsive layout
- MobileChatView: full-screen mobile chat using 100dvh, back button, safe-area input
- ChatPanel: conditionally renders MobileChatView on mobile via useMediaQuery
- ChatConversationList: wraps ScrollArea in PullToRefresh for mobile
- ChatInput: pb-[env(safe-area-inset-bottom)] padding + 44px Send button touch target
- ChatConversationItem: min-h-[48px] touch target per UI-SPEC
2026-04-04 03:55:48 +00:00
Nexus Dev
512a4aa448 feat(26-02): create useMediaQuery hook, usePullToRefresh hook, and PullToRefresh component
- 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
2026-04-04 03:55:48 +00:00
Nexus Dev
324551538b feat(25-04): wire ChatCodeFilePreview into ChatFilePreview and mark FILE-07 FILE-13 Complete
- Add code category branch in ChatFilePreview routing to ChatCodeFilePreview
- Mark FILE-07 (one-click download) as Complete in REQUIREMENTS.md
- Mark FILE-13 (cross-device access) as Complete in REQUIREMENTS.md
- Update Traceability table for FILE-07 and FILE-13
2026-04-04 03:55:48 +00:00
Nexus Dev
03df062bec feat(25-04): create ChatCodeFilePreview with syntax highlighting
- Add ChatCodeFilePreview component with hljs syntax highlighting
- Fetch file content from contentPath with credentials
- Use DOMParser-based safe rendering (no dangerouslySetInnerHTML)
- Include copy button, language label, and ChatFileCard download below
- Add extToLang extension-to-language mapping
- Register 14 common languages with hljs
- Add highlight.js as direct dependency in ui/package.json
2026-04-04 03:55:48 +00:00
Nexus Dev
dea5ea2bb7 feat(25-08): wire VoiceRecordButton into ChatInput and mark INPUT-02/03/04 complete
- Add enableVoiceInput prop to ChatInput props interface
- Add handleTranscription callback that appends transcription text to textarea state
- Render VoiceRecordButton conditionally when enableVoiceInput is true
- Pass enableVoiceInput={true} from ChatPanel to ChatInput
- Mark INPUT-02, INPUT-03, INPUT-04 as Complete in REQUIREMENTS.md traceability table
2026-04-04 03:55:48 +00:00
Nexus Dev
64a90c284e feat(25-08): create VoiceRecordButton and server transcription endpoint
- Add VoiceRecordButton with MediaRecorder API, recording/transcribing/idle states
- Add POST /transcribe endpoint to chat-files.ts using execFileAsync (safe, no shell)
- Tries whisper-cpp first, falls back to openai-whisper Python CLI
- Returns 503 with helpful message if whisper is not installed
2026-04-04 03:55:48 +00:00
Nexus Dev
9aee875239 feat(25-03): wire files into ChatMessage, ChatPanel, and server listMessages
- ChatMessage: files prop, renders ChatFilePreview for each attached file
- ChatMessageList: passes files prop through to ChatMessage
- ChatPanel: wires useChatFileUpload, passes pendingFiles/onRemoveFile/onFilesPicked to ChatInput
- ChatPanel handleSend: attaches uploaded files to message after creation, invalidates query
- chatApi: adds attachFilesToMessage (parallel PATCH /files/:fileId for each fileId)
- server/chat.ts: listMessages fetches chatFiles by messageId (inArray), attaches files array
- server/chat.ts: addMessage returns files: [] for consistency
2026-04-04 03:55:48 +00:00
Nexus Dev
5d385c5f92 feat(25-03): create ChatFilePreview and ChatFileCard components
- ChatFileCard: icon, filename, size, download button with theme-aware bg-muted styling
- ChatFilePreview: inline image rendering with constrained max-h-[300px], ChatFileCard for all other types
- formatFileSize helper (B, KB, MB)
- lucide icons: ImageIcon, FileCode, FileText, File per category
2026-04-04 03:55:48 +00:00
Nexus Dev
c876b9f142 feat(25-02): create ChatFileDropZone and integrate into ChatInput
- Create ChatFileDropZone component with drag-and-drop state and overlay
- Add onFilesPicked/pendingFiles/onRemoveFile props to ChatInput
- Wrap form in ChatFileDropZone for drag-and-drop support
- Add handlePaste for clipboard image paste (clipboardData.files)
- Add Paperclip icon button with hidden file input for file picker
- Show pending file chips above textarea with progress and remove button
- Add tests: renders file attach button, calls onFilesPicked, shows pending chips
2026-04-04 03:55:48 +00:00