-
Notifications
You must be signed in to change notification settings - Fork 51
Daily branch 2026 01 28 #194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Remove city, country, and region fields from user context to reduce sensitive data in logs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, when users aborted a request, usage was not being saved because: 1. The streamText.onFinish callback (which sets streamUsage) hadn't fired yet 2. The backend skipped saving when message already existed from frontend 3. The Convex saveMessage mutation ignored usage when updating existing messages This fix: - Awaits result.usage before deciding to skip backend save - Adds hasUsageToRecord condition to proceed with save if usage available - Updates Convex saveMessage to patch usage/model/metrics on existing messages Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Switch ask-model, ask-vision-model, ask-vision-model-for-pdfs, and summarization-model from AI Gateway to OpenRouter with google/gemini-3-flash-preview. - Add @openrouter/ai-sdk-provider dependency - Add OPENROUTER_API_KEY to env example - Update README with OpenRouter requirement Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe PR integrates OpenRouter as an AI provider by adding environment variables and dependencies, switching model providers from gateway to OpenRouter endpoints, refactoring message update logic to conditionally patch fields, enhancing usage data capture during abort scenarios, and removing location tracking from user event logging. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
convex/messages.ts (1)
126-149: Verify file ownership before attaching to existing messages.Line 136–149 marks new files as attached without checking that the file belongs to
args.userId. This can let callers associate and mutate other users’ file records. Filter newFileIds by ownership before patchingfile_idsandis_attached.🔧 Suggested fix (validate ownership before attaching)
- if (newFileIds.length > 0) { - patch.file_ids = [...currentFileIds, ...newFileIds]; - - // Mark new files as linked - for (const fileId of newFileIds) { + if (newFileIds.length > 0) { + const verifiedNewFileIds: Id<"files">[] = []; + // Mark new files as linked (only if owned by the user) + for (const fileId of newFileIds) { try { const file = await ctx.db.get(fileId); - if (file && !file.is_attached) { + if (!file) continue; + if (file.user_id !== args.userId) { + console.warn("Skipping file not owned by user:", fileId); + continue; + } + verifiedNewFileIds.push(fileId); + if (!file.is_attached) { await ctx.db.patch(file._id, { is_attached: true }); } } catch (error) { console.error( `Failed to mark file ${fileId} as attached:`, error, ); } } + if (verifiedNewFileIds.length > 0) { + patch.file_ids = [...currentFileIds, ...verifiedNewFileIds]; + } }
🤖 Fix all issues with AI agents
In `@convex/messages.ts`:
- Around line 153-167: The current updates use truthy checks that will skip
valid falsy values (e.g., 0 or empty string); change the presence checks for
args.generationTimeMs, args.model, args.finishReason (and any similar checks
like args.usage if needed) from truthy checks to explicit !== undefined checks
so values like 0 or "" are persisted; keep the existingMessage checks as-is
(e.g., !existingMessage.generation_time_ms) or adjust them to === undefined if
you want symmetric semantics, and update the conditions around
patch.generation_time_ms, patch.model, and patch.finish_reason accordingly.
In `@lib/logger.ts`:
- Around line 158-161: WideEventBuilder.setUser currently types its parameter as
{ id: string; subscription: string } causing TypeScript errors when chat-logger
(lib/api/chat-logger.ts) and chat-handler (lib/api/chat-handler.ts) pass a
UserContext that includes an optional location; update the
WideEventBuilder.setUser signature to accept an optional location property
(e.g., location?: { city?: string; country?: string; region?: string }) so the
method accepts the full UserContext object passed by chatLogger.setUser and
chatLogger callers, and ensure the implementation stores the location on
this.event.user without changing other behavior.
In `@package.json`:
- Line 62: The package version for `@openrouter/ai-sdk-provider` in package.json
is incorrect and causes install failures; update the dependency entry
"@openrouter/ai-sdk-provider": "^2.1.1" to use the published version "^1.2.0" so
npm can resolve and install the package successfully.
| // Update usage if provided and not already set (e.g., on abort) | ||
| if (args.usage && !existingMessage.usage) { | ||
| patch.usage = args.usage; | ||
| } | ||
|
|
||
| // Update metrics if provided and not already set | ||
| if (args.model && !existingMessage.model) { | ||
| patch.model = args.model; | ||
| } | ||
| if (args.generationTimeMs && !existingMessage.generation_time_ms) { | ||
| patch.generation_time_ms = args.generationTimeMs; | ||
| } | ||
| if (args.finishReason && !existingMessage.finish_reason) { | ||
| patch.finish_reason = args.finishReason; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid truthy checks that drop valid zero/empty values.
Line 153–167 uses truthy checks (args.generationTimeMs, args.model, args.finishReason). If values are valid but falsy (e.g., 0), they won’t be persisted. Use !== undefined checks instead.
✅ Safer conditional checks
- if (args.usage && !existingMessage.usage) {
+ if (args.usage !== undefined && !existingMessage.usage) {
patch.usage = args.usage;
}
- if (args.model && !existingMessage.model) {
+ if (args.model !== undefined && !existingMessage.model) {
patch.model = args.model;
}
- if (args.generationTimeMs && !existingMessage.generation_time_ms) {
+ if (
+ args.generationTimeMs !== undefined &&
+ !existingMessage.generation_time_ms
+ ) {
patch.generation_time_ms = args.generationTimeMs;
}
- if (args.finishReason && !existingMessage.finish_reason) {
+ if (args.finishReason !== undefined && !existingMessage.finish_reason) {
patch.finish_reason = args.finishReason;
}🤖 Prompt for AI Agents
In `@convex/messages.ts` around lines 153 - 167, The current updates use truthy
checks that will skip valid falsy values (e.g., 0 or empty string); change the
presence checks for args.generationTimeMs, args.model, args.finishReason (and
any similar checks like args.usage if needed) from truthy checks to explicit !==
undefined checks so values like 0 or "" are persisted; keep the existingMessage
checks as-is (e.g., !existingMessage.generation_time_ms) or adjust them to ===
undefined if you want symmetric semantics, and update the conditions around
patch.generation_time_ms, patch.model, and patch.finish_reason accordingly.
| setUser(user: { id: string; subscription: string }): this { | ||
| this.event.user = user; | ||
| return this; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the chat-handler.ts file to see if it passes location to setUser
rg -n "setUser" lib/api/chat-handler.ts -A 10Repository: hackerai-tech/hackerai
Length of output: 551
🏁 Script executed:
# Also check the ChatWideEvent interface definition
rg -n "ChatWideEvent\|interface.*Event" lib/logger.ts -A 5Repository: hackerai-tech/hackerai
Length of output: 48
🏁 Script executed:
# Check the actual setUser method in logger.ts around lines 158-161
sed -n '155,165p' lib/logger.tsRepository: hackerai-tech/hackerai
Length of output: 245
🏁 Script executed:
# Search for all setUser calls in the codebase
rg -n "\.setUser\(" --type ts --type tsxRepository: hackerai-tech/hackerai
Length of output: 93
🏁 Script executed:
# Check if there are any overloads or other definitions of setUser in logger.ts
rg -n "setUser" lib/logger.tsRepository: hackerai-tech/hackerai
Length of output: 131
🏁 Script executed:
# Search for all setUser calls in the codebase
rg -n "\.setUser\(" --type tsRepository: hackerai-tech/hackerai
Length of output: 688
🏁 Script executed:
# Check the chat-logger.ts to see what builder.setUser is doing
sed -n '75,85p' lib/api/chat-logger.tsRepository: hackerai-tech/hackerai
Length of output: 225
🏁 Script executed:
# Also check the context around line 81 to understand what builder is
sed -n '70,90p' lib/api/chat-logger.tsRepository: hackerai-tech/hackerai
Length of output: 490
🏁 Script executed:
# Check what UserContext is defined as in chat-logger.ts
rg -n "UserContext" lib/api/chat-logger.ts -B 2 -A 2Repository: hackerai-tech/hackerai
Length of output: 271
🏁 Script executed:
# Check what builder is in chat-logger.ts
rg -n "builder.*=" lib/api/chat-logger.ts | head -5Repository: hackerai-tech/hackerai
Length of output: 142
🏁 Script executed:
# Look at the full context of where builder is initialized in chat-logger.ts
sed -n '1,50p' lib/api/chat-logger.tsRepository: hackerai-tech/hackerai
Length of output: 1175
🏁 Script executed:
# Let's check the WideEventBuilder type definition to confirm
rg -n "WideEventBuilder\|createWideEventBuilder" lib/logger.ts -A 10 | head -40Repository: hackerai-tech/hackerai
Length of output: 48
🏁 Script executed:
# Search for WideEventBuilder definition across the codebase
rg -n "WideEventBuilder\|createWideEventBuilder" lib/Repository: hackerai-tech/hackerai
Length of output: 48
🏁 Script executed:
# Also check what's exported from lib/logger.ts
rg -n "export.*WideEventBuilder\|export.*createWideEventBuilder\|class.*EventBuilder\|function.*createWideEventBuilder" lib/logger.tsRepository: hackerai-tech/hackerai
Length of output: 48
🏁 Script executed:
# Let's look at the full logger.ts file to find where WideEventBuilder is defined
wc -l lib/logger.tsRepository: hackerai-tech/hackerai
Length of output: 83
🏁 Script executed:
# Search for class definitions or function definitions that might be WideEventBuilder
rg -n "class\|function\|export" lib/logger.ts | head -30Repository: hackerai-tech/hackerai
Length of output: 48
🏁 Script executed:
# Let's look at the structure of logger.ts
sed -n '100,200p' lib/logger.tsRepository: hackerai-tech/hackerai
Length of output: 2491
🏁 Script executed:
# Also search for the word "class" or "export" differently
grep -n "^class\|^export\|^const.*EventBuilder" lib/logger.tsRepository: hackerai-tech/hackerai
Length of output: 209
Type mismatch: WideEventBuilder.setUser() rejects the location field passed by chat-logger.
The WideEventBuilder.setUser() method (lib/logger.ts, line 158) accepts only { id: string; subscription: string }. However, lib/api/chat-logger.ts wraps this with a UserContext interface that includes an optional location field (lines 27-33). When chat-logger calls builder.setUser(user) at line 81, it passes the entire UserContext object, which TypeScript will reject because location is not in the accepted type signature.
Additionally, lib/api/chat-handler.ts (lines 137-147) passes a location object to chatLogger.setUser(), which compounds the issue downstream.
Fix by updating WideEventBuilder.setUser() to accept the location field:
setUser(user: { id: string; subscription: string; location?: { city?: string; country?: string; region?: string } }): this {🤖 Prompt for AI Agents
In `@lib/logger.ts` around lines 158 - 161, WideEventBuilder.setUser currently
types its parameter as { id: string; subscription: string } causing TypeScript
errors when chat-logger (lib/api/chat-logger.ts) and chat-handler
(lib/api/chat-handler.ts) pass a UserContext that includes an optional location;
update the WideEventBuilder.setUser signature to accept an optional location
property (e.g., location?: { city?: string; country?: string; region?: string })
so the method accepts the full UserContext object passed by chatLogger.setUser
and chatLogger callers, and ensure the implementation stores the location on
this.event.user without changing other behavior.
| "@e2b/code-interpreter": "2.3.3", | ||
| "@langchain/community": "^1.1.7", | ||
| "@monaco-editor/react": "^4.7.0", | ||
| "@openrouter/ai-sdk-provider": "^2.1.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
@openrouter/ai-sdk-provider npm package latest version
💡 Result:
The latest published version of @openrouter/ai-sdk-provider on npm is 1.2.0. [1]
🏁 Script executed:
# Check if this dependency is used in lib/ai/providers.ts
fd providers.tsRepository: hackerai-tech/hackerai
Length of output: 103
🏁 Script executed:
# Check lib/ai/providers.ts to see the import
head -50 lib/ai/providers.ts
# Get context around line 62 in package.json
sed -n '55,70p' package.jsonRepository: hackerai-tech/hackerai
Length of output: 2523
Incorrect dependency version—npm install will fail.
The specified version ^2.1.1 does not exist. The latest published version of @openrouter/ai-sdk-provider on npm is 1.2.0. Update to ^1.2.0 to match the actual package.
🤖 Prompt for AI Agents
In `@package.json` at line 62, The package version for `@openrouter/ai-sdk-provider`
in package.json is incorrect and causes install failures; update the dependency
entry "@openrouter/ai-sdk-provider": "^2.1.1" to use the published version
"^1.2.0" so npm can resolve and install the package successfully.
Summary by CodeRabbit
New Features
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.