Simplify databunny api.#92
Conversation
|
@sbansal1999 is attempting to deploy a commit to the Databuddy Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughRefactors assistant request shape to use a messages array and camelCased websiteId/websiteHostname, replaces unified prompt with a system prompt, updates AI client/processor flow to use getAICompletion, renames prompt export, defaults chart handler chartType to 'bar', and updates dashboard streaming payload and icon names; minor layout spacing change. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Dashboard as Dashboard (use-chat)
participant API as API /v1/assistant/stream
participant Processor
participant AIClient as AI Client
participant LLM as AI Model
participant Handlers as Metric/Chart Handlers
User->>Dashboard: Type message
Dashboard->>API: POST { messages[], websiteId, model }
API->>Processor: AssistantRequest { messages, websiteId, websiteHostname, model }
Processor->>AIClient: getAICompletion(request)
AIClient->>AIClient: Build system prompt (comprehensiveSystemPrompt)
AIClient->>LLM: messages = [system, ...request.messages]
LLM-->>AIClient: aiResponse
AIClient-->>Processor: content + meta
Processor->>Processor: Parse response_type
alt text
Processor-->>API: stream text response
else metric
Processor->>Handlers: handleMetricResponse
Handlers-->>Processor: metric result
Processor-->>API: stream metric response
else chart
Processor->>Handlers: handleChartResponse(sql, timing)
Handlers-->>Processor: chart result
Processor-->>API: stream chart response
else invalid
Processor-->>API: error response
end
API-->>Dashboard: SSE stream
Dashboard-->>User: Render assistant reply
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 7
🔭 Outside diff range comments (1)
apps/api/src/agent/handlers/chart-handler.ts (1)
67-76: Align completion message with the defaulted chartType to avoid user-facing mismatchWhen chart_type is absent, data.chartType defaults to 'bar', but the completion message falls back to 'chart'. This can confuse users. Compute a single resolved chart type and use it consistently in both places.
Apply this diff:
yield { type: 'complete', - content: - queryResult.data.length > 0 - ? `Found ${queryResult.data.length} data points. Displaying as a ${parsedAiJson.chart_type ? parsedAiJson.chart_type.replace(/_/g, ' ') : 'chart'}.` - : getRandomMessage(noDataMessages), + // Use a single resolved chart type for message and payload + content: (() => { + const resolvedChartType = + (parsedAiJson.chart_type?.trim() as string | undefined) || 'bar'; + return queryResult.data.length > 0 + ? `Found ${queryResult.data.length} data points. Displaying as a ${resolvedChartType.replace(/_/g, ' ')}.` + : getRandomMessage(noDataMessages); + })(), data: { hasVisualization: queryResult.data.length > 0, - chartType: parsedAiJson.chart_type || 'bar', + chartType: + (parsedAiJson.chart_type?.trim() as string | undefined) || 'bar', data: queryResult.data, responseType: 'chart', },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
apps/api/src/agent/handlers/chart-handler.ts(1 hunks)apps/api/src/agent/index.ts(1 hunks)apps/api/src/agent/processor.ts(3 hunks)apps/api/src/agent/prompts/agent.ts(2 hunks)apps/api/src/agent/utils/ai-client.ts(2 hunks)apps/api/src/routes/assistant.ts(2 hunks)apps/api/src/schemas/assistant-schemas.ts(1 hunks)apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsx(1 hunks)apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx(8 hunks)apps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{jsx,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't pass children as props.
Don't use the return value of React.render.
Make sure all dependencies are correctly specified in React hooks.
Make sure all React hooks are called from the top level of component functions.
Don't forget key props in iterators and collection literals.
Don't destructure props inside JSX components in Solid projects.
Don't define React components inside other components.
Don't use event handlers on non-interactive elements.
Don't assign to React component props.
Don't use both children and dangerouslySetInnerHTML props on the same element.
Don't use dangerous JSX props.
Don't use Array index in keys.
Don't insert comments as text nodes.
Don't assign JSX properties multiple times.
Don't add extra closing tags for components without children.
Use <>...</> instead of ....
Watch out for possible "wrong" semicolons inside JSX elements.
Don't use accessKey attribute on any HTML element.
Don't set aria-hidden="true" on focusable elements.
Don't add ARIA roles, states, and properties to elements that don't support them.
Don't use distracting elements like or .
Only use the scope prop on elements.
Don't assign non-interactive ARIA roles to interactive HTML elements.
Make sure label elements have text content and are associated with an input.
Don't assign interactive ARIA roles to non-interactive HTML elements.
Don't assign tabIndex to non-interactive HTML elements.
Don't use positive integers for tabIndex property.
Don't include "image", "picture", or "photo" in img alt prop.
Don't use explicit role property that's the same as the implicit/default role.
Make static elements with click handlers use a valid role attribute.
Always include a title element for SVG elements.
Give all elements requiring alt text meaningful information for screen readers.
Make sure anchors have content that's accessible ...Files:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx**/*.{js,ts,jsx,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,ts,jsx,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't use global eval().
Don't use var.
Don't use console.
Don't use debugger.
Don't assign directly to document.cookie.
Don't use duplicate case labels.
Don't use duplicate class members.
Don't use duplicate function parameter names.
Don't use empty block statements and static blocks.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Use for...of statements instead of Array.forEach.
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names that aren't base 10 or use underscore separators.
Remove redundant terms from logical expressions.
Use while loops instead of for loops when you don't need initializer and update expressions.
Don't reassign const variables.
Don't use constant expressions in conditions.
Don't use Math.min and Math.max to clamp values when the result is constant.
Don't return a value from a constructor.
Don't use empty character classes in regular expression literals.
Don't use empty destructuring patterns.
Don't call global object properties as functions.
Don't declare functions and vars that are accessible outside their block.
Don't use variables and function parameters before they're declared.
Don't use 8 and 9 escape sequences in string literals.
Don't use literal numbers that lose precision.
Don't use duplicate conditions in if-else-if chains.
Don't use two keys with the same name inside objects...Files:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsxapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use TypeScript namespaces.
Don't use the TypeScript directive @ts-ignore.
Don't use any type.
Don't use implicit any type on variable declarations.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't declare empty interfaces.
Use export type for types.
Use import type for types.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
**/*.{ts,tsx}: Ensure TypeScript type-safety; avoidanyunless absolutely necessary
Create proper interfaces/types for APIs, responses, and components; place them in shared types folders rather than in the same fileFiles:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsxapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
**/*.{js,jsx,ts,tsx}: Usebun <file>instead ofnode <file>orts-node <file>
Do not use dotenv; Bun automatically loads .env files
Do not useexpress; useBun.serve()for HTTP servers
Do not usebetter-sqlite3; usebun:sqlitefor SQLite
Do not useioredis; useBun.redisfor Redis
Do not usepgorpostgres.js; useBun.sqlfor Postgres
Do not usews; use built-inWebSocket
PreferBun.fileovernode:fs's readFile/writeFile
UseBun.$instead of execa for running shell commandsFiles:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsxapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts**/*.{tsx,jsx}
📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)
**/*.{tsx,jsx}: In Tailwind CSS usage, useroundedonly; do not userounded-mdorrounded-xl
Use Phosphor icons, not Lucide; default to weight="duotone", use fill for arrows, and for plus icons do not set weight
In view components, decouple state management, data transformations, and API interactions from the React lifecycle
Simplify data flow in components to avoid prop drilling and callback chains
Prioritize modularity and testability in all React components
Use React Error Boundaries appropriately
Avoid useEffect in React unless it is truly criticalFiles:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)
**/*.{ts,tsx,js,jsx}: Use console methods appropriately (e.g., console.error, console.time, console.table, console.json)
Use Dayjs instead of date-fns
Use TanStack Query for hooks; do not use SWR
When adding debugging, use JSON.stringify() for structured outputFiles:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsxapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts**/*.{tsx,jsx,ts,js}
📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)
When using Phosphor React icons, append 'Icon' to component names (e.g., CaretIcon, not Caret)
Files:
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsxapps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsxapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts**/*.{js,ts}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,ts}: Make sure to use the "use strict" directive in script files.
Don't have redundant "use strict".
Make sure to use the "use strict" directive in script files.Files:
apps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts**/*.{html,ts,css}
📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
Use
bun build <file.html|file.ts|file.css>instead ofwebpackoresbuildFiles:
apps/api/src/agent/index.tsapps/api/src/agent/handlers/chart-handler.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/processor.tsapps/api/src/agent/prompts/agent.ts🧠 Learnings (2)
📚 Learning: 2025-08-11T10:37:28.419Z
Learnt from: CR PR: databuddy-analytics/Databuddy#0 File: .cursor/rules/01-MUST-DO.mdc:0-0 Timestamp: 2025-08-11T10:37:28.419Z Learning: Applies to **/*.{tsx,jsx,ts,js} : When using Phosphor React icons, append 'Icon' to component names (e.g., CaretIcon, not Caret)Applied to files:
apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx📚 Learning: 2025-08-11T10:37:28.419Z
Learnt from: CR PR: databuddy-analytics/Databuddy#0 File: .cursor/rules/01-MUST-DO.mdc:0-0 Timestamp: 2025-08-11T10:37:28.419Z Learning: Applies to **/*.{tsx,jsx} : Use Phosphor icons, not Lucide; default to weight="duotone", use fill for arrows, and for plus icons do not set weightApplied to files:
apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx🧬 Code Graph Analysis (5)
apps/api/src/routes/assistant.ts (1)
apps/api/src/lib/website-utils.ts (1)
validateWebsite(196-206)apps/api/src/schemas/assistant-schemas.ts (1)
packages/rpc/src/trpc.ts (1)
t(27-32)apps/api/src/agent/utils/ai-client.ts (2)
apps/api/src/agent/processor.ts (1)
AssistantRequest(26-28)apps/api/src/agent/prompts/agent.ts (1)
comprehensiveSystemPrompt(45-636)apps/api/src/agent/processor.ts (3)
apps/api/src/agent/index.ts (2)
AssistantRequest(5-5)getAICompletion(12-12)apps/api/src/schemas/assistant-schemas.ts (1)
AssistantRequestType(16-16)apps/api/src/agent/utils/ai-client.ts (1)
getAICompletion(26-74)apps/api/src/agent/prompts/agent.ts (2)
apps/api/src/agent/index.ts (1)
comprehensiveSystemPrompt(10-10)apps/api/src/schemas/assistant-schemas.ts (1)
AssistantRequestType(16-16)🔇 Additional comments (9)
apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsx (1)
917-917: Confirm layout spacing remains consistent
Removing the top padding (pt-6) can cause the overview tab’s content to shift upward. Please verify:
- There’s no overlap with any sticky headers or navigation bars
- Vertical spacing still matches sibling tabs across all breakpoints
apps/api/src/routes/assistant.ts (1)
48-51: No fallback needed:website.domainis non-nullable
The sharedWebsitetype definesdomain: string(non-optional), and our database model enforces a non-null value. Thereforewebsite.domaincan’t beundefined, so the existing code is safe as-is.apps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.ts (1)
185-197: Messages-based payload construction is correct; aligns with backend schemaGood switch to a unified messages array and camel-cased websiteId. Appending the current user message explicitly avoids the stale-state duplication pitfall since
messagesis the pre-send snapshot.
- Please confirm the server route expects camelCase
websiteIdin the JSON body (and notwebsite_id) and does not requirewebsiteHostnamefrom the client. If it does, we should include it here as well.- Also consider guarding against empty
websiteIdbefore sending to avoid avoidable 4xx responses.If you want, I can add a small guard that early-returns with a user-friendly message when
websiteIdis missing.apps/api/src/agent/utils/ai-client.ts (1)
31-36: System prompt integration LGTMInjecting a single system message in front of the chat history matches the new flow and keeps the request lean. Keeping temperature fixed at 0.1 is fine for determinism.
apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx (2)
4-13: Icon import renames comply with project conventionSwitching to Icon-suffixed Phosphor components matches the repository’s guideline and prior learnings.
101-111: Quick questions UI update LGTMThe quick actions reference the updated Icon variants and remain accessible, keyed, and guarded by rate-limit/loading states.
apps/api/src/agent/prompts/agent.ts (1)
2-2: Type import is appropriateTying the prompt generator’s optional
_modelparam toAssistantRequestType['model']keeps it aligned with schema changes.apps/api/src/agent/processor.ts (2)
26-28: AssistantRequest interface extension looks goodExtending the schema type and adding
websiteHostnamehere keeps the contract centralized and consistent for downstream consumers.
59-60: Verified AssistantRequest construction & chart defaulting
- In apps/api/src/routes/assistant.ts, the POST /stream handler builds the
AssistantRequestwith
• messages
• websiteId
• websiteHostname:website.domain
• model (defaulting to'chat')- In apps/api/src/agent/handlers/chart-handler.ts,
chartTypefalls back to'bar'whenparsedAiJson.chart_typeis falsy.No changes required—approving as-is.
| export const comprehensiveSystemPrompt = ( | ||
| websiteId: string, | ||
| websiteHostname: string, | ||
| mode: 'analysis_only' | 'execute_chat' | 'execute_agent_step', | ||
| previousMessages?: Array<{ role: string; content: string }>, | ||
| agentToolResult?: Record<string, unknown>, | ||
| _model?: 'chat' | 'agent' | 'agent-max' | ||
| _model?: AssistantRequestType['model'] | ||
| ) => ` |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Prompt still references <user_query> and includes invalid ClickHouse INTERVAL examples—please fix
- The new flow no longer supplies
<user_query>; the prompt should instruct the model to use “the latest user message in the provided messages” instead of<user_query>. - Several SQL examples use Postgres-like INTERVAL literals (e.g.,
INTERVAL '7' DAY). ClickHouse syntax isINTERVAL 7 DAY(numeric, no quotes). This will lead to invalid queries if the model copies these patterns. There’s also aQUALIFYusage in an example that ClickHouse doesn’t support—prefer subqueries or window + WHERE/HAVING alternatives.
Suggested changes:
- Replace occurrences of “process the <user_query>” with “process the latest user message in the conversation”.
- Fix INTERVAL literals:
'7' DAY→7 DAY,'30' DAY→30 DAY, etc. - Replace
QUALIFYexamples with ClickHouse-compatible patterns (CTEs or nested subqueries with ROW_NUMBER() in a subquery and filter in outer SELECT).
Additionally, to enforce correctness at the schema level (and reduce reliance on defaults), consider switching to Zod discriminated unions so chart responses must include a chart type:
// Outside this hunk: refactor AIResponseJsonSchema to a discriminated union
const Base = z.object({
sql: z.string().nullable().optional(),
thinking_steps: z.array(z.string()).optional(),
});
const TextResp = Base.extend({
response_type: z.literal('text'),
text_response: z.string().nullable().optional(),
chart_type: z.null().optional(),
});
const MetricResp = Base.extend({
response_type: z.literal('metric'),
metric_value: z.string(),
metric_label: z.string().nullable().optional(),
text_response: z.string().nullable().optional(),
chart_type: z.null().optional(),
});
const ChartResp = Base.extend({
response_type: z.literal('chart'),
sql: z.string(), // require SQL for charts
chart_type: z.enum([/* …all chart types… */]).default('bar'), // enforce presence with default
text_response: z.string().nullable().optional(),
});
export const AIResponseJsonSchema = z.discriminatedUnion('response_type', [
TextResp, MetricResp, ChartResp,
]);This aligns with the PR note about discriminated unions and ensures the LLM output is structurally valid for each response type.
7e92487 to
77bd3ab
Compare
|
will take a look at these tomorrow, do not merge till then |
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (5)
apps/api/src/agent/handlers/chart-handler.ts (1)
71-76: Unify chartType fallback between display text and data payloadCurrently, the user-facing message falls back to "chart" while data.chartType falls back to "bar". This creates inconsistent UX and can confuse the frontend. Use the same fallback ("bar") for both.
Apply this diff:
- ? `Found ${queryResult.data.length} data points. Displaying as a ${parsedAiJson.chart_type ? parsedAiJson.chart_type.replace(/_/g, ' ') : 'chart'}.` + ? `Found ${queryResult.data.length} data points. Displaying as a ${(parsedAiJson.chart_type || 'bar').replace(/_/g, ' ')}.`Follow-up: Consider validating chart_type against a known allowlist and/or switching to a discriminated union in the schema so invalid types are rejected early.
apps/api/src/agent/utils/ai-client.ts (1)
52-57: Avoid logging full AI content (PII and log volume risk).Logging content can leak user data and balloon logs. Keep only metrics unless an admin/debug flag is set.
- console.info('🤖 [AI Client] Completion completed', { - timeTaken: `${aiTime}ms`, - contentLength: JSON.stringify(content).length, - usage: chat.usage, - content, - }); + console.info('🤖 [AI Client] Completion completed', { + timeTaken: `${aiTime}ms`, + contentLength: JSON.stringify(content).length, + usage: chat.usage, + });apps/api/src/agent/prompts/agent.ts (3)
4-34: Enforce structural validity with a discriminated union; default chart_type to 'bar' only for charts.Current schema allows incomplete/invalid combos (e.g., chart without SQL, metric without value). Move to a discriminated union and set chart_type default only on chart responses. This aligns with the PR goal and reduces downstream guard code.
-export const AIResponseJsonSchema = z.object({ - sql: z.string().nullable().optional(), - chart_type: z - .enum([ - 'bar', - 'horizontal_bar', - 'line', - 'sparkline', - 'pie', - 'donut', - 'area', - 'unstacked_area', - 'stacked_bar', - 'multi_line', - 'scatter', - 'bubble', - 'radar', - 'funnel', - 'grouped_bar', - 'histogram', - 'treemap', - 'gauge', - ]) - .nullable() - .optional(), - response_type: z.enum(['chart', 'text', 'metric']), - text_response: z.string().nullable().optional(), - metric_value: z.string().nullable().optional(), - metric_label: z.string().nullable().optional(), - thinking_steps: z.array(z.string()).optional(), -}); +const Base = z.object({ + thinking_steps: z.array(z.string()).optional(), +}); + +const TextResp = Base.extend({ + response_type: z.literal('text'), + sql: z.null().optional(), + chart_type: z.null().optional(), + text_response: z.string().nullable().optional(), + metric_value: z.null().optional(), + metric_label: z.string().nullable().optional(), +}); + +const MetricResp = Base.extend({ + response_type: z.literal('metric'), + sql: z.null().optional(), + chart_type: z.null().optional(), + metric_value: z.string(), + metric_label: z.string().nullable().optional(), + text_response: z.string().nullable().optional(), +}); + +const ChartResp = Base.extend({ + response_type: z.literal('chart'), + sql: z.string(), + chart_type: z + .enum([ + 'bar','horizontal_bar','line','sparkline','pie','donut','area', + 'unstacked_area','stacked_bar','multi_line','scatter','bubble', + 'radar','funnel','grouped_bar','histogram','treemap','gauge', + ]) + .default('bar'), + text_response: z.string().nullable().optional(), + metric_value: z.null().optional(), + metric_label: z.null().optional(), +}); + +export const AIResponseJsonSchema = z.discriminatedUnion('response_type', [ + TextResp, + MetricResp, + ChartResp, +]);
297-298: Use a valid enum value for chart_type; avoid “multi_line or stacked_bar”.The schema enumerates discrete values. Provide one (e.g., multi_line) and let the assistant choose contextually.
- <chart_type>multi_line or stacked_bar</chart_type> + <chart_type>multi_line</chart_type>
453-458: Fix reference to non-existent errors.id; use COUNT(*) instead.The declared analytics.errors schema has no id column. Counting e.id will fail.
- SELECT es.session_id, COUNT(e.id) as error_count + SELECT es.session_id, COUNT(*) as error_count
♻️ Duplicate comments (12)
apps/api/src/schemas/assistant-schemas.ts (1)
4-14: Tighten request validation: require non-empty messages, non-empty content, and disallow extra fieldsReiterating prior feedback: harden the schema to reject malformed inputs and simplify downstream assumptions.
Apply this diff:
-export const AssistantRequestSchema = t.Object({ - messages: t.Array( - t.Object({ - role: t.Union([t.Literal('user'), t.Literal('assistant')]), - content: t.String(), - }) - ), - websiteId: t.String(), - model: t.Optional( - t.Union([t.Literal('chat'), t.Literal('agent'), t.Literal('agent-max')]) - ) -}); +export const AssistantRequestSchema = t.Object( + { + messages: t.Array( + t.Object( + { + role: t.Union([t.Literal('user'), t.Literal('assistant')]), + content: t.String({ minLength: 1 }), + }, + { additionalProperties: false } + ), + { minItems: 1 } + ), + websiteId: t.String(), + model: t.Optional( + t.Union([t.Literal('chat'), t.Literal('agent'), t.Literal('agent-max')]) + ), + }, + { additionalProperties: false } +); export type AssistantRequestType = typeof AssistantRequestSchema.static;Also applies to: 16-16
apps/api/src/agent/index.ts (1)
8-11: Add backward-compatibility alias for renamed exportRenaming the public export is a breaking change for consumers. Preserve an alias temporarily.
Apply this diff:
export { AIPlanSchema, AIResponseJsonSchema, - comprehensiveSystemPrompt, + comprehensiveSystemPrompt, + // Temporary compatibility alias; remove in next major + comprehensiveSystemPrompt as comprehensiveUnifiedPrompt, } from './prompts/agent';apps/api/src/routes/assistant.ts (1)
28-33: Add a guard for empty messages to fail fast (until schema hardening lands)Reject requests with no messages array or an empty one before doing further work.
Apply this diff:
- const { messages, websiteId, model } = body; + const { messages, websiteId, model } = body; + if (!messages?.length) { + return createStreamingResponse( + createErrorResponse('At least one message is required') + ); + }apps/api/src/agent/utils/ai-client.ts (1)
41-45: Sanitize incoming roles before sending to the model (prevent client-supplied system/tool messages).You're directly spreading request.messages into the messages array. A client could inject system/tool roles and override guardrails. Filter strictly to user/assistant and map to role/content only.
Apply this diff:
- messages: [ - { role: 'system', content: systemPrompt }, - ...request.messages, - ], + messages: [ + { role: 'system', content: systemPrompt }, + ...(Array.isArray(request.messages) + ? request.messages + .filter((m) => m.role === 'user' || m.role === 'assistant') + .map((m) => ({ role: m.role, content: m.content })) + : []), + ],Optionally, validate/limit message count and size upstream to avoid token bloat.
apps/api/src/agent/prompts/agent.ts (8)
173-175: Replace <user_query> with “latest user message” to match the new messages-based flow.The prompt still references <user_query>. Update wording to avoid stale placeholders.
-Your task is to process the <user_query> according to the current <mode>, while strictly adhering to the <core_directives>. When in 'execute_chat' mode, you must consult the extensive <knowledge_base> to construct your response. +Your task is to process the latest user message in the provided conversation according to the current <mode>, while strictly adhering to the <core_directives>. When in 'execute_chat' mode, you must consult the extensive <knowledge_base> to construct your response.
204-215: Fix ClickHouse INTERVAL syntax in time rules and guidance.Use INTERVAL 7 DAY (no quotes). The current examples use Postgres-style literals and will mislead the model.
- - For "this week" or "last 7 days": use time >= today() - INTERVAL '7' DAY + - For "this week" or "last 7 days": use time >= today() - INTERVAL 7 DAY - - For "last 30 days": use time >= today() - INTERVAL '30' DAY + - For "last 30 days": use time >= today() - INTERVAL 30 DAY - - Always use proper ClickHouse date functions: today(), yesterday(), date_trunc(), INTERVAL syntax. + - Always use proper ClickHouse date functions: today(), yesterday(), date_trunc(), and correct INTERVAL syntax (no quotes).
291-291: Correct INTERVAL syntax in “Simple Time Series” example.- <sql>SELECT toDate(time) as date, COUNT(*) AS views FROM analytics.events WHERE client_id = '${websiteId}' AND event_name = 'screen_view' AND time >= today() - INTERVAL '7' DAY GROUP BY date ORDER BY date</sql> + <sql>SELECT toDate(time) as date, COUNT(*) AS views FROM analytics.events WHERE client_id = '${websiteId}' AND event_name = 'screen_view' AND time >= today() - INTERVAL 7 DAY GROUP BY date ORDER BY date</sql>
446-447: Correct INTERVAL syntax in “Error Trends Over Time”.- <sql>SELECT toDate(timestamp) as date, COUNT(*) as error_count FROM analytics.errors WHERE client_id = '${websiteId}' AND timestamp >= today() - INTERVAL '30' DAY GROUP BY date ORDER BY date</sql> + <sql>SELECT toDate(timestamp) as date, COUNT(*) as error_count FROM analytics.errors WHERE client_id = '${websiteId}' AND timestamp >= today() - INTERVAL 30 DAY GROUP BY date ORDER BY date</sql>
575-581: Fix INTERVAL syntax in metric examples (bounce rate and session duration).- <sql>WITH session_metrics AS (SELECT session_id, countIf(event_name = 'screen_view') as page_count FROM analytics.events WHERE client_id = '${websiteId}' AND time >= today() - INTERVAL '7' DAY GROUP BY session_id) SELECT (countIf(page_count = 1) / count()) * 100 AS bounce_rate FROM session_metrics</sql> + <sql>WITH session_metrics AS (SELECT session_id, countIf(event_name = 'screen_view') as page_count FROM analytics.events WHERE client_id = '${websiteId}' AND time >= today() - INTERVAL 7 DAY GROUP BY session_id) SELECT (countIf(page_count = 1) / count()) * 100 AS bounce_rate FROM session_metrics</sql> - <sql>WITH session_durations AS (SELECT session_id, dateDiff('second', MIN(time), MAX(time)) as duration FROM analytics.events WHERE client_id = '${websiteId}' AND time >= today() - INTERVAL '7' DAY GROUP BY session_id HAVING duration > 0) SELECT AVG(duration) AS avg_duration_seconds FROM session_durations</sql> + <sql>WITH session_durations AS (SELECT session_id, dateDiff('second', MIN(time), MAX(time)) as duration FROM analytics.events WHERE client_id = '${websiteId}' AND time >= today() - INTERVAL 7 DAY GROUP BY session_id HAVING duration > 0) SELECT AVG(duration) AS avg_duration_seconds FROM session_durations</sql>
595-596: Fix INTERVAL syntax in “Error Rate” metric example.- <sql>WITH total_sessions AS (SELECT uniq(session_id) as total FROM analytics.events WHERE client_id = '${websiteId}' AND time >= today() - INTERVAL '7' DAY), error_sessions AS (SELECT uniq(session_id) as error_count FROM analytics.errors WHERE client_id = '${websiteId}' AND timestamp >= today() - INTERVAL '7' DAY) SELECT (error_count / total) * 100 AS error_rate FROM error_sessions CROSS JOIN total_sessions</sql> + <sql>WITH total_sessions AS (SELECT uniq(session_id) as total FROM analytics.events WHERE client_id = '${websiteId}' AND time >= today() - INTERVAL 7 DAY), error_sessions AS (SELECT uniq(session_id) as error_count FROM analytics.errors WHERE client_id = '${websiteId}' AND timestamp >= today() - INTERVAL 7 DAY) SELECT (error_count / total) * 100 AS error_rate FROM error_sessions CROSS JOIN total_sessions</sql>
475-476: Replace QUALIFY with ClickHouse-compatible approach; simplify entry-page derivation.ClickHouse doesn't support QUALIFY. Use argMin() to get the first path by time per session.
- <sql>WITH entry_pages AS (SELECT session_id, path, MIN(time) as entry_time FROM analytics.events WHERE client_id = '${websiteId}' AND event_name = 'screen_view' GROUP BY session_id, path QUALIFY ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY entry_time) = 1), session_metrics AS (SELECT ep.path, ep.session_id, countIf(e.event_name = 'screen_view') as page_count FROM entry_pages ep LEFT JOIN analytics.events e ON ep.session_id = e.session_id WHERE e.client_id = '${websiteId}' GROUP BY ep.path, ep.session_id) SELECT path, COUNT(*) as sessions, (countIf(page_count = 1) / count()) * 100 as bounce_rate FROM session_metrics GROUP BY path HAVING sessions >= 10 ORDER BY bounce_rate DESC LIMIT 15</sql> + <sql>WITH entry_pages AS ( + SELECT session_id, argMin(path, time) AS path + FROM analytics.events + WHERE client_id = '${websiteId}' AND event_name = 'screen_view' + GROUP BY session_id + ), + session_metrics AS ( + SELECT ep.path, ep.session_id, countIf(e.event_name = 'screen_view') AS page_count + FROM entry_pages ep + LEFT JOIN analytics.events e ON ep.session_id = e.session_id + WHERE e.client_id = '${websiteId}' + GROUP BY ep.path, ep.session_id + ) + SELECT path, COUNT(*) AS sessions, (countIf(page_count = 1) / count()) * 100 AS bounce_rate + FROM session_metrics + GROUP BY path + HAVING sessions >= 10 + ORDER BY bounce_rate DESC + LIMIT 15</sql>
503-504: Remove QUALIFY in “Performance Correlation” subquery; use argMin() per session.- SELECT session_id, path, MIN(time) as entry_time - FROM analytics.events - WHERE client_id = '${websiteId}' AND event_name = 'screen_view' - GROUP BY session_id, path - QUALIFY ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY entry_time) = 1 + SELECT session_id, argMin(path, time) as path + FROM analytics.events + WHERE client_id = '${websiteId}' AND event_name = 'screen_view' + GROUP BY session_id
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
apps/api/src/agent/handlers/chart-handler.ts(1 hunks)apps/api/src/agent/index.ts(1 hunks)apps/api/src/agent/processor.ts(3 hunks)apps/api/src/agent/prompts/agent.ts(2 hunks)apps/api/src/agent/utils/ai-client.ts(2 hunks)apps/api/src/routes/assistant.ts(2 hunks)apps/api/src/schemas/assistant-schemas.ts(1 hunks)apps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,ts,jsx,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't use global eval().
Don't use var.
Don't use console.
Don't use debugger.
Don't assign directly to document.cookie.
Don't use duplicate case labels.
Don't use duplicate class members.
Don't use duplicate function parameter names.
Don't use empty block statements and static blocks.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Use for...of statements instead of Array.forEach.
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names that aren't base 10 or use underscore separators.
Remove redundant terms from logical expressions.
Use while loops instead of for loops when you don't need initializer and update expressions.
Don't reassign const variables.
Don't use constant expressions in conditions.
Don't use Math.min and Math.max to clamp values when the result is constant.
Don't return a value from a constructor.
Don't use empty character classes in regular expression literals.
Don't use empty destructuring patterns.
Don't call global object properties as functions.
Don't declare functions and vars that are accessible outside their block.
Don't use variables and function parameters before they're declared.
Don't use 8 and 9 escape sequences in string literals.
Don't use literal numbers that lose precision.
Don't use duplicate conditions in if-else-if chains.
Don't use two keys with the same name inside objects...
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use TypeScript namespaces.
Don't use the TypeScript directive @ts-ignore.
Don't use any type.
Don't use implicit any type on variable declarations.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't declare empty interfaces.
Use export type for types.
Use import type for types.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
**/*.{ts,tsx}: Ensure TypeScript type-safety; avoidanyunless absolutely necessary
Create proper interfaces/types for APIs, responses, and components; place them in shared types folders rather than in the same file
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
**/*.{js,ts}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,ts}: Make sure to use the "use strict" directive in script files.
Don't have redundant "use strict".
Make sure to use the "use strict" directive in script files.
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
**/*.{js,jsx,ts,tsx}: Usebun <file>instead ofnode <file>orts-node <file>
Do not use dotenv; Bun automatically loads .env files
Do not useexpress; useBun.serve()for HTTP servers
Do not usebetter-sqlite3; usebun:sqlitefor SQLite
Do not useioredis; useBun.redisfor Redis
Do not usepgorpostgres.js; useBun.sqlfor Postgres
Do not usews; use built-inWebSocket
PreferBun.fileovernode:fs's readFile/writeFile
UseBun.$instead of execa for running shell commands
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
**/*.{html,ts,css}
📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
Use
bun build <file.html|file.ts|file.css>instead ofwebpackoresbuild
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)
**/*.{ts,tsx,js,jsx}: Use console methods appropriately (e.g., console.error, console.time, console.table, console.json)
Use Dayjs instead of date-fns
Use TanStack Query for hooks; do not use SWR
When adding debugging, use JSON.stringify() for structured output
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
**/*.{tsx,jsx,ts,js}
📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)
When using Phosphor React icons, append 'Icon' to component names (e.g., CaretIcon, not Caret)
Files:
apps/api/src/agent/handlers/chart-handler.tsapps/api/src/agent/utils/ai-client.tsapps/api/src/agent/index.tsapps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.tsapps/api/src/agent/prompts/agent.tsapps/api/src/routes/assistant.tsapps/api/src/schemas/assistant-schemas.tsapps/api/src/agent/processor.ts
🧬 Code Graph Analysis (4)
apps/api/src/agent/utils/ai-client.ts (3)
apps/api/src/agent/index.ts (2)
AssistantRequest(5-5)comprehensiveSystemPrompt(10-10)apps/api/src/agent/processor.ts (1)
AssistantRequest(26-28)apps/api/src/agent/prompts/agent.ts (1)
comprehensiveSystemPrompt(45-636)
apps/api/src/agent/prompts/agent.ts (2)
apps/api/src/agent/index.ts (1)
comprehensiveSystemPrompt(10-10)apps/api/src/schemas/assistant-schemas.ts (1)
AssistantRequestType(16-16)
apps/api/src/routes/assistant.ts (1)
apps/api/src/lib/website-utils.ts (1)
validateWebsite(196-206)
apps/api/src/agent/processor.ts (3)
apps/api/src/agent/index.ts (2)
AssistantRequest(5-5)getAICompletion(12-12)apps/api/src/schemas/assistant-schemas.ts (1)
AssistantRequestType(16-16)apps/api/src/agent/utils/ai-client.ts (1)
getAICompletion(26-74)
🔇 Additional comments (3)
apps/api/src/agent/utils/ai-client.ts (1)
41-45: Schema Validates Incoming Roles; System Role Only Injected InternallyThe
AssistantRequestSchemainassistant-schemas.tsenforces
•messages: t.Arraywith
•role: t.Union([t.Literal('user'), t.Literal('assistant')])Incoming payloads cannot include a
systemrole. Inai-client.tswe intentionally inject{ role: 'system', content: systemPrompt }—this is the single authorized source of a system message. A search of
routes/assistant.tsshows no other remapping or injection of roles.No changes needed here.
apps/api/src/agent/processor.ts (2)
59-60: Good: AI call timing isolated and captured.Measuring AI latency (aiTime) separately from overall processing is helpful for SLOs and optimization.
103-118: Ensure a defaultchart_typeof'bar'before invoking the chart handlerTo prevent UI errors when the AI response omits
chart_type, apply a nullish fallback inline—unlesshandleChartResponsealready handles this internally:- yield* handleChartResponse(parsedResponse, { + yield* handleChartResponse( + { ...parsedResponse, chart_type: parsedResponse.chart_type ?? 'bar' }, + { ...context, startTime, aiTime, - }); + } + );Please confirm whether
handleChartResponsealready defaultschart_typeto'bar'. If it does, you can omit this inline fallback to keep a single source of truth.
| async ({ body, user }: { body: AssistantRequestType; user: User }) => { | ||
| const { message, website_id, model, context } = body; | ||
| const { messages, websiteId, model } = body; | ||
|
|
||
| try { | ||
| const websiteValidation = await validateWebsite(website_id); | ||
| const websiteValidation = await validateWebsite(websiteId); | ||
|
|
||
| if (!websiteValidation.success) { |
There was a problem hiding this comment.
Critical: Ensure websiteId in body matches authenticated header to prevent cross-website access
The route validates the website using the body.websiteId while auth likely relies on the X-Website-Id header. If these diverge and aren’t checked, a client could authenticate with one site and attempt to query another. Enforce equality.
Apply this diff:
- async ({ body, user }: { body: AssistantRequestType; user: User }) => {
+ async ({
+ body,
+ user,
+ headers,
+ }: {
+ body: AssistantRequestType;
+ user: User;
+ headers: Record<string, string>;
+ }) => {
const { messages, websiteId, model } = body;
+ const headerWebsiteId = headers['x-website-id'];
+ if (headerWebsiteId && headerWebsiteId !== websiteId) {
+ return createStreamingResponse(
+ createErrorResponse('websiteId mismatch between header and body')
+ );
+ }If websiteAuth already injects a canonical websiteId elsewhere, alternatively drop websiteId from the body and use the authenticated one everywhere.
📝 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.
| async ({ body, user }: { body: AssistantRequestType; user: User }) => { | |
| const { message, website_id, model, context } = body; | |
| const { messages, websiteId, model } = body; | |
| try { | |
| const websiteValidation = await validateWebsite(website_id); | |
| const websiteValidation = await validateWebsite(websiteId); | |
| if (!websiteValidation.success) { | |
| async ({ | |
| body, | |
| user, | |
| headers, | |
| }: { | |
| body: AssistantRequestType; | |
| user: User; | |
| headers: Record<string, string>; | |
| }) => { | |
| const { messages, websiteId, model } = body; | |
| const headerWebsiteId = headers['x-website-id']; | |
| if (headerWebsiteId && headerWebsiteId !== websiteId) { | |
| return createStreamingResponse( | |
| createErrorResponse('websiteId mismatch between header and body') | |
| ); | |
| } | |
| try { | |
| const websiteValidation = await validateWebsite(websiteId); | |
| if (!websiteValidation.success) { | |
| // … |
🤖 Prompt for AI Agents
In apps/api/src/routes/assistant.ts around lines 27 to 33, the handler currently
validates websiteId from the request body but does not ensure it matches the
authenticated website id supplied via headers/middleware; enforce equality by
comparing body.websiteId to the authenticated website id (e.g., req.header or
user.websiteId injected by websiteAuth) and return a 403/validation error if
they differ, or remove/ignore websiteId from the body and always use the
canonical authenticated website id throughout the route (update subsequent calls
to validateWebsite/use websiteId accordingly).
There was a problem hiding this comment.
We should add this, isn't it? @izadoesdev
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
|
let me fix the comments! |
db0a8bf to
03fd9e8
Compare
03fd9e8 to
a51751a
Compare
|
addressed |

Had to add default chart type as
bar, because for some reason the LLM response was not giving one.Might be solved by making use of discriminated unions in the schema.
Summary by CodeRabbit
Bug Fixes
Documentation
Refactor
Style