From b9b57a311a8856d31c88181e40306d02968d5716 Mon Sep 17 00:00:00 2001 From: Devyash Saini Date: Sun, 31 May 2026 22:28:03 +0530 Subject: [PATCH 1/2] feat: rename SdkEventBuilder to BasicUsageBuilder, fix eventType to BASIC_USAGE, update codegen --- examples/ai-sdk-wrapper-usage.ts | 14 ++++++++++++++ packages/analytics/scripts/gen-fields.ts | 8 ++++---- packages/analytics/src/analytics.ts | 16 ++++++++-------- packages/analytics/src/query/basicUsage.ts | 11 +++++++++++ packages/analytics/src/query/fields.ts | 2 +- packages/analytics/src/query/sdkEvent.ts | 9 --------- 6 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 packages/analytics/src/query/basicUsage.ts delete mode 100644 packages/analytics/src/query/sdkEvent.ts diff --git a/examples/ai-sdk-wrapper-usage.ts b/examples/ai-sdk-wrapper-usage.ts index 2b74f72..4073ade 100644 --- a/examples/ai-sdk-wrapper-usage.ts +++ b/examples/ai-sdk-wrapper-usage.ts @@ -2,6 +2,7 @@ import * as ai from "ai"; import { google } from "@ai-sdk/google"; import { biller } from "./scrawn/biller.js"; import { config } from "dotenv"; +import { mul, outputTokens } from "@scrawn/core"; config({ path: ".env.local" }); async function main() { @@ -16,6 +17,19 @@ async function main() { prompt: "Write a 2 sentence story about a robot.", }); + const result1 = await ai.streamText({ + model: google("gemini-2.5-flash"), + prompt: "Write a 2 sentence story about a robot.", + onFinish: (event) => { + biller.trackAI({ + userId: "c0971bcb-b901-4c3e-a191-c9a97871c39f", + event, + inputDebit: biller.tag("PREMIUM_CALL"), + outputDebit: mul(outputTokens(), 0.0001), + }); + }, + }); + console.log(`Generated: "${await result.text}"\n`); } diff --git a/packages/analytics/scripts/gen-fields.ts b/packages/analytics/scripts/gen-fields.ts index 16bc369..fc01d6a 100644 --- a/packages/analytics/scripts/gen-fields.ts +++ b/packages/analytics/scripts/gen-fields.ts @@ -20,7 +20,7 @@ type FieldEntry = { name: string; type: string; protoName: string }; // ── Parse EventRow interface from query.ts ── function parseQueryFields(): { - sdkCall: FieldEntry[]; + basicUsage: FieldEntry[]; aiToken: FieldEntry[]; payment: FieldEntry[]; } { @@ -63,7 +63,7 @@ function parseQueryFields(): { { name: "apiKeyId", type: "string", protoName: "api_key_id" }, ]; - const sdkCall: FieldEntry[] = [ + const basicUsage: FieldEntry[] = [ ...common, { name: "basicUsageType", type: "string", protoName: "basic_usage_type" }, { name: "debitAmount", type: "number", protoName: "debit_amount" }, @@ -100,7 +100,7 @@ function parseQueryFields(): { { name: "creditAmount", type: "number", protoName: "credit_amount" }, ]; - return { sdkCall, aiToken, payment }; + return { basicUsage, aiToken, payment }; } // ── Parse per-table enums from data_pb.d.ts ── @@ -183,7 +183,7 @@ function generateFieldsFile( const queryFields = parseQueryFields(); generateFieldsFile( { - sdkEvent: queryFields.sdkCall, + basicUsage: queryFields.basicUsage, aiToken: queryFields.aiToken, payment: queryFields.payment, }, diff --git a/packages/analytics/src/analytics.ts b/packages/analytics/src/analytics.ts index 0317205..75e405a 100644 --- a/packages/analytics/src/analytics.ts +++ b/packages/analytics/src/analytics.ts @@ -1,6 +1,6 @@ import type { Scrawn } from "@scrawn/core"; import type { GrpcClient } from "@scrawn/core"; -import { SdkEventBuilder } from "./query/sdkEvent.js"; +import { BasicUsageBuilder } from "./query/basicUsage.js"; import { AiTokenBuilder } from "./query/aiToken.js"; import { PaymentBuilder } from "./query/payment.js"; import { @@ -16,7 +16,7 @@ import { * Each builder is pre-scoped to the correct event type. */ export interface EventQueries { - sdkEvent: SdkEventBuilder; + basicUsage: BasicUsageBuilder; aiToken: AiTokenBuilder; payment: PaymentBuilder; } @@ -46,13 +46,13 @@ export interface DataQueries { * * const analytics = new Analytics(biller); * - * // Query SDK events - * const events = await analytics.query.sdkEvent + * // Query basic usage events + * const events = await analytics.query.basicUsage * .where(and( - * eq(analytics.query.sdkEvent.fields.sdkCallType, "RAW"), - * gt(analytics.query.sdkEvent.fields.debitAmount, 100), + * eq(analytics.query.basicUsage.fields.basicUsageType, "RAW"), + * gt(analytics.query.basicUsage.fields.debitAmount, 100), * )) - * .orderBy(desc(analytics.query.sdkEvent.fields.reportedTimestamp)) + * .orderBy(desc(analytics.query.basicUsage.fields.reportedTimestamp)) * .limit(10) * .execute(); * @@ -77,7 +77,7 @@ export class Analytics { const apiKey = biller.apikey; this.query = { - sdkEvent: new SdkEventBuilder(this.grpc, apiKey), + basicUsage: new BasicUsageBuilder(this.grpc, apiKey), aiToken: new AiTokenBuilder(this.grpc, apiKey), payment: new PaymentBuilder(this.grpc, apiKey), }; diff --git a/packages/analytics/src/query/basicUsage.ts b/packages/analytics/src/query/basicUsage.ts new file mode 100644 index 0000000..8ee20c9 --- /dev/null +++ b/packages/analytics/src/query/basicUsage.ts @@ -0,0 +1,11 @@ +import { BaseEventBuilder } from "./base.js"; +import type { GrpcClient } from "@scrawn/core"; +import { basicUsageFields } from "./fields.js"; + +export class BasicUsageBuilder extends BaseEventBuilder< + typeof basicUsageFields +> { + constructor(grpc: GrpcClient, apiKey: string) { + super(basicUsageFields, "BASIC_USAGE", grpc, apiKey); + } +} diff --git a/packages/analytics/src/query/fields.ts b/packages/analytics/src/query/fields.ts index f292317..ccb0bca 100644 --- a/packages/analytics/src/query/fields.ts +++ b/packages/analytics/src/query/fields.ts @@ -1,7 +1,7 @@ // AUTO-GENERATED by scripts/gen-fields.ts — do not edit import { FieldRef } from "../fieldRef.js"; -export const sdkEventFields = { +export const basicUsageFields = { eventId: new FieldRef("eventId"), eventType: new FieldRef("eventType"), userId: new FieldRef("userId"), diff --git a/packages/analytics/src/query/sdkEvent.ts b/packages/analytics/src/query/sdkEvent.ts deleted file mode 100644 index 1ff47c0..0000000 --- a/packages/analytics/src/query/sdkEvent.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { BaseEventBuilder } from "./base.js"; -import type { GrpcClient } from "@scrawn/core"; -import { sdkEventFields } from "./fields.js"; - -export class SdkEventBuilder extends BaseEventBuilder { - constructor(grpc: GrpcClient, apiKey: string) { - super(sdkEventFields, "SDK_CALL", grpc, apiKey); - } -} From a599ed60f42eb9be6fa10f9483c9fc12d6baed52 Mon Sep 17 00:00:00 2001 From: Devyash Saini Date: Sun, 31 May 2026 22:36:09 +0530 Subject: [PATCH 2/2] chore: release Signed-off-by: Devyash Saini --- .changeset/eager-bottles-train.md | 5 +++++ examples/analytics-usage.ts | 27 +++++++++++++-------------- 2 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 .changeset/eager-bottles-train.md diff --git a/.changeset/eager-bottles-train.md b/.changeset/eager-bottles-train.md new file mode 100644 index 0000000..71b1108 --- /dev/null +++ b/.changeset/eager-bottles-train.md @@ -0,0 +1,5 @@ +--- +"@scrawn/analytics": patch +--- + +fix: broken analytics layer diff --git a/examples/analytics-usage.ts b/examples/analytics-usage.ts index c0e3f99..a2236b0 100644 --- a/examples/analytics-usage.ts +++ b/examples/analytics-usage.ts @@ -1,7 +1,6 @@ import { Analytics, eq, - neq, gt, and, asc, @@ -16,28 +15,28 @@ config({ path: ".env.local" }); async function main() { const analytics = new Analytics(biller); - const { sdkEvent, aiToken, payment } = analytics.query; + const { basicUsage, aiToken, payment } = analytics.query; const { users, tags, sessions, expressions, metadata } = analytics.data; // ── Event Queries ── // List recent SDK call events - const recentSdkCalls = await sdkEvent - .where(eq(sdkEvent.fields.basicUsageType, "RAW")) - .orderBy(desc(sdkEvent.fields.reportedTimestamp)) + const recentSdkCalls = await basicUsage + .where(eq(basicUsage.fields.basicUsageType, "RAW")) + .orderBy(desc(basicUsage.fields.reportedTimestamp)) .limit(10) .execute(); console.log("Recent SDK calls:", JSON.stringify(recentSdkCalls, null, 2)); // Middleware events with high debit - const expensiveMiddleware = await sdkEvent + const expensiveMiddleware = await basicUsage .where( and( - eq(sdkEvent.fields.basicUsageType, "MIDDLEWARE_CALL"), - gt(sdkEvent.fields.debitAmount, 100) + eq(basicUsage.fields.basicUsageType, "MIDDLEWARE_CALL"), + gt(basicUsage.fields.debitAmount, 100) ) ) - .orderBy(desc(sdkEvent.fields.debitAmount)) + .orderBy(desc(basicUsage.fields.debitAmount)) .limit(5) .execute(); console.log( @@ -49,15 +48,15 @@ async function main() { const gpt4Usage = await aiToken .where(eq(aiToken.fields.model, "gpt-4")) .orderBy(desc(aiToken.fields.reportedTimestamp)) - .limit(20) + .limit(10) .execute(); console.log("GPT-4 token usage:", JSON.stringify(gpt4Usage, null, 2)); // Total debit per user (aggregation) - const totalByUser = await sdkEvent - .where(gt(sdkEvent.fields.debitAmount, 0)) - .aggregate(sum(sdkEvent.fields.debitAmount)) - .groupBy(sdkEvent.fields.userId) + const totalByUser = await basicUsage + .where(gt(basicUsage.fields.debitAmount, 0)) + .aggregate(sum(basicUsage.fields.debitAmount)) + .groupBy(basicUsage.fields.userId) .limit(10) .execute(); console.log("Total debit by user:", JSON.stringify(totalByUser, null, 2));