dev3000 0.0.121 → 0.0.124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/cli.js +19 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/dev-environment.d.ts.map +1 -1
  4. package/dist/dev-environment.js +11 -0
  5. package/dist/dev-environment.js.map +1 -1
  6. package/dist/utils/log-filename.d.ts.map +1 -1
  7. package/dist/utils/log-filename.js +8 -3
  8. package/dist/utils/log-filename.js.map +1 -1
  9. package/mcp-server/app/mcp/route.ts +81 -7
  10. package/mcp-server/app/mcp/tools.ts +33 -3
  11. package/mcp-server/next-env.d.ts +1 -1
  12. package/mcp-server/package.json +0 -12
  13. package/package.json +6 -7
  14. package/mcp-server/.next/build/chunks/[root-of-the-server]__25374c4f._.js +0 -500
  15. package/mcp-server/.next/build/chunks/[root-of-the-server]__25374c4f._.js.map +0 -11
  16. package/mcp-server/.next/build/chunks/[root-of-the-server]__6e020478._.js +0 -441
  17. package/mcp-server/.next/build/chunks/[root-of-the-server]__6e020478._.js.map +0 -7
  18. package/mcp-server/.next/build/chunks/[root-of-the-server]__c438ef56._.js +0 -205
  19. package/mcp-server/.next/build/chunks/[root-of-the-server]__c438ef56._.js.map +0 -8
  20. package/mcp-server/.next/build/chunks/[root-of-the-server]__c7ae8543._.js +0 -500
  21. package/mcp-server/.next/build/chunks/[root-of-the-server]__c7ae8543._.js.map +0 -11
  22. package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_80bff36f._.js +0 -13
  23. package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_80bff36f._.js.map +0 -5
  24. package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_webpack-loaders_ts_c84aa21a._.js +0 -12
  25. package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_webpack-loaders_ts_c84aa21a._.js.map +0 -5
  26. package/mcp-server/.next/build/chunks/[turbopack]_runtime.js +0 -770
  27. package/mcp-server/.next/build/chunks/[turbopack]_runtime.js.map +0 -10
  28. package/mcp-server/.next/build/chunks/node_modules__pnpm_806d01c0._.js +0 -6758
  29. package/mcp-server/.next/build/chunks/node_modules__pnpm_806d01c0._.js.map +0 -47
  30. package/mcp-server/.next/build/package.json +0 -1
  31. package/mcp-server/.next/build/postcss.js +0 -6
  32. package/mcp-server/.next/build/postcss.js.map +0 -5
  33. package/mcp-server/.next/build/webpack-loaders.js +0 -6
  34. package/mcp-server/.next/build/webpack-loaders.js.map +0 -5
  35. package/mcp-server/.next/package.json +0 -1
  36. package/mcp-server/app/api/auth/authorize/route.ts +0 -52
  37. package/mcp-server/app/api/auth/callback/route.ts +0 -128
  38. package/mcp-server/app/api/auth/signout/route.ts +0 -34
  39. package/mcp-server/app/api/auth/token/route.ts +0 -16
  40. package/mcp-server/app/api/cloud/check-pr/route.ts +0 -53
  41. package/mcp-server/app/api/cloud/check-pr/steps.ts +0 -458
  42. package/mcp-server/app/api/cloud/check-pr/workflow.ts +0 -109
  43. package/mcp-server/app/api/cloud/fix-workflow/health/route.ts +0 -10
  44. package/mcp-server/app/api/cloud/fix-workflow/route.ts +0 -50
  45. package/mcp-server/app/api/cloud/fix-workflow/steps.ts +0 -2091
  46. package/mcp-server/app/api/cloud/fix-workflow/workflow.ts +0 -296
  47. package/mcp-server/app/api/cloud/start-fix/route.ts +0 -192
  48. package/mcp-server/app/api/integration/webhook/route.ts +0 -290
  49. package/mcp-server/app/api/projects/[projectId]/bypass-token/route.ts +0 -48
  50. package/mcp-server/app/api/projects/branches/route.ts +0 -115
  51. package/mcp-server/app/api/projects/check-protection/route.ts +0 -33
  52. package/mcp-server/app/api/projects/route.ts +0 -97
  53. package/mcp-server/app/api/workflows/route.ts +0 -105
  54. package/mcp-server/app/auth/error/page.tsx +0 -47
  55. package/mcp-server/app/signin/page.tsx +0 -37
  56. package/mcp-server/app/workflows/[id]/report/agent-analysis.tsx +0 -7
  57. package/mcp-server/app/workflows/[id]/report/page.tsx +0 -199
  58. package/mcp-server/app/workflows/new/new-workflow-client.tsx +0 -32
  59. package/mcp-server/app/workflows/new/page.tsx +0 -13
  60. package/mcp-server/app/workflows/new-workflow-modal.tsx +0 -973
  61. package/mcp-server/app/workflows/page.tsx +0 -16
  62. package/mcp-server/app/workflows/workflows-client.tsx +0 -290
@@ -1,296 +0,0 @@
1
- /**
2
- * Cloud Fix Workflow Function - Core workflow logic
3
- *
4
- * This file contains ONLY the workflow function and step wrappers.
5
- * It does NOT import workflow/api to avoid bundler issues.
6
- */
7
-
8
- /**
9
- * Main workflow function that orchestrates the fix process
10
- */
11
- export async function cloudFixWorkflow(params: {
12
- devUrl: string
13
- projectName: string
14
- vercelToken?: string
15
- vercelOidcToken?: string
16
- repoOwner?: string
17
- repoName?: string
18
- baseBranch?: string
19
- bypassToken?: string
20
- repoUrl?: string
21
- repoBranch?: string
22
- runId?: string // For progress tracking
23
- userId?: string // For progress tracking
24
- }) {
25
- "use workflow"
26
-
27
- const {
28
- devUrl,
29
- projectName,
30
- vercelToken,
31
- vercelOidcToken: vercelOidcTokenParam,
32
- repoOwner,
33
- repoName,
34
- baseBranch = "main",
35
- bypassToken,
36
- repoUrl,
37
- repoBranch,
38
- runId,
39
- userId
40
- } = params
41
- const timestamp = new Date().toISOString()
42
-
43
- console.log("[Workflow] Starting cloud fix workflow...")
44
- console.log(`[Workflow] Dev URL: ${devUrl}`)
45
- console.log(`[Workflow] Project: ${projectName}`)
46
- console.log(`[Workflow] Timestamp: ${new Date().toISOString()}`)
47
- console.log(`[Workflow] Bypass Token: ${bypassToken ? "provided" : "not provided"}`)
48
- if (repoOwner && repoName) {
49
- console.log(`[Workflow] GitHub Repo: ${repoOwner}/${repoName}`)
50
- console.log(`[Workflow] Base Branch: ${baseBranch}`)
51
- }
52
- if (repoUrl) {
53
- console.log(`[Workflow] Will create sandbox from: ${repoUrl}`)
54
- console.log(`[Workflow] Branch: ${repoBranch || "main"}`)
55
- }
56
-
57
- // Use VERCEL_OIDC_TOKEN from params (passed from request header) or fall back to env
58
- // At runtime, OIDC token is in x-vercel-oidc-token header, not process.env
59
- const vercelOidcToken = vercelOidcTokenParam || process.env.VERCEL_OIDC_TOKEN
60
- console.log(`[Workflow] VERCEL_OIDC_TOKEN from param: ${!!vercelOidcTokenParam}`)
61
- console.log(`[Workflow] VERCEL_OIDC_TOKEN from env: ${!!process.env.VERCEL_OIDC_TOKEN}`)
62
- console.log(`[Workflow] VERCEL_OIDC_TOKEN available: ${!!vercelOidcToken}`)
63
-
64
- // Helper to update progress if tracking is enabled
65
- const updateProgress = async (stepNumber: number, currentStep: string, sandboxUrl?: string) => {
66
- if (runId && userId) {
67
- await updateWorkflowProgressStep(userId, runId, projectName, timestamp, stepNumber, currentStep, sandboxUrl)
68
- }
69
- }
70
-
71
- // Step 0: Create d3k sandbox if repoUrl provided
72
- // This step also captures CLS data, "before" screenshot, git diff, and d3k artifacts from inside the sandbox
73
- // It also saves an initial report to blob storage so we have data even if later steps fail
74
- let sandboxInfo: {
75
- mcpUrl: string
76
- devUrl: string
77
- bypassToken?: string
78
- clsData?: unknown
79
- mcpError?: string | null
80
- beforeScreenshotUrl?: string | null
81
- chromiumPath?: string
82
- gitDiff?: string | null
83
- d3kArtifacts?: {
84
- clsScreenshots: Array<{ label: string; blobUrl: string; timestamp: number }>
85
- screencastSessionId: string | null
86
- fullLogs: string | null
87
- metadata: Record<string, unknown> | null
88
- }
89
- reportId?: string
90
- reportBlobUrl?: string
91
- agentAnalysis?: string | null
92
- } | null = null
93
- if (repoUrl) {
94
- await updateProgress(0, "Creating development sandbox...")
95
- sandboxInfo = await createD3kSandbox(
96
- repoUrl,
97
- repoBranch || "main",
98
- projectName,
99
- vercelToken,
100
- vercelOidcToken,
101
- runId // Pass runId so Step 0 can save the initial report with consistent ID
102
- )
103
- if (sandboxInfo?.devUrl) {
104
- await updateProgress(0, "Sandbox ready, capturing CLS metrics...", sandboxInfo.devUrl)
105
- }
106
- if (sandboxInfo?.reportBlobUrl) {
107
- console.log(`[Workflow] Report saved: ${sandboxInfo.reportBlobUrl}`)
108
- }
109
- if (sandboxInfo?.agentAnalysis) {
110
- console.log(`[Workflow] Agent analysis completed in Step 0`)
111
- }
112
- }
113
-
114
- // Step 1: Fetch real logs (only if we don't have sandbox data)
115
- // Skip if we already got CLS data and agent analysis from Step 0
116
- let logAnalysis = ""
117
- let beforeScreenshotUrl: string | null = sandboxInfo?.beforeScreenshotUrl || null
118
-
119
- if (!sandboxInfo?.clsData) {
120
- await updateProgress(1, "Capturing performance metrics (CLS, LCP, errors)...")
121
- const effectiveBypassToken = sandboxInfo?.bypassToken || bypassToken
122
- const step1Result = await fetchRealLogs(
123
- sandboxInfo?.mcpUrl || devUrl,
124
- effectiveBypassToken,
125
- sandboxInfo?.devUrl,
126
- sandboxInfo?.clsData,
127
- sandboxInfo?.mcpError,
128
- sandboxInfo?.beforeScreenshotUrl
129
- )
130
- logAnalysis = step1Result.logAnalysis
131
- beforeScreenshotUrl = step1Result.beforeScreenshotUrl
132
- await updateProgress(1, `Captured ${logAnalysis.length > 5000 ? "detailed" : "initial"} diagnostics`)
133
- } else {
134
- logAnalysis = JSON.stringify(sandboxInfo.clsData, null, 2)
135
- await updateProgress(1, "Using CLS data from sandbox")
136
- }
137
-
138
- // Step 2: AI agent analysis
139
- // If we already ran the agent in Step 0 (with sandbox tools), use that result
140
- // Otherwise, run the basic agent without sandbox access
141
- let fixProposal: string
142
-
143
- if (sandboxInfo?.agentAnalysis) {
144
- // Agent already ran with sandbox tools in Step 0
145
- fixProposal = sandboxInfo.agentAnalysis
146
- await updateProgress(2, "AI agent completed analysis with code access")
147
- } else {
148
- // Fallback: run agent without sandbox (limited mode)
149
- await updateProgress(2, "AI agent analyzing logs (limited mode)...")
150
- fixProposal = await analyzeLogsWithAgent(logAnalysis, sandboxInfo?.devUrl || devUrl)
151
- }
152
-
153
- // Provide feedback on what was found
154
- const hasError = fixProposal.toLowerCase().includes("error") || fixProposal.toLowerCase().includes("issue")
155
- const hasFix = fixProposal.includes("```diff")
156
- if (hasFix) {
157
- await updateProgress(2, "AI generated a fix proposal with code changes")
158
- } else if (hasError) {
159
- await updateProgress(2, "AI identified issues but no code fix needed")
160
- } else {
161
- await updateProgress(2, "AI analysis complete - system appears healthy")
162
- }
163
-
164
- // Step 3: Upload to blob storage as JSON with full context
165
- await updateProgress(3, "Compiling full report with screenshots...")
166
- const agentAnalysisModel = "anthropic/claude-sonnet-4-20250514" // Model used in analyzeLogsWithAgent
167
- const blobResult = await uploadToBlob(
168
- fixProposal,
169
- projectName,
170
- logAnalysis,
171
- sandboxInfo?.devUrl || devUrl,
172
- beforeScreenshotUrl,
173
- sandboxInfo?.gitDiff,
174
- sandboxInfo?.d3kArtifacts,
175
- runId,
176
- sandboxInfo?.mcpUrl,
177
- agentAnalysisModel
178
- )
179
- await updateProgress(3, "Report uploaded to Vercel Blob")
180
-
181
- // Step 4: Create GitHub PR if repo info provided AND there are actual fixes to apply
182
- let prResult = null
183
- const hasGitPatch = fixProposal.includes("```diff")
184
- if (repoOwner && repoName && hasGitPatch) {
185
- await updateProgress(4, `Creating PR on ${repoOwner}/${repoName}...`)
186
- prResult = await createGitHubPR(fixProposal, blobResult.blobUrl, repoOwner, repoName, baseBranch, projectName)
187
- if (prResult?.success) {
188
- await updateProgress(4, `PR #${prResult.prNumber} created successfully`)
189
- }
190
- } else if (repoOwner && repoName && !hasGitPatch) {
191
- await updateProgress(4, "No code changes needed - skipping PR")
192
- console.log("[Workflow] No git patch found - skipping PR creation (system is healthy)")
193
- }
194
-
195
- // Note: Sandbox cleanup is handled automatically by the sandbox timeout
196
- // We cannot store cleanup functions as they're not serializable
197
-
198
- return Response.json({
199
- ...blobResult,
200
- pr: prResult
201
- })
202
- }
203
-
204
- // Step function wrappers that dynamically import the actual implementations
205
- async function createD3kSandbox(
206
- repoUrl: string,
207
- branch: string,
208
- projectName: string,
209
- vercelToken?: string,
210
- vercelOidcToken?: string,
211
- runId?: string
212
- ) {
213
- "use step"
214
- const { createD3kSandbox } = await import("./steps")
215
- return createD3kSandbox(repoUrl, branch, projectName, vercelToken, vercelOidcToken, runId)
216
- }
217
-
218
- async function fetchRealLogs(
219
- mcpUrlOrDevUrl: string,
220
- bypassToken?: string,
221
- sandboxDevUrl?: string,
222
- clsData?: unknown,
223
- mcpError?: string | null,
224
- beforeScreenshotUrlFromStep0?: string | null
225
- ): Promise<{ logAnalysis: string; beforeScreenshotUrl: string | null }> {
226
- "use step"
227
- const { fetchRealLogs } = await import("./steps")
228
- return fetchRealLogs(mcpUrlOrDevUrl, bypassToken, sandboxDevUrl, clsData, mcpError, beforeScreenshotUrlFromStep0)
229
- }
230
-
231
- async function analyzeLogsWithAgent(logAnalysis: string, devUrl: string) {
232
- "use step"
233
- const { analyzeLogsWithAgent } = await import("./steps")
234
- return analyzeLogsWithAgent(logAnalysis, devUrl)
235
- }
236
-
237
- async function uploadToBlob(
238
- fixProposal: string,
239
- projectName: string,
240
- logAnalysis: string,
241
- devUrl: string,
242
- beforeScreenshotUrl?: string | null,
243
- gitDiff?: string | null,
244
- d3kArtifacts?: {
245
- clsScreenshots: Array<{ label: string; blobUrl: string; timestamp: number }>
246
- screencastSessionId: string | null
247
- fullLogs: string | null
248
- metadata: Record<string, unknown> | null
249
- },
250
- runId?: string,
251
- sandboxMcpUrl?: string,
252
- agentAnalysisModel?: string
253
- ) {
254
- "use step"
255
- const { uploadToBlob } = await import("./steps")
256
- return uploadToBlob(
257
- fixProposal,
258
- projectName,
259
- logAnalysis,
260
- devUrl,
261
- beforeScreenshotUrl,
262
- gitDiff,
263
- d3kArtifacts,
264
- runId,
265
- sandboxMcpUrl,
266
- agentAnalysisModel
267
- )
268
- }
269
-
270
- async function createGitHubPR(
271
- fixProposal: string,
272
- blobUrl: string,
273
- repoOwner: string,
274
- repoName: string,
275
- baseBranch: string,
276
- projectName: string
277
- ) {
278
- "use step"
279
- const { createGitHubPR } = await import("./steps")
280
- return createGitHubPR(fixProposal, blobUrl, repoOwner, repoName, baseBranch, projectName)
281
- }
282
-
283
- // Step wrapper for updating workflow progress (uses dynamic import like other steps)
284
- async function updateWorkflowProgressStep(
285
- userId: string,
286
- runId: string,
287
- projectName: string,
288
- timestamp: string,
289
- stepNumber: number,
290
- currentStep: string,
291
- sandboxUrl?: string
292
- ) {
293
- "use step"
294
- const { updateWorkflowProgress } = await import("@/lib/workflow-storage")
295
- return updateWorkflowProgress(userId, runId, projectName, timestamp, stepNumber, currentStep, sandboxUrl)
296
- }
@@ -1,192 +0,0 @@
1
- import { randomUUID } from "crypto"
2
- import { start } from "workflow/api"
3
- import { saveWorkflowRun } from "@/lib/workflow-storage"
4
- import { cloudFixWorkflow } from "../fix-workflow/workflow"
5
-
6
- /**
7
- * API Route to Start Cloud Fix Workflow
8
- *
9
- * This endpoint uses the Workflow SDK's start() API to invoke the workflow
10
- * and waits for the result using run.returnValue, which includes the blob URL
11
- * where the fix proposal was uploaded.
12
- */
13
-
14
- // Configure longer timeout for workflow execution (10 minutes)
15
- export const maxDuration = 600
16
-
17
- // CORS headers - allowing credentials from localhost
18
- const corsHeaders = {
19
- "Access-Control-Allow-Origin": "http://localhost:3000",
20
- "Access-Control-Allow-Methods": "POST, OPTIONS",
21
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
22
- "Access-Control-Allow-Credentials": "true"
23
- }
24
-
25
- // Handle OPTIONS preflight request
26
- export async function OPTIONS() {
27
- return new Response(null, {
28
- status: 204,
29
- headers: corsHeaders
30
- })
31
- }
32
-
33
- export async function POST(request: Request) {
34
- let userId: string | undefined
35
- let projectName: string | undefined
36
- let runId: string | undefined
37
- let runTimestamp: string | undefined
38
-
39
- try {
40
- // Get user's access token from cookies or Authorization header
41
- const { cookies: getCookies } = await import("next/headers")
42
- const cookieStore = await getCookies()
43
- let accessToken = cookieStore.get("access_token")?.value
44
-
45
- // Fallback to Authorization header for cross-origin requests
46
- if (!accessToken) {
47
- const authHeader = request.headers.get("Authorization")
48
- if (authHeader?.startsWith("Bearer ")) {
49
- accessToken = authHeader.substring(7)
50
- }
51
- }
52
-
53
- if (!accessToken) {
54
- return Response.json(
55
- { success: false, error: "Not authenticated. Please sign in to use workflows." },
56
- { status: 401, headers: corsHeaders }
57
- )
58
- }
59
-
60
- // Get VERCEL_OIDC_TOKEN from request header (runtime token)
61
- const vercelOidcToken = request.headers.get("x-vercel-oidc-token") || process.env.VERCEL_OIDC_TOKEN
62
- console.log(`[Start Fix] VERCEL_OIDC_TOKEN available: ${!!vercelOidcToken}`)
63
-
64
- const body = await request.json()
65
- const { devUrl, repoOwner, repoName, baseBranch, bypassToken, repoUrl, repoBranch } = body
66
- userId = body.userId
67
- projectName = body.projectName
68
-
69
- console.log("[Start Fix] Starting cloud fix workflow...")
70
- console.log(`[Start Fix] Dev URL: ${devUrl}`)
71
- console.log(`[Start Fix] Project: ${projectName}`)
72
- console.log(`[Start Fix] User ID: ${userId}`)
73
- console.log(`[Start Fix] Bypass Token: ${bypassToken ? "provided" : "not provided"}`)
74
- if (repoUrl) {
75
- console.log(`[Start Fix] Will create sandbox from: ${repoUrl}`)
76
- console.log(`[Start Fix] Branch: ${repoBranch || "main"}`)
77
- }
78
- if (repoOwner && repoName) {
79
- console.log(`[Start Fix] GitHub: ${repoOwner}/${repoName} (base: ${baseBranch || "main"})`)
80
- }
81
-
82
- // Start the workflow and get a Run object
83
- // Pass serializable data instead of Request object
84
- // The workflow will fetch real logs from the devUrl and optionally create a PR
85
- const workflowParams: Parameters<typeof cloudFixWorkflow>[0] = {
86
- devUrl,
87
- projectName,
88
- vercelToken: accessToken, // Pass user's access token for sandbox creation
89
- vercelOidcToken, // Pass OIDC token from request header for sandbox creation
90
- ...(repoOwner && { repoOwner }),
91
- ...(repoName && { repoName }),
92
- ...(baseBranch && { baseBranch }),
93
- ...(bypassToken && { bypassToken }),
94
- ...(repoUrl && { repoUrl }),
95
- ...(repoBranch && { repoBranch })
96
- }
97
-
98
- // Save workflow run metadata at start if userId and projectName provided
99
- if (userId && projectName) {
100
- runId = randomUUID()
101
- runTimestamp = new Date().toISOString()
102
- await saveWorkflowRun({
103
- id: runId,
104
- userId,
105
- projectName,
106
- timestamp: runTimestamp,
107
- status: "running",
108
- currentStep: "Starting workflow...",
109
- stepNumber: 0
110
- })
111
- console.log(`[Start Fix] Saved workflow run metadata (running): ${runId}`)
112
- }
113
-
114
- // Pass runId and userId to workflow for progress tracking
115
- const workflowParamsWithTracking = {
116
- ...workflowParams,
117
- runId,
118
- userId
119
- }
120
-
121
- const run = await start(cloudFixWorkflow, [workflowParamsWithTracking])
122
-
123
- console.log(`[Start Fix] Workflow started, waiting for completion...`)
124
-
125
- // Wait for workflow to complete and get the Response
126
- const workflowResponse = await run.returnValue
127
-
128
- // Parse the JSON result from the Response
129
- const result = await workflowResponse.json()
130
-
131
- console.log(`[Start Fix] Workflow completed successfully`)
132
- if (result.blobUrl) {
133
- console.log(`[Start Fix] Fix proposal uploaded to: ${result.blobUrl}`)
134
- }
135
- if (result.pr?.prUrl) {
136
- console.log(`[Start Fix] GitHub PR created: ${result.pr.prUrl}`)
137
- }
138
-
139
- // Update workflow run metadata with success status (use same timestamp to overwrite)
140
- if (userId && projectName && runId && runTimestamp) {
141
- await saveWorkflowRun({
142
- id: runId,
143
- userId,
144
- projectName,
145
- timestamp: runTimestamp,
146
- status: "done",
147
- reportBlobUrl: result.blobUrl,
148
- prUrl: result.pr?.prUrl,
149
- beforeScreenshotUrl: result.beforeScreenshotUrl || undefined
150
- })
151
- console.log(`[Start Fix] Updated workflow run metadata to done: ${runId}`)
152
- }
153
-
154
- return Response.json(
155
- {
156
- success: true,
157
- message: "Cloud fix workflow completed successfully",
158
- projectName,
159
- runId,
160
- blobUrl: result.blobUrl,
161
- fixProposal: result.fixProposal,
162
- pr: result.pr
163
- },
164
- {
165
- headers: corsHeaders
166
- }
167
- )
168
- } catch (error) {
169
- console.error("[Start Fix] Error running workflow:", error)
170
-
171
- // Update workflow run metadata with failure status (use same timestamp to overwrite)
172
- if (userId && projectName && runId && runTimestamp) {
173
- await saveWorkflowRun({
174
- id: runId,
175
- userId,
176
- projectName,
177
- timestamp: runTimestamp,
178
- status: "failure",
179
- error: error instanceof Error ? error.message : String(error)
180
- }).catch((err) => console.error("[Start Fix] Failed to save error metadata:", err))
181
- console.log(`[Start Fix] Updated workflow run metadata to failure: ${runId}`)
182
- }
183
-
184
- return Response.json(
185
- {
186
- success: false,
187
- error: error instanceof Error ? error.message : String(error)
188
- },
189
- { status: 500, headers: corsHeaders }
190
- )
191
- }
192
- }