-
Notifications
You must be signed in to change notification settings - Fork 0
fix: Replace any types in AI and monitoring modules #1091
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
base: main
Are you sure you want to change the base?
Conversation
- resilient-azure-embedding-service.ts: Replace metrics: any with proper interface, use CircuitState enum instead of string cast - ddtrace-instrumentation.ts: Add type guard for tracer initialization - index.ts: Replace VectorStoreRetriever any stub with proper interface, fix return types for secureQuery and securePromptProcessing - azure-embedding-metrics.ts: Remove unnecessary as any[] cast - agentapi-prometheus.ts: Add proper interfaces for config and HTTP handlers, use typed casts for PrometheusExporter - setup-monitoring.ts: Add helper function for environment string conversion - llm-tracer.ts: Add LLMResponseLike interface with type guard, properly type error handling, decorator parameters Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
WalkthroughThe PR improves type safety and integration patterns across AI and monitoring modules by replacing any-casts with proper type guards and interfaces. Changes include introducing a tracer initialization guard, implementing proper VectorStoreRetriever integration with typed search results, enhancing circuit-breaker state handling, refactoring Prometheus metrics initialization with explicit types, strengthening LLM response detection, and adding environment validation logic. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 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
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the 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 |
🔒 Security Audit Results✅ Secret Scanning: No secrets detected 📊 View full results: Security Audit Summary |
PR Analysis 📊Changed Files Summary:
CI Status: Running automated checks... |
Quick Checks Results
✅ All quick checks passed! |
Dependency Audit Results |
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
🤖 Fix all issues with AI agents
In `@src/lib/ai/index.ts`:
- Line 30: Replace the outdated langchain import for VectorStoreRetriever: find
the import statement that references VectorStoreRetriever (currently "import {
VectorStoreRetriever } from 'langchain/vectorstores/base';") and change it to
import from the new package export (use the `@langchain/core` vectorstores export)
so the module resolves correctly in current LangChain.js versions.
In `@src/lib/ai/resilient-azure-embedding-service.ts`:
- Around line 6-7: The imports in resilient-azure-embedding-service.ts use a mix
of relative and absolute paths; update both imports to use the project absolute
alias so they follow guidelines—replace the './azureEmbeddingService' import for
AzureEmbeddingService and the '../resilience/circuit-breaker' import for
circuitBreakerManager, CircuitBreakerError, CircuitState with their
corresponding '@/...' absolute-import paths (e.g.,
'@/lib/ai/azureEmbeddingService' and '@/resilience/circuit-breaker') so both
imports are consistent.
In `@src/lib/monitoring/agentapi-prometheus.ts`:
- Around line 84-88: The code incorrectly casts this.exporter to
PeriodicExportingMetricReader when constructing the MeterProvider; instead pass
the PrometheusExporter directly since it implements MetricReader. In the
MeterProvider constructor (symbol: MeterProvider, property: readers) remove the
cast to PeriodicExportingMetricReader and use this.exporter (or this.exporter as
MetricReader if an explicit typing is required); also update the inline comment
(PrometheusExporter extends MetricReader) to reflect that no cast is necessary.
🧹 Nitpick comments (7)
src/lib/ai/ddtrace-instrumentation.ts (1)
13-15: Consider using a type predicate for better type narrowing.The function works correctly as a boolean check, but since this is meant to be a type guard, using a type predicate return type would provide better TypeScript integration and allow type narrowing in conditional blocks.
♻️ Suggested improvement
-function isTracerInitialized(t: unknown): boolean { +function isTracerInitialized(t: unknown): t is TracerWithInitialized & { _initialized: true } { return typeof t === 'object' && t !== null && '_initialized' in t && Boolean((t as TracerWithInitialized)._initialized); }Note: The current implementation is functionally correct for the usage at line 18. The type predicate is only beneficial if you need type narrowing after the guard.
src/lib/monitoring/setup-monitoring.ts (1)
43-58: Handle NODE_ENV aliases/casing to avoid misclassification.
Right now only exact lowercase values are accepted; common variants like"prod"or"PROD"will fall back to"development"and mis-tag telemetry. Consider normalizing and mapping common aliases.♻️ Suggested tweak
- const envToEnvironment = (env: string | undefined): 'development' | 'staging' | 'production' => { - if (env === 'production' || env === 'staging' || env === 'development') { - return env; - } - return 'development'; - }; + const envToEnvironment = (env: string | undefined): 'development' | 'staging' | 'production' => { + const normalized = env?.toLowerCase() + if (normalized === 'production' || normalized === 'prod') return 'production' + if (normalized === 'staging' || normalized === 'stage') return 'staging' + return 'development' + }src/lib/monitoring/azure-embedding-metrics.ts (1)
49-53: Consider addingenvandversionto standardTags for Datadog compliance.Based on learnings, all Datadog metrics should be tagged with
env,service,version,team, andcomponent. The currentstandardTagsis missingenvandversion.Suggested improvement
this.standardTags = { component: 'azure_embedding', service: 'vector_search', - team: 'ai' + team: 'ai', + env: process.env.NODE_ENV || 'development', + version: process.env.npm_package_version || '1.0.0' };src/lib/monitoring/llm-tracer.ts (1)
49-52: Type guard is overly permissive.The
isLLMResponseguard only checks if the value is a non-null object, which means any object will pass. This is intentional for flexibility but could be strengthened to provide more safety by checking for at least one expected property.Optional: More specific type guard
function isLLMResponse(value: unknown): value is LLMResponseLike { - return typeof value === 'object' && value !== null; + if (typeof value !== 'object' || value === null) return false; + const v = value as Record<string, unknown>; + return 'output' in v || 'text' in v || 'content' in v || 'usage' in v || 'tokenUsage' in v || 'cost' in v; }src/lib/ai/index.ts (2)
126-143: Double castas unknown as VectorStoreRetrieverindicates interface mismatch.The custom retriever object doesn't fully implement
VectorStoreRetriever, requiring a double cast throughunknown. This suggests the adapter may break if langchain expects methods not implemented here.Consider:
- Implementing the full
VectorStoreRetrieverinterface- Using a different langchain abstraction that better fits your needs
- Creating a proper wrapper class that extends
VectorStoreRetriever
149-149: Replaceconsole.errorwith Winston logger.Per coding guidelines,
console.logand related methods should not be used; use the Winston logger instead. This applies to multiple locations in this file (lines 149, 193, 224, 243, 246).Example fix
+import { logger } from '@/lib/logger'; // ... - console.error('Failed to initialize default prompts:', error); + logger.error('Failed to initialize default prompts:', error);src/lib/monitoring/agentapi-prometheus.ts (1)
54-54: Replace console methods with Winston logger.Per coding guidelines, use the Winston logger instead of
console.warn,console.info, andconsole.error. This applies to multiple locations (lines 54, 77-78, 90, 92, 180, 282).
| import { aiAnalytics } from './analytics'; | ||
| // import { VectorStoreRetriever } from 'langchain/vectorstores/base'; | ||
| // import { Document } from 'langchain/document'; | ||
| import { VectorStoreRetriever } from 'langchain/vectorstores/base'; |
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:
cat -n src/lib/ai/index.ts | head -150Repository: ryanmaclean/vibecode-webgui
Length of output: 271
🌐 Web query:
langchain VectorStoreRetriever import path 2025 current version
💡 Result:
In current LangChain Python (the split-packages era, incl. 0.2.x and later), VectorStoreRetriever lives in langchain_core.vectorstores:
from langchain_core.vectorstores import VectorStoreRetrieverThis matches the reference docs/source for langchain_core.vectorstores.VectorStoreRetriever. [1], [2]
Note: In most code you don’t need to import it directly—create it via:
retriever = vector_store.as_retriever()[2]
Sources: [1], [2]
🌐 Web query:
langchain.js VectorStoreRetriever import path JavaScript TypeScript @langchain/core``
💡 Result:
In LangChain.js, VectorStoreRetriever is exported from the @langchain/core/vectorstores entrypoint:
import { VectorStoreRetriever } from "@langchain/core/vectorstores";Types are in the same module, e.g.:
import type { VectorStoreRetrieverInput } from "@langchain/core/vectorstores";[1] [2]
Update langchain import to use @langchain/core package.
The import path langchain/vectorstores/base is outdated. In current LangChain.js versions (the split-packages structure), VectorStoreRetriever is exported from @langchain/core/vectorstores:
import { VectorStoreRetriever } from "@langchain/core/vectorstores";Update line 30 to use the correct import path.
🤖 Prompt for AI Agents
In `@src/lib/ai/index.ts` at line 30, Replace the outdated langchain import for
VectorStoreRetriever: find the import statement that references
VectorStoreRetriever (currently "import { VectorStoreRetriever } from
'langchain/vectorstores/base';") and change it to import from the new package
export (use the `@langchain/core` vectorstores export) so the module resolves
correctly in current LangChain.js versions.
| import { AzureEmbeddingService } from './azureEmbeddingService' | ||
| import { circuitBreakerManager, CircuitBreakerError } from '../resilience/circuit-breaker' | ||
| import { circuitBreakerManager, CircuitBreakerError, CircuitState } from '../resilience/circuit-breaker' |
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.
🛠️ Refactor suggestion | 🟠 Major
Use @/ absolute imports for the new resilience import.
The added relative import breaks the project guideline for absolute imports; consider updating both imports for consistency.
Suggested update
-import { AzureEmbeddingService } from './azureEmbeddingService'
-import { circuitBreakerManager, CircuitBreakerError, CircuitState } from '../resilience/circuit-breaker'
+import { AzureEmbeddingService } from '@/lib/ai/azureEmbeddingService'
+import { circuitBreakerManager, CircuitBreakerError, CircuitState } from '@/lib/resilience/circuit-breaker'As per coding guidelines, prefer @/ absolute imports.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { AzureEmbeddingService } from './azureEmbeddingService' | |
| import { circuitBreakerManager, CircuitBreakerError } from '../resilience/circuit-breaker' | |
| import { circuitBreakerManager, CircuitBreakerError, CircuitState } from '../resilience/circuit-breaker' | |
| import { AzureEmbeddingService } from '@/lib/ai/azureEmbeddingService' | |
| import { circuitBreakerManager, CircuitBreakerError, CircuitState } from '@/lib/resilience/circuit-breaker' |
🤖 Prompt for AI Agents
In `@src/lib/ai/resilient-azure-embedding-service.ts` around lines 6 - 7, The
imports in resilient-azure-embedding-service.ts use a mix of relative and
absolute paths; update both imports to use the project absolute alias so they
follow guidelines—replace the './azureEmbeddingService' import for
AzureEmbeddingService and the '../resilience/circuit-breaker' import for
circuitBreakerManager, CircuitBreakerError, CircuitState with their
corresponding '@/...' absolute-import paths (e.g.,
'@/lib/ai/azureEmbeddingService' and '@/resilience/circuit-breaker') so both
imports are consistent.
| // PrometheusExporter extends MetricReader, so it can be used directly | ||
| this.meterProvider = new MeterProvider({ | ||
| resource, | ||
| readers: [this.exporter as any] | ||
| readers: [this.exporter as unknown as PeriodicExportingMetricReader] | ||
| }); |
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.
Incorrect cast to PeriodicExportingMetricReader.
The comment states PrometheusExporter extends MetricReader, but the code casts to PeriodicExportingMetricReader. These are different types. The readers array expects MetricReader, and PrometheusExporter already implements this interface.
Suggested fix
+import { MeterProvider, MetricReader } from '@opentelemetry/sdk-metrics';
// ...
this.meterProvider = new MeterProvider({
resource,
- readers: [this.exporter as unknown as PeriodicExportingMetricReader]
+ readers: [this.exporter as MetricReader]
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // PrometheusExporter extends MetricReader, so it can be used directly | |
| this.meterProvider = new MeterProvider({ | |
| resource, | |
| readers: [this.exporter as any] | |
| readers: [this.exporter as unknown as PeriodicExportingMetricReader] | |
| }); | |
| // PrometheusExporter extends MetricReader, so it can be used directly | |
| this.meterProvider = new MeterProvider({ | |
| resource, | |
| readers: [this.exporter as MetricReader] | |
| }); |
🤖 Prompt for AI Agents
In `@src/lib/monitoring/agentapi-prometheus.ts` around lines 84 - 88, The code
incorrectly casts this.exporter to PeriodicExportingMetricReader when
constructing the MeterProvider; instead pass the PrometheusExporter directly
since it implements MetricReader. In the MeterProvider constructor (symbol:
MeterProvider, property: readers) remove the cast to
PeriodicExportingMetricReader and use this.exporter (or this.exporter as
MetricReader if an explicit typing is required); also update the inline comment
(PrometheusExporter extends MetricReader) to reflect that no cast is necessary.
Build Status ✅ Build successful✅ Build completed successfully! |
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.
Pull request overview
This pull request improves type safety by replacing 17 explicit as any casts with proper TypeScript interfaces across AI and monitoring modules. The changes introduce type guards, interfaces for external library types, and proper error handling patterns.
Changes:
- Replaces implicit type casts with explicit type guards and interfaces
- Adds proper typing for Datadog tracing, Prometheus metrics, and LLM observability
- Improves error handling by replacing
anywithunknownand proper type narrowing
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/monitoring/setup-monitoring.ts | Adds envToEnvironment helper to safely convert environment strings to typed literals |
| src/lib/monitoring/llm-tracer.ts | Introduces LLMResponseLike interface and type guards for LLM response detection |
| src/lib/monitoring/azure-embedding-metrics.ts | Removes unnecessary type cast on line 103 |
| src/lib/monitoring/agentapi-prometheus.ts | Adds PrometheusExporterConfig interface and HTTP request/response types |
| src/lib/ai/resilient-azure-embedding-service.ts | Uses CircuitState enum instead of string literal cast |
| src/lib/ai/index.ts | Imports proper VectorStoreRetriever and SearchResult types |
| src/lib/ai/ddtrace-instrumentation.ts | Adds TracerWithInitialized interface with type guard for dd-trace initialization check |
| await this.search.addDocuments(documents.map(doc => ({ | ||
| pageContent: doc.pageContent, | ||
| metadata: doc.metadata || {} | ||
| })), 'prompts'); |
Copilot
AI
Jan 23, 2026
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.
The mapped documents are plain objects, but VectorSearch.addDocuments expects Document[] from '@langchain/core/documents'. The Document class needs to be imported and instantiated for each document. The plain objects should be wrapped like new Document({ pageContent: doc.pageContent, metadata: doc.metadata || {} }).
| this.meterProvider = new MeterProvider({ | ||
| resource, | ||
| readers: [this.exporter as any] | ||
| readers: [this.exporter as unknown as PeriodicExportingMetricReader] |
Copilot
AI
Jan 23, 2026
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.
The cast as unknown as PeriodicExportingMetricReader on line 87 is problematic. PrometheusExporter is not a PeriodicExportingMetricReader - it's a MetricReader. The MeterProvider's readers array expects MetricReader[], not PeriodicExportingMetricReader[]. This cast should be as unknown as MetricReader or ideally removed if PrometheusExporter already extends MetricReader (which it should according to the comment).
| host: config.host, | ||
| preventServerStart: config.preventServerStart | ||
| } as any, | ||
| exporterConfig as ConstructorParameters<typeof PrometheusExporter>[0], |
Copilot
AI
Jan 23, 2026
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.
Using ConstructorParameters<typeof PrometheusExporter>[0] as the cast target is overly complex and fragile. Since PrometheusExporterConfig was already defined with the exact same properties as the PrometheusExporter constructor accepts, the cast could be simplified or potentially removed entirely. Consider either: (1) verifying that PrometheusExporterConfig matches the actual constructor signature and removing the cast, or (2) using a simpler type assertion if truly needed.
| exporterConfig as ConstructorParameters<typeof PrometheusExporter>[0], | |
| exporterConfig, |
| if (typeof (this.exporter as unknown as { collect?: () => Promise<void> }).collect === 'function') { | ||
| await (this.exporter as unknown as { collect: () => Promise<void> }).collect(); | ||
| } |
Copilot
AI
Jan 23, 2026
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.
The runtime type checking for the collect method is good defensive programming, but the implementation still uses type assertions. Consider creating a proper interface for this:
interface CollectableExporter {
collect(): Promise<void>;
}Then use a type guard: function hasCollect(obj: unknown): obj is CollectableExporter to make the type checking more explicit and maintainable.
|
|
||
| // Type guard for LLM response | ||
| function isLLMResponse(value: unknown): value is LLMResponseLike { | ||
| return typeof value === 'object' && value !== null; |
Copilot
AI
Jan 23, 2026
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.
The type guard isLLMResponse on line 50 is too permissive - it only checks if the value is a non-null object. This will return true for any object, including arrays, Error instances, etc. The guard should verify at least one of the expected properties exists, for example: return typeof value === 'object' && value !== null && ('output' in value || 'text' in value || 'content' in value || 'usage' in value || 'tokenUsage' in value || 'cost' in value);
| return typeof value === 'object' && value !== null; | |
| return ( | |
| typeof value === 'object' && | |
| value !== null && | |
| ('output' in value || | |
| 'text' in value || | |
| 'content' in value || | |
| 'usage' in value || | |
| 'tokenUsage' in value || | |
| 'cost' in value) | |
| ); |
Test Results ✅ PassedTest Suites: 2 skipped, 343 passed, 343 of 345 total ✅ All tests passed! Ready for review. View test outputCheck the Actions tab for detailed test output. |
PR Status Summary
✅ All checks passed! This PR is ready to merge. 🎉 |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
Quick Checks Results
✅ All quick checks passed! |
PR Analysis 📊Changed Files Summary:
CI Status: Running automated checks... |
Test Results ✅ PassedTest Suites: 2 skipped, 343 passed, 343 of 345 total ✅ All tests passed! Ready for review. View test outputCheck the Actions tab for detailed test output. |
Build Status ✅ Build successful✅ Build completed successfully! |
PR Status Summary
✅ All checks passed! This PR is ready to merge. 🎉 |
Dependency Audit Results |
Summary
as anycasts across 7 AI and monitoring filesChanges
src/lib/ai/resilient-azure-embedding-service.ts- CircuitState enum usagesrc/lib/ai/ddtrace-instrumentation.ts- TracerWithInitialized interfacesrc/lib/ai/index.ts- VectorStoreRetriever and SearchResult typessrc/lib/monitoring/azure-embedding-metrics.ts- Removed unnecessary castsrc/lib/monitoring/agentapi-prometheus.ts- PrometheusExporterConfig interfacesrc/lib/monitoring/setup-monitoring.ts- envToEnvironment helpersrc/lib/monitoring/llm-tracer.ts- LLMResponseLike interface, type guardsTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
Bug Fixes
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.