Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
172 lines
9.5 KiB
Markdown
172 lines
9.5 KiB
Markdown
# 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)
|
|
- 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
|
|
1. User presses `⌘↑` / `Ctrl↑`.
|
|
2. Overlay opens centered and focuses the input.
|
|
3. User types question and hits `Enter`.
|
|
4. Overlay expands; assistant response streams in.
|
|
5. User hits `Esc` to close overlay.
|
|
|
|
### Flow B: Follow-Ups in Overlay
|
|
1. User opens overlay and asks question.
|
|
2. While response is shown, user asks a follow-up in the same overlay.
|
|
3. Chat continues as a single persisted chat session.
|
|
|
|
### Flow C: Move to Sidebar
|
|
1. User opens overlay, asks question, sees response.
|
|
2. User clicks “Open in sidebar”.
|
|
3. Right sidebar opens showing the same session.
|
|
4. 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., `Esc` to close, `Enter` to 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
|
|
- `Esc` closes
|
|
- reasonable ARIA labeling via existing `Dialog` component 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:
|
|
- `Enter` submits prompt (single-line mode).
|
|
- `Shift+Enter` inserts a newline (multiline input supported).
|
|
- `Esc` closes 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.tsx` via `⌘/Ctrl + L`.
|
|
- EE sidebar chat uses `ee/server/src/components/layout/RightSidebarContent.tsx`, which renders `ee/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 to `ee/server/src/services/chatCompletionsService.ts`).
|
|
- Streaming endpoints exist at `POST /api/chat/stream/*` (delegates to `ee/server/src/services/chatStreamService.ts`), and there is a client-side SSE parser in `ee/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)
|
|
- `chatId` lifecycle (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 `ChatSessionProvider` at layout/root that stores the active session and exposes:
|
|
- `activeSessionId` / `activeSession`
|
|
- `setActiveSession(...)`
|
|
- `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.
|
|
- 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-stuff` feature flag check in `ee/server/src/components/layout/RightSidebarContent.tsx` should 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
|
|
1. Where should “chat history” live for revisiting past sessions (if not already present in the product)?
|
|
|
|
## Acceptance Criteria / Definition of Done
|
|
- Pressing `⌘↑` on macOS or `Ctrl↑` 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.
|