feat(askAi): no-issue: add Ask AI chatbot#9505
Conversation
|
🦸 Review Hero Summary Below consensus threshold (7 unique issues not confirmed by majority)
Local fix prompt (copy to your coding agent)Fix these issues identified on the pull request. One commit per issue fixed.
|
|
🦸 Review Hero Summary Below consensus threshold (7 unique issues not confirmed by majority)
Local fix prompt (copy to your coding agent)Fix these issues identified on the pull request. One commit per issue fixed.
|
🍹
|
26d07d8 to
68d52f9
Compare
|
🦸 Review Hero Summary Below consensus threshold (10 unique issues not confirmed by majority)
Local fix prompt (copy to your coding agent)Fix these issues identified on the pull request. One commit per issue fixed.
|
Adds a RAG-powered AI chatbot to Tamanu that allows clinical staff to ask questions about how Tamanu works. Uses Voyage AI for embeddings, a PostgreSQL RAG database for context retrieval, and Claude via BAML for answer generation. - Database migrations and models for AskAiConversation and AskAiMessage - AskAiService with hybrid vector + full-text RAG search (top 10 results) - API routes on both facility and central servers under /ask-ai/conversations - BAML schema and generated client for structured LLM responses - Floating chat panel in the web sidebar footer (toggle on/off) - Markdown rendering for AI responses via react-markdown - Sources omitted for tamanu namespace (codebase paths not useful to end users) - Prompt instructs AI to note facility vs central server availability
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents RAG database architecture, deployment sequence, manual re-indexing, rollback procedure, and verification steps for the Ask AI feature. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion or class' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…tion or class' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
The baml_client/ directory is generated by `baml generate` during build and is already listed in .gitignore. Removing it from the index to avoid diff noise, staleness, and merge conflicts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… and fix timezone fallback - Extract Ask AI routes into a shared askAiRouter so central and facility servers use the same handler logic - Add RAG hybrid search (vector + FTS) and conversation history to AskAiService - Add useAskAiStatusQuery hook and wire Ask AI panel to status check in App - Fix centralServerLogin to fall back to local config primaryTimeZone when central server returns null, preventing DateTimeProvider context error Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion or class' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds dbt model files for the new ask_ai.conversations and ask_ai.messages tables, and removes stale available_facilities columns from public schema model files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…es dbt model Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…in procedures dbt model Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Match what npm ci + npm i produces in CI: convert dev to devOptional for babel syntax plugins and v8 packages, and add peer flag to OS-specific esbuild and rollup optional packages. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…branch Local npm (Node.js 23) converted devOptional->dev for jest/babel/istanbul packages. Realign with origin/main's flags which match what CI's npm ci + npm i produces (Node.js 20). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nical format devOptional and other flags must appear after integrity in each entry, matching exactly the key ordering produced by npm ci + npm i on Node.js 20. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…10.8.0 Regenerated with npm ci + npm i using the same Node.js version as CI (v20.19.4, npm v10.8.0) to ensure flags and key ordering match exactly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…untu.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ining The previous query had three bugs: - FULL OUTER JOIN on (file_path, text) caused a near-Cartesian blowup because chunks from vector and FTS searches rarely share identical text - ROW_NUMBER() windows were computed over the entire joined result, not per-source, making RRF scores meaningless - FTS used inline to_tsvector (no GIN index) Fix: rank within each source CTE first, then UNION ALL + GROUP BY to dedup and sum RRF scores. Adds a comment flagging the inline tsvector as a future optimisation target. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Interpolating 1024 floats into the SQL string produces ~40 KB of literal text per request (the vector appears 4 times) that Postgres must re-parse on every call. Using $embedding::vector and $query as bind parameters sends the values out-of-band, allowing Postgres to cache the query plan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds limit/offset pagination to avoid loading all conversations for a user in a single query. Defaults to limit=50, max 100. count is now the total matching rows from findAndCountAll so the client can determine whether more pages exist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…/:id Long conversations load unbounded message history. Add limit/offset pagination matching the conversations endpoint — defaults to 50, max 100. Returns messageCount (total) alongside the page so the client can detect whether more messages exist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
github-repo-rag already creates {table}_fts_idx (GIN on
to_tsvector('english', text)) and uses CREATE TABLE IF NOT EXISTS with
upsert, so indexes survive re-indexing. No migration needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The cache grew without bound — one Sequelize pool per unique URL, never closed. Add a MAX_RAG_DB_CACHE_SIZE guard: when full, close and evict the oldest entry (Map insertion order) before adding a new one. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tor value Guard the Map iterator result before destructuring to satisfy TypeScript's type check — entries().next().value is [string, Sequelize] | undefined. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
06f47a8 to
a0a2014
Compare
…rial and add sequelize dep to shared Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Android builds 📱
|
….8.5 entries Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…json npm ci requires explicit lock file entries for react@16.8.5 and scheduler@0.13.6 used by central-server and facility-server, which were lost during previous lock file regenerations on this branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ion in package-lock.json central-server and facility-server directly depend on react@16.8.5 which requires nested node_modules entries in the lock file for npm ci. These entries were lost during previous lock file regenerations on this branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hared in package-lock.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ring test context setup BamlRuntime.fromFiles runs at module load time via globals.ts, which caused createTestContext() to hang (exceeding 30s) in central-server tests when buildRoutes imports askAiRoutes. Moving the import inside chat() means the BAML runtime is only initialised on the first LLM call, not during server/test startup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ask-ai The ask-ai LLM was receiving a sanitised copy of the merged server config (including local.json5 overrides) on every chat request. Removing this eliminates any risk of local configuration values being exposed via the assistant, even through the existing allowlist. The assistant retains access to front-end app settings (getFrontEndSettings), which are the user-facing feature flags it needs to answer configuration questions accurately. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Changes
feat(askAi): no-issue: add Ask AI chatbot feature
Adds a RAG-powered AI chatbot to Tamanu that allows clinical staff to ask
questions about how Tamanu works. Uses Voyage AI for embeddings, a PostgreSQL
RAG database for context retrieval, and Claude via BAML for answer generation.
Auto-Deploy
Options
Tests
Review Hero
Remember to...