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:
Kevin Turcios 2026-04-10 15:49:09 -05:00 committed by GitHub
parent f9d78e5cf2
commit ec39cd5190
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 3823 additions and 4300 deletions

File diff suppressed because it is too large Load diff

View file

@ -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": {

File diff suppressed because it is too large Load diff

View file

@ -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"
}
}

View file

@ -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">
@ -128,4 +128,4 @@ export function TraceSummary({
</div>
</div>
)
}
}

File diff suppressed because it is too large Load diff

View file

@ -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,16 +69,17 @@ 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(
pullRequestRaw != null &&
typeof pullRequestRaw === "object" &&
!Array.isArray(pullRequestRaw) &&
Object.keys(pullRequestRaw as Record<string, unknown>).length > 0,
typeof pullRequestRaw === "object" &&
!Array.isArray(pullRequestRaw) &&
Object.keys(pullRequestRaw as Record<string, unknown>).length > 0,
)
// Map candidate ID to rank position (1-based, 1 = best)
@ -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 &quot;View full details&quot; to see prompts and responses.
latency, and timestamp. Use &quot;View full details&quot; 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,88 +472,92 @@ 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 (
<details
key={candidate.id}
className={`rounded-lg border ${
isBest
? "border-emerald-500 dark:border-emerald-600 bg-emerald-50/50 dark:bg-emerald-900/20"
: "border-gray-200 dark:border-gray-600"
}`}
>
<summary className="p-3 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/50 flex items-center justify-between rounded-lg">
<div className="flex items-center gap-2 flex-wrap">
<span className="font-medium text-gray-900 dark:text-white">
Candidate {candidate.index}
</span>
<span className="font-mono text-xs text-gray-500 dark:text-gray-400">
{candidate.id.substring(0, 8)}...
</span>
{rank != null && (
<span className="bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200 text-xs px-2 py-0.5 rounded font-semibold">
Rank #{rank}
<details
key={candidate.id}
className={`rounded-lg border ${
isBest
? "border-emerald-500 dark:border-emerald-600 bg-emerald-50/50 dark:bg-emerald-900/20"
: "border-gray-200 dark:border-gray-600"
}`}
>
<summary className="p-3 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/50 flex items-center justify-between rounded-lg">
<div className="flex items-center gap-2 flex-wrap">
<span className="font-medium text-gray-900 dark:text-white">
Candidate {candidate.index}
</span>
)}
{isBest && (
<span className="bg-emerald-100 dark:bg-emerald-900 text-emerald-800 dark:text-emerald-200 text-xs px-2 py-0.5 rounded font-semibold">
Best
<span className="font-mono text-xs text-gray-500 dark:text-gray-400">
{candidate.id.substring(0, 8)}...
</span>
)}
{showUsedForPr && (
<span className="bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 text-xs px-2 py-0.5 rounded font-semibold">
Used for PR
</span>
)}
{candidate.model && (
<span className="bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 text-xs px-2 py-0.5 rounded">
{candidate.model}
</span>
)}
</div>
<span className="text-gray-400 text-sm"></span>
</summary>
<div className="p-3 pt-0 border-t border-gray-200 dark:border-gray-600 mt-2 space-y-3">
{candidateExplanations[candidate.id] && (
<div>
<div className="flex items-center gap-1.5 mb-1">
<CodeIcon className="h-3.5 w-3.5 text-gray-500 dark:text-gray-400" />
<h5 className="text-xs font-medium text-gray-500 dark:text-gray-400">
Explanation
</h5>
{rank != null && (
<span className="bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200 text-xs px-2 py-0.5 rounded font-semibold">
Rank #{rank}
</span>
)}
{isBest && (
<span className="bg-emerald-100 dark:bg-emerald-900 text-emerald-800 dark:text-emerald-200 text-xs px-2 py-0.5 rounded font-semibold">
Best
</span>
)}
{showUsedForPr && (
<span className="bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 text-xs px-2 py-0.5 rounded font-semibold">
Used for PR
</span>
)}
{candidate.model && (
<span className="bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 text-xs px-2 py-0.5 rounded">
{candidate.model}
</span>
)}
</div>
<span className="text-gray-400 text-sm"></span>
</summary>
<div className="p-3 pt-0 border-t border-gray-200 dark:border-gray-600 mt-2 space-y-3">
{candidateExplanations[candidate.id] && (
<div>
<div className="flex items-center gap-1.5 mb-1">
<CodeIcon className="h-3.5 w-3.5 text-gray-500 dark:text-gray-400" />
<h5 className="text-xs font-medium text-gray-500 dark:text-gray-400">
Explanation
</h5>
</div>
<p className="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap leading-relaxed">
{candidateExplanations[candidate.id]}
</p>
</div>
<p className="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap leading-relaxed">
{candidateExplanations[candidate.id]}
</p>
</div>
)}
<div>
<div className="flex items-center justify-between mb-2">
<h5 className="text-xs font-medium text-gray-500 dark:text-gray-400">
Code
</h5>
<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>
</pre>
</div>
{llmCallForType && (
)}
<div>
<Link
href={`/observability/llm-call/${llmCallForType.id}`}
className="text-blue-600 dark:text-blue-400 hover:underline text-sm font-medium inline-flex items-center gap-1"
>
View LLM Call Details
</Link>
<div className="flex items-center justify-between mb-2">
<h5 className="text-xs font-medium text-gray-500 dark:text-gray-400">
Code
</h5>
<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>
</pre>
</div>
)}
</div>
</details>
)})}
{llmCallForType && (
<div>
<Link
href={`/observability/llm-call/${llmCallForType.id}`}
className="text-blue-600 dark:text-blue-400 hover:underline text-sm font-medium inline-flex items-center gap-1"
>
View LLM Call Details
</Link>
</div>
)}
</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
| {
test_name?: string
failure_reason?: string
test_output?: string
expected?: string
actual?: string
}
| null
const errorContext = error.context as {
test_name?: string
failure_reason?: string
test_output?: string
expected?: string
actual?: string
} | 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>

View file

@ -781,104 +781,105 @@ 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">
<ReactMarkdown
className="prose prose-sm prose-invert max-w-none"
remarkPlugins={[remarkGfm]}
components={{
pre: ({ children, ...props }) => {
return (
<div className="not-prose">
<pre className="bg-slate-900/50 rounded-md overflow-x-auto" {...props}>
<div className="prose prose-sm prose-invert max-w-none">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
pre: ({ children, ...props }) => {
return (
<div className="not-prose">
<pre className="bg-slate-900/50 rounded-md overflow-x-auto" {...props}>
{children}
</pre>
</div>
)
},
code: props => {
const { inline, className, children, ...restProps } = props as {
inline?: boolean
className?: string
children: React.ReactNode
[key: string]: unknown
}
const match = /language-(\w+)/.exec(className || "")
const language = match ? match[1] : null
return !inline && language ? (
<SyntaxHighlighter
style={vscDarkPlus}
language={language}
PreTag="div"
className="!bg-slate-900/50 !text-[10px] sm:!text-xs rounded-md"
customStyle={{
margin: 0,
padding: "0.5rem",
backgroundColor: "rgb(15 23 42 / 0.5)",
fontSize: "0.625rem",
lineHeight: "1.4",
}}
{...restProps}
>
{String(children).replace(/\n$/, "")}
</SyntaxHighlighter>
) : (
<code
className="bg-slate-700/50 px-1 py-0.5 rounded text-[10px] sm:text-xs text-cyan-300 font-mono"
{...restProps}
>
{children}
</pre>
</div>
)
},
code: props => {
const { inline, className, children, ...restProps } = props as {
inline?: boolean
className?: string
children: React.ReactNode
[key: string]: unknown
}
const match = /language-(\w+)/.exec(className || "")
const language = match ? match[1] : null
return !inline && language ? (
<SyntaxHighlighter
style={vscDarkPlus}
language={language}
PreTag="div"
className="!bg-slate-900/50 !text-[10px] sm:!text-xs rounded-md"
customStyle={{
margin: 0,
padding: "0.5rem",
backgroundColor: "rgb(15 23 42 / 0.5)",
fontSize: "0.625rem",
lineHeight: "1.4",
}}
{...restProps}
>
{String(children).replace(/\n$/, "")}
</SyntaxHighlighter>
) : (
<code
className="bg-slate-700/50 px-1 py-0.5 rounded text-[10px] sm:text-xs text-cyan-300 font-mono"
{...restProps}
>
</code>
)
},
p: ({ children }) => (
<p className="text-xs sm:text-sm text-slate-300 mb-2 sm:mb-3">{children}</p>
),
h1: ({ children }) => (
<h1 className="text-base sm:text-lg font-bold text-white mb-1.5 sm:mb-2">
{children}
</code>
)
},
p: ({ children }) => (
<p className="text-xs sm:text-sm text-slate-300 mb-2 sm:mb-3">{children}</p>
),
h1: ({ children }) => (
<h1 className="text-base sm:text-lg font-bold text-white mb-1.5 sm:mb-2">
{children}
</h1>
),
h2: ({ children }) => (
<h2 className="text-sm sm:text-base font-semibold text-white mb-1.5 sm:mb-2">
{children}
</h2>
),
h3: ({ children }) => (
<h3 className="text-xs sm:text-sm font-semibold text-white mb-1">
{children}
</h3>
),
ul: ({ children }) => (
<ul className="list-disc list-inside text-xs sm:text-sm text-slate-300 mb-2 sm:mb-3">
{children}
</ul>
),
ol: ({ children }) => (
<ol className="list-decimal list-inside text-xs sm:text-sm text-slate-300 mb-2 sm:mb-3">
{children}
</ol>
),
li: ({ children }) => (
<li className="text-xs sm:text-sm text-slate-300 mb-0.5 sm:mb-1">
{children}
</li>
),
}}
>
{(() => {
// Check if generatedTests already has markdown code blocks
const testsContent = metadata.generatedTests.trim()
const hasCodeBlocks = testsContent.includes("```")
</h1>
),
h2: ({ children }) => (
<h2 className="text-sm sm:text-base font-semibold text-white mb-1.5 sm:mb-2">
{children}
</h2>
),
h3: ({ children }) => (
<h3 className="text-xs sm:text-sm font-semibold text-white mb-1">
{children}
</h3>
),
ul: ({ children }) => (
<ul className="list-disc list-inside text-xs sm:text-sm text-slate-300 mb-2 sm:mb-3">
{children}
</ul>
),
ol: ({ children }) => (
<ol className="list-decimal list-inside text-xs sm:text-sm text-slate-300 mb-2 sm:mb-3">
{children}
</ol>
),
li: ({ children }) => (
<li className="text-xs sm:text-sm text-slate-300 mb-0.5 sm:mb-1">
{children}
</li>
),
}}
>
{(() => {
// Check if generatedTests already has markdown code blocks
const testsContent = metadata.generatedTests.trim()
const hasCodeBlocks = testsContent.includes("```")
// If it doesn't have code blocks, wrap it as Python code
if (!hasCodeBlocks) {
return "```python\n" + testsContent + "\n```"
}
// If it doesn't have code blocks, wrap it as Python code
if (!hasCodeBlocks) {
return "```python\n" + testsContent + "\n```"
}
// Otherwise, return as-is
return testsContent
})()}
</ReactMarkdown>
// Otherwise, return as-is
return testsContent
})()}
</ReactMarkdown>
</div>
</div>
)}
</div>

File diff suppressed because it is too large Load diff

View file

@ -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"