refactor: eliminate remaining 'any' types in ai.ts#17
refactor: eliminate remaining 'any' types in ai.ts#17cosmicallycooked wants to merge 1 commit into1a35e1:mainfrom
Conversation
Add typed interfaces for vendor response shapes (VendorErrorBody, OpenAIResponsesResult, OpenAIChatCompletionResult, AnthropicMessagesResult) and replace every explicit `any` cast and annotation. No logic changes.
📝 WalkthroughWalkthroughChanges to Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/lib/ai.ts (1)
241-247: Add runtime shape guards before assertingtoolBlock.inputtypes.
inputis stillunknownat runtime; direct assertions can silently pass malformed payloads downstream. A small type-guard step would make these paths resilient without changing happy-path behavior.♻️ Suggested hardening diff
+function isGeneratedInterest(value: unknown): value is GeneratedInterest { + if (!value || typeof value !== 'object') return false + const v = value as Partial<GeneratedInterest> + return ( + typeof v.name === 'string' && + typeof v.description === 'string' && + Array.isArray(v.keywords) && + v.keywords.every((k) => typeof k === 'string') && + Array.isArray(v.relatedTopics) && + v.relatedTopics.every((t) => typeof t === 'string') + ) +} + +function isGeneratedReply(value: unknown): value is GeneratedReply { + return !!value && typeof value === 'object' && typeof (value as { reply?: unknown }).reply === 'string' +}- return toolBlock.input as GeneratedInterest + if (!isGeneratedInterest(toolBlock.input)) { + throw new Error('Anthropic tool output did not match GeneratedInterest schema') + } + return toolBlock.input- return toolBlock.input as GeneratedReply + if (!isGeneratedReply(toolBlock.input)) { + throw new Error('Anthropic tool output did not match GeneratedReply schema') + } + return toolBlock.input- const wrapper = toolBlock.input as { suggestions: GeneratedInterest[] } - return wrapper.suggestions + const wrapper = toolBlock.input as { suggestions?: unknown } + if (!Array.isArray(wrapper.suggestions) || !wrapper.suggestions.every(isGeneratedInterest)) { + throw new Error('Anthropic tool output did not include valid suggestions') + } + return wrapper.suggestionsAlso applies to: 338-344, 498-505
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/ai.ts` around lines 241 - 247, The code currently asserts toolBlock.input as GeneratedInterest without runtime validation; add a small runtime shape guard (e.g., isGeneratedInterest or validateToolInput) that checks required fields and types on toolBlock.input before casting, and throw a clear Error if validation fails; update the parsing sites that reference data, toolBlock and the cast to GeneratedInterest (the block in src/lib/ai.ts around the return of toolBlock.input and the similar places at the other two occurrences) to call the guard and only then return the properly-typed value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/lib/ai.ts`:
- Around line 241-247: The code currently asserts toolBlock.input as
GeneratedInterest without runtime validation; add a small runtime shape guard
(e.g., isGeneratedInterest or validateToolInput) that checks required fields and
types on toolBlock.input before casting, and throw a clear Error if validation
fails; update the parsing sites that reference data, toolBlock and the cast to
GeneratedInterest (the block in src/lib/ai.ts around the return of
toolBlock.input and the similar places at the other two occurrences) to call the
guard and only then return the properly-typed value.
Summary
Rebased on current main (post-#11 structured outputs). Replaces every remaining
anytype insrc/lib/ai.tswith dedicated interfaces:VendorErrorBody— typed error response shape (replaces 6×(err as any))OpenAIResponsesResult/OpenAIResponsesContent— Responses API output chain (replaces 8×(b: any)/(c: any))OpenAIChatCompletionResult— Chat Completions choices shapeAnthropicMessagesResult/AnthropicContentBlock— Messages API withtool_useblocks (replaces 3×(b: any))No logic changes, no runtime behavior changes. Zero new type errors introduced.
Test plan
pnpm typecheck— zero new errors (pre-existingink-text-inputandvitestmodule errors unchanged)grep -w any src/lib/ai.tsconfirms noanytype annotations remain🤖 Generated with Claude Code