Skip to content

Refactor/the entire thing - #40

Merged
SteakFisher merged 10 commits into
mainfrom
refactor/the_entire_thing
May 17, 2026
Merged

Refactor/the entire thing#40
SteakFisher merged 10 commits into
mainfrom
refactor/the_entire_thing

Conversation

@SteakFisher

@SteakFisher SteakFisher commented May 16, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • AI token usage now records cached token counts and cached cost, and captures provider and optional metadata.
    • Payment events now persist associated API key IDs.
  • Refactor

    • Event model and storage reworked to use unified basic-usage events and consolidated metrics payloads.
    • Query engines rewritten to route and aggregate across the new per-type event tables.
  • Bug Fixes

    • Validation rejects negative cache token/count inputs to prevent bad data.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR replaces the SDK_CALL event kind with BASIC_USAGE, introduces structured metrics (including input-cache metrics and provider) and a metrics Zod schema, splits polymorphic events into per-type tables, and updates insert, query, and pricing handlers for ClickHouse and Postgres to persist and aggregate JSON metrics.

Changes

Event Storage Refactor: SDK_CALL → BASIC_USAGE with Cache Metrics

Layer / File(s) Summary
Event type contracts & validation schemas
src/interface/event/Event.ts, src/interface/storage/Storage.ts, src/zod/event.ts, src/zod/metrics.ts
Replace SDK_CALL with BASIC_USAGE; add BasicUsageEventData; extend AI token usage types with provider, inputCacheTokens, inputCacheDebitAmount, and optional metadata; add metricsSchema for nested token/debit JSON validation and adapt Zod schemas to compute cache debit.
ClickHouse schema migration
src/storage/adapter/clickhouse/schema.ts
Add basic_usage_events DDL with type, provider, and metrics JSON; remove sdk_call_events DDL; add api_key_id to payment_events; update migration runner.
ClickHouse insert & aggregation handlers
src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts, addSdkCall.ts, addPayment.ts
AI token handler validates cache fields, aggregates input-cache tokens/debits, emits provider and a metrics JSON payload; SDK call handler inserts into basic_usage_events using basicUsageType; payment insert includes api_key_id.
ClickHouse query & pricing
src/storage/adapter/clickhouse/handlers/queryEvents.ts, priceRequestAiTokenUsage.ts, priceRequestSdkCall.ts
Unify projections across tables; extract/de-sum debit amounts from metrics JSON via JSONExtractInt; parse lastBilled as UTC when present to apply lower-bound filtering, otherwise fall back to before-only filter; rebuild list/aggregation flows with typed parameters.
Postgres schema redesign
src/storage/db/postgres/schema.ts
Replace polymorphic eventsTable with basicUsageEventsTable, paymentEventsTable, aiTokenUsageEventsTable; store AI metrics as typed jsonb (Metrics); update user/apiKey relations to expose per-type relations.
Postgres insert handler rewrites
src/storage/adapter/postgres/handlers/addAiTokenUsage.ts, addSdkCall.ts, addPayment.ts, addEventUtils.ts
Remove generic insertEvent; AI token usage aggregates cache fields and batch-inserts into aiTokenUsageEventsTable using metricsSchema.parse; SDK call and payment handlers insert directly into their tables and return inserted ids; validate non-negative cache values.
Postgres query & pricing handlers
src/storage/adapter/postgres/handlers/queryEvents.ts, priceRequest.ts, priceRequestAiTokenUsage.ts, priceRequestSdkCall.ts
Introduce table-driven SQL generation with per-table field registry; build UNION ALL across selected tables for list and aggregation queries; pricing queries read priceTable with usersTable and sum JSON metric debit fields for AI token usage.
Event instantiation & routing
src/events/BasicUsage.ts, src/utils/eventHelpers.ts, src/routes/gRPC/query/queryEvents.ts
Rename/produce BasicUsage events, create BasicUsage instances for BASIC_USAGE payloads, route queries to BASIC_USAGE adapter, and stringify metadata for gRPC row responses.
Adapter factory & dispatch
src/factory/EventStorageAdapterFactory.ts, src/storage/adapter/clickhouse/ClickHouseAdapter.ts, src/storage/adapter/postgres/postgres.ts, src/storage/adapter/common/priceRequestPayment.ts
Switch routing keys from SDK_CALL to BASIC_USAGE across storage adapter selection and pricing calls.
Event query table mappings
src/storage/adapter/common/queryEventsBase.ts
Add mapping constants between event labels and table names, enumerate tables/types, and provide getTablesForRequest() to resolve target tables from nested query filters.
Routes & minor cleanup
src/routes/http/registerWebhookRoutes.ts, src/routes/gRPC/events/streamEvents.ts, src/utils/parseExpr.ts, proto
Minor formatting changes to imports/calls, small comment removal, and update of proto submodule gitlink pointer.

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

"🐰 I nibbled through schemas, neat and light,
Metrics tucked in JSON, cache counted right,
BASIC_USAGE hops in place of SDK,
Tables stand alone to brighten the day,
A small rabbit dance for a clearer night."

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

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.
Title check ❓ Inconclusive The title 'Refactor/the entire thing' is vague and generic, using non-descriptive phrasing that does not convey meaningful information about the specific changes made in this substantial refactoring. Replace with a specific title that captures the main refactoring objective, such as 'Replace SDK_CALL events with BASIC_USAGE and restructure event storage schema' or 'Migrate event system from polymorphic to dedicated event tables'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/the_entire_thing

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/storage/adapter/postgres/handlers/addAiTokenUsage.ts (1)

98-98: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Aggregation key missing provider may merge events incorrectly.

The aggregation key is ${userId}:${model} but events with the same user and model but different providers will be merged together, with the first provider being retained. This could lead to incorrect attribution of token usage to the wrong provider.

Proposed fix
-    const key = `${event_data.userId}:${event_data.data.model}`;
+    const key = `${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/postgres/handlers/addAiTokenUsage.ts` at line 98, The
aggregation key built in addAiTokenUsage (const key =
`${event_data.userId}:${event_data.data.model}`) omits the provider, causing
events with the same user and model but different providers to collapse; update
the key to include event_data.data.provider (e.g.,
`${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`)
wherever the key is used so provider-specific usage is tracked and attributed
correctly, and adjust any lookup/merge logic that relies on the old key format.
src/zod/event.ts (1)

53-89: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce non-negative cache debit values before returning parsed event

Line 53 accepts negative raw amounts, and Line 85-89 can also resolve to negative values via tag/expr. This allows negative inputCacheDebitAmount into storage/billing aggregation.

Suggested fix
-    inputcacheamount: z.number(),
+    inputcacheamount: z.number().min(0),
@@
     } else {
       inputCacheDebitAmount = v.inputcacheamount;
     }
+    if (inputCacheDebitAmount < 0) {
+      throw new Error("inputCacheDebitAmount must be non-negative");
+    }

As per coding guidelines, "Use Zod schemas for all request validation; catch ZodError and convert to domain errors".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zod/event.ts` around lines 53 - 89, After computing inputCacheDebitAmount
(from fetchTagAmount/parseAndEvaluateExpr or v.inputcacheamount) ensure it is
non-negative by adding a check after the computation that throws a z.ZodError
(construct a ZodIssue indicating path 'inputcacheamount' and message like
"inputCacheDebitAmount must be non-negative") when inputCacheDebitAmount < 0 so
the invalid value is rejected by the schema transform; reference the
variables/functions inputCacheDebitAmount, fetchTagAmount, parseAndEvaluateExpr
and the async .transform block so the validation happens before returning the
parsed AITokenUsageEventData.
src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts (1)

92-109: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Aggregation key drops provider, causing cross-provider data corruption.

On Lines 92/109, events are keyed by userId:model but now persist provider. If a batch includes the same model from different providers, amounts are merged and attributed to one provider incorrectly.

Targeted fix
-    const key = `${event_data.userId}:${event_data.data.model}`;
+    const key = `${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts` around lines 92 -
109, The aggregation key currently built as
`${event_data.userId}:${event_data.data.model}` drops provider and causes merges
across providers; update the key construction (the variable key used with
aggregationMap) to include provider (e.g.,
`${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`) and
ensure all lookups/sets against aggregationMap use that new key so stored
objects (created in the else branch and updated in the existing branch) keep
provider-specific aggregates and reported_timestamp logic remains unchanged.
src/storage/adapter/clickhouse/schema.ts (1)

19-45: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Existing ClickHouse tables are not migrated for new columns.

Using only CREATE TABLE IF NOT EXISTS won’t add api_key_id (Line 38) or the new provider/metrics columns on already-created tables, so inserts can fail after deploy.

Suggested migration direction
 export async function runClickHouseMigrations(): Promise<void> {
   const client = getClickHouseDB();

   await client.command({ query: BASIC_USAGE_EVENTS_TABLE });
   logger.lifecycle("ClickHouse: basic_usage_events table ensured");

   await client.command({ query: AI_TOKEN_USAGE_EVENTS_TABLE });
   logger.lifecycle("ClickHouse: ai_token_usage_events table ensured");

   await client.command({ query: PAYMENT_EVENTS_TABLE });
   logger.lifecycle("ClickHouse: payment_events table ensured");
+
+  // Backward-compatible schema evolution for existing deployments
+  await client.command({
+    query:
+      "ALTER TABLE ai_token_usage_events ADD COLUMN IF NOT EXISTS provider String AFTER model",
+  });
+  await client.command({
+    query:
+      "ALTER TABLE ai_token_usage_events ADD COLUMN IF NOT EXISTS metrics String AFTER provider",
+  });
+  await client.command({
+    query:
+      "ALTER TABLE payment_events ADD COLUMN IF NOT EXISTS api_key_id Nullable(String) AFTER user_id",
+  });
 }

Also applies to: 56-57

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/clickhouse/schema.ts` around lines 19 - 45, The CREATE
TABLE IF NOT EXISTS definitions (AI_TOKEN_USAGE_EVENTS_TABLE and
PAYMENT_EVENTS_TABLE) won't add new columns to existing ClickHouse tables; add
an explicit migration that runs ALTER TABLE ... ADD COLUMN IF NOT EXISTS for the
missing columns (api_key_id on payment_events, and provider and metrics on
ai_token_usage_events, using the same types Nullable(String)/String as in the
CREATEs) or include these ALTERs in startup migration logic so existing tables
gain those columns before inserts occur; reference AI_TOKEN_USAGE_EVENTS_TABLE
and PAYMENT_EVENTS_TABLE and ensure column types and nullability match the
CREATE definitions.
🧹 Nitpick comments (1)
src/storage/adapter/postgres/handlers/queryEvents.ts (1)

1-393: ⚖️ Poor tradeoff

Consider removing dead code rather than commenting it out.

The entire query handler is commented out since queries have migrated to ClickHouse. Commented-out code adds noise and maintenance burden. Consider either deleting this file or adding a clear TODO comment explaining when/if this code should be restored.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/postgres/handlers/queryEvents.ts` around lines 1 - 393,
The file contains a large block of commented-out Postgres query logic (including
PG_FIELDS, handleQueryEvents, queryListForType, handleListQuery,
handleAggregationQuery, resolveAggCol, buildConditions, buildSelect,
getEventTypes, etc.); remove this dead code entirely (delete the file) or, if
you must keep it for future restoration, replace the commented block with a
short top-level TODO comment stating why it was removed and when it can be
restored (e.g., "Postgres query handlers removed — ClickHouse now used; restore
only if migrating back to Postgres") and ensure exported symbols like
handleQueryEvents are not left commented but removed/updated to avoid stale
exports.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/routes/gRPC/events/streamEvents.ts`:
- Around line 41-47: Replace the raw console.log calls that print req.toObject()
and eventSkeleton in streamEvents.ts with the project's structured logging
helpers: call logOperationInfo to record non-sensitive, structured fields (e.g.,
request id, event type, user id) extracted from req.toObject() or the parsed
streamEventSchema result, and call logOperationError if parsing or downstream
processing fails; do not log full objects or raw payloads—select and redact
sensitive fields before passing them to logOperationInfo/logOperationError so
the logs conform to the project's contract.

In `@src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts`:
- Around line 65-79: The validation for inputCacheTokens and
inputCacheDebitAmount currently only rejects negative numbers but allows
NaN/Infinity; update the checks in addAiTokenUsage handler to ensure each value
is a finite non-negative number (use Number.isFinite or global isFinite + typeof
=== "number") before proceeding, and throw the existing
StorageError.insertFailed (preserving the user context via event_data.userId)
with a clear message when the value is not a finite non-negative number; refer
to the variables inputCacheTokens and inputCacheDebitAmount in your changes.

In `@src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts`:
- Around line 50-51: The code currently falls back to the raw lastBilled string
when DateTime.fromSQL fails, which can blow up when binding to a DateTime64
parameter; change the fallback so params.lastBilled is set to null (not the raw
string) when lastBilledDt.isValid is false, and update the query to treat a null
param as "no lower bound" (e.g. use an SQL clause like "WHERE (timestamp >=
{lastBilled:DateTime64(3,'UTC')} OR {lastBilled} IS NULL)" or COALESCE-based
logic). Specifically, in the priceRequestAiTokenUsage handler replace the
existing assignment using lastBilledDt/isValid/toClickHouseDateTime so the else
branch assigns null, and ensure the query that consumes params.lastBilled
handles null as "no lower bound".

In `@src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts`:
- Around line 48-49: The current code binds a raw unparseable lastBilled value
into params.lastBilled (using DateTime.fromSQL -> toClickHouseDateTime) which
can break DateTime64 queries; change the logic in the handler so that after
computing lastBilledDt = DateTime.fromSQL(lastBilled, { zone: 'utc' }) you only
set params.lastBilled = toClickHouseDateTime(lastBilledDt) when
lastBilledDt.isValid is true, and when invalid remove/omit params.lastBilled (or
follow the existing no-lastBilled query path) instead of assigning the raw
lastBilled string so the SDK uses the no-`lastBilled` branch.

In `@src/storage/adapter/clickhouse/handlers/queryEvents.ts`:
- Around line 21-60: CH_FIELDS is missing an entry for ai_token_usage_events
which causes buildSelectColumns to fall back to '*' and breaks UNION ALL column
compatibility; add an ai_token_usage_events object to CH_FIELDS mirroring the
same keys used for basic_usage_events/payment_events (eventId, eventType,
userId, apiKeyId, reportedTimestamp, ingestedTimestamp, sdkCallType,
debitAmount, model, inputTokens, outputTokens, inputDebitAmount,
outputDebitAmount, inputCacheTokens, inputCacheDebitAmount, creditAmount,
provider) and provide appropriate select (and where where applicable)
expressions (e.g., eventId: "toString(id)", eventType: "'SDK_CALL'" or
"'PAYMENT'" as needed, reportedTimestamp: "toString(reported_timestamp)", etc.)
so getTablesForRequest + buildSelectColumns produce consistent column shapes for
UNIONs and preserve alias-based ordering like reportedTimestamp.

In `@src/storage/adapter/postgres/handlers/addPayment.ts`:
- Around line 77-87: The catch in addPayment.ts is re-wrapping a
previously-thrown StorageError.emptyResult as StorageError.insertFailed; update
the catch so that if the caught error is already a StorageError (e.g., e
instanceof StorageError or a type check for StorageError.emptyResult) you
rethrow it unchanged, otherwise wrap non-StorageError exceptions with
StorageError.insertFailed("Failed to insert payment event", ...). Ensure this
change is applied around the try/catch that surrounds the result check and the
return of { id: result.id } so the original emptyResult error and its context
are preserved.

In `@src/storage/adapter/postgres/handlers/addSdkCall.ts`:
- Around line 51-61: The empty-result error thrown by StorageError.emptyResult
in addSdkCall (the check that throws "SDK call insert returned no ID") is being
caught and re-wrapped by the catch that creates StorageError.insertFailed;
update the handler so StorageError.emptyResult is propagated unchanged: either
move the null/empty check outside the try block or, inside the catch for the
function handling SDK call insert, detect if the caught error is an instance of
StorageError (or specifically StorageError.emptyResult) and rethrow it
immediately before wrapping other errors with StorageError.insertFailed.
Reference addSdkCall, the result null-check that throws
StorageError.emptyResult, and the catch that currently throws
StorageError.insertFailed.

In `@src/storage/adapter/postgres/postgres.ts`:
- Around line 113-116: The current stub in PostgresAdapter.async query(request:
QueryRequest): Promise<QueryResponse> returns a string and breaks the
QueryResponse contract; replace the stub with an explicit non-implementation
error or delegate to the real handler. Specifically, in the query method remove
`return "smth" as any;` and either throw a clear Error like `throw new
Error("PostgresAdapter.query not implemented");` or call and return the real
implementation (e.g., `return await handleQueryEvents(request);`) so the method
returns a valid QueryResponse shape and avoids using `any`.

In `@src/zod/metrics.ts`:
- Around line 9-13: The debit_amount schema in src/zod/metrics.ts uses
z.number().int() for fields input, input_cache, and output which will reject
fractional values; update the debit_amount object (fields input, input_cache,
output) to accept fractional numbers (e.g., use z.number() to match the types
used in src/zod/event.ts for inputamount, inputcacheamount, and outputamount) so
metrics validation accepts non-integer debits.

---

Outside diff comments:
In `@src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts`:
- Around line 92-109: The aggregation key currently built as
`${event_data.userId}:${event_data.data.model}` drops provider and causes merges
across providers; update the key construction (the variable key used with
aggregationMap) to include provider (e.g.,
`${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`) and
ensure all lookups/sets against aggregationMap use that new key so stored
objects (created in the else branch and updated in the existing branch) keep
provider-specific aggregates and reported_timestamp logic remains unchanged.

In `@src/storage/adapter/clickhouse/schema.ts`:
- Around line 19-45: The CREATE TABLE IF NOT EXISTS definitions
(AI_TOKEN_USAGE_EVENTS_TABLE and PAYMENT_EVENTS_TABLE) won't add new columns to
existing ClickHouse tables; add an explicit migration that runs ALTER TABLE ...
ADD COLUMN IF NOT EXISTS for the missing columns (api_key_id on payment_events,
and provider and metrics on ai_token_usage_events, using the same types
Nullable(String)/String as in the CREATEs) or include these ALTERs in startup
migration logic so existing tables gain those columns before inserts occur;
reference AI_TOKEN_USAGE_EVENTS_TABLE and PAYMENT_EVENTS_TABLE and ensure column
types and nullability match the CREATE definitions.

In `@src/storage/adapter/postgres/handlers/addAiTokenUsage.ts`:
- Line 98: The aggregation key built in addAiTokenUsage (const key =
`${event_data.userId}:${event_data.data.model}`) omits the provider, causing
events with the same user and model but different providers to collapse; update
the key to include event_data.data.provider (e.g.,
`${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`)
wherever the key is used so provider-specific usage is tracked and attributed
correctly, and adjust any lookup/merge logic that relies on the old key format.

In `@src/zod/event.ts`:
- Around line 53-89: After computing inputCacheDebitAmount (from
fetchTagAmount/parseAndEvaluateExpr or v.inputcacheamount) ensure it is
non-negative by adding a check after the computation that throws a z.ZodError
(construct a ZodIssue indicating path 'inputcacheamount' and message like
"inputCacheDebitAmount must be non-negative") when inputCacheDebitAmount < 0 so
the invalid value is rejected by the schema transform; reference the
variables/functions inputCacheDebitAmount, fetchTagAmount, parseAndEvaluateExpr
and the async .transform block so the validation happens before returning the
parsed AITokenUsageEventData.

---

Nitpick comments:
In `@src/storage/adapter/postgres/handlers/queryEvents.ts`:
- Around line 1-393: The file contains a large block of commented-out Postgres
query logic (including PG_FIELDS, handleQueryEvents, queryListForType,
handleListQuery, handleAggregationQuery, resolveAggCol, buildConditions,
buildSelect, getEventTypes, etc.); remove this dead code entirely (delete the
file) or, if you must keep it for future restoration, replace the commented
block with a short top-level TODO comment stating why it was removed and when it
can be restored (e.g., "Postgres query handlers removed — ClickHouse now used;
restore only if migrating back to Postgres") and ensure exported symbols like
handleQueryEvents are not left commented but removed/updated to avoid stale
exports.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a0e1f267-2861-4d00-b753-955b97b81499

📥 Commits

Reviewing files that changed from the base of the PR and between acaac30 and 5defd19.

⛔ Files ignored due to path filters (6)
  • src/gen/data/v1/data_pb.d.ts is excluded by !**/gen/**
  • src/gen/data/v1/data_pb.js is excluded by !**/gen/**
  • src/gen/event/v1/event_pb.d.ts is excluded by !**/gen/**
  • src/gen/event/v1/event_pb.js is excluded by !**/gen/**
  • src/gen/query/v1/query_pb.d.ts is excluded by !**/gen/**
  • src/gen/query/v1/query_pb.js is excluded by !**/gen/**
📒 Files selected for processing (27)
  • proto
  • src/factory/EventStorageAdapterFactory.ts
  • src/interface/event/Event.ts
  • src/interface/storage/Storage.ts
  • src/routes/gRPC/events/streamEvents.ts
  • src/routes/http/registerWebhookRoutes.ts
  • src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts
  • src/storage/adapter/clickhouse/handlers/addPayment.ts
  • src/storage/adapter/clickhouse/handlers/addSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts
  • src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
  • src/storage/adapter/clickhouse/schema.ts
  • src/storage/adapter/postgres/handlers/addAiTokenUsage.ts
  • src/storage/adapter/postgres/handlers/addEventUtils.ts
  • src/storage/adapter/postgres/handlers/addPayment.ts
  • src/storage/adapter/postgres/handlers/addSdkCall.ts
  • src/storage/adapter/postgres/handlers/index.ts
  • src/storage/adapter/postgres/handlers/priceRequest.ts
  • src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts
  • src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts
  • src/storage/adapter/postgres/handlers/queryEvents.ts
  • src/storage/adapter/postgres/postgres.ts
  • src/storage/db/postgres/schema.ts
  • src/utils/parseExpr.ts
  • src/zod/event.ts
  • src/zod/metrics.ts
💤 Files with no reviewable changes (2)
  • src/utils/parseExpr.ts
  • src/storage/adapter/postgres/handlers/addEventUtils.ts

Comment thread src/routes/gRPC/events/streamEvents.ts Outdated
Comment thread src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts
Comment thread src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts Outdated
Comment thread src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts Outdated
Comment thread src/storage/adapter/clickhouse/handlers/queryEvents.ts Outdated
Comment thread src/storage/adapter/postgres/handlers/addPayment.ts
Comment thread src/storage/adapter/postgres/handlers/addSdkCall.ts
Comment thread src/storage/adapter/postgres/postgres.ts
Comment thread src/zod/metrics.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts (1)

48-58: ⚡ Quick win

Simplify by flattening the conditional and eliminating duplicate queries.

Lines 54 and 57 are identical, and the nested structure can be flattened. Building the lastBilled clause conditionally removes duplication and makes the logic clearer.

♻️ Proposed refactor
-    if (lastBilled) {
-      const lastBilledDt = DateTime.fromSQL(lastBilled, { zone: 'utc' });
-      if (lastBilledDt.isValid) {
-        query = `SELECT sum(JSONExtractInt(metrics, 'debit_amount', 'input') + JSONExtractInt(metrics, 'debit_amount', 'input_cache') + JSONExtractInt(metrics, 'debit_amount', 'output')) as total FROM ai_token_usage_events WHERE user_id = {userId:String} AND mode = {mode:String} AND reported_timestamp > {lastBilled:DateTime64(3, 'UTC')} AND reported_timestamp < {before:DateTime64(3, 'UTC')}`;
-        params.lastBilled = toClickHouseDateTime(lastBilledDt);
-      } else {
-        query = `SELECT sum(JSONExtractInt(metrics, 'debit_amount', 'input') + JSONExtractInt(metrics, 'debit_amount', 'input_cache') + JSONExtractInt(metrics, 'debit_amount', 'output')) as total FROM ai_token_usage_events WHERE user_id = {userId:String} AND mode = {mode:String} AND reported_timestamp < {before:DateTime64(3, 'UTC')}`;
-      }
-    } else {
-      query = `SELECT sum(JSONExtractInt(metrics, 'debit_amount', 'input') + JSONExtractInt(metrics, 'debit_amount', 'input_cache') + JSONExtractInt(metrics, 'debit_amount', 'output')) as total FROM ai_token_usage_events WHERE user_id = {userId:String} AND mode = {mode:String} AND reported_timestamp < {before:DateTime64(3, 'UTC')}`;
-    }
+    const lastBilledDt = lastBilled ? DateTime.fromSQL(lastBilled, { zone: 'utc' }) : null;
+    const hasValidLastBilled = lastBilledDt?.isValid ?? false;
+
+    const sumExpr = `sum(JSONExtractInt(metrics, 'debit_amount', 'input') + JSONExtractInt(metrics, 'debit_amount', 'input_cache') + JSONExtractInt(metrics, 'debit_amount', 'output'))`;
+    const lastBilledClause = hasValidLastBilled ? `AND reported_timestamp > {lastBilled:DateTime64(3, 'UTC')}` : '';
+
+    query = `SELECT ${sumExpr} as total FROM ai_token_usage_events WHERE user_id = {userId:String} AND mode = {mode:String} ${lastBilledClause} AND reported_timestamp < {before:DateTime64(3, 'UTC')}`;
+
+    if (hasValidLastBilled && lastBilledDt) {
+      params.lastBilled = toClickHouseDateTime(lastBilledDt);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts` around
lines 48 - 58, The code duplicates the same SELECT query in multiple branches;
flatten by building a single base query for ai_token_usage_events and then
conditionally append the reported_timestamp > {lastBilled...} clause only if
lastBilled is present and lastBilledDt.isValid; set params.lastBilled =
toClickHouseDateTime(lastBilledDt) only when that clause is appended and always
include the common params.userId, params.mode and params.before. Update
references in priceRequestAiTokenUsage.ts to use the single query variable and
remove the duplicate query strings in the nested if/else.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts`:
- Around line 48-58: The code duplicates the same SELECT query in multiple
branches; flatten by building a single base query for ai_token_usage_events and
then conditionally append the reported_timestamp > {lastBilled...} clause only
if lastBilled is present and lastBilledDt.isValid; set params.lastBilled =
toClickHouseDateTime(lastBilledDt) only when that clause is appended and always
include the common params.userId, params.mode and params.before. Update
references in priceRequestAiTokenUsage.ts to use the single query variable and
remove the duplicate query strings in the nested if/else.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e9ea512-e9f6-47e6-868d-0bae7e8e7979

📥 Commits

Reviewing files that changed from the base of the PR and between 5defd19 and dfedd2c.

📒 Files selected for processing (4)
  • src/routes/gRPC/events/streamEvents.ts
  • src/storage/adapter/clickhouse/handlers/priceRequestAiTokenUsage.ts
  • src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
✅ Files skipped from review due to trivial changes (1)
  • src/routes/gRPC/events/streamEvents.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/storage/adapter/postgres/handlers/addAiTokenUsage.ts (1)

99-124: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t aggregate different providers into the same row.

Line 99 keys the batch by userId:model, but the persisted row also includes provider and metadata. If the same user/model appears from multiple providers in one batch, this merges them and stores the first provider/metadata for the whole sum, which silently corrupts attribution. Include provider in the aggregation key at minimum, and avoid merging rows with conflicting metadata.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/postgres/handlers/addAiTokenUsage.ts` around lines 99 -
124, The aggregation currently keys by
`${event_data.userId}:${event_data.data.model}` and thus merges different
providers/metadata into one entry; change the key to include provider (e.g.,
`${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`) and
ensure when checking/creating entries in aggregationMap you use that new key;
additionally, when metadata can differ, avoid silently merging by either
including a stable serialization of metadata in the key or by detecting
mismatched metadata on an existing entry and creating a separate aggregation
entry (do not overwrite the existing provider/metadata), and preserve the
reported_timestamp update logic (compare reported_timestamp with
existing.reported_timestamp) as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/routes/gRPC/events/registerEvent.ts`:
- Line 36: Replace the raw console.log(req.toObject()) in the registerEvent
handler with a structured, sanitized logger call: import and use
logOperationInfo from errors/logger, pass a clear operation name (e.g.,
"registerEvent") and a minimal context object (e.g., eventId, eventType, source)
derived from req.toObject() but excluding sensitive payload fields; if an error
path exists, use logOperationError similarly. Ensure no full request object is
logged and that the log call follows the project contract (operation name +
small context).

In `@src/storage/adapter/postgres/handlers/addAiTokenUsage.ts`:
- Around line 143-183: The metricsSchema.parse call is executed outside the try
block (via aiTokenUsageValues) so a ZodError can escape; move the construction
of aiTokenUsageValues (including metricsSchema.parse(...)) inside the try before
calling txn.insert(aiTokenUsageEventsTable). Add a separate catch branch for
ZodError to wrap it into StorageError.insertFailed (with a clear message like
"Invalid metrics for AI token usage event") and rethrow, and keep your existing
catch for other errors that wraps them via StorageError.insertFailed around the
txn.insert(...) operation; retain the returning({ id: aiTokenUsageEventsTable.id
}) and the check that inserted[0].id exists.

---

Outside diff comments:
In `@src/storage/adapter/postgres/handlers/addAiTokenUsage.ts`:
- Around line 99-124: The aggregation currently keys by
`${event_data.userId}:${event_data.data.model}` and thus merges different
providers/metadata into one entry; change the key to include provider (e.g.,
`${event_data.userId}:${event_data.data.model}:${event_data.data.provider}`) and
ensure when checking/creating entries in aggregationMap you use that new key;
additionally, when metadata can differ, avoid silently merging by either
including a stable serialization of metadata in the key or by detecting
mismatched metadata on an existing entry and creating a separate aggregation
entry (do not overwrite the existing provider/metadata), and preserve the
reported_timestamp update logic (compare reported_timestamp with
existing.reported_timestamp) as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2abe699c-0535-4ab2-8abf-8f3c475d60fa

📥 Commits

Reviewing files that changed from the base of the PR and between dfedd2c and 3c7ddc6.

⛔ Files ignored due to path filters (4)
  • src/gen/event/v1/event_pb.d.ts is excluded by !**/gen/**
  • src/gen/event/v1/event_pb.js is excluded by !**/gen/**
  • src/gen/query/v1/query_pb.d.ts is excluded by !**/gen/**
  • src/gen/query/v1/query_pb.js is excluded by !**/gen/**
📒 Files selected for processing (12)
  • src/interface/event/Event.ts
  • src/interface/storage/Storage.ts
  • src/routes/gRPC/events/registerEvent.ts
  • src/routes/gRPC/query/queryEvents.ts
  • src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts
  • src/storage/adapter/clickhouse/handlers/addSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
  • src/storage/adapter/clickhouse/schema.ts
  • src/storage/adapter/postgres/handlers/addAiTokenUsage.ts
  • src/storage/adapter/postgres/handlers/addSdkCall.ts
  • src/storage/db/postgres/schema.ts
  • src/zod/event.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/interface/event/Event.ts
  • src/storage/adapter/postgres/handlers/addSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/addSdkCall.ts
  • src/interface/storage/Storage.ts
  • src/storage/adapter/clickhouse/handlers/addAiTokenUsage.ts
  • src/storage/adapter/clickhouse/schema.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
  • src/storage/db/postgres/schema.ts
  • src/zod/event.ts

Comment thread src/routes/gRPC/events/registerEvent.ts Outdated
Comment thread src/storage/adapter/postgres/handlers/addAiTokenUsage.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/zod/event.ts (1)

30-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move metadata JSON parsing into Zod validation.

Malformed metadata currently throws a raw SyntaxError here, so it skips the normal Zod/domain-error path and turns bad client input into an internal error. It also accepts non-object JSON despite the Record<string, unknown> contract.

Suggested direction
+const metadataSchema = z
+  .string()
+  .transform((value, ctx): Record<string, unknown> => {
+    try {
+      const parsed: unknown = JSON.parse(value);
+      if (parsed == null || Array.isArray(parsed) || typeof parsed !== "object") {
+        ctx.addIssue({
+          code: z.ZodIssueCode.custom,
+          message: "metadata must be a JSON object",
+        });
+        return {} as Record<string, unknown>;
+      }
+      return parsed as Record<string, unknown>;
+    } catch {
+      ctx.addIssue({
+        code: z.ZodIssueCode.custom,
+        message: "metadata must be valid JSON",
+      });
+      return {} as Record<string, unknown>;
+    }
+  })
+  .optional();
+
 const BasicUsageDataSchema: z.ZodType<BasicUsageEventData> = z
   .object({
 ...
-    metadata: z.string().optional(),
+    metadata: metadataSchema,
   })
   .transform(async (v): Promise<BasicUsageEventData> => {
 ...
-    return { basicUsageType: v.sdkcalltype, debitAmount, metadata: v.metadata ? JSON.parse(v.metadata) as Record<string, unknown> : undefined };
+    return { basicUsageType: v.sdkcalltype, debitAmount, metadata: v.metadata };
   });

 const AITokenUsageDataSchema: z.ZodType<AITokenUsageEventData> = z
   .object({
 ...
-    metadata: z.string().optional(),
+    metadata: metadataSchema,
   })
 ...
-      metadata: v.metadata ? JSON.parse(v.metadata) as Record<string, unknown> : undefined,
+      metadata: v.metadata,

As per coding guidelines, "Use Zod schemas for all request validation; catch ZodError and convert to domain errors".

Also applies to: 60-115

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zod/event.ts` around lines 30 - 41, Replace the runtime JSON.parse in the
transform with Zod-level parsing/validation: change the metadata field
definition (currently metadata: z.string().optional()) to a preprocessing schema
like z.preprocess((val) => { if (typeof val === 'string') { try { return
JSON.parse(val); } catch (e) { throw new Error('Invalid JSON for metadata'); } }
return val; }, z.record(z.unknown()).optional()), and remove the JSON.parse(...)
call inside the transform so the transform uses the already-validated metadata
as a Record<string, unknown> or undefined; this ensures malformed JSON becomes a
ZodError and non-object JSON is rejected according to the Record<string,
unknown>() contract.
🧹 Nitpick comments (2)
src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts (2)

10-87: 💤 Low value

Consider renaming function to match the new event type.

The function is still named handlePriceRequestSdkCall but now handles BASIC_USAGE events (queries basic_usage_events table, error message references BASIC_USAGE). Consider renaming to handlePriceRequestBasicUsage for consistency with the refactor.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts` around lines
10 - 87, Rename the exported function handlePriceRequestSdkCall to
handlePriceRequestBasicUsage and update all internal and external references
(imports/exports, tests, call sites) accordingly; keep the same signature and
behavior, update any JSDoc/comments to reference BASIC_USAGE/basic_usage_events
if present, and ensure error construction that mentions
StorageError.priceCalculationFailed and StorageError.invalidData still use the
new function name where applicable so names are consistent across the codebase.

74-81: 💤 Low value

Avoid any in error type checking.

The coding guidelines specify avoiding any. Consider using a type guard or more explicit typing.

Suggested fix
   } catch (e) {
     if (
       e &&
       typeof e === "object" &&
       "type" in e &&
-      (e as any).name === "StorageError"
+      "name" in e &&
+      (e as { name: string }).name === "StorageError"
     ) {
       throw e;
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts` around lines
74 - 81, Replace the inline cast to any by introducing a proper type guard and
using it in the existing error-check block: add a function like
isStorageError(error: unknown): error is StorageError that verifies error is an
object, has a string name === "StorageError" (and the expected "type" property
if applicable), then replace the current check (the block that inspects e and
uses (e as any).name === "StorageError") to call isStorageError(e) and throw e
when it returns true; this removes the any usage and makes the intent explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage/adapter/common/queryEventsBase.ts`:
- Around line 45-63: collectRawEventTypeValues and getTablesForRequest are
currently only picking the first "eventType" condition per group and ignoring
the condition operator, causing NEQ/NOT IN to be treated as positive filters;
update collectRawEventTypeValues to collect all eventType conditions (not just
the first) including their operators, then change getTablesForRequest to
interpret operators: for EQ/IN aggregate the matching EventTypeLabel values and
return their mapped EVENT_TYPE_TO_TABLE entries; for NEQ/NOT IN remove the
mapped tables from ALL_TABLES (i.e., treat as exclusions) and return the
remainder; use QueryFilterGroup, collectRawEventTypeValues, getTablesForRequest
and EVENT_TYPE_TO_TABLE identifiers to locate and implement this behavior.

In `@src/storage/adapter/postgres/handlers/queryEvents.ts`:
- Around line 300-306: The SUM aggregation uses
PG_FIELDS[t]?.[agg.field]?.whereCol which is null for computed fields like
ai_token_usage_events.debitAmount, causing 0 results; add a new PGFieldDef
property (e.g., aggExpr) for fields that are computed but aggregatable, set
ai_token_usage_events.debitAmount.aggExpr to the correct SQL/JSON expression,
and update the aggregator in queryEvents.ts (the if (isSum && agg.field) block)
to prefer aggExpr if present before falling back to whereCol and the 0::bigint
default so SUM uses the computed expression.

---

Outside diff comments:
In `@src/zod/event.ts`:
- Around line 30-41: Replace the runtime JSON.parse in the transform with
Zod-level parsing/validation: change the metadata field definition (currently
metadata: z.string().optional()) to a preprocessing schema like
z.preprocess((val) => { if (typeof val === 'string') { try { return
JSON.parse(val); } catch (e) { throw new Error('Invalid JSON for metadata'); } }
return val; }, z.record(z.unknown()).optional()), and remove the JSON.parse(...)
call inside the transform so the transform uses the already-validated metadata
as a Record<string, unknown> or undefined; this ensures malformed JSON becomes a
ZodError and non-object JSON is rejected according to the Record<string,
unknown>() contract.

---

Nitpick comments:
In `@src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts`:
- Around line 10-87: Rename the exported function handlePriceRequestSdkCall to
handlePriceRequestBasicUsage and update all internal and external references
(imports/exports, tests, call sites) accordingly; keep the same signature and
behavior, update any JSDoc/comments to reference BASIC_USAGE/basic_usage_events
if present, and ensure error construction that mentions
StorageError.priceCalculationFailed and StorageError.invalidData still use the
new function name where applicable so names are consistent across the codebase.
- Around line 74-81: Replace the inline cast to any by introducing a proper type
guard and using it in the existing error-check block: add a function like
isStorageError(error: unknown): error is StorageError that verifies error is an
object, has a string name === "StorageError" (and the expected "type" property
if applicable), then replace the current check (the block that inspects e and
uses (e as any).name === "StorageError") to call isStorageError(e) and throw e
when it returns true; this removes the any usage and makes the intent explicit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 60a1a039-5da7-425c-9bf8-19de410e90f4

📥 Commits

Reviewing files that changed from the base of the PR and between 3c7ddc6 and 92eabac.

📒 Files selected for processing (19)
  • proto
  • src/events/BasicUsage.ts
  • src/factory/EventStorageAdapterFactory.ts
  • src/interface/event/Event.ts
  • src/interface/storage/Storage.ts
  • src/routes/gRPC/query/queryEvents.ts
  • src/storage/adapter/clickhouse/ClickHouseAdapter.ts
  • src/storage/adapter/clickhouse/handlers/addSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/priceRequestSdkCall.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
  • src/storage/adapter/common/priceRequestPayment.ts
  • src/storage/adapter/common/queryEventsBase.ts
  • src/storage/adapter/postgres/handlers/addAiTokenUsage.ts
  • src/storage/adapter/postgres/handlers/addSdkCall.ts
  • src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts
  • src/storage/adapter/postgres/handlers/queryEvents.ts
  • src/storage/adapter/postgres/postgres.ts
  • src/utils/eventHelpers.ts
  • src/zod/event.ts
✅ Files skipped from review due to trivial changes (1)
  • proto
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/interface/storage/Storage.ts
  • src/storage/adapter/postgres/handlers/addAiTokenUsage.ts

Comment thread src/storage/adapter/common/queryEventsBase.ts Outdated
Comment thread src/storage/adapter/postgres/handlers/queryEvents.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage/adapter/clickhouse/handlers/queryEvents.ts`:
- Around line 202-206: The code uses DateTime.fromISO(condition.value) which
parses zone-less ISO strings in local time; change it to parse in UTC by using
DateTime.fromISO(condition.value, { zone: 'utc' }) (or immediately call
.toUTC()/setZone('utc')) before passing dt into toClickHouseDateTime, keeping
the existing dt.isValid check and using the same variables (DateTime.fromISO,
dt, condition.value, toClickHouseDateTime).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ef2a7cfa-d70c-4e88-ac3e-007238f26839

📥 Commits

Reviewing files that changed from the base of the PR and between 92eabac and 718efbe.

📒 Files selected for processing (3)
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
  • src/storage/adapter/common/queryEventsBase.ts
  • src/storage/adapter/postgres/handlers/queryEvents.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/storage/adapter/postgres/handlers/queryEvents.ts
  • src/storage/adapter/common/queryEventsBase.ts

Comment thread src/storage/adapter/clickhouse/handlers/queryEvents.ts Outdated
@SteakFisher
SteakFisher merged commit 29d4a18 into main May 17, 2026
3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request May 17, 2026
@SteakFisher
SteakFisher deleted the refactor/the_entire_thing branch May 17, 2026 22:24
@coderabbitai coderabbitai Bot mentioned this pull request May 30, 2026
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