codeflash-internal/js/cf-webapp/src/app/observability/components/format-llm-export.ts
Kevin Turcios e5374c3f50
fix: provide JWT_SECRET to CI build workflows (#2607)
## Summary
- Reverts lazy JWT_SECRET initialization — keeps eager fail-fast at
module load
- Adds `JWT_SECRET` secret to both `deploy_cfwebapp_to_azure.yml` and
`nextjs-build.yaml` CI workflows so `next build` page data collection
succeeds for the `/codeflash/auth/oauth/token` route

## Context
The deploy workflow ([run
#24425211765](https://github.com/codeflash-ai/codeflash-internal/actions/runs/24425211765/job/71357530269))
was failing because `JWT_SECRET` isn't available during CI build,
causing an eager throw at module load time. The secret already exists as
a GitHub repo secret.
2026-04-14 19:25:41 -05:00

175 lines
5.4 KiB
TypeScript

import type { TimelineSection } from "./timeline-types"
interface LLMExportInput {
traceId: string
functionName: string | null
filePath: string | null
originalCode: string | null
sections: TimelineSection[]
errors: Array<{
error_type: string | null
severity: string | null
error_message: string | null
context: {
test_name?: string
failure_reason?: string
test_output?: string
expected?: string
actual?: string
} | null
created_at: Date
}>
totalDuration: number
}
function formatDuration(ms: number): string {
if (ms < 1000) return `${Math.round(ms)}ms`
return `${(ms / 1000).toFixed(1)}s`
}
function formatCost(cost: number | null | undefined): string {
if (cost == null || cost === 0) return "$0.00"
if (cost < 0.01) return `$${cost.toFixed(4)}`
return `$${cost.toFixed(2)}`
}
export function formatTimelineForLLM(input: LLMExportInput): string {
const { traceId, functionName, filePath, originalCode, sections, errors, totalDuration } = input
const lines: string[] = []
lines.push(`# Optimization Trace: ${traceId}`)
if (functionName) lines.push(`## Function: ${functionName}`)
if (filePath) lines.push(`File: ${filePath}`)
lines.push("")
if (originalCode) {
lines.push("### Original Code")
lines.push("```python")
lines.push(originalCode)
lines.push("```")
lines.push("")
}
lines.push("---")
lines.push("## Timeline")
lines.push("")
let sectionNum = 0
for (const section of sections) {
sectionNum++
lines.push(`### ${sectionNum}. ${section.title}`)
const meta: string[] = []
if (section.model) meta.push(`Model: ${section.model}`)
if (section.cost != null) meta.push(`Cost: ${formatCost(section.cost)}`)
if (section.tokens != null) meta.push(`Tokens: ${section.tokens}`)
if (section.duration != null) meta.push(`Duration: ${formatDuration(section.duration)}`)
meta.push(`Status: ${section.status}`)
if (meta.length > 0) lines.push(meta.join(" | "))
lines.push("")
const content = section.content
if (content.type === "tests") {
if (content.testFramework) {
lines.push(`Test framework: ${content.testFramework}`)
lines.push("")
}
for (const group of content.testGroups) {
if (group.generated) {
lines.push(`#### Generated Test ${group.index}`)
lines.push("```python")
lines.push(group.generated.code)
lines.push("```")
lines.push("")
}
}
} else if (content.type === "candidate" || content.type === "refinement") {
if (content.rank != null) {
lines.push(`Rank: #${content.rank}${content.isBest ? " (Best)" : ""}`)
lines.push("")
}
if (content.explanation) {
lines.push("#### Explanation")
lines.push(content.explanation)
lines.push("")
}
lines.push("#### Optimized Code")
lines.push("```python")
lines.push(content.code)
lines.push("```")
lines.push("")
} else if (content.type === "ranking") {
if (content.explanation) {
lines.push("#### Ranking Explanation")
lines.push(content.explanation)
lines.push("")
}
for (const r of content.rankings) {
lines.push(`${r.rank}. ${r.label}${r.isBest ? " (Best)" : ""}`)
}
if (content.usedForPr) {
lines.push("")
lines.push("*Used for pull request*")
}
lines.push("")
} else if (content.type === "summary") {
lines.push(`- Total Cost: ${formatCost(content.metrics.totalCost)}`)
lines.push(`- Total Tokens: ${content.metrics.totalTokens}`)
lines.push(`- Total Duration: ${formatDuration(content.metrics.totalDuration)}`)
lines.push(`- Candidates: ${content.metrics.candidatesCount}`)
lines.push("")
}
if (section.debugData) {
lines.push(`#### Debug: LLM Call ID: ${section.debugData.callId}`)
lines.push("")
}
}
if (errors.length > 0) {
lines.push("---")
lines.push("## Errors")
lines.push("")
for (const error of errors) {
lines.push(
`### ${error.error_type || "Error"}${error.severity ? ` (${error.severity})` : ""}`,
)
if (error.error_message) lines.push(error.error_message)
if (error.context) {
const ctx = error.context
if (ctx.test_name) lines.push(`Test: ${ctx.test_name}`)
if (ctx.failure_reason) lines.push(`Reason: ${ctx.failure_reason}`)
if (ctx.test_output) {
lines.push("```")
lines.push(ctx.test_output)
lines.push("```")
}
if (ctx.expected) lines.push(`Expected: ${ctx.expected}`)
if (ctx.actual) lines.push(`Actual: ${ctx.actual}`)
}
lines.push("")
}
}
const totalCost = sections.reduce((sum, s) => sum + (s.cost ?? 0), 0)
const totalTokens = sections.reduce((sum, s) => sum + (s.tokens ?? 0), 0)
const candidatesCount = sections.filter(
s =>
s.type === "optimization" ||
s.type === "line_profiler" ||
s.type === "refinement" ||
s.type === "adaptive",
).length
lines.push("---")
lines.push("## Summary")
lines.push(`- Total Cost: ${formatCost(totalCost)}`)
lines.push(`- Total Tokens: ${totalTokens}`)
lines.push(`- Total Duration: ${formatDuration(totalDuration)}`)
lines.push(`- Candidates: ${candidatesCount}`)
if (errors.length > 0) lines.push(`- Errors: ${errors.length}`)
lines.push("")
return lines.join("\n")
}