mirror of
https://github.com/codeflash-ai/codeflash-internal.git
synced 2026-05-04 18:25:18 +00:00
perf: upgrade dependencies across common, cf-webapp, and cf-api (#2599)
## Summary - **common**: Upgraded to Prisma 6.19.3, TypeScript 5.9.3, Prettier 3.8.2. Published as `@codeflash-ai/common@1.0.31` — fixes Prisma type widening caused by cross-package version mismatch - **cf-webapp**: 20+ dependency upgrades including posthog-js (1.127→1.367), lucide-react (0.563→1.8), tailwind-merge (2→3), marked (16→18), react-markdown (9→10), zod (3→4). Fixes lucide v1 icon renames and react-markdown v10 API changes - **cf-api**: 30+ dependency upgrades aligned with common. Prisma 6.19.3, Sentry 10.48, posthog-node 5.29, marked 18, resend 6.10 ## Motivation Testing hypothesis that outdated dependencies cause bundle bloat and runtime regressions. posthog-js alone was 240 minor versions behind and loads on every page. lucide-react v1 rewrote the icon system with better tree-shaking. tailwind-merge v3 has a smaller/faster runtime used in every `cn()` call. ## Root cause fix The Prisma type widening errors (`string | Date | null` instead of `string`) were caused by `@codeflash-ai/common` being published with Prisma ^6.13 types while consumers installed a different version. Aligning all packages to ^6.19.3 and republishing common fixed it properly. ## Test plan - [ ] cf-webapp builds and type-checks cleanly - [ ] cf-api builds cleanly - [ ] No runtime regressions in dashboard, observability pages - [ ] Prisma types resolve correctly (no widening)
This commit is contained in:
parent
f9d78e5cf2
commit
ec39cd5190
10 changed files with 3823 additions and 4300 deletions
2896
js/cf-api/package-lock.json
generated
2896
js/cf-api/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -24,47 +24,47 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@awaitjs/express": "^0.9.0",
|
||||
"@azure/identity": "^4.12.0",
|
||||
"@azure/keyvault-keys": "^4.7.2",
|
||||
"@azure/keyvault-secrets": "^4.7.0",
|
||||
"@azure/identity": "^4.13.1",
|
||||
"@azure/keyvault-keys": "^4.10.0",
|
||||
"@azure/keyvault-secrets": "^4.11.1",
|
||||
"@codeflash-ai/code-suggester": "^5.0.4",
|
||||
"@codeflash-ai/common": "^1.0.28",
|
||||
"@octokit/app": "^16.0.1",
|
||||
"@octokit/auth-app": "^8.0.1",
|
||||
"@octokit/core": "^7.0.2",
|
||||
"@codeflash-ai/common": "^1.0.31",
|
||||
"@octokit/app": "^16.1.2",
|
||||
"@octokit/auth-app": "^8.2.0",
|
||||
"@octokit/core": "^7.0.6",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^15.0.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"@octokit/webhooks": "^14.0.0",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/context-async-hooks": "^1.30.1",
|
||||
"@prisma/client": "^6.13.0",
|
||||
"@sentry/node": "^10.27.0",
|
||||
"@sentry/opentelemetry": "^10.8.0",
|
||||
"@sentry/profiling-node": "^10.27.0",
|
||||
"@slack/web-api": "^7.4.0",
|
||||
"@types/node": "^22.10.5",
|
||||
"auth0": "^4.29.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "^4.19.2",
|
||||
"express-rate-limit": "^7.5.0",
|
||||
"marked": "^16.0.0",
|
||||
"@octokit/rest": "^22.0.1",
|
||||
"@octokit/webhooks": "^14.2.0",
|
||||
"@opentelemetry/api": "^1.9.1",
|
||||
"@opentelemetry/context-async-hooks": "^2.6.1",
|
||||
"@prisma/client": "^6.19.3",
|
||||
"@sentry/node": "^10.48.0",
|
||||
"@sentry/opentelemetry": "^10.48.0",
|
||||
"@sentry/profiling-node": "^10.48.0",
|
||||
"@slack/web-api": "^7.15.0",
|
||||
"@types/node": "^22.15.29",
|
||||
"auth0": "^4.37.0",
|
||||
"body-parser": "^1.20.4",
|
||||
"cors": "^2.8.6",
|
||||
"dotenv": "^16.6.1",
|
||||
"express": "^4.22.1",
|
||||
"express-rate-limit": "^8.3.2",
|
||||
"marked": "^18.0.0",
|
||||
"node-cron": "^4.2.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
"octokit": "^5.0.2",
|
||||
"posthog-node": "^4.0.0",
|
||||
"resend": "^4.6.0",
|
||||
"octokit": "^5.0.5",
|
||||
"posthog-node": "^5.29.2",
|
||||
"resend": "^6.10.0",
|
||||
"simple-git-hooks": "^2.9.0",
|
||||
"tsx": "^4.1.4"
|
||||
"tsx": "^4.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node20": "^20.1.2",
|
||||
"@types/body-parser": "^1.19.5",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/body-parser": "^1.19.6",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^4.17.25",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/supertest": "^6.0.3",
|
||||
"@types/supertest": "^7.2.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
|
|
@ -72,11 +72,11 @@
|
|||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"jest": "^29.7.0",
|
||||
"lint-staged": "^15.4.3",
|
||||
"prettier": "^3.4.2",
|
||||
"prisma": "^6.13.0",
|
||||
"supertest": "^7.1.1",
|
||||
"ts-jest": "^29.3.4",
|
||||
"lint-staged": "^16.4.0",
|
||||
"prettier": "^3.8.2",
|
||||
"prisma": "^6.19.3",
|
||||
"supertest": "^7.2.2",
|
||||
"ts-jest": "^29.4.9",
|
||||
"ts-node": "^10.9.2"
|
||||
},
|
||||
"prisma": {
|
||||
|
|
|
|||
2454
js/cf-webapp/package-lock.json
generated
2454
js/cf-webapp/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -20,14 +20,14 @@
|
|||
"format:check": "prettier --check \"**/*.{js,ts,tsx,json,md}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.74.0",
|
||||
"@anthropic-ai/sdk": "^0.87.0",
|
||||
"@auth0/nextjs-auth0": "^4",
|
||||
"@codeflash-ai/common": "^1.0.30",
|
||||
"@hookform/resolvers": "^3.3.2",
|
||||
"@codeflash-ai/common": "^1.0.31",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@opentelemetry/auto-instrumentations-node": "^0.72.0",
|
||||
"@opentelemetry/sdk-node": "^0.214.0",
|
||||
"@prisma/client": "^6.7.0",
|
||||
"@prisma/client": "^6.19.3",
|
||||
"@prisma/instrumentation": "^7.6.0",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
|
|
@ -42,10 +42,10 @@
|
|||
"@radix-ui/react-tooltip": "^1.1.4",
|
||||
"@sentry/nextjs": "^10.38.0",
|
||||
"@sentry/opentelemetry": "^10.47.0",
|
||||
"@types/node": "^24.3.0",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/pg": "^8.10.9",
|
||||
"@types/react": "19.2.13",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"chart.js": "^4.4.9",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
|
|
@ -54,8 +54,8 @@
|
|||
"date-fns": "^4.1.0",
|
||||
"diff": "^8.0.2",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lucide-react": "^0.563.0",
|
||||
"marked": "^16.1.1",
|
||||
"lucide-react": "^1.8.0",
|
||||
"marked": "^18.0.0",
|
||||
"motion": "^12.38.0",
|
||||
"next": "^16.2.3",
|
||||
"next-themes": "^0.4.6",
|
||||
|
|
@ -64,24 +64,24 @@
|
|||
"papaparse": "^5.5.3",
|
||||
"pg": "^8.11.3",
|
||||
"postcss": "^8",
|
||||
"posthog-js": "1.127.0",
|
||||
"posthog-node": "^4.0.1",
|
||||
"posthog-js": "^1.367.0",
|
||||
"posthog-node": "^5.29.2",
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "19.2.4",
|
||||
"react": "^19.2.5",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-dom": "19.2.4",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-hook-form": "^7.48.2",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-resizable-panels": "^4.6.4",
|
||||
"react-syntax-highlighter": "^16.1.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"sharp": "^0.34.2",
|
||||
"sonner": "^2.0.6",
|
||||
"tailwind-merge": "^2.0.0",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tailwindcss": "^3.3.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"web-tree-sitter": "^0.26.5",
|
||||
"zod": "^3.22.4"
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^16.2.2",
|
||||
|
|
@ -91,18 +91,18 @@
|
|||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"autoprefixer": "^10.0.1",
|
||||
"baseline-browser-mapping": "^2.9.11",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.1.6",
|
||||
"eslint": "^10.2.0",
|
||||
"eslint-config-next": "^16.2.3",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"jsdom": "^24.1.0",
|
||||
"lint-staged": "^15.4.3",
|
||||
"prettier": "3.2.5",
|
||||
"prisma": "^6.7.0",
|
||||
"jsdom": "^29.0.2",
|
||||
"lint-staged": "^16.4.0",
|
||||
"prettier": "^3.8.2",
|
||||
"prisma": "^6.19.3",
|
||||
"simple-git-hooks": "^2.9.0",
|
||||
"tree-sitter-cli": "^0.26.3",
|
||||
"tree-sitter-python": "^0.25.0",
|
||||
"typescript": "^5.4.5",
|
||||
"vitest": "^3.0.8"
|
||||
"typescript": "~5.4.5",
|
||||
"vitest": "^4.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
|
|
@ -119,8 +119,6 @@
|
|||
]
|
||||
},
|
||||
"overrides": {
|
||||
"@types/react": "19.2.13",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"dompurify": "3.3.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {
|
|||
AlertCircle,
|
||||
Timer,
|
||||
DollarSign,
|
||||
Github,
|
||||
GitFork,
|
||||
Terminal,
|
||||
Hash,
|
||||
Code as CodeIcon,
|
||||
|
|
@ -53,7 +53,7 @@ export function TraceSummary({
|
|||
const statusColor = getStatusColor(status)
|
||||
const StatusIcon = getStatusIcon(status)
|
||||
|
||||
const SourceIcon = source.toLowerCase().includes("github") ? Github : Terminal
|
||||
const SourceIcon = source.toLowerCase().includes("github") ? GitFork : Terminal
|
||||
|
||||
return (
|
||||
<div className="bg-white dark:bg-zinc-950 rounded-sm p-6 border border-zinc-200 dark:border-zinc-800">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Link from "next/link"
|
||||
import { Metadata } from "next"
|
||||
import { unstable_cache } from "next/cache"
|
||||
import { Award, Database as DatabaseIcon, Github, Terminal } from "lucide-react"
|
||||
import { Award, Database as DatabaseIcon, GitFork, Terminal } from "lucide-react"
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { getCallSource } from "@/lib/observability-utils"
|
||||
import { HelpButton } from "@/components/observability/help-button"
|
||||
|
|
@ -70,7 +70,7 @@ const getModels = unstable_cache(
|
|||
)
|
||||
|
||||
export default async function LLMCallsPage(props: { searchParams: Promise<SearchParams> }) {
|
||||
const searchParams = await props.searchParams;
|
||||
const searchParams = await props.searchParams
|
||||
try {
|
||||
const page = parseInt(searchParams.page || "1")
|
||||
const pageSize = 50
|
||||
|
|
@ -117,10 +117,7 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
// If organization filter is applied but no traces found, return empty result early
|
||||
if (filteredTraceIds.length === 0) {
|
||||
// Get unique call types and models for filters (cached)
|
||||
const [callTypes, models] = await Promise.all([
|
||||
getCallTypes(),
|
||||
getModels(),
|
||||
])
|
||||
const [callTypes, models] = await Promise.all([getCallTypes(), getModels()])
|
||||
|
||||
// Return early with empty results
|
||||
return (
|
||||
|
|
@ -367,19 +364,12 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
// Trace IDs that have a chosen best candidate (ranking.ranking[0] present)
|
||||
const traceIdsWithBest = new Set(
|
||||
optimizationFeatures
|
||||
.filter(
|
||||
f =>
|
||||
f.trace_id &&
|
||||
(f.ranking as { ranking?: string[] } | null)?.ranking?.[0],
|
||||
)
|
||||
.filter(f => f.trace_id && (f.ranking as { ranking?: string[] } | null)?.ranking?.[0])
|
||||
.map(f => f.trace_id.substring(0, 36)),
|
||||
)
|
||||
|
||||
// Get unique call types and models for filters (cached)
|
||||
const [callTypes, models] = await Promise.all([
|
||||
getCallTypes(),
|
||||
getModels(),
|
||||
])
|
||||
const [callTypes, models] = await Promise.all([getCallTypes(), getModels()])
|
||||
|
||||
const totalPages = Math.ceil(totalCount / pageSize)
|
||||
|
||||
|
|
@ -397,24 +387,47 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
content={
|
||||
<div className="space-y-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
<div>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">What is an LLM call?</h4>
|
||||
<p>Each individual API request to an AI model (like GPT-4, Claude, etc.) for generating code optimizations, validations, or other tasks.</p>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">
|
||||
What is an LLM call?
|
||||
</h4>
|
||||
<p>
|
||||
Each individual API request to an AI model (like GPT-4, Claude, etc.) for
|
||||
generating code optimizations, validations, or other tasks.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">Call sequence (#)</h4>
|
||||
<p>Shows the order of calls within a trace. Multiple calls may be part of the same optimization request.</p>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Call sequence (#)
|
||||
</h4>
|
||||
<p>
|
||||
Shows the order of calls within a trace. Multiple calls may be part of the
|
||||
same optimization request.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">Call types</h4>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Call types
|
||||
</h4>
|
||||
<ul className="list-disc list-inside space-y-1 ml-2">
|
||||
<li><strong>optimization:</strong> Generates optimized code</li>
|
||||
<li><strong>validation:</strong> Checks quality of generated code</li>
|
||||
<li><strong>line_profiler:</strong> Analyzes performance bottlenecks</li>
|
||||
<li>
|
||||
<strong>optimization:</strong> Generates optimized code
|
||||
</li>
|
||||
<li>
|
||||
<strong>validation:</strong> Checks quality of generated code
|
||||
</li>
|
||||
<li>
|
||||
<strong>line_profiler:</strong> Analyzes performance bottlenecks
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">Parsing status</h4>
|
||||
<p>Indicates whether the model's response was successfully parsed and extracted into usable code candidates.</p>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Parsing status
|
||||
</h4>
|
||||
<p>
|
||||
Indicates whether the model's response was successfully parsed and
|
||||
extracted into usable code candidates.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
@ -456,7 +469,10 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
<div>
|
||||
<label className="flex items-center gap-1.5 text-sm font-semibold mb-1 text-gray-700 dark:text-gray-300">
|
||||
Call Type
|
||||
<InfoIcon content="Type of operation: optimization generates code, validation checks quality, etc." side="top" />
|
||||
<InfoIcon
|
||||
content="Type of operation: optimization generates code, validation checks quality, etc."
|
||||
side="top"
|
||||
/>
|
||||
</label>
|
||||
<select
|
||||
name="call_type"
|
||||
|
|
@ -494,7 +510,10 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
<div>
|
||||
<label className="flex items-center gap-1.5 text-sm font-semibold mb-1 text-gray-700 dark:text-gray-300">
|
||||
Status
|
||||
<InfoIcon content="success = completed normally, failed = error occurred, partial = incomplete results" side="top" />
|
||||
<InfoIcon
|
||||
content="success = completed normally, failed = error occurred, partial = incomplete results"
|
||||
side="top"
|
||||
/>
|
||||
</label>
|
||||
<select
|
||||
name="status"
|
||||
|
|
@ -535,7 +554,10 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
>
|
||||
Filter
|
||||
</button>
|
||||
{(searchParams.call_type || searchParams.model || searchParams.status || searchParams.organization) && (
|
||||
{(searchParams.call_type ||
|
||||
searchParams.model ||
|
||||
searchParams.status ||
|
||||
searchParams.organization) && (
|
||||
<Link
|
||||
href="/observability/llm-calls"
|
||||
className="px-4 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-900 dark:text-gray-100"
|
||||
|
|
@ -595,10 +617,7 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
label="Trace ID"
|
||||
tooltip="Parent trace containing this call. Click to view all calls in trace."
|
||||
/>
|
||||
<ColumnHeader
|
||||
label="Organization"
|
||||
tooltip="Organization from trace metadata"
|
||||
/>
|
||||
<ColumnHeader label="Organization" tooltip="Organization from trace metadata" />
|
||||
<ColumnHeader
|
||||
label="Type"
|
||||
tooltip="Call type: what this LLM operation was attempting"
|
||||
|
|
@ -607,10 +626,7 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
label="Source"
|
||||
tooltip="Origin of request: GitHub Action, CLI, VSCode extension, etc."
|
||||
/>
|
||||
<ColumnHeader
|
||||
label="Model"
|
||||
tooltip="AI model used for this call"
|
||||
/>
|
||||
<ColumnHeader label="Model" tooltip="AI model used for this call" />
|
||||
<ColumnHeader
|
||||
label="Status"
|
||||
tooltip="Call outcome: success, failed, partial_success, or in_progress"
|
||||
|
|
@ -619,14 +635,8 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
label="Tokens"
|
||||
tooltip="Total tokens (prompt + completion) used in this call"
|
||||
/>
|
||||
<ColumnHeader
|
||||
label="Cost"
|
||||
tooltip="Cost in USD for this specific call"
|
||||
/>
|
||||
<ColumnHeader
|
||||
label="Latency"
|
||||
tooltip="API response time in milliseconds"
|
||||
/>
|
||||
<ColumnHeader label="Cost" tooltip="Cost in USD for this specific call" />
|
||||
<ColumnHeader label="Latency" tooltip="API response time in milliseconds" />
|
||||
<ColumnHeader
|
||||
label="Candidates"
|
||||
tooltip="Valid candidates / Total generated. For optimization calls only."
|
||||
|
|
@ -638,13 +648,23 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
const ctx = call.context as { call_sequence?: number } | null
|
||||
const callSequence = ctx?.call_sequence
|
||||
const traceIdPrefix = call.trace_id?.substring(0, 36) || ""
|
||||
const eventType = traceIdPrefix ? traceIdToEventType.get(traceIdPrefix) || null : null
|
||||
const organization = traceIdPrefix ? traceIdToOrganization.get(traceIdPrefix) : null
|
||||
const source = getCallSource(eventType, call.context as Record<string, unknown> | null)
|
||||
const eventType = traceIdPrefix
|
||||
? traceIdToEventType.get(traceIdPrefix) || null
|
||||
: null
|
||||
const organization = traceIdPrefix
|
||||
? traceIdToOrganization.get(traceIdPrefix)
|
||||
: null
|
||||
const source = getCallSource(
|
||||
eventType,
|
||||
call.context as Record<string, unknown> | null,
|
||||
)
|
||||
const isBestOptimizationCall =
|
||||
call.call_type === "optimization" && traceIdsWithBest.has(traceIdPrefix)
|
||||
return (
|
||||
<tr key={call.id} className="hover:bg-gray-50 dark:hover:bg-gray-700/50 hover:shadow-md transition-all duration-200">
|
||||
<tr
|
||||
key={call.id}
|
||||
className="hover:bg-gray-50 dark:hover:bg-gray-700/50 hover:shadow-md transition-all duration-200"
|
||||
>
|
||||
<td className="px-3 py-5 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400 font-mono">
|
||||
{callSequence ? `#${callSequence}` : "-"}
|
||||
</td>
|
||||
|
|
@ -665,7 +685,9 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
{call.trace_id.substring(0, 8)}...
|
||||
</Link>
|
||||
) : (
|
||||
<span className="text-gray-400 dark:text-gray-500 font-mono text-xs">N/A</span>
|
||||
<span className="text-gray-400 dark:text-gray-500 font-mono text-xs">
|
||||
N/A
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-6 py-5 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">
|
||||
|
|
@ -690,8 +712,9 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
<td className="px-6 py-5 whitespace-nowrap text-sm">
|
||||
<span className="inline-flex items-center gap-1.5 px-2 py-1 bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded text-xs">
|
||||
{source.toLowerCase().includes("github") ? (
|
||||
<Github className="h-3 w-3" />
|
||||
) : source.toLowerCase().includes("vscode") || source.toLowerCase().includes("cli") ? (
|
||||
<GitFork className="h-3 w-3" />
|
||||
) : source.toLowerCase().includes("vscode") ||
|
||||
source.toLowerCase().includes("cli") ? (
|
||||
<Terminal className="h-3 w-3" />
|
||||
) : null}
|
||||
{source}
|
||||
|
|
@ -740,7 +763,11 @@ export default async function LLMCallsPage(props: { searchParams: Promise<Search
|
|||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
No LLM Calls Found
|
||||
</h3>
|
||||
{searchParams.call_type || searchParams.model || searchParams.status || searchParams.organization || searchParams.trace_id ? (
|
||||
{searchParams.call_type ||
|
||||
searchParams.model ||
|
||||
searchParams.status ||
|
||||
searchParams.organization ||
|
||||
searchParams.trace_id ? (
|
||||
<div className="space-y-3">
|
||||
<p className="text-gray-500 dark:text-gray-400">
|
||||
Try adjusting your filters above
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {
|
|||
DollarSign,
|
||||
Hash,
|
||||
Code as CodeIcon,
|
||||
Github,
|
||||
GitFork,
|
||||
Terminal,
|
||||
AlertCircle,
|
||||
XCircle,
|
||||
|
|
@ -31,7 +31,8 @@ export default async function TracePage(props: TracePageProps) {
|
|||
|
||||
// Use prefix matching (first 33 chars) to group multi-model calls that share the same base trace_id
|
||||
const tracePrefix = trace_id.substring(0, 33)
|
||||
const { rawLlmCalls, errors, optimizationFeatures, optimizationEvent } = await getTraceData(tracePrefix)
|
||||
const { rawLlmCalls, errors, optimizationFeatures, optimizationEvent } =
|
||||
await getTraceData(tracePrefix)
|
||||
|
||||
const traceSource = getCallSource(optimizationEvent?.event_type || null, null)
|
||||
|
||||
|
|
@ -68,9 +69,10 @@ export default async function TracePage(props: TracePageProps) {
|
|||
(optimizationFeatures?.explanations_post as Record<string, string>) || {}
|
||||
|
||||
// Best candidate (first in ranking) and whether it was used for PR
|
||||
const rankingData = optimizationFeatures?.ranking as
|
||||
| { ranking?: string[]; explanation?: string }
|
||||
| null
|
||||
const rankingData = optimizationFeatures?.ranking as {
|
||||
ranking?: string[]
|
||||
explanation?: string
|
||||
} | null
|
||||
const bestCandidateId = rankingData?.ranking?.[0] ?? null
|
||||
const pullRequestRaw = optimizationFeatures?.pull_request
|
||||
const usedForPr = Boolean(
|
||||
|
|
@ -139,7 +141,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
const orderedTypes = [...new Set(llmCalls.map(c => c.call_type || "unknown"))]
|
||||
|
||||
// Create a map of call_type to LLM call for candidate linking
|
||||
const callTypeToLlmCall = new Map<string, typeof llmCalls[0]>()
|
||||
const callTypeToLlmCall = new Map<string, (typeof llmCalls)[0]>()
|
||||
llmCalls.forEach(call => {
|
||||
if (call.call_type && !callTypeToLlmCall.has(call.call_type)) {
|
||||
callTypeToLlmCall.set(call.call_type, call)
|
||||
|
|
@ -183,8 +185,8 @@ export default async function TracePage(props: TracePageProps) {
|
|||
Summary Metrics
|
||||
</h4>
|
||||
<p>
|
||||
View key metrics including status, source, duration, cost, tokens, and number
|
||||
of generated candidates for this optimization request.
|
||||
View key metrics including status, source, duration, cost, tokens, and number of
|
||||
generated candidates for this optimization request.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -202,8 +204,9 @@ export default async function TracePage(props: TracePageProps) {
|
|||
Generated Candidates
|
||||
</h4>
|
||||
<p>
|
||||
Code optimization candidates generated during this trace. Each candidate includes
|
||||
an explanation and the generated code. Use the copy button to copy candidate code.
|
||||
Code optimization candidates generated during this trace. Each candidate
|
||||
includes an explanation and the generated code. Use the copy button to copy
|
||||
candidate code.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -234,25 +237,19 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<AlertCircle className="h-4 w-4" />
|
||||
)}
|
||||
<span>Status</span>
|
||||
<InfoIcon
|
||||
content="Overall trace status based on all contained calls"
|
||||
side="top"
|
||||
/>
|
||||
<InfoIcon content="Overall trace status based on all contained calls" side="top" />
|
||||
</div>
|
||||
<div className={`text-xl font-bold ${statusColor}`}>{status}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-1.5 text-sm text-gray-600 dark:text-gray-400 font-medium mb-2">
|
||||
{traceSource.toLowerCase().includes("github") ? (
|
||||
<Github className="h-4 w-4" />
|
||||
<GitFork className="h-4 w-4" />
|
||||
) : (
|
||||
<Terminal className="h-4 w-4" />
|
||||
)}
|
||||
<span>Source</span>
|
||||
<InfoIcon
|
||||
content="Where this optimization was triggered from"
|
||||
side="top"
|
||||
/>
|
||||
<InfoIcon content="Where this optimization was triggered from" side="top" />
|
||||
</div>
|
||||
<div className="text-xl font-bold text-gray-900 dark:text-white">
|
||||
<span className="px-2 py-1 bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded text-sm">
|
||||
|
|
@ -264,10 +261,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<div className="flex items-center gap-1.5 text-sm text-gray-600 dark:text-gray-400 font-medium mb-2">
|
||||
<Timer className="h-4 w-4" />
|
||||
<span>Duration</span>
|
||||
<InfoIcon
|
||||
content="Total time from first call to last call completion"
|
||||
side="top"
|
||||
/>
|
||||
<InfoIcon content="Total time from first call to last call completion" side="top" />
|
||||
</div>
|
||||
<div className="text-xl font-bold text-gray-900 dark:text-white">
|
||||
{(totalDuration / 1000).toFixed(2)}s
|
||||
|
|
@ -277,10 +271,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<div className="flex items-center gap-1.5 text-sm text-gray-600 dark:text-gray-400 font-medium mb-2">
|
||||
<DollarSign className="h-4 w-4" />
|
||||
<span>Cost</span>
|
||||
<InfoIcon
|
||||
content="Sum of all LLM call costs in this trace"
|
||||
side="top"
|
||||
/>
|
||||
<InfoIcon content="Sum of all LLM call costs in this trace" side="top" />
|
||||
</div>
|
||||
<div className="text-xl font-bold text-gray-900 dark:text-white">
|
||||
${totalCost.toFixed(4)}
|
||||
|
|
@ -290,10 +281,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<div className="flex items-center gap-1.5 text-sm text-gray-600 dark:text-gray-400 font-medium mb-2">
|
||||
<Hash className="h-4 w-4" />
|
||||
<span>Tokens</span>
|
||||
<InfoIcon
|
||||
content="Total tokens (prompt + completion) across all calls"
|
||||
side="top"
|
||||
/>
|
||||
<InfoIcon content="Total tokens (prompt + completion) across all calls" side="top" />
|
||||
</div>
|
||||
<div className="text-xl font-bold text-gray-900 dark:text-white">
|
||||
{totalTokens.toLocaleString()}
|
||||
|
|
@ -303,10 +291,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<div className="flex items-center gap-1.5 text-sm text-gray-600 dark:text-gray-400 font-medium mb-2">
|
||||
<CodeIcon className="h-4 w-4" />
|
||||
<span>Candidates</span>
|
||||
<InfoIcon
|
||||
content="Number of valid optimization candidates generated"
|
||||
side="top"
|
||||
/>
|
||||
<InfoIcon content="Number of valid optimization candidates generated" side="top" />
|
||||
</div>
|
||||
<div className="text-xl font-bold text-gray-900 dark:text-white">
|
||||
{optimizationCandidates.length}
|
||||
|
|
@ -353,7 +338,8 @@ export default async function TracePage(props: TracePageProps) {
|
|||
</h4>
|
||||
<p>
|
||||
Click any call to expand and see detailed metrics including token usage,
|
||||
latency, and timestamp. Use "View full details" to see prompts and responses.
|
||||
latency, and timestamp. Use "View full details" to see prompts and
|
||||
responses.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -431,25 +417,33 @@ export default async function TracePage(props: TracePageProps) {
|
|||
{/* Call details */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-x-6 gap-y-3 text-sm">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">Tokens</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">
|
||||
Tokens
|
||||
</span>
|
||||
<span className="text-gray-900 dark:text-white font-medium">
|
||||
{call.total_tokens?.toLocaleString() ?? "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">Latency</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">
|
||||
Latency
|
||||
</span>
|
||||
<span className="text-gray-900 dark:text-white font-medium">
|
||||
{call.latency_ms ? `${call.latency_ms}ms` : "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">Time</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">
|
||||
Time
|
||||
</span>
|
||||
<span className="text-gray-900 dark:text-white font-medium">
|
||||
{new Date(call.created_at).toLocaleTimeString()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col sm:col-span-2 lg:col-span-1">
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">Details</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-xs mb-1">
|
||||
Details
|
||||
</span>
|
||||
<Link
|
||||
href={`/observability/llm-call/${call.id}`}
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline text-sm font-medium inline-block"
|
||||
|
|
@ -478,8 +472,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
</div>
|
||||
<div className="space-y-2">
|
||||
{candidatesForType.map(candidate => {
|
||||
const isBest =
|
||||
bestCandidateId != null && candidate.id === bestCandidateId
|
||||
const isBest = bestCandidateId != null && candidate.id === bestCandidateId
|
||||
const showUsedForPr = isBest && usedForPr
|
||||
const rank = candidateRankMap.get(candidate.id)
|
||||
return (
|
||||
|
|
@ -541,7 +534,11 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<h5 className="text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||
Code
|
||||
</h5>
|
||||
<CopyButton text={candidate.code} label="candidate code" size="sm" />
|
||||
<CopyButton
|
||||
text={candidate.code}
|
||||
label="candidate code"
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
<pre className="bg-gray-900 text-gray-100 p-3 rounded-lg overflow-x-auto text-xs font-mono leading-relaxed">
|
||||
<code>{candidate.code}</code>
|
||||
|
|
@ -559,7 +556,8 @@ export default async function TracePage(props: TracePageProps) {
|
|||
)}
|
||||
</div>
|
||||
</details>
|
||||
)})}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -598,9 +596,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
{errors.length > 0 ? (
|
||||
<>
|
||||
<AlertCircle className="h-5 w-5 text-red-600 dark:text-red-400" />
|
||||
<h2 className="text-xl font-bold text-red-600 dark:text-red-400">
|
||||
Errors
|
||||
</h2>
|
||||
<h2 className="text-xl font-bold text-red-600 dark:text-red-400">Errors</h2>
|
||||
<span className="bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 text-sm px-2.5 py-0.5 rounded font-semibold">
|
||||
{errors.length}
|
||||
</span>
|
||||
|
|
@ -619,15 +615,13 @@ export default async function TracePage(props: TracePageProps) {
|
|||
<div className="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
{errors.map(error => {
|
||||
const isTestFailure = error.error_type === "test_failure"
|
||||
const errorContext = error.context as
|
||||
| {
|
||||
const errorContext = error.context as {
|
||||
test_name?: string
|
||||
failure_reason?: string
|
||||
test_output?: string
|
||||
expected?: string
|
||||
actual?: string
|
||||
}
|
||||
| null
|
||||
} | null
|
||||
|
||||
return (
|
||||
<div key={error.id} className="p-6 border-l-4 border-red-500">
|
||||
|
|
@ -728,9 +722,7 @@ export default async function TracePage(props: TracePageProps) {
|
|||
) : (
|
||||
<div className="flex flex-col items-center justify-center py-12 text-center">
|
||||
<CheckCircle className="h-16 w-16 text-green-500 dark:text-green-400 mb-4" />
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
All Clear!
|
||||
</h3>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">All Clear!</h3>
|
||||
<p className="text-gray-500 dark:text-gray-400 text-sm">
|
||||
This trace completed successfully with no errors detected.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -781,8 +781,8 @@ const MonacoDiffViewer: React.FC<MonacoDiffViewerProps> = ({
|
|||
</button>
|
||||
{showGeneratedTests && (
|
||||
<div className="mt-2 sm:mt-3 bg-slate-800/50 rounded-lg p-2 sm:p-3 max-h-48 sm:max-h-64 overflow-y-auto scrollbar-thin scrollbar-thumb-slate-600 scrollbar-track-slate-800">
|
||||
<div className="prose prose-sm prose-invert max-w-none">
|
||||
<ReactMarkdown
|
||||
className="prose prose-sm prose-invert max-w-none"
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
pre: ({ children, ...props }) => {
|
||||
|
|
@ -880,6 +880,7 @@ const MonacoDiffViewer: React.FC<MonacoDiffViewerProps> = ({
|
|||
})()}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
923
js/common/package-lock.json
generated
923
js/common/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codeflash-ai/common",
|
||||
"version": "1.0.30",
|
||||
"version": "1.0.31",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"repository": {
|
||||
|
|
@ -15,25 +15,25 @@
|
|||
"format:check": "prettier --check \"**/*.{js,ts,json,md}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/identity": "^4.2.0",
|
||||
"@azure/keyvault-secrets": "^4.8.0",
|
||||
"@azure/msal-node": "^2.9.0",
|
||||
"@prisma/client": "^6.13.0",
|
||||
"stripe": "^18.2.0"
|
||||
"@azure/identity": "^4.13.1",
|
||||
"@azure/keyvault-secrets": "^4.11.1",
|
||||
"@azure/msal-node": "^2.16.3",
|
||||
"@prisma/client": "^6.19.3",
|
||||
"stripe": "^18.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.22.0",
|
||||
"@types/node": "^20.10.1",
|
||||
"@eslint/js": "^9.39.4",
|
||||
"@types/node": "^20.19.39",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"globals": "^16.0.0",
|
||||
"lint-staged": "^16.1.6",
|
||||
"prettier": "^3.3.0",
|
||||
"prisma": "^6.13.0",
|
||||
"globals": "^16.5.0",
|
||||
"lint-staged": "^16.4.0",
|
||||
"prettier": "^3.8.2",
|
||||
"prisma": "^6.19.3",
|
||||
"simple-git-hooks": "^2.9.0",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.26.1"
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.58.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
|
|
|
|||
Loading…
Reference in a new issue