Skip to content

Commit 7e322ac

Browse files
authored
Simplify databunny api. (#92)
* fix: remove extra padding from overview tab * refactor: update icon imports in databunny chat * feat: Simplify databunny api
1 parent 4a594d4 commit 7e322ac

File tree

10 files changed

+93
-125
lines changed

10 files changed

+93
-125
lines changed

apps/api/src/agent/handlers/chart-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export async function* handleChartResponse(
7272
: getRandomMessage(noDataMessages),
7373
data: {
7474
hasVisualization: queryResult.data.length > 0,
75-
chartType: parsedAiJson.chart_type,
75+
chartType: parsedAiJson.chart_type || 'bar',
7676
data: queryResult.data,
7777
responseType: 'chart',
7878
},

apps/api/src/agent/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export { processAssistantRequest } from './processor';
77
export {
88
AIPlanSchema,
99
AIResponseJsonSchema,
10-
comprehensiveUnifiedPrompt,
10+
comprehensiveSystemPrompt,
1111
} from './prompts/agent';
1212
export { getAICompletion } from './utils/ai-client';
1313
export { executeQuery } from './utils/query-executor';

apps/api/src/agent/processor.ts

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type { User } from '@databuddy/auth';
22
import type { Website } from '@databuddy/shared';
3+
import type { AssistantRequestType } from '../schemas';
34
import { handleChartResponse } from './handlers/chart-handler';
45
import { handleMetricResponse } from './handlers/metric-handler';
5-
import { comprehensiveUnifiedPrompt } from './prompts/agent';
66
import { getAICompletion } from './utils/ai-client';
77
import type { StreamingUpdate } from './utils/stream-utils';
88
import { generateThinkingSteps } from './utils/stream-utils';
@@ -23,17 +23,8 @@ const unexpectedErrorMessages = [
2323
'Something went a bit wonky on my end. Try asking me again?',
2424
];
2525

26-
export interface AssistantRequest {
27-
message: string;
28-
website_id: string;
29-
website_hostname: string;
30-
model?: 'chat' | 'agent' | 'agent-max';
31-
context?: {
32-
previousMessages?: Array<{
33-
role?: string;
34-
content: string;
35-
}>;
36-
};
26+
export interface AssistantRequest extends AssistantRequestType {
27+
websiteHostname: string;
3728
}
3829

3930
export interface AssistantContext {
@@ -50,34 +41,22 @@ export async function* processAssistantRequest(
5041

5142
try {
5243
console.info('✅ [Assistant Processor] Input validated', {
53-
message: request.message,
54-
website_id: request.website_id,
55-
website_hostname: request.website_hostname,
44+
message: request.messages.at(-1),
45+
websiteId: request.websiteId,
46+
websiteHostname: request.websiteHostname,
5647
});
5748

5849
if (context.user?.role === 'ADMIN') {
5950
context.debugInfo.validatedInput = {
60-
message: request.message,
61-
website_id: request.website_id,
62-
website_hostname: request.website_hostname,
51+
message: request.messages.at(-1),
52+
websiteId: request.websiteId,
53+
websiteHostname: request.websiteHostname,
6354
};
6455
}
6556

6657
const aiStart = Date.now();
67-
const fullPrompt = comprehensiveUnifiedPrompt(
68-
request.message,
69-
request.website_id,
70-
request.website_hostname,
71-
'execute_chat',
72-
request.context?.previousMessages?.map((msg) => ({
73-
role: msg.role || 'user',
74-
content: msg.content,
75-
})),
76-
undefined,
77-
request.model
78-
);
79-
80-
const aiResponse = await getAICompletion({ prompt: fullPrompt });
58+
59+
const aiResponse = await getAICompletion(request);
8160
const aiTime = Date.now() - aiStart;
8261

8362
const parsedResponse = aiResponse.content;

apps/api/src/agent/prompts/agent.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { z } from 'zod';
2+
import type { AssistantRequestType } from '../../schemas/assistant-schemas';
23

34
export const AIResponseJsonSchema = z.object({
45
sql: z.string().nullable().optional(),
@@ -41,14 +42,11 @@ export const AIPlanSchema = z.object({
4142
plan: z.array(z.string()),
4243
});
4344

44-
export const comprehensiveUnifiedPrompt = (
45-
userQuery: string,
45+
export const comprehensiveSystemPrompt = (
4646
websiteId: string,
4747
websiteHostname: string,
4848
mode: 'analysis_only' | 'execute_chat' | 'execute_agent_step',
49-
previousMessages?: Array<{ role: string; content: string }>,
50-
agentToolResult?: Record<string, unknown>,
51-
_model?: 'chat' | 'agent' | 'agent-max'
49+
_model?: AssistantRequestType['model']
5250
) => `
5351
<persona>
5452
You are Databunny, a world-class, specialized data analyst for the website ${websiteHostname}. You are precise, analytical, and secure. Your sole purpose is to help users understand their website's analytics data by providing insights, generating SQL queries, and creating visualizations.
@@ -168,25 +166,8 @@ You are Databunny, a world-class, specialized data analyst for the website ${web
168166
<website_id>${websiteId}</website_id>
169167
<website_hostname>${websiteHostname}</website_hostname>
170168
<mode>${mode}</mode>
171-
<user_query>${userQuery}</user_query>
172169
<current_date_utc>${new Date().toISOString().split('T')[0]}</current_date_utc>
173170
<current_timestamp_utc>${new Date().toISOString()}</current_timestamp_utc>
174-
${
175-
previousMessages && previousMessages.length > 0
176-
? `
177-
<conversation_history>
178-
${previousMessages
179-
.slice(-4)
180-
.map(
181-
(msg) =>
182-
`<message role="${msg.role}">${msg.content?.substring(0, 200)}${msg.content?.length > 200 ? '...' : ''}</message>`
183-
)
184-
.join('\n')}
185-
</conversation_history>
186-
`
187-
: ''
188-
}
189-
${agentToolResult ? `<agent_tool_result>${JSON.stringify(agentToolResult)}</agent_tool_result>` : ''}
190171
</request_context>
191172
192173
<workflow_instructions>

apps/api/src/agent/utils/ai-client.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
22
import { generateObject } from 'ai';
33
import type { z } from 'zod';
4-
import { AIResponseJsonSchema } from '../prompts/agent';
4+
import type { AssistantRequest } from '../processor';
5+
import {
6+
AIResponseJsonSchema,
7+
comprehensiveSystemPrompt,
8+
} from '../prompts/agent';
59

610
const openrouter = createOpenRouter({
711
apiKey: process.env.AI_API_KEY,
@@ -10,11 +14,6 @@ const openrouter = createOpenRouter({
1014
const AI_MODEL = 'google/gemini-2.5-flash-lite-preview-06-17';
1115
// const AI_MODEL = 'openrouter/horizon-beta';
1216

13-
interface AICompletionRequest {
14-
prompt: string;
15-
temperature?: number;
16-
}
17-
1817
interface AICompletionResponse {
1918
content: z.infer<typeof AIResponseJsonSchema>;
2019
usage: {
@@ -25,15 +24,25 @@ interface AICompletionResponse {
2524
}
2625

2726
export async function getAICompletion(
28-
request: AICompletionRequest
27+
request: AssistantRequest
2928
): Promise<AICompletionResponse> {
3029
const startTime = Date.now();
3130

31+
const systemPrompt = comprehensiveSystemPrompt(
32+
request.websiteId,
33+
request.websiteHostname,
34+
'execute_chat',
35+
request.model
36+
);
37+
3238
try {
3339
const chat = await generateObject({
3440
model: openrouter.chat(AI_MODEL),
35-
messages: [{ role: 'user', content: request.prompt }],
36-
temperature: request.temperature ?? 0.1,
41+
messages: [
42+
{ role: 'system', content: systemPrompt },
43+
...request.messages,
44+
],
45+
temperature: 0.1,
3746
schema: AIResponseJsonSchema,
3847
});
3948

apps/api/src/routes/assistant.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ export const assistant = new Elysia({ prefix: '/v1/assistant' })
2525
.post(
2626
'/stream',
2727
async ({ body, user }: { body: AssistantRequestType; user: User }) => {
28-
const { message, website_id, model, context } = body;
28+
const { messages, websiteId, model } = body;
2929

3030
try {
31-
const websiteValidation = await validateWebsite(website_id);
31+
const websiteValidation = await validateWebsite(websiteId);
3232

3333
if (!websiteValidation.success) {
3434
return createStreamingResponse(
@@ -45,11 +45,10 @@ export const assistant = new Elysia({ prefix: '/v1/assistant' })
4545
}
4646

4747
const assistantRequest: AssistantRequest = {
48-
message,
49-
website_id,
50-
website_hostname: website.domain,
48+
messages,
49+
websiteId,
50+
websiteHostname: website.domain,
5151
model: model || 'chat',
52-
context,
5352
};
5453

5554
const assistantContext: AssistantContext = {
Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,23 @@
11
import { t } from 'elysia';
22

3-
export const AssistantRequestSchema = t.Object({
4-
message: t.String(),
5-
website_id: t.String(),
6-
model: t.Optional(
7-
t.Union([t.Literal('chat'), t.Literal('agent'), t.Literal('agent-max')])
8-
),
9-
context: t.Optional(
10-
t.Object({
11-
previousMessages: t.Optional(
12-
t.Array(
13-
t.Object({
14-
role: t.Optional(t.String()),
15-
content: t.String(),
16-
})
17-
)
3+
export const AssistantRequestSchema = t.Object(
4+
{
5+
messages: t.Array(
6+
t.Object(
7+
{
8+
role: t.Union([t.Literal('user'), t.Literal('assistant')]),
9+
content: t.String(),
10+
},
11+
{ additionalProperties: false }
1812
),
19-
})
20-
),
21-
});
13+
{ minItems: 1 }
14+
),
15+
websiteId: t.String(),
16+
model: t.Optional(
17+
t.Union([t.Literal('chat'), t.Literal('agent'), t.Literal('agent-max')])
18+
),
19+
},
20+
{ additionalProperties: false }
21+
);
2222

23-
export type AssistantRequestType = {
24-
message: string;
25-
website_id: string;
26-
model?: 'chat' | 'agent' | 'agent-max';
27-
context?: {
28-
previousMessages?: Array<{
29-
role?: string;
30-
content: string;
31-
}>;
32-
};
33-
};
23+
export type AssistantRequestType = typeof AssistantRequestSchema.static;

apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ export function WebsiteOverviewTab({
914914
);
915915

916916
return (
917-
<div className="space-y-6 pt-6">
917+
<div className="space-y-6">
918918
<EventLimitIndicator />
919919
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-6">
920920
{[

0 commit comments

Comments
 (0)