mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
Merge pull request #10 from RooCodeInc/cte/sync-types
This commit is contained in:
commit
3b0eb65457
5 changed files with 110 additions and 54 deletions
|
|
@ -2,7 +2,7 @@ import { auth } from '@clerk/nextjs/server';
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { eventSchema } from '@/schemas';
|
||||
import { cloudEventSchema } from '@/schemas';
|
||||
import { captureEvent } from '@/lib/server/analytics';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
|
|
@ -15,10 +15,9 @@ export async function POST(request: NextRequest) {
|
|||
);
|
||||
}
|
||||
|
||||
const payload = await request.json();
|
||||
const id = uuidv4();
|
||||
const timestamp = Date.now() / 1000;
|
||||
const result = eventSchema.safeParse({ ...payload, id, userId, timestamp });
|
||||
const timestamp = Math.round(Date.now() / 1000);
|
||||
const result = cloudEventSchema.safeParse(await request.json());
|
||||
|
||||
if (!result.success) {
|
||||
return NextResponse.json(
|
||||
|
|
@ -28,8 +27,10 @@ export async function POST(request: NextRequest) {
|
|||
}
|
||||
|
||||
try {
|
||||
await captureEvent(result.data);
|
||||
await captureEvent({ id, userId, timestamp, event: result.data });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
|
|
|
|||
|
|
@ -1,22 +1,37 @@
|
|||
export const createEvents = `
|
||||
CREATE TABLE default.events
|
||||
(
|
||||
\`id\` UUID,
|
||||
\`userId\` String,
|
||||
\`type\` String,
|
||||
\`timestamp\` Int32,
|
||||
\`taskId\` Nullable(String),
|
||||
\`provider\` Nullable(String),
|
||||
\`modelId\` Nullable(String),
|
||||
\`prompt\` Nullable(String),
|
||||
\`mode\` Nullable(String),
|
||||
\`inputTokens\` Nullable(Int32),
|
||||
\`outputTokens\` Nullable(Int32),
|
||||
\`cacheReadTokens\` Nullable(Int32),
|
||||
\`cacheWriteTokens\` Nullable(Int32),
|
||||
\`cost\` Nullable(Float32)
|
||||
)
|
||||
ENGINE = SharedMergeTree('/clickhouse/tables/{uuid}/{shard}', '{replica}')
|
||||
ORDER BY (id, type, timestamp)
|
||||
SETTINGS index_granularity = 8192;
|
||||
`;
|
||||
/*
|
||||
|
||||
CREATE TABLE default.events
|
||||
(
|
||||
-- Shared
|
||||
`id` UUID,
|
||||
`userId` String,
|
||||
`timestamp` Int32,
|
||||
`type` String,
|
||||
|
||||
-- App
|
||||
`appVersion` String,
|
||||
`vscodeVersion` String,
|
||||
`platform` String,
|
||||
`editorName` String,
|
||||
`language` String,
|
||||
`mode` String,
|
||||
|
||||
-- Task
|
||||
`taskId` Nullable(String),
|
||||
`apiProvider` Nullable(String),
|
||||
`modelId` Nullable(String),
|
||||
`diffStrategy` Nullable(String),
|
||||
`isSubtask` Nullable(Bool),
|
||||
|
||||
-- Completion
|
||||
`inputTokens` Nullable(Int32),
|
||||
`outputTokens` Nullable(Int32),
|
||||
`cacheReadTokens` Nullable(Int32),
|
||||
`cacheWriteTokens` Nullable(Int32),
|
||||
`cost` Nullable(Float32)
|
||||
)
|
||||
ENGINE = SharedMergeTree('/clickhouse/tables/{uuid}/{shard}', '{replica}')
|
||||
ORDER BY (id, type, timestamp)
|
||||
SETTINGS index_granularity = 8192;
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createClient } from '@clickhouse/client';
|
||||
|
||||
import { Event } from '@/schemas';
|
||||
import { CloudEvent } from '@/schemas';
|
||||
import { Env } from './env';
|
||||
|
||||
const client = createClient({
|
||||
|
|
@ -9,10 +9,25 @@ const client = createClient({
|
|||
password: Env.CLICKHOUSE_PASSWORD,
|
||||
});
|
||||
|
||||
export const captureEvent = async ({ properties, ...event }: Event) => {
|
||||
type AnalyticsEvent = {
|
||||
id: string;
|
||||
userId: string;
|
||||
timestamp: number;
|
||||
event: CloudEvent;
|
||||
};
|
||||
|
||||
export const captureEvent = async ({
|
||||
event: { properties, ...cloudEvent },
|
||||
...analyticsEvent
|
||||
}: AnalyticsEvent) => {
|
||||
// The destructuring here flattens the `AnalyticsEvent` to match the ClickHouse
|
||||
// schema.
|
||||
const value = { ...analyticsEvent, ...cloudEvent, ...properties };
|
||||
console.log(`captureEvent`, value);
|
||||
|
||||
await client.insert({
|
||||
table: 'events',
|
||||
values: [{ ...event, ...properties }],
|
||||
values: [value],
|
||||
format: 'JSONEachRow',
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export default clerkMiddleware(
|
|||
await auth.protect();
|
||||
}
|
||||
},
|
||||
{ debug: process.env.NODE_ENV !== "production" },
|
||||
{ debug: false },
|
||||
);
|
||||
|
||||
// Also exclude tunnelRoute used in Sentry from the matcher.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
// TODO: I'll add these types to our @roo-code/types NPM package so we
|
||||
// don't need to manually copy them.
|
||||
|
||||
// Copied from `src/schemas/index.ts`
|
||||
|
||||
export const providerNames = [
|
||||
'anthropic',
|
||||
'glama',
|
||||
|
|
@ -24,36 +29,56 @@ export const providerNames = [
|
|||
'litellm',
|
||||
] as const;
|
||||
|
||||
const baseEventSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
userId: z.string(),
|
||||
timestamp: z.number(),
|
||||
// Copied from `src/services/telemetry/types.ts`
|
||||
|
||||
export const appPropertiesSchema = z.object({
|
||||
appVersion: z.string(),
|
||||
vscodeVersion: z.string(),
|
||||
platform: z.string(),
|
||||
editorName: z.string(),
|
||||
language: z.string(),
|
||||
mode: z.string(),
|
||||
});
|
||||
|
||||
export const eventSchema = z.discriminatedUnion('type', [
|
||||
baseEventSchema.extend({
|
||||
type: z.literal('task_created'),
|
||||
export const taskPropertiesSchema = z.object({
|
||||
taskId: z.string(),
|
||||
apiProvider: z.enum(providerNames).optional(),
|
||||
modelId: z.string().optional(),
|
||||
diffStrategy: z.string().optional(),
|
||||
isSubtask: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const completionPropertiesSchema = z.object({
|
||||
inputTokens: z.number(),
|
||||
outputTokens: z.number(),
|
||||
cacheReadTokens: z.number().optional(),
|
||||
cacheWriteTokens: z.number().optional(),
|
||||
cost: z.number().optional(),
|
||||
});
|
||||
|
||||
// Copied from `src/services/cloud/types.ts`.
|
||||
|
||||
export enum CloudEventType {
|
||||
TaskCreated = 'task_created',
|
||||
Completion = 'completion',
|
||||
}
|
||||
|
||||
export const cloudEventSchema = z.discriminatedUnion('type', [
|
||||
z.object({
|
||||
type: z.literal(CloudEventType.TaskCreated),
|
||||
properties: z.object({
|
||||
taskId: z.string(),
|
||||
provider: z.enum(providerNames),
|
||||
modelId: z.string(),
|
||||
prompt: z.string(),
|
||||
mode: z.string(),
|
||||
...appPropertiesSchema.shape,
|
||||
...taskPropertiesSchema.shape,
|
||||
}),
|
||||
}),
|
||||
baseEventSchema.extend({
|
||||
type: z.literal('completion'),
|
||||
z.object({
|
||||
type: z.literal(CloudEventType.Completion),
|
||||
properties: z.object({
|
||||
taskId: z.string(),
|
||||
provider: z.enum(providerNames),
|
||||
modelId: z.string(),
|
||||
inputTokens: z.number(),
|
||||
outputTokens: z.number(),
|
||||
cacheReadTokens: z.number().optional(),
|
||||
cacheWriteTokens: z.number().optional(),
|
||||
cost: z.number().optional(),
|
||||
...appPropertiesSchema.shape,
|
||||
...taskPropertiesSchema.shape,
|
||||
...completionPropertiesSchema.shape,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
|
||||
export type Event = z.infer<typeof eventSchema>;
|
||||
export type CloudEvent = z.infer<typeof cloudEventSchema>;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue