Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
9.5 KiB
Spotlight Quick Ask Overlay (AI Chat)
Summary
Add a Spotlight-style “Quick Ask” overlay that opens centered over the app and lets users ask a question fast. When an answer begins returning, the UI expands into a chat-style dialog with the response streaming in. The user can then optionally move the in-progress chat into the existing chat sidebar (right sidebar), continuing with the normal chat UI.
Quick Ask and the sidebar chat are the same underlying chat session (same persistence, same chat id, same messages). The difference is primarily UX: Quick Ask is optimized for “one quick question”, while the sidebar is optimized for extended interaction.
Problem Statement
Today, AI chat lives in the right sidebar and requires a more deliberate UI mode switch. Users often want to ask a fast question without opening/committing to the sidebar. We need a lightweight, global entry point that feels like macOS Spotlight: a focused input that can quickly expand to show results.
Goals
- A global keyboard shortcut opens a centered overlay:
- macOS:
⌘+↑(hardcoded initially) - Windows/Linux:
Ctrl+↑(hardcoded initially)
- macOS:
- Quick Ask starts as a minimal input UI; upon sending a prompt and receiving the first response bytes/chunks, it transitions to an expanded dialog showing:
- user prompt
- assistant response streaming in (token/chunk streaming supported)
- follow-up prompts supported (multi-turn)
- Quick Ask shares as much logic as possible with the existing sidebar chat:
- message persistence (create chat + save messages)
- request/response handling (including “function proposed” / approval flows if enabled)
- stop/cancel
- error handling
- In “expanded dialog” state, provide an action to move/open the chat in the right sidebar:
- The right sidebar should open and display the same session seamlessly.
- Quick Ask should close (or optionally remain open in minimized state; see Open Questions).
- Messages asked via Quick Ask must persist exactly as messages asked via the sidebar chat do today.
Non-Goals
- A configurable shortcut UI (future enhancement; we will hardcode initially).
- A full “command palette” that searches app entities (assets/tickets/etc).
- A chat history list UI (the current sidebar chat does not expose prior chats).
- New analytics/telemetry, observability, or rollout flags beyond existing AI gating (unless requested).
Users / Personas
- Technician: wants a fast answer while working in tickets/projects without changing context.
- Dispatcher/Coordinator: uses quick prompts for “how do I…” and procedural guidance.
- Admin: may use AI to understand settings/integrations quickly.
Primary User Flows
Flow A: Quick One-Off Answer
- User presses
⌘↑/Ctrl↑. - Overlay opens centered and focuses the input.
- User types question and hits
Enter. - Overlay expands; assistant response streams in.
- User hits
Escto close overlay.
Flow B: Follow-Ups in Overlay
- User opens overlay and asks question.
- While response is shown, user asks a follow-up in the same overlay.
- Chat continues as a single persisted chat session.
Flow C: Move to Sidebar
- User opens overlay, asks question, sees response.
- User clicks “Open in sidebar”.
- Right sidebar opens showing the same session.
- User continues in the normal sidebar chat UI.
UX / UI Notes
Overlay look & feel (“Spotlight style”)
- Centered on screen horizontally + vertically.
- Rounded container, subtle border/shadow; darkened translucent backdrop.
- Collapsed state:
- single prominent input (optionally with “Ask Alga…” placeholder)
- small hint row (e.g.,
Escto close,Enterto ask)
- Expanded dialog state:
- input remains available at bottom for follow-ups
- transcript area above (user + assistant)
- streaming indicator while generating
- “Open in sidebar” control (only in expanded state)
- Accessibility:
- focus trap while open
Esccloses- reasonable ARIA labeling via existing
Dialogcomponent patterns
Transition (“seamless switch”)
- Use a single Dialog container; animate height/width between collapsed and expanded states.
- Expansion should trigger when:
- user submits a prompt, and
- the response begins (first SSE chunk / first tokens received), OR
- immediately after submit if non-streaming response is used.
Keyboard behaviors
- Global shortcut toggles open/close when appropriate.
- Inside overlay:
Entersubmits prompt (single-line mode).Shift+Enterinserts a newline (multiline input supported).Esccloses overlay.
- Shortcut should still work even when focus is inside a text input/textarea/contentEditable in the main app.
- If the right sidebar chat is already open, the shortcut should focus the sidebar chat (instead of opening Quick Ask).
Technical Design Notes
Current-State Notes (as observed in repo)
- Right sidebar is toggled in
server/src/components/layout/DefaultLayout.tsxvia⌘/Ctrl + L. - EE sidebar chat uses
ee/server/src/components/layout/RightSidebarContent.tsx, which rendersee/server/src/components/chat/Chat.tsx. - Chat persistence is handled via server actions in
ee/server/src/lib/chat-actions/chatActions.tsx(createNewChatAction,addMessageToChatAction,updateMessageAction). - Chat requests are currently sent to
POST /api/chat/v1/completions(delegates toee/server/src/services/chatCompletionsService.ts). - Streaming endpoints exist at
POST /api/chat/stream/*(delegates toee/server/src/services/chatStreamService.ts), and there is a client-side SSE parser inee/server/src/services/streaming.ts.
Proposed Architecture
1) Extract shared chat “session” logic
Create a headless hook/service (EE-only) that encapsulates:
- conversation state (model messages + UI messages)
chatIdlifecycle (create on first send)- persistence for user + assistant messages
- request execution (completions today; optional SSE streaming)
- abort/stop
- function proposal/approval flow state (if applicable)
This logic becomes the single source of truth for both:
- sidebar chat UI
- Quick Ask overlay UI
2) Add an EE “Quick Ask Overlay” component
Implement QuickAskOverlay as an EE component that:
- is controlled from
DefaultLayout(open state + close handler) - uses the shared chat session hook for sending and rendering
- supports “collapsed” and “expanded” UI states
- exposes an “Open in sidebar” action to hand off the active session
In CE builds (or when AI is disabled), the overlay should either:
- do nothing on shortcut, or
- show a small “EE required / AI unavailable” message consistent with existing patterns (decision).
3) Enable handoff (“Open in sidebar”)
Introduce a minimal shared state channel between overlay and sidebar:
- Option A (preferred): a
ChatSessionProviderat layout/root that stores the active session and exposes:activeSessionId/activeSessionsetActiveSession(...)openInSidebar(sessionId)helper
- Sidebar chat reads from this provider; if a session is active, it renders that session (instead of creating a new one).
- The overlay calls
openInSidebar()and closes itself.
This avoids brittle prop drilling and ensures both UIs show the same in-memory stream while also persisting to the DB.
Streaming vs non-streaming
- The Quick Ask overlay UI must support streamed updates.
- Implementation can start by:
- using the existing
POST /api/chat/stream/...SSE endpoint and progressively appending chunks, OR - extending the completions service to provide an SSE mode.
- using the existing
- Even if the backend currently emits a single SSE chunk, the UI should be built to handle true token streaming later without rewrites.
Persistence requirements
- On first user message in a session:
- create chat row (title defaults to first user message)
- persist user message
- On assistant completion:
- persist assistant message
- When using streaming:
- persist assistant message once final (or update incrementally if/when supported by server actions; optional).
Gating / Feature Availability
- The existing
AI-stufffeature flag check inee/server/src/components/layout/RightSidebarContent.tsxshould be reused for Quick Ask. - If AI is disabled, opening Quick Ask should present a clear disabled state and not call the API.
Risks / Edge Cases
- Global shortcut conflicts with OS/browser navigation or app keybindings.
- Focus stealing: opening Quick Ask while typing in a form could be disruptive.
- Session handoff consistency: ensuring the sidebar renders the exact in-memory state (esp. during streaming) without duplicating sends.
- SSE parsing and abort behavior across browsers.
Open Questions
- Where should “chat history” live for revisiting past sessions (if not already present in the product)?
Acceptance Criteria / Definition of Done
- Pressing
⌘↑on macOS orCtrl↑on Windows opens a centered Spotlight-like overlay with focused input. - If the right sidebar chat is already open, pressing
⌘↑/Ctrl↑focuses the sidebar chat instead of opening Quick Ask. - Submitting a question causes the overlay to expand and display the assistant response streaming in.
- Messages asked in Quick Ask persist using the same storage path as the sidebar chat.
- Clicking “Open in sidebar” opens the right sidebar and shows the same session, allowing continued conversation.
- The right sidebar continues to work as before for starting a new chat; the new shared logic does not regress existing chat behavior.