Skip to content

feat(chat): in-app platform instructor assistant - #163

Merged
mirnaderbieh merged 2 commits into
pharmacy-ali-mazen-mirnafrom
chatbot-pharmacy
Jul 18, 2026
Merged

feat(chat): in-app platform instructor assistant#163
mirnaderbieh merged 2 commits into
pharmacy-ali-mazen-mirnafrom
chatbot-pharmacy

Conversation

@mznsh11

@mznsh11 mznsh11 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds an in-app instructor assistant — a floating chatbot that helps the
logged-in user understand and use MedFind. It explains pages, features, roles,
and statuses, walks through tasks, and answers questions about the user's own
data using live, tenant-scoped tools. It stays in scope and never invents numbers.

What's included

Contracts (@repo/contracts)

  • chat request/response schemas shared by API and web.

API (apps/api/src/chat)

  • POST /chat (auth-guarded, @CurrentUser) running an Anthropic tool-use loop
    on claude-sonnet-5 (overridable via ANTHROPIC_MODEL).
  • Data tools reuse the existing StatsService (platform / pharmacy / branch).
  • System prompt carries the instructor persona + a per-user identity block.

Web (apps/web)

  • Floating ChatWidget + useChat hook, mounted in the authenticated layout.
  • Markdown-rendered replies, role-based starter prompts, open/close animations,
    click-outside + Escape dismiss, and scroll-to-start-of-reply for long answers.

Tenant safety

Every data tool derives the tenant from the session user, never from model
input
, and tools are filtered by role before the model sees them — mirroring
the authorization the existing stats endpoints already enforce. The assistant
cannot request or reveal another organization's data.

Configuration

  • Set ANTHROPIC_API_KEY in apps/api/.env (see .env.example). Without it,
    POST /chat returns a clean 503 and the widget shows an "unavailable" toast —
    nothing else breaks. ANTHROPIC_* vars are declared in turbo.json.

Notes

  • Roles without a stats endpoint (stock manager, inquiry officer, client) get
    no data tool; their starter prompts are how-to/concept only, so the bot never
    reaches for a number it can't fetch.
  • Non-streaming for now; the full conversation is resent each turn (no cap).

Summary by CodeRabbit

  • New Features
    • Added the MedFind Assistant chat widget to the authenticated dashboard.
    • Users can ask questions, choose suggested prompts, and view formatted responses.
    • Added role-aware, permission-controlled access to live application data.
    • Added loading states, error handling, message limits, and conversation reset support.
    • Added secure chat configuration with a 503 response when AI access is unavailable.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b708262-3727-4bd1-b917-004c66b1bbac

📥 Commits

Reviewing files that changed from the base of the PR and between 117a9de and a0b950e.

📒 Files selected for processing (5)
  • apps/api/src/chat/chat.constants.ts
  • apps/api/src/chat/chat.controller.ts
  • apps/api/src/chat/chat.service.ts
  • apps/web/components/chat/chat-widget.tsx
  • apps/web/hooks/use-chat.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/api/src/chat/chat.controller.ts
  • apps/web/hooks/use-chat.ts
  • apps/api/src/chat/chat.constants.ts
  • apps/api/src/chat/chat.service.ts
  • apps/web/components/chat/chat-widget.tsx

📝 Walkthrough

Walkthrough

Adds an authenticated POST /chat endpoint backed by Anthropic tool calling and tenant-scoped statistics, shared request/response contracts, and a dashboard chat widget with local conversation state and Markdown rendering.

Changes

Instructor assistant chat

Layer / File(s) Summary
Chat contracts and module wiring
packages/contracts/src/chat/*, packages/contracts/src/index.ts, apps/api/.env.example, apps/api/package.json, apps/api/src/stats/stats.module.ts, apps/api/src/chat/chat.module.ts, apps/api/src/app.module.ts
Defines validated chat request/response contracts and wires the chat module, Anthropic dependency, environment settings, and exported StatsService.
Anthropic tool orchestration
apps/api/src/chat/chat.constants.ts, apps/api/src/chat/chat.service.ts, apps/api/src/chat/chat.controller.ts
Adds role-aware prompts and tools, bounded Anthropic tool-use execution, timeout and error handling, and the authenticated POST /chat controller.
Web chat state and rendering
apps/web/hooks/use-chat.ts, apps/web/components/chat/chat-widget.tsx, apps/web/components/chat/markdown.tsx, apps/web/package.json, apps/web/app/(authenticated)/layout.tsx
Adds conversation state, optimistic submission and rollback, the floating chat interface, Markdown replies, role-based suggestions, and dashboard integration.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: chrisshaddad

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: an in-app chat assistant.
Description check ✅ Passed The description is mostly complete and covers the feature, safety, and configuration, though QA steps, screenshots, and ticket link are missing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chatbot-pharmacy

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/api/src/chat/chat.controller.ts (1)

20-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider returning 200 OK instead of 201 Created.

By default, NestJS @Post() handlers return 201 Created. Since this endpoint generates a conversational completion without persisting a new RESTful resource, returning 200 OK is semantically more appropriate and aligns with common AI API conventions.

♻️ Proposed refactor
-  `@Post`()
+  `@Post`()
+  `@HttpCode`(200)
   chat(

(You will also need to import HttpCode from @nestjs/common)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/chat/chat.controller.ts` around lines 20 - 24, Update the chat
method in the controller to explicitly return HTTP 200 OK by applying NestJS’s
HttpCode decorator and importing HttpCode from `@nestjs/common`. Keep the existing
POST route, validation pipe, parameters, and response type unchanged.
apps/api/src/chat/chat.service.ts (1)

104-111: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add an explicit timeout to the Anthropic API call.

Since this is a synchronous endpoint and LLM generation can occasionally hang or be heavily delayed under load, a slow response might silently exceed your upstream load balancer or frontend's API timeout limit (which are often set between 10 to 60 seconds). This results in an opaque 504 error for the end-user.

Setting a reasonable explicit timeout on the SDK request ensures you can catch the timeout internally and gracefully return your ServiceUnavailableException fallback.

♻️ Proposed refactor
         const response = await this.client.messages.create({
           model: CHAT_MODEL,
           max_tokens: CHAT_MAX_TOKENS,
           system,
           messages: conversation,
           tools: toolDefs.length > 0 ? toolDefs : undefined,
-        });
+        }, { timeout: 15000 }); // Adjust threshold as needed
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/chat/chat.service.ts` around lines 104 - 111, Update the
Anthropic request in the chat iteration loop around client.messages.create to
pass an explicit SDK timeout appropriate for the synchronous endpoint. Ensure
timeout errors flow through the existing error handling so the
ServiceUnavailableException fallback is returned rather than allowing the
request to hang.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/components/chat/chat-widget.tsx`:
- Around line 83-99: Update the chat widget’s dismissal flow around the
open-state useEffect to keep a ref for the launcher and focus that element after
Escape, outside-pointer dismissal, and close-button dismissal. Attach the ref to
the launcher, and reuse a single close handler so every path sets open false and
restores launcher focus after the panel becomes hidden.

In `@apps/web/hooks/use-chat.ts`:
- Around line 41-46: Update the error path in the chat submission flow around
the catch block to remove or mark the failed optimistic user message so it is
not treated as a completed conversation turn or resent on the next submission.
Preserve the unsent draft for retry, and ensure manual retries do not append a
duplicate user message; use the existing messages state and submission symbols.

In `@turbo.json`:
- Around line 14-16: Remove ANTHROPIC_API_KEY from the shared environment
variable list in turbo.json, while preserving it in the API package or
task-specific environment configuration so only API tasks receive the secret.

---

Nitpick comments:
In `@apps/api/src/chat/chat.controller.ts`:
- Around line 20-24: Update the chat method in the controller to explicitly
return HTTP 200 OK by applying NestJS’s HttpCode decorator and importing
HttpCode from `@nestjs/common`. Keep the existing POST route, validation pipe,
parameters, and response type unchanged.

In `@apps/api/src/chat/chat.service.ts`:
- Around line 104-111: Update the Anthropic request in the chat iteration loop
around client.messages.create to pass an explicit SDK timeout appropriate for
the synchronous endpoint. Ensure timeout errors flow through the existing error
handling so the ServiceUnavailableException fallback is returned rather than
allowing the request to hang.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0417b98e-0b5e-4239-ac1b-a4f83c3b33cc

📥 Commits

Reviewing files that changed from the base of the PR and between b3c444b and 117a9de.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (18)
  • apps/api/.env.example
  • apps/api/package.json
  • apps/api/src/app.module.ts
  • apps/api/src/chat/chat.constants.ts
  • apps/api/src/chat/chat.controller.ts
  • apps/api/src/chat/chat.module.ts
  • apps/api/src/chat/chat.service.ts
  • apps/api/src/stats/stats.module.ts
  • apps/web/app/(authenticated)/layout.tsx
  • apps/web/components/chat/chat-widget.tsx
  • apps/web/components/chat/markdown.tsx
  • apps/web/hooks/use-chat.ts
  • apps/web/package.json
  • packages/contracts/src/chat/chat.request.ts
  • packages/contracts/src/chat/chat.response.ts
  • packages/contracts/src/chat/index.ts
  • packages/contracts/src/index.ts
  • turbo.json

Comment thread apps/web/components/chat/chat-widget.tsx
Comment thread apps/web/hooks/use-chat.ts
Comment thread turbo.json Outdated
@mirnaderbieh
mirnaderbieh self-requested a review July 18, 2026 17:55
@mirnaderbieh
mirnaderbieh merged commit ae77219 into pharmacy-ali-mazen-mirna Jul 18, 2026
2 checks passed
@mirnaderbieh
mirnaderbieh deleted the chatbot-pharmacy branch July 18, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants