Skip to content

feat: Add medical-assistant AgentKit#69

Open
SandipM03 wants to merge 1 commit intoLamatic:mainfrom
SandipM03:feat/medical-assistant
Open

feat: Add medical-assistant AgentKit#69
SandipM03 wants to merge 1 commit intoLamatic:mainfrom
SandipM03:feat/medical-assistant

Conversation

@SandipM03
Copy link

@SandipM03 SandipM03 commented Mar 1, 2026

What This Kit Does

The Medical Assistant AgentKit is an AI-powered chatbot that provides general medical information, symptom checks, and health guidance through a conversational interface built with Lamatic.ai. It solves the need for accessible, on-demand health information with proper safety guardrails:

  • Conversational Interface — Chat-style Q&A with message history and session management
  • Symptom Guidance — Describe symptoms to get relevant medical information
  • Suggested Prompts — Quick-start chips for common health questions
  • Markdown Rendering — Rich formatted responses with headers, lists, and emphasis
  • Medical Disclaimers — Persistent disclaimer banner + per-response reminders
  • Copy to Clipboard — Easy sharing of responses
  • Emergency Detection — Advises calling emergency services when appropriate

Providers & Prerequisites

  • Lamatic.ai: Core orchestration and workflow execution engine
  • Lamatic GraphQL Endpoint: Project-specific endpoint for flow execution
  • Project IDs & API Keys: Required for secure authentication

How to Run Locally

  1. Navigate to kits/assistant/medical-assistant
  2. Install with npm install
  3. Create a .env file using .env.example as a template
  4. Run development server: npm run dev
  5. Open http://localhost:3000

Issue

Issue: #25

Lamatic Flow

Flow configurations and schemas are maintained in the flows/medical-assistant-chat/ directory of the kit.

PR Checklist [Kit]

Kit runs locally with npm run dev
.env.example has no secrets, only placeholders
README.mddocuments setup, environment variables, and usageFolder structure: kits/assistant/medical-assistant/
config.json and orchestrate.js are present and valid
All flows exported in flows/ folder

Demo

Screen.Recording.2026-03-01.165915.mp4

Privacy & Data Handling

  • No user data is stored persistently — chat history exists only in the browser session
  • No personal health information (PHI) is collected or stored

Summary

New Features

  • Medical Assistant kit with chat UI for health queries and AI-generated, evidence-based responses
  • Session management with sidebar for multiple conversations
  • Medical disclaimer components (banner + per-response)
  • Suggested prompt chips for quick-start interactions

Configuration

  • Environment template, README, and project config added to simplify setup
  • Flow exported with config, inputs, meta, and README

Chores

  • .gitignore and build tooling configs included

Summary by CodeRabbit

Release Notes

  • New Features

    • Multi-session medical chat assistant with persistent conversation history
    • Copy-to-clipboard functionality for assistant responses
    • Collapsible session sidebar for easy navigation
    • Dark mode interface support
    • Medical disclaimers with professional consultation guidance
    • Markdown message rendering
  • Documentation

    • Comprehensive setup and configuration guide
    • Medical Assistant chat flow documentation with examples

@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

📝 Walkthrough

Walkthrough

This PR introduces a complete medical assistant kit featuring a Next.js frontend application with multi-session chat UI, Lamatic workflow integration for LLM-powered medical queries, comprehensive configuration files, styling system, and backend orchestration logic.

Changes

Cohort / File(s) Summary
Configuration & Setup
kits/assistant/medical-assistant/.env.example, .gitignore, config.json, orchestrate.js, package.json
Adds environment configuration template, build artifact ignores, kit metadata, flow orchestration config with API endpoint/credentials, and npm package manifest with dependencies (Next.js 15, React 19, Tailwind, Radix UI).
Flow Definition
kits/assistant/medical-assistant/flows/medical-assistant-chat/*
Defines medical chat flow with API trigger node, LLM node with medical-aware system prompt constraints, input/output schemas, model configuration, metadata, test inputs, and flow documentation with medical disclaimers.
Next.js App Configuration
kits/assistant/medical-assistant/app/layout.tsx, globals.css, next.config.mjs, tailwind.config.ts, tsconfig.json, postcss.config.cjs
Sets up Next.js app layout with metadata and fonts, implements comprehensive global styling with Tailwind dark mode theming, chat message animations, and prose formatting; configures Tailwind, TypeScript, PostCSS, and Next.js build settings.
Chat UI & Components
kits/assistant/medical-assistant/app/page.tsx, components/disclaimer.tsx, lib/utils.ts
Implements client-side multi-session medical chat interface with message history, auto-titled sessions, user input handling, markdown rendering, copy-to-clipboard, and collapsible sidebar; adds reusable disclaimer components and Tailwind class composition utility.
Backend Integration
kits/assistant/medical-assistant/actions/orchestrate.ts, lib/lamatic-client.ts
Adds server action to execute Lamatic medical queries with polling support for async responses, error handling, and answer extraction; initializes and exports preconfigured Lamatic client with environment variable and config validation.
Documentation
kits/assistant/medical-assistant/README.md, components.json
Provides comprehensive kit documentation covering Lamatic setup, environment configuration, repo structure, features, privacy, development commands; defines shadcn UI configuration with Tailwind integration and component aliases.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Browser as Browser/Client
    participant NextApp as Next.js App
    participant LamaticAPI as Lamatic API
    participant LLM as LLM (Medical AI)

    User->>Browser: Enters medical query
    Browser->>NextApp: sendMedicalQuery(query)
    activate NextApp
    NextApp->>LamaticAPI: executeFlow(workflowId, inputs)
    activate LamaticAPI
    LamaticAPI->>LLM: Process with medical system prompt
    activate LLM
    LLM-->>LamaticAPI: Generated medical response
    deactivate LLM
    LamaticAPI-->>NextApp: Execute result (immediate or requestId)
    deactivate LamaticAPI
    
    alt Async Response
        NextApp->>LamaticAPI: checkStatus(requestId)
        LamaticAPI-->>NextApp: Status & answer
    end
    
    NextApp->>NextApp: Parse answer from response
    deactivate NextApp
    NextApp-->>Browser: { success: true, data: answer }
    Browser->>Browser: Update session, render markdown
    Browser-->>User: Display medical response with disclaimer
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Fix : Config Removal #42: Modifies Lamatic client initialization, environment variable validation, and config.api sourcing pattern—shares similar authentication and configuration handling approach with this PR's lamatic-client.ts implementation.

Poem

🐰 A medical kit hops into place,
With chat flows and UI grace,
Lamatic learns to heal with care,
Disclaimers ensure we play fair,
Next.js and Tailwind dance in pair! 🏥✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Add medical-assistant AgentKit' accurately and concisely summarizes the main change: adding a new Medical Assistant AgentKit component to the repository.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (5)
kits/assistant/medical-assistant/package.json (1)

16-16: Consider moving autoprefixer to devDependencies.

autoprefixer is a build-time tool for PostCSS and doesn't need to be in production dependencies. Moving it to devDependencies reduces the production bundle footprint.

♻️ Proposed fix
   "dependencies": {
     "@radix-ui/react-scroll-area": "^1.2.3",
     "@radix-ui/react-slot": "^1.1.1",
     "@tailwindcss/typography": "^0.5.19",
     "@vercel/analytics": "^1.5.0",
-    "autoprefixer": "^10.4.27",
     "class-variance-authority": "^0.7.1",
   "devDependencies": {
     "@tailwindcss/postcss": "^4.0.6",
     "@types/node": "^20",
     "@types/react": "^19",
     "@types/react-dom": "^19",
+    "autoprefixer": "^10.4.27",
     "postcss": "^8.5.6",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/package.json` at line 16, The package.json
currently lists "autoprefixer" in dependencies; move it to devDependencies by
removing the "autoprefixer" entry from the top-level "dependencies" object and
adding the same version string under "devDependencies" so it is installed only
in development/build environments; update any package-lock or yarn.lock by
reinstalling deps if needed to reflect the change.
kits/assistant/medical-assistant/.env.example (1)

1-4: Remove spaces around equal signs in .env.example.

Some .env parsers don't handle spaces around the = sign correctly, which could lead to configuration issues. The standard convention is KEY=value without spaces.

♻️ Proposed fix
-MEDICAL_ASSISTANT_CHAT = "MEDICAL_ASSISTANT_CHAT Flow ID"
-LAMATIC_API_URL = "LAMATIC_API_URL"
-LAMATIC_PROJECT_ID = "LAMATIC_PROJECT_ID"
-LAMATIC_API_KEY = "LAMATIC_API_KEY"
+MEDICAL_ASSISTANT_CHAT="your_flow_id_here"
+LAMATIC_API_URL="https://api.lamatic.ai"
+LAMATIC_PROJECT_ID="your_project_id_here"
+LAMATIC_API_KEY="your_api_key_here"

Note: The proposed fix also aligns placeholder values with the README documentation format for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/.env.example` around lines 1 - 4, Remove the
spaces around the equals signs in the environment variable declarations for
MEDICAL_ASSISTANT_CHAT, LAMATIC_API_URL, LAMATIC_PROJECT_ID, and LAMATIC_API_KEY
so each line follows KEY=value format (no surrounding spaces) and update the
placeholder values to match the README's placeholder style for consistency.
kits/assistant/medical-assistant/tsconfig.json (1)

11-13: Consider enabling full strict mode for better type safety.

The current configuration sets strict: false while manually enabling strictNullChecks and noImplicitAny. This is an unusual pattern. Using strict: true would enable all strict options (including strictBindCallApply, strictFunctionTypes, strictPropertyInitialization, etc.) for more comprehensive type checking.

♻️ Proposed change
-    "strict": false,
-    "strictNullChecks": true,
-    "noImplicitAny": true,
+    "strict": true,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/tsconfig.json` around lines 11 - 13, The
tsconfig currently has "strict": false while individually enabling
"strictNullChecks" and "noImplicitAny"; change to enable full strict mode by
setting "strict": true and remove or keep the individual flags for clarity (they
become redundant) so that all strict checks (e.g., strictBindCallApply,
strictFunctionTypes, strictPropertyInitialization) are enforced; update the JSON
entry for the "strict" compiler option and ensure the "strictNullChecks" and
"noImplicitAny" lines are consistent with that change.
kits/assistant/medical-assistant/actions/orchestrate.ts (1)

6-14: Add server-side query guardrails (empty/oversized).

Relying only on client checks is fragile. A lightweight server boundary check will reduce avoidable provider calls and failure noise.

✅ Suggested guardrails
 export async function sendMedicalQuery(
   query: string,
 ): Promise<{
@@
 }> {
   try {
+    const trimmedQuery = query?.trim()
+    if (!trimmedQuery) {
+      return { success: false, error: "Query cannot be empty." }
+    }
+    if (trimmedQuery.length > 2000) {
+      return { success: false, error: "Query is too long. Please shorten and try again." }
+    }
-    console.log("[medical-assistant] Processing query, length:", query.length)
+    console.log("[medical-assistant] Processing query, length:", trimmedQuery.length)
@@
-      query,
+      query: trimmedQuery,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/actions/orchestrate.ts` around lines 6 - 14,
In sendMedicalQuery add server-side guardrails: trim the incoming query and if
it's empty return { success: false, error: "empty query" } without calling
downstream providers; if query.length exceeds a defined MAX_QUERY_LENGTH
constant (e.g., MAX_QUERY_LENGTH = 2000) log the event and return { success:
false, error: "query too long" }; use the existing console/logging pattern
(console.log or processLogger) to record rejected queries and ensure all early
returns match the function's Promise<{success:boolean, data?:any,
error?:string}> shape so no provider/client calls happen for invalid input.
kits/assistant/medical-assistant/app/page.tsx (1)

416-420: Copy action should be keyboard-visible, not hover-only.

The button is visually hidden unless hovered; add focus-visible styles so keyboard users can discover it.

⌨️ Accessibility tweak
-                                                            className="absolute top-2 opacity-0 group-hover:opacity-100 transition-all duration-200 p-1.5 rounded-lg"
+                                                            className="absolute top-2 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 focus-visible:outline focus-visible:outline-2 transition-all duration-200 p-1.5 rounded-lg"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/app/page.tsx` around lines 416 - 420, The
copy control is hidden via opacity unless hovered; make it discoverable to
keyboard users by adding focus/focus-visible styles and ensuring it's focusable:
update the element using className (the element that currently has "absolute
top-2 opacity-0 group-hover:opacity-100 ...") to include
"focus-visible:opacity-100" (and/or "focus:opacity-100") and a visible focus
outline class (e.g., "focus-visible:outline" or similar), and if the element is
not already a native button ensure it has tabIndex={0} and keyboard handlers;
keep the existing aria-label logic (aria-label={copiedId === msg.id ? "Copied" :
"Copy response"}) and reference copiedId and msg.id as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/assistant/medical-assistant/actions/orchestrate.ts`:
- Around line 56-60: Replace raw payload logging in orchestrate.ts by removing
verbose prints of asyncResult and error; instead log only non-sensitive metadata
(e.g., requestId, status code, duration, and a redacted/summary message).
Specifically update the console.log calls around lamaticClient.checkStatus
(where requestId and asyncResult are logged) and the catch/log that prints error
to redact or stringify only safe fields (avoid user medical content or provider
internals) and add a correlation id if available; keep the detailed payloads
available only for secure debug endpoints or structured logs behind a privacy
guard.
- Around line 8-11: The returned payload currently types data as any and can
propagate non-string values; change the return type to data?: string and ensure
every assignment to data (in the orchestrate function and the parsing/return
branches around the 75-91 range) converts values to a string using a small
helper like ensureString(value) that returns '' for null/undefined, returns the
value if typeof value === 'string', otherwise returns JSON.stringify(value);
update the Promise signature from data?: any to data?: string and replace direct
data assignments with ensureString(...) to guarantee downstream UI always
receives text.

In `@kits/assistant/medical-assistant/app/globals.css`:
- Around line 3-5: Linting fails because Tailwind v4 at-rules like `@plugin` and
`@custom-variant` (and others: `@theme`, `@apply`, `@layer`, `@import`, `@tailwind`) are not
allowed by current CSS linters; update .stylelintrc.json to add these directives
to the "ignoreAtRules" list for the "at-rule-no-unknown" rule, and update
biome.json to enable Tailwind CSS parsing or disable conflicting CSS rules so
Biome's CSS linter accepts Tailwind directives; also rename the animation
identifier `@keyframes` chatMessageEnter to kebab-case `@keyframes`
chat-message-enter (and update any references to that animation) to satisfy
naming conventions.

In `@kits/assistant/medical-assistant/app/page.tsx`:
- Around line 169-247: The sidebar remains mounted and keyboard-focusable when
collapsed; change the rendering so the <aside> is only mounted when sidebarOpen
is true (e.g., wrap the aside JSX with a conditional check on the sidebarOpen
state) to remove hidden focus targets, and ensure any handlers that reference
sessions, createNewSession, setActiveSessionId, or activeSessionId still work
when the sidebar mounts/unmounts.

In `@kits/assistant/medical-assistant/flows/medical-assistant-chat/README.md`:
- Around line 23-28: The Output Schema table is malformed: the row with `query`
has four cells while the header defines three and it incorrectly documents the
input instead of the LLM response; update the table so header and all rows have
the same three columns (Field, Type, Description) and replace the `query` row
with the actual output field name from the Lamatic flow (e.g., `response` or
whatever the flow uses), its type (e.g., `string`), and a concise description of
the model's reply; verify the exact output field name in the
medical-assistant-chat flow configuration and use that identifier in the `Field`
column.

In `@kits/assistant/medical-assistant/lib/lamatic-client.ts`:
- Around line 10-19: The validation currently requires config.api.endpoint,
config.api.projectId and config.api.apiKey but lamaticClient instantiation uses
a nullable fallback for projectId; pick one behavior and make them consistent:
if projectId is required, remove the "?? null" fallback in Lamatic construction
and pass config.api.projectId (non-null) directly to new Lamatic, ensuring types
match; alternatively, if projectId should be optional, remove projectId from the
initial throw check and document/handle its absence before creating
lamaticClient (adjust the validation block and the instantiation of
lamaticClient accordingly). Reference: the validation block checking
config.api?.endpoint/config.api?.projectId/config.api?.apiKey and the exported
lamaticClient = new Lamatic({...}) lines.

In `@kits/assistant/medical-assistant/package.json`:
- Line 19: The package.json currently lists an unavailable dependency version
"lamatic": "^0.3.2"; update the dependency entry for "lamatic" to a published
version such as "lamatic": "^0.3.1" (or "0.3.1") so the dependency resolves
correctly when installing.

---

Nitpick comments:
In `@kits/assistant/medical-assistant/.env.example`:
- Around line 1-4: Remove the spaces around the equals signs in the environment
variable declarations for MEDICAL_ASSISTANT_CHAT, LAMATIC_API_URL,
LAMATIC_PROJECT_ID, and LAMATIC_API_KEY so each line follows KEY=value format
(no surrounding spaces) and update the placeholder values to match the README's
placeholder style for consistency.

In `@kits/assistant/medical-assistant/actions/orchestrate.ts`:
- Around line 6-14: In sendMedicalQuery add server-side guardrails: trim the
incoming query and if it's empty return { success: false, error: "empty query" }
without calling downstream providers; if query.length exceeds a defined
MAX_QUERY_LENGTH constant (e.g., MAX_QUERY_LENGTH = 2000) log the event and
return { success: false, error: "query too long" }; use the existing
console/logging pattern (console.log or processLogger) to record rejected
queries and ensure all early returns match the function's
Promise<{success:boolean, data?:any, error?:string}> shape so no provider/client
calls happen for invalid input.

In `@kits/assistant/medical-assistant/app/page.tsx`:
- Around line 416-420: The copy control is hidden via opacity unless hovered;
make it discoverable to keyboard users by adding focus/focus-visible styles and
ensuring it's focusable: update the element using className (the element that
currently has "absolute top-2 opacity-0 group-hover:opacity-100 ...") to include
"focus-visible:opacity-100" (and/or "focus:opacity-100") and a visible focus
outline class (e.g., "focus-visible:outline" or similar), and if the element is
not already a native button ensure it has tabIndex={0} and keyboard handlers;
keep the existing aria-label logic (aria-label={copiedId === msg.id ? "Copied" :
"Copy response"}) and reference copiedId and msg.id as-is.

In `@kits/assistant/medical-assistant/package.json`:
- Line 16: The package.json currently lists "autoprefixer" in dependencies; move
it to devDependencies by removing the "autoprefixer" entry from the top-level
"dependencies" object and adding the same version string under "devDependencies"
so it is installed only in development/build environments; update any
package-lock or yarn.lock by reinstalling deps if needed to reflect the change.

In `@kits/assistant/medical-assistant/tsconfig.json`:
- Around line 11-13: The tsconfig currently has "strict": false while
individually enabling "strictNullChecks" and "noImplicitAny"; change to enable
full strict mode by setting "strict": true and remove or keep the individual
flags for clarity (they become redundant) so that all strict checks (e.g.,
strictBindCallApply, strictFunctionTypes, strictPropertyInitialization) are
enforced; update the JSON entry for the "strict" compiler option and ensure the
"strictNullChecks" and "noImplicitAny" lines are consistent with that change.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 994954e and c3e4f3a.

⛔ Files ignored due to path filters (1)
  • kits/assistant/medical-assistant/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • kits/assistant/medical-assistant/.env.example
  • kits/assistant/medical-assistant/.gitignore
  • kits/assistant/medical-assistant/README.md
  • kits/assistant/medical-assistant/actions/orchestrate.ts
  • kits/assistant/medical-assistant/app/globals.css
  • kits/assistant/medical-assistant/app/layout.tsx
  • kits/assistant/medical-assistant/app/page.tsx
  • kits/assistant/medical-assistant/components.json
  • kits/assistant/medical-assistant/components/disclaimer.tsx
  • kits/assistant/medical-assistant/config.json
  • kits/assistant/medical-assistant/flows/medical-assistant-chat/README.md
  • kits/assistant/medical-assistant/flows/medical-assistant-chat/config.json
  • kits/assistant/medical-assistant/flows/medical-assistant-chat/inputs.json
  • kits/assistant/medical-assistant/flows/medical-assistant-chat/meta.json
  • kits/assistant/medical-assistant/lib/lamatic-client.ts
  • kits/assistant/medical-assistant/lib/utils.ts
  • kits/assistant/medical-assistant/next.config.mjs
  • kits/assistant/medical-assistant/orchestrate.js
  • kits/assistant/medical-assistant/package.json
  • kits/assistant/medical-assistant/postcss.config.cjs
  • kits/assistant/medical-assistant/tailwind.config.ts
  • kits/assistant/medical-assistant/tsconfig.json

Comment on lines +56 to +60
console.log("[medical-assistant] Async response, polling with requestId:", requestId)

const asyncResult = await lamaticClient.checkStatus(requestId, 2, 60)
console.log("[medical-assistant] Async poll result:", asyncResult)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid logging raw workflow payloads/errors in a medical context.

Line [59] logs full asyncResult and Line [93] logs raw error. These can include user medical content or provider internals and should be sanitized.

🔒 Suggested logging hardening
-      console.log("[medical-assistant] Async poll result:", asyncResult)
+      console.log("[medical-assistant] Async poll status:", asyncResult?.status)

@@
-    console.error("[medical-assistant] Query error:", error)
+    const safeError =
+      error instanceof Error ? { name: error.name, message: error.message } : { message: "Unknown error" }
+    console.error("[medical-assistant] Query error:", safeError)

Also applies to: 93-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/actions/orchestrate.ts` around lines 56 -
60, Replace raw payload logging in orchestrate.ts by removing verbose prints of
asyncResult and error; instead log only non-sensitive metadata (e.g., requestId,
status code, duration, and a redacted/summary message). Specifically update the
console.log calls around lamaticClient.checkStatus (where requestId and
asyncResult are logged) and the catch/log that prints error to redact or
stringify only safe fields (avoid user medical content or provider internals)
and add a correlation id if available; keep the detailed payloads available only
for secure debug endpoints or structured logs behind a privacy guard.

Comment on lines +3 to +5
@plugin "@tailwindcss/typography";

@custom-variant dark (&:is(.dark *));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Tailwind directives used in globals.css"
rg -n '@plugin|@custom-variant|@theme|@apply' kits/assistant/medical-assistant/app/globals.css

echo
echo "2) Lint config files"
fd -HI '(^|/)(\.stylelintrc(\..+)?|stylelint\.config\.(js|cjs|mjs|json|yaml|yml)|biome\.jsonc?|biome\.json)$' .

CONFIGS="$(fd -HI '(^|/)(\.stylelintrc(\..+)?|stylelint\.config\.(js|cjs|mjs|json|yaml|yml)|biome\.jsonc?|biome\.json)$' .)"
if [ -n "$CONFIGS" ]; then
  echo
  echo "3) Relevant parser/rule entries"
  rg -n 'at-rule-no-unknown|ignoreAtRules|keyframes-name-pattern|tailwind|css' $CONFIGS
fi

Repository: Lamatic/AgentKit

Length of output: 567


🏁 Script executed:

# Also check the full globals.css file to see the extent of the issues
wc -l kits/assistant/medical-assistant/app/globals.css

Repository: Lamatic/AgentKit

Length of output: 112


🏁 Script executed:

# Read the globals.css file to understand the full context
cat -n kits/assistant/medical-assistant/app/globals.css

Repository: Lamatic/AgentKit

Length of output: 6935


🏁 Script executed:

# Check the actual stylelint and biome configuration content
cat -n .stylelintrc.json

Repository: Lamatic/AgentKit

Length of output: 1276


🏁 Script executed:

cat -n biome.json

Repository: Lamatic/AgentKit

Length of output: 2345


Configure linting tools to support Tailwind v4 syntax.

Stylelint and Biome are configured but neither supports Tailwind v4 at-rules (@plugin, @custom-variant, @theme, @apply). This will cause CI failures.

Update .stylelintrc.json to allow these directives:

{
  "extends": ["stylelint-config-standard-scss"],
  "rules": {
    "at-rule-no-unknown": [
      true,
      {
        "ignoreAtRules": [
          "plugin",
          "custom-variant",
          "theme",
          "layer",
          "apply",
          "import",
          "tailwind"
        ]
      }
    ]
    // ... existing rules
  }
}

Configure Biome's CSS linter for Tailwind in biome.json (lines 60-67) by adding Tailwind parser support or disabling conflicting CSS rules.

Also, rename @keyframes chatMessageEnter (line 129) to @keyframes chat-message-enter to follow kebab-case convention.

🧰 Tools
🪛 Biome (2.4.4)

[error] 3-3: Tailwind-specific syntax is disabled.

(parse)


[error] 5-5: Tailwind-specific syntax is disabled.

(parse)

🪛 Stylelint (17.3.0)

[error] 3-3: Unexpected unknown at-rule "@plugin" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)


[error] 5-5: Unexpected unknown at-rule "@custom-variant" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/app/globals.css` around lines 3 - 5, Linting
fails because Tailwind v4 at-rules like `@plugin` and `@custom-variant` (and others:
`@theme`, `@apply`, `@layer`, `@import`, `@tailwind`) are not allowed by current CSS
linters; update .stylelintrc.json to add these directives to the "ignoreAtRules"
list for the "at-rule-no-unknown" rule, and update biome.json to enable Tailwind
CSS parsing or disable conflicting CSS rules so Biome's CSS linter accepts
Tailwind directives; also rename the animation identifier `@keyframes`
chatMessageEnter to kebab-case `@keyframes` chat-message-enter (and update any
references to that animation) to satisfy naming conventions.

Comment on lines +169 to +247
<aside
className={`${sidebarOpen ? "w-72" : "w-0"
} transition-all duration-300 flex flex-col overflow-hidden flex-shrink-0`}
style={{ background: '#fff', borderRight: sidebarOpen ? '1px solid #e2e8f0' : 'none' }}
>
{/* Brand */}
<div className="h-14 flex items-center gap-2 px-5 flex-shrink-0" style={{ borderBottom: '1px solid #f1f5f9' }}>
<Stethoscope className="w-5 h-5" style={{ color: '#f43f5e' }} />
<span className="text-lg font-bold tracking-tight whitespace-nowrap">
<span style={{ color: '#0f172a' }}>Medical</span>{" "}
<span style={{ color: '#f43f5e' }}>Assistant</span>
</span>
</div>

{/* New Session */}
<div className="p-3 flex-shrink-0">
<button
onClick={createNewSession}
className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-colors shadow-sm"
style={{ background: '#f43f5e', color: '#fff' }}
onMouseEnter={(e) => (e.currentTarget.style.background = '#e11d48')}
onMouseLeave={(e) => (e.currentTarget.style.background = '#f43f5e')}
>
<Plus className="w-4 h-4" />
New Session
</button>
</div>

{/* Session List */}
<div className="flex-1 overflow-y-auto px-3 pb-3">
<div className="flex flex-col gap-1">
{sessions.length === 0 ? (
<p className="text-center py-8 text-sm" style={{ color: '#94a3b8' }}>No sessions yet</p>
) : (
sessions.map((session) => (
<button
key={session.id}
onClick={() => setActiveSessionId(session.id)}
className="w-full text-left px-3 py-2.5 rounded-lg text-sm transition-colors flex items-center gap-2.5"
style={{
background: session.id === activeSessionId ? '#f1f5f9' : 'transparent',
color: session.id === activeSessionId ? '#0f172a' : '#475569',
fontWeight: session.id === activeSessionId ? 500 : 400,
}}
>
<MessageSquare className="w-4 h-4 flex-shrink-0" />
<span className="truncate">{session.title}</span>
</button>
))
)}
</div>
</div>

{/* Sidebar Footer Links */}
<div className="p-3 flex-shrink-0" style={{ borderTop: '1px solid #f1f5f9' }}>
<div className="flex flex-col gap-1">
<Link
href="https://lamatic.ai/docs"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors"
style={{ color: '#475569' }}
>
<FileText className="w-4 h-4" style={{ color: '#94a3b8' }} />
Documentation
</Link>
<Link
href="https://github.com/Lamatic/AgentKit"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors"
style={{ color: '#475569' }}
>
<Github className="w-4 h-4" style={{ color: '#94a3b8' }} />
GitHub
</Link>
</div>
</div>
</aside>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Collapsed sidebar stays in tab order while visually hidden.

When sidebarOpen is false, the sidebar content is still mounted and can remain keyboard-focusable, creating hidden focus targets.

♿ Suggested fix (render sidebar only when open)
-            <aside
-                className={`${sidebarOpen ? "w-72" : "w-0"
-                    } transition-all duration-300 flex flex-col overflow-hidden flex-shrink-0`}
-                style={{ background: '#fff', borderRight: sidebarOpen ? '1px solid `#e2e8f0`' : 'none' }}
-            >
+            {sidebarOpen && (
+            <aside
+                className="w-72 transition-all duration-300 flex flex-col overflow-hidden flex-shrink-0"
+                style={{ background: '#fff', borderRight: '1px solid `#e2e8f0`' }}
+            >
@@
-            </aside>
+            </aside>
+            )}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<aside
className={`${sidebarOpen ? "w-72" : "w-0"
} transition-all duration-300 flex flex-col overflow-hidden flex-shrink-0`}
style={{ background: '#fff', borderRight: sidebarOpen ? '1px solid #e2e8f0' : 'none' }}
>
{/* Brand */}
<div className="h-14 flex items-center gap-2 px-5 flex-shrink-0" style={{ borderBottom: '1px solid #f1f5f9' }}>
<Stethoscope className="w-5 h-5" style={{ color: '#f43f5e' }} />
<span className="text-lg font-bold tracking-tight whitespace-nowrap">
<span style={{ color: '#0f172a' }}>Medical</span>{" "}
<span style={{ color: '#f43f5e' }}>Assistant</span>
</span>
</div>
{/* New Session */}
<div className="p-3 flex-shrink-0">
<button
onClick={createNewSession}
className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-colors shadow-sm"
style={{ background: '#f43f5e', color: '#fff' }}
onMouseEnter={(e) => (e.currentTarget.style.background = '#e11d48')}
onMouseLeave={(e) => (e.currentTarget.style.background = '#f43f5e')}
>
<Plus className="w-4 h-4" />
New Session
</button>
</div>
{/* Session List */}
<div className="flex-1 overflow-y-auto px-3 pb-3">
<div className="flex flex-col gap-1">
{sessions.length === 0 ? (
<p className="text-center py-8 text-sm" style={{ color: '#94a3b8' }}>No sessions yet</p>
) : (
sessions.map((session) => (
<button
key={session.id}
onClick={() => setActiveSessionId(session.id)}
className="w-full text-left px-3 py-2.5 rounded-lg text-sm transition-colors flex items-center gap-2.5"
style={{
background: session.id === activeSessionId ? '#f1f5f9' : 'transparent',
color: session.id === activeSessionId ? '#0f172a' : '#475569',
fontWeight: session.id === activeSessionId ? 500 : 400,
}}
>
<MessageSquare className="w-4 h-4 flex-shrink-0" />
<span className="truncate">{session.title}</span>
</button>
))
)}
</div>
</div>
{/* Sidebar Footer Links */}
<div className="p-3 flex-shrink-0" style={{ borderTop: '1px solid #f1f5f9' }}>
<div className="flex flex-col gap-1">
<Link
href="https://lamatic.ai/docs"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors"
style={{ color: '#475569' }}
>
<FileText className="w-4 h-4" style={{ color: '#94a3b8' }} />
Documentation
</Link>
<Link
href="https://github.com/Lamatic/AgentKit"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors"
style={{ color: '#475569' }}
>
<Github className="w-4 h-4" style={{ color: '#94a3b8' }} />
GitHub
</Link>
</div>
</div>
</aside>
{sidebarOpen && (
<aside
className="w-72 transition-all duration-300 flex flex-col overflow-hidden flex-shrink-0"
style={{ background: '#fff', borderRight: '1px solid `#e2e8f0`' }}
>
{/* Brand */}
<div className="h-14 flex items-center gap-2 px-5 flex-shrink-0" style={{ borderBottom: '1px solid `#f1f5f9`' }}>
<Stethoscope className="w-5 h-5" style={{ color: '#f43f5e' }} />
<span className="text-lg font-bold tracking-tight whitespace-nowrap">
<span style={{ color: '#0f172a' }}>Medical</span>{" "}
<span style={{ color: '#f43f5e' }}>Assistant</span>
</span>
</div>
{/* New Session */}
<div className="p-3 flex-shrink-0">
<button
onClick={createNewSession}
className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-colors shadow-sm"
style={{ background: '#f43f5e', color: '#fff' }}
onMouseEnter={(e) => (e.currentTarget.style.background = '#e11d48')}
onMouseLeave={(e) => (e.currentTarget.style.background = '#f43f5e')}
>
<Plus className="w-4 h-4" />
New Session
</button>
</div>
{/* Session List */}
<div className="flex-1 overflow-y-auto px-3 pb-3">
<div className="flex flex-col gap-1">
{sessions.length === 0 ? (
<p className="text-center py-8 text-sm" style={{ color: '#94a3b8' }}>No sessions yet</p>
) : (
sessions.map((session) => (
<button
key={session.id}
onClick={() => setActiveSessionId(session.id)}
className="w-full text-left px-3 py-2.5 rounded-lg text-sm transition-colors flex items-center gap-2.5"
style={{
background: session.id === activeSessionId ? '#f1f5f9' : 'transparent',
color: session.id === activeSessionId ? '#0f172a' : '#475569',
fontWeight: session.id === activeSessionId ? 500 : 400,
}}
>
<MessageSquare className="w-4 h-4 flex-shrink-0" />
<span className="truncate">{session.title}</span>
</button>
))
)}
</div>
</div>
{/* Sidebar Footer Links */}
<div className="p-3 flex-shrink-0" style={{ borderTop: '1px solid `#f1f5f9`' }}>
<div className="flex flex-col gap-1">
<Link
href="https://lamatic.ai/docs"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors"
style={{ color: '#475569' }}
>
<FileText className="w-4 h-4" style={{ color: '#94a3b8' }} />
Documentation
</Link>
<Link
href="https://github.com/Lamatic/AgentKit"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors"
style={{ color: '#475569' }}
>
<Github className="w-4 h-4" style={{ color: '#94a3b8' }} />
GitHub
</Link>
</div>
</div>
</aside>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/app/page.tsx` around lines 169 - 247, The
sidebar remains mounted and keyboard-focusable when collapsed; change the
rendering so the <aside> is only mounted when sidebarOpen is true (e.g., wrap
the aside JSX with a conditional check on the sidebarOpen state) to remove
hidden focus targets, and ensure any handlers that reference sessions,
createNewSession, setActiveSessionId, or activeSessionId still work when the
sidebar mounts/unmounts.

Comment on lines +23 to +28
## Output Schema

| Field | Type | Description |
| -------- | -------- | ----------------------------------------------------- |
| `query` | `string` | Max 1000 chars, sanitized for safety | The user's medical question or symptom description |

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix malformed table in Output Schema section.

Line 27 has 4 cells but the table header defines only 3 columns, causing rendering issues. Additionally, the output schema appears to duplicate the input field (query) rather than documenting the actual LLM response output.

📝 Proposed fix
 ## Output Schema

 | Field    | Type     | Description                                           |
 | -------- | -------- | ----------------------------------------------------- |
-| `query` | `string` | Max 1000 chars, sanitized for safety | The user's medical question or symptom description |
+| `response` | `string` | The LLM-generated medical information response |

Please verify the actual output field name from your Lamatic flow configuration.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Output Schema
| Field | Type | Description |
| -------- | -------- | ----------------------------------------------------- |
| `query` | `string` | Max 1000 chars, sanitized for safety | The user's medical question or symptom description |
## Output Schema
| Field | Type | Description |
| -------- | -------- | ----------------------------------------------------- |
| `response` | `string` | The LLM-generated medical information response |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/assistant/medical-assistant/flows/medical-assistant-chat/README.md`
around lines 23 - 28, The Output Schema table is malformed: the row with `query`
has four cells while the header defines three and it incorrectly documents the
input instead of the LLM response; update the table so header and all rows have
the same three columns (Field, Type, Description) and replace the `query` row
with the actual output field name from the Lamatic flow (e.g., `response` or
whatever the flow uses), its type (e.g., `string`), and a concise description of
the model's reply; verify the exact output field name in the
medical-assistant-chat flow configuration and use that identifier in the `Field`
column.

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.

1 participant