dev3000 0.0.114 → 0.0.116
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.
- package/dist/cdp-monitor.d.ts.map +1 -1
- package/dist/cdp-monitor.js +20 -28
- package/dist/cdp-monitor.js.map +1 -1
- package/dist/cli.js +74 -22
- package/dist/cli.js.map +1 -1
- package/dist/dev-environment.d.ts.map +1 -1
- package/dist/dev-environment.js +43 -11
- package/dist/dev-environment.js.map +1 -1
- package/dist/src/tui-interface-impl.tsx +175 -127
- package/dist/tui-interface-impl.d.ts.map +1 -1
- package/dist/tui-interface-impl.js +113 -74
- package/dist/tui-interface-impl.js.map +1 -1
- package/mcp-server/.next/BUILD_ID +1 -1
- package/mcp-server/.next/build-manifest.json +2 -2
- package/mcp-server/.next/fallback-build-manifest.json +2 -2
- package/mcp-server/.next/prerender-manifest.json +3 -3
- package/mcp-server/.next/server/app/_global-error.html +2 -2
- package/mcp-server/.next/server/app/_global-error.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/_not-found.html +1 -1
- package/mcp-server/.next/server/app/_not-found.rsc +2 -2
- package/mcp-server/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/mcp-server/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/mcp-server/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/mcp-server/.next/server/app/api/cloud/start-fix/route.js +2 -2
- package/mcp-server/.next/server/app/api/cloud/start-fix/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/auth/error/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/auth/error.html +1 -1
- package/mcp-server/.next/server/app/auth/error.rsc +2 -2
- package/mcp-server/.next/server/app/auth/error.segments/_full.segment.rsc +2 -2
- package/mcp-server/.next/server/app/auth/error.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/auth/error.segments/_index.segment.rsc +2 -2
- package/mcp-server/.next/server/app/auth/error.segments/_tree.segment.rsc +2 -2
- package/mcp-server/.next/server/app/auth/error.segments/auth/error/__PAGE__.segment.rsc +1 -1
- package/mcp-server/.next/server/app/auth/error.segments/auth/error.segment.rsc +1 -1
- package/mcp-server/.next/server/app/auth/error.segments/auth.segment.rsc +1 -1
- package/mcp-server/.next/server/app/index.html +1 -1
- package/mcp-server/.next/server/app/index.rsc +3 -3
- package/mcp-server/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/mcp-server/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/mcp-server/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/mcp-server/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/mcp-server/.next/server/app/logs/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/mcp/route.js +2 -2
- package/mcp-server/.next/server/app/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/signin/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/video/[session]/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/workflows/[id]/report/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/workflows/new/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/workflows/new/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/workflows/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/workflows/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__157de66b._.js +284 -37
- package/mcp-server/.next/server/chunks/[root-of-the-server]__157de66b._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__730a8fd0._.js +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__730a8fd0._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__748f411f._.js +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__748f411f._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__8a84f9f4._.js +20 -20
- package/mcp-server/.next/server/chunks/[root-of-the-server]__8a84f9f4._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__c1681338._.js +3 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__c1681338._.js.map +1 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__ec6a1335._.js.map +1 -1
- package/mcp-server/.next/server/chunks/bee4f_next_dist_esm_build_templates_app-route_1ece9366.js +5 -5
- package/mcp-server/.next/server/chunks/bee4f_next_dist_esm_build_templates_app-route_1ece9366.js.map +1 -1
- package/mcp-server/.next/server/chunks/mcp-server_app_api_cloud_fix-workflow_steps_ts_b65f3271._.js +121 -27
- package/mcp-server/.next/server/chunks/mcp-server_app_api_cloud_fix-workflow_steps_ts_b65f3271._.js.map +1 -1
- package/mcp-server/.next/server/chunks/node_modules__pnpm_85ddbe9c._.js +1 -1
- package/mcp-server/.next/server/chunks/node_modules__pnpm_85ddbe9c._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__2e44f0db._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__2e44f0db._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__3585c949._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__3585c949._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__477c3bbb._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__477c3bbb._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__570677dc._.js → [root-of-the-server]__880839a0._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__880839a0._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/_41b8f993._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/_41b8f993._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/_9ba0ef29._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/_9ba0ef29._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/_cd4dc25e._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_new_new-workflow-client_tsx_1312c046._.js +2 -2
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_new_new-workflow-client_tsx_1312c046._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_workflows-client_tsx_268cfd4a._.js +7 -0
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_workflows-client_tsx_268cfd4a._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_961f21c4._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_961f21c4._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_a82244bf._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_a82244bf._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/{node_modules__pnpm_07527699._.js → node_modules__pnpm_eb98e511._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_eb98e511._.js.map +1 -0
- package/mcp-server/.next/server/server-reference-manifest.js +1 -1
- package/mcp-server/.next/server/server-reference-manifest.json +1 -1
- package/mcp-server/.next/static/chunks/000849a6a897f531.css +1 -0
- package/mcp-server/.next/static/chunks/048cee2510ddb1a0.js +1 -0
- package/mcp-server/.next/static/chunks/0622bd0e093adee7.js +3 -0
- package/mcp-server/.next/static/chunks/{46f60efee5f19794.js → 16359f64918a93f3.js} +1 -1
- package/mcp-server/.next/static/chunks/1851a3e70d7efc10.js +1 -0
- package/mcp-server/.next/static/chunks/{cc6addc4bb10fa11.js → 2ad16eeb719786f1.js} +1 -1
- package/mcp-server/.next/static/chunks/57feca7a4e06545e.js +7 -0
- package/mcp-server/.next/static/chunks/93db5737a327ab0c.js +6 -0
- package/mcp-server/.next/static/chunks/9fd3c715ecfb4d05.js +1 -0
- package/mcp-server/.next/static/chunks/b4b1ec6435790587.js +1 -0
- package/mcp-server/.next/static/chunks/cfe150cb2048b7e8.js +1 -0
- package/mcp-server/app/api/cloud/fix-workflow/steps.ts +359 -28
- package/mcp-server/app/api/cloud/fix-workflow/workflow.ts +16 -8
- package/mcp-server/app/api/cloud/start-fix/route.ts +2 -2
- package/mcp-server/app/api/tools/route.ts +11 -12
- package/mcp-server/app/api/workflows/route.ts +45 -1
- package/mcp-server/app/mcp/tools.ts +58 -98
- package/mcp-server/app/workflows/workflows-client.tsx +259 -100
- package/package.json +1 -1
- package/src/tui-interface-impl.tsx +175 -127
- package/mcp-server/.next/server/chunks/[root-of-the-server]__75d68567._.js +0 -3
- package/mcp-server/.next/server/chunks/[root-of-the-server]__75d68567._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__0ff05d72._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__0ff05d72._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__27cc5956._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__27cc5956._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__570677dc._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__ef510343._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__ef510343._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_07527699._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_7cc36047._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_7cc36047._.js.map +0 -1
- package/mcp-server/.next/static/chunks/07848f6bd2a7e5f6.js +0 -3
- package/mcp-server/.next/static/chunks/637a66565f27572f.js +0 -6
- package/mcp-server/.next/static/chunks/aed4fb5252a4bc95.js +0 -3
- package/mcp-server/.next/static/chunks/e8d521464b0c96ca.css +0 -1
- package/mcp-server/.next/static/chunks/ff53279afa939907.js +0 -1
- package/mcp-server/.next/static/chunks/ffa2ecb6845be49c.js +0 -1
- /package/mcp-server/.next/static/{ZvLsxTWoDyQzaSsr_VeX6 → G5taiQ-Jp0B_MdvkQuoIT}/_buildManifest.js +0 -0
- /package/mcp-server/.next/static/{ZvLsxTWoDyQzaSsr_VeX6 → G5taiQ-Jp0B_MdvkQuoIT}/_clientMiddlewareManifest.json +0 -0
- /package/mcp-server/.next/static/{ZvLsxTWoDyQzaSsr_VeX6 → G5taiQ-Jp0B_MdvkQuoIT}/_ssgManifest.js +0 -0
|
@@ -4,11 +4,184 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { put } from "@vercel/blob"
|
|
7
|
+
import type { Sandbox } from "@vercel/sandbox"
|
|
7
8
|
import { createGateway, generateText } from "ai"
|
|
8
9
|
import { createD3kSandbox as createD3kSandboxUtil } from "@/lib/cloud/d3k-sandbox"
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Helper function to properly consume sandbox command output
|
|
13
|
+
* The Vercel Sandbox SDK returns a result object with an async logs() iterator
|
|
14
|
+
*/
|
|
15
|
+
async function runSandboxCommand(
|
|
16
|
+
sandbox: Sandbox,
|
|
17
|
+
cmd: string,
|
|
18
|
+
args: string[]
|
|
19
|
+
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
20
|
+
const result = await sandbox.runCommand({ cmd, args })
|
|
21
|
+
let stdout = ""
|
|
22
|
+
let stderr = ""
|
|
23
|
+
for await (const log of result.logs()) {
|
|
24
|
+
if (log.stream === "stdout") {
|
|
25
|
+
stdout += log.data
|
|
26
|
+
} else {
|
|
27
|
+
stderr += log.data
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
await result.wait()
|
|
31
|
+
return { exitCode: result.exitCode, stdout, stderr }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Capture a screenshot using puppeteer-core inside the sandbox
|
|
36
|
+
* Returns the base64 encoded PNG image data and logs the page title
|
|
37
|
+
*/
|
|
38
|
+
async function captureScreenshotInSandbox(
|
|
39
|
+
sandbox: Sandbox,
|
|
40
|
+
appUrl: string,
|
|
41
|
+
chromiumPath: string,
|
|
42
|
+
label: string,
|
|
43
|
+
sandboxCwd = "/vercel/sandbox"
|
|
44
|
+
): Promise<string | null> {
|
|
45
|
+
console.log(`[Screenshot] Capturing ${label} screenshot of ${appUrl}...`)
|
|
46
|
+
|
|
47
|
+
// Create a Node.js script to capture screenshot with puppeteer-core
|
|
48
|
+
// The script is placed in the sandbox cwd so it can find puppeteer-core from node_modules
|
|
49
|
+
// Output format: JSON with { title, screenshot } on first line, then base64 data
|
|
50
|
+
const screenshotScript = `
|
|
51
|
+
const puppeteer = require('puppeteer-core');
|
|
52
|
+
|
|
53
|
+
(async () => {
|
|
54
|
+
let browser;
|
|
55
|
+
try {
|
|
56
|
+
browser = await puppeteer.launch({
|
|
57
|
+
executablePath: '${chromiumPath}',
|
|
58
|
+
headless: true,
|
|
59
|
+
args: [
|
|
60
|
+
'--no-sandbox',
|
|
61
|
+
'--disable-setuid-sandbox',
|
|
62
|
+
'--disable-dev-shm-usage',
|
|
63
|
+
'--disable-gpu',
|
|
64
|
+
'--single-process'
|
|
65
|
+
]
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const page = await browser.newPage();
|
|
69
|
+
await page.setViewport({ width: 1280, height: 720 });
|
|
70
|
+
|
|
71
|
+
// Navigate with a reasonable timeout
|
|
72
|
+
await page.goto('${appUrl}', {
|
|
73
|
+
waitUntil: 'networkidle2',
|
|
74
|
+
timeout: 30000
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Get the page title for verification
|
|
78
|
+
const title = await page.title();
|
|
79
|
+
console.error('PAGE_TITLE:' + title);
|
|
80
|
+
|
|
81
|
+
// Wait a bit for any animations/layout shifts
|
|
82
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
83
|
+
|
|
84
|
+
// Take screenshot as base64
|
|
85
|
+
const screenshot = await page.screenshot({
|
|
86
|
+
encoding: 'base64',
|
|
87
|
+
fullPage: false
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
console.log(screenshot);
|
|
91
|
+
|
|
92
|
+
await browser.close();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Screenshot error:', error.message);
|
|
95
|
+
if (browser) await browser.close();
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
})();
|
|
99
|
+
`
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// Write the script to the sandbox cwd so it can find puppeteer-core from node_modules
|
|
103
|
+
const scriptPath = `${sandboxCwd}/_screenshot.js`
|
|
104
|
+
const writeResult = await runSandboxCommand(sandbox, "sh", [
|
|
105
|
+
"-c",
|
|
106
|
+
`cat > ${scriptPath} << 'SCRIPT_EOF'
|
|
107
|
+
${screenshotScript}
|
|
108
|
+
SCRIPT_EOF`
|
|
109
|
+
])
|
|
110
|
+
|
|
111
|
+
if (writeResult.exitCode !== 0) {
|
|
112
|
+
console.log(`[Screenshot] Failed to write script: ${writeResult.stderr}`)
|
|
113
|
+
return null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Run the script from the sandbox directory so node can find puppeteer-core in node_modules
|
|
117
|
+
const screenshotResult = await sandbox.runCommand({
|
|
118
|
+
cmd: "node",
|
|
119
|
+
args: [scriptPath],
|
|
120
|
+
cwd: sandboxCwd
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
let stdout = ""
|
|
124
|
+
let stderr = ""
|
|
125
|
+
for await (const log of screenshotResult.logs()) {
|
|
126
|
+
if (log.stream === "stdout") {
|
|
127
|
+
stdout += log.data
|
|
128
|
+
} else {
|
|
129
|
+
stderr += log.data
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
await screenshotResult.wait()
|
|
133
|
+
|
|
134
|
+
// Extract page title from stderr (format: PAGE_TITLE:xxx)
|
|
135
|
+
const titleMatch = stderr.match(/PAGE_TITLE:(.*)/)
|
|
136
|
+
if (titleMatch) {
|
|
137
|
+
console.log(`[Screenshot] Page title: "${titleMatch[1]}"`)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (screenshotResult.exitCode !== 0) {
|
|
141
|
+
console.log(`[Screenshot] Failed to capture: ${stderr}`)
|
|
142
|
+
return null
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// The stdout should be the base64 image
|
|
146
|
+
const base64Data = stdout.trim()
|
|
147
|
+
if (base64Data && base64Data.length > 100) {
|
|
148
|
+
console.log(`[Screenshot] Captured ${label} screenshot (${base64Data.length} bytes base64)`)
|
|
149
|
+
return base64Data
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.log(`[Screenshot] No valid screenshot data returned`)
|
|
153
|
+
return null
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.log(`[Screenshot] Error: ${error instanceof Error ? error.message : String(error)}`)
|
|
156
|
+
return null
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Upload a base64 screenshot to Vercel Blob
|
|
162
|
+
*/
|
|
163
|
+
async function uploadScreenshot(base64Data: string, label: string, projectName: string): Promise<string | null> {
|
|
164
|
+
try {
|
|
165
|
+
const imageBuffer = Buffer.from(base64Data, "base64")
|
|
166
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-")
|
|
167
|
+
const filename = `screenshot-${label}-${projectName}-${timestamp}.png`
|
|
168
|
+
|
|
169
|
+
const blob = await put(filename, imageBuffer, {
|
|
170
|
+
access: "public",
|
|
171
|
+
contentType: "image/png"
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
console.log(`[Screenshot] Uploaded ${label} screenshot: ${blob.url}`)
|
|
175
|
+
return blob.url
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.log(`[Screenshot] Upload failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
178
|
+
return null
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
10
182
|
/**
|
|
11
183
|
* Step 0: Create d3k sandbox with MCP tools pre-configured
|
|
184
|
+
* Also captures a "before" screenshot of the app
|
|
12
185
|
*/
|
|
13
186
|
export async function createD3kSandbox(
|
|
14
187
|
repoUrl: string,
|
|
@@ -48,34 +221,137 @@ export async function createD3kSandbox(
|
|
|
48
221
|
console.log(`[Step 0] Dev URL: ${sandboxResult.devUrl}`)
|
|
49
222
|
console.log(`[Step 0] MCP URL: ${sandboxResult.mcpUrl}`)
|
|
50
223
|
|
|
224
|
+
// Get the chromium path for screenshots
|
|
225
|
+
console.log(`[Step 0] Getting Chromium path for screenshots...`)
|
|
226
|
+
let chromiumPath = "/tmp/chromium"
|
|
227
|
+
try {
|
|
228
|
+
const chromiumResult = await runSandboxCommand(sandboxResult.sandbox, "node", [
|
|
229
|
+
"-e",
|
|
230
|
+
"require('@sparticuz/chromium').executablePath().then(p => console.log(p))"
|
|
231
|
+
])
|
|
232
|
+
if (chromiumResult.exitCode === 0 && chromiumResult.stdout.trim()) {
|
|
233
|
+
chromiumPath = chromiumResult.stdout.trim()
|
|
234
|
+
console.log(`[Step 0] Chromium path: ${chromiumPath}`)
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
console.log(`[Step 0] Could not get chromium path, using default: ${chromiumPath}`)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// CRITICAL DIAGNOSTIC: Test Chrome with EXACT d3k command
|
|
241
|
+
// d3k uses: --user-data-dir, no --remote-debugging-address, loading page, etc.
|
|
242
|
+
console.log(`[Step 0] ===== CHROMIUM CDP TEST (d3k exact command) =====`)
|
|
243
|
+
try {
|
|
244
|
+
const chromeTestScript = `
|
|
245
|
+
exec 2>&1
|
|
246
|
+
echo "=== Chromium CDP Test (d3k exact command) ==="
|
|
247
|
+
echo "Chromium path: ${chromiumPath}"
|
|
248
|
+
echo ""
|
|
249
|
+
|
|
250
|
+
# Create user-data-dir like d3k does
|
|
251
|
+
USER_DATA_DIR="/tmp/d3k-test-profile"
|
|
252
|
+
mkdir -p "$USER_DATA_DIR"
|
|
253
|
+
echo "1. Created user-data-dir: $USER_DATA_DIR"
|
|
254
|
+
|
|
255
|
+
# Create loading page like d3k does
|
|
256
|
+
LOADING_DIR="/tmp/dev3000-loading"
|
|
257
|
+
mkdir -p "$LOADING_DIR"
|
|
258
|
+
cat > "$LOADING_DIR/loading.html" << 'LOADINGHTML'
|
|
259
|
+
<!DOCTYPE html>
|
|
260
|
+
<html>
|
|
261
|
+
<head><title>Loading...</title></head>
|
|
262
|
+
<body><h1>Loading dev3000...</h1></body>
|
|
263
|
+
</html>
|
|
264
|
+
LOADINGHTML
|
|
265
|
+
echo "2. Created loading page: $LOADING_DIR/loading.html"
|
|
266
|
+
echo ""
|
|
267
|
+
|
|
268
|
+
# Use EXACT d3k command (from cdp-monitor.ts)
|
|
269
|
+
# Note: d3k does NOT use --remote-debugging-address
|
|
270
|
+
echo "3. Starting Chrome with d3k's exact args..."
|
|
271
|
+
echo " Command: ${chromiumPath} --remote-debugging-port=9222 --user-data-dir=$USER_DATA_DIR --no-first-run --no-default-browser-check --disable-component-extensions-with-background-pages --disable-background-networking --disable-sync --metrics-recording-only --disable-default-apps --disable-session-crashed-bubble --disable-restore-session-state --headless=new --no-sandbox --disable-setuid-sandbox --disable-gpu --disable-dev-shm-usage file://$LOADING_DIR/loading.html"
|
|
272
|
+
|
|
273
|
+
timeout 15 "${chromiumPath}" \\
|
|
274
|
+
--remote-debugging-port=9222 \\
|
|
275
|
+
--user-data-dir="$USER_DATA_DIR" \\
|
|
276
|
+
--no-first-run \\
|
|
277
|
+
--no-default-browser-check \\
|
|
278
|
+
--disable-component-extensions-with-background-pages \\
|
|
279
|
+
--disable-background-networking \\
|
|
280
|
+
--disable-sync \\
|
|
281
|
+
--metrics-recording-only \\
|
|
282
|
+
--disable-default-apps \\
|
|
283
|
+
--disable-session-crashed-bubble \\
|
|
284
|
+
--disable-restore-session-state \\
|
|
285
|
+
--headless=new \\
|
|
286
|
+
--no-sandbox \\
|
|
287
|
+
--disable-setuid-sandbox \\
|
|
288
|
+
--disable-gpu \\
|
|
289
|
+
--disable-dev-shm-usage \\
|
|
290
|
+
"file://$LOADING_DIR/loading.html" &
|
|
291
|
+
PID=$!
|
|
292
|
+
echo " Chrome PID: $PID"
|
|
293
|
+
sleep 3
|
|
294
|
+
echo ""
|
|
295
|
+
|
|
296
|
+
echo "4. Checking if Chrome is still running..."
|
|
297
|
+
if ps -p $PID > /dev/null 2>&1; then
|
|
298
|
+
echo " Chrome is RUNNING after 3s"
|
|
299
|
+
echo ""
|
|
300
|
+
echo "5. Trying CDP (note: d3k doesn't use --remote-debugging-address)..."
|
|
301
|
+
echo " Trying 127.0.0.1..."
|
|
302
|
+
curl -s --max-time 5 http://127.0.0.1:9222/json/version 2>&1 || echo " 127.0.0.1 failed"
|
|
303
|
+
echo ""
|
|
304
|
+
echo " Trying localhost..."
|
|
305
|
+
curl -s --max-time 5 http://localhost:9222/json/version 2>&1 || echo " localhost failed"
|
|
306
|
+
echo ""
|
|
307
|
+
echo "6. Checking what's listening on 9222..."
|
|
308
|
+
ss -tlnp 2>/dev/null | grep 9222 || netstat -tlnp 2>/dev/null | grep 9222 || echo " Could not check listening ports"
|
|
309
|
+
echo ""
|
|
310
|
+
echo "7. Killing test Chrome..."
|
|
311
|
+
kill $PID 2>/dev/null
|
|
312
|
+
else
|
|
313
|
+
echo " Chrome DIED within 3s"
|
|
314
|
+
wait $PID 2>/dev/null
|
|
315
|
+
EXIT_CODE=$?
|
|
316
|
+
echo " Exit code: $EXIT_CODE"
|
|
317
|
+
echo ""
|
|
318
|
+
echo " Checking for crash logs..."
|
|
319
|
+
ls -la "$USER_DATA_DIR" 2>&1 | head -10 || echo " No user-data-dir"
|
|
320
|
+
fi
|
|
321
|
+
echo ""
|
|
322
|
+
echo "=== End d3k exact command test ==="
|
|
323
|
+
`
|
|
324
|
+
const chromeTest = await runSandboxCommand(sandboxResult.sandbox, "bash", ["-c", chromeTestScript])
|
|
325
|
+
console.log(`[Step 0] d3k Chrome test (exit ${chromeTest.exitCode}):\n${chromeTest.stdout || "(no output)"}`)
|
|
326
|
+
if (chromeTest.stderr) console.log(`[Step 0] d3k Chrome test stderr: ${chromeTest.stderr}`)
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.log(`[Step 0] d3k Chrome test error: ${error instanceof Error ? error.message : String(error)}`)
|
|
329
|
+
}
|
|
330
|
+
console.log(`[Step 0] ===== END d3k EXACT COMMAND TEST =====`)
|
|
331
|
+
|
|
332
|
+
// Capture "BEFORE" screenshot - this shows the app before any fixes
|
|
333
|
+
console.log(`[Step 0] Capturing BEFORE screenshot...`)
|
|
334
|
+
let beforeScreenshotUrl: string | null = null
|
|
335
|
+
try {
|
|
336
|
+
const beforeBase64 = await captureScreenshotInSandbox(
|
|
337
|
+
sandboxResult.sandbox,
|
|
338
|
+
"http://localhost:3000",
|
|
339
|
+
chromiumPath,
|
|
340
|
+
"before"
|
|
341
|
+
)
|
|
342
|
+
if (beforeBase64) {
|
|
343
|
+
beforeScreenshotUrl = await uploadScreenshot(beforeBase64, "before", projectName)
|
|
344
|
+
}
|
|
345
|
+
} catch (error) {
|
|
346
|
+
console.log(`[Step 0] Before screenshot failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
347
|
+
}
|
|
348
|
+
|
|
51
349
|
// Now capture CLS and errors using MCP from INSIDE the sandbox
|
|
52
|
-
// We must do this in Step 0 while we have the sandbox object
|
|
53
350
|
console.log(`[Step 0] Capturing CLS metrics from inside sandbox...`)
|
|
54
351
|
|
|
55
352
|
let clsData: unknown = null
|
|
56
353
|
let mcpError: string | null = null
|
|
57
354
|
|
|
58
|
-
// Helper function to properly consume sandbox command output
|
|
59
|
-
// The Vercel Sandbox SDK returns a result object with an async logs() iterator
|
|
60
|
-
async function runSandboxCommand(
|
|
61
|
-
sandbox: typeof sandboxResult.sandbox,
|
|
62
|
-
cmd: string,
|
|
63
|
-
args: string[]
|
|
64
|
-
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
65
|
-
const result = await sandbox.runCommand({ cmd, args })
|
|
66
|
-
let stdout = ""
|
|
67
|
-
let stderr = ""
|
|
68
|
-
for await (const log of result.logs()) {
|
|
69
|
-
if (log.stream === "stdout") {
|
|
70
|
-
stdout += log.data
|
|
71
|
-
} else {
|
|
72
|
-
stderr += log.data
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
await result.wait()
|
|
76
|
-
return { exitCode: result.exitCode, stdout, stderr }
|
|
77
|
-
}
|
|
78
|
-
|
|
79
355
|
try {
|
|
80
356
|
// Call fix_my_app MCP tool via curl from inside the sandbox
|
|
81
357
|
// This avoids network isolation issues - we're calling localhost:3684 from within the sandbox
|
|
@@ -156,6 +432,27 @@ export async function createD3kSandbox(
|
|
|
156
432
|
}
|
|
157
433
|
console.log(`[Step 0] === End sandbox log dump ===`)
|
|
158
434
|
|
|
435
|
+
// Capture git diff from sandbox - this shows any changes made by d3k
|
|
436
|
+
console.log(`[Step 0] Capturing git diff from sandbox...`)
|
|
437
|
+
let gitDiff: string | null = null
|
|
438
|
+
try {
|
|
439
|
+
const diffResult = await runSandboxCommand(sandboxResult.sandbox, "sh", [
|
|
440
|
+
"-c",
|
|
441
|
+
"cd /vercel/sandbox && git diff --no-color 2>/dev/null || echo 'No git diff available'"
|
|
442
|
+
])
|
|
443
|
+
if (diffResult.exitCode === 0 && diffResult.stdout.trim() && diffResult.stdout.trim() !== "No git diff available") {
|
|
444
|
+
gitDiff = diffResult.stdout.trim()
|
|
445
|
+
console.log(`[Step 0] Git diff captured (${gitDiff.length} chars)`)
|
|
446
|
+
console.log(`[Step 0] Git diff preview:\n${gitDiff.substring(0, 500)}...`)
|
|
447
|
+
} else {
|
|
448
|
+
console.log(`[Step 0] No git changes detected in sandbox`)
|
|
449
|
+
}
|
|
450
|
+
} catch (diffError) {
|
|
451
|
+
console.log(
|
|
452
|
+
`[Step 0] Failed to capture git diff: ${diffError instanceof Error ? diffError.message : String(diffError)}`
|
|
453
|
+
)
|
|
454
|
+
}
|
|
455
|
+
|
|
159
456
|
// Note: We cannot return the cleanup function or sandbox object as they're not serializable
|
|
160
457
|
// Sandbox cleanup will happen automatically when the sandbox times out
|
|
161
458
|
return {
|
|
@@ -163,7 +460,10 @@ export async function createD3kSandbox(
|
|
|
163
460
|
devUrl: sandboxResult.devUrl,
|
|
164
461
|
bypassToken: sandboxResult.bypassToken,
|
|
165
462
|
clsData,
|
|
166
|
-
mcpError
|
|
463
|
+
mcpError,
|
|
464
|
+
beforeScreenshotUrl,
|
|
465
|
+
chromiumPath,
|
|
466
|
+
gitDiff
|
|
167
467
|
}
|
|
168
468
|
}
|
|
169
469
|
|
|
@@ -176,14 +476,18 @@ export async function fetchRealLogs(
|
|
|
176
476
|
bypassToken?: string,
|
|
177
477
|
sandboxDevUrl?: string,
|
|
178
478
|
clsData?: unknown,
|
|
179
|
-
mcpError?: string | null
|
|
479
|
+
mcpError?: string | null,
|
|
480
|
+
beforeScreenshotUrlFromStep0?: string | null
|
|
180
481
|
) {
|
|
181
482
|
"use step"
|
|
182
483
|
|
|
183
|
-
// If we already have CLS data from Step 0, use it
|
|
484
|
+
// If we already have CLS data from Step 0, use it along with the screenshot
|
|
184
485
|
if (clsData) {
|
|
185
486
|
console.log("[Step 1] Using CLS data captured in Step 0")
|
|
186
|
-
|
|
487
|
+
if (beforeScreenshotUrlFromStep0) {
|
|
488
|
+
console.log(`[Step 1] Before screenshot from Step 0: ${beforeScreenshotUrlFromStep0}`)
|
|
489
|
+
}
|
|
490
|
+
return { logAnalysis: JSON.stringify(clsData, null, 2), beforeScreenshotUrl: beforeScreenshotUrlFromStep0 || null }
|
|
187
491
|
}
|
|
188
492
|
|
|
189
493
|
// If there was an MCP error in Step 0, log it
|
|
@@ -573,7 +877,13 @@ Format your response as a clear, structured report that helps identify what's br
|
|
|
573
877
|
const response = await fetch(urlWithBypass, { method: "GET", headers })
|
|
574
878
|
const body = await response.text()
|
|
575
879
|
|
|
880
|
+
// Extract and log page title from HTML
|
|
881
|
+
const titleMatch = body.match(/<title[^>]*>([^<]*)<\/title>/i)
|
|
882
|
+
const pageTitle = titleMatch ? titleMatch[1].trim() : "(no title found)"
|
|
883
|
+
console.log(`[Step 1] HTTP fallback - Page title: "${pageTitle}"`)
|
|
884
|
+
|
|
576
885
|
let logAnalysis = `Dev Server URL: ${devUrl}\n`
|
|
886
|
+
logAnalysis += `Page Title: ${pageTitle}\n`
|
|
577
887
|
logAnalysis += `HTTP Status: ${response.status} ${response.statusText}\n\n`
|
|
578
888
|
logAnalysis += `Note: Browser automation failed, using fallback HTTP fetch.\n\n`
|
|
579
889
|
|
|
@@ -685,7 +995,8 @@ export async function uploadToBlob(
|
|
|
685
995
|
projectName: string,
|
|
686
996
|
logAnalysis: string,
|
|
687
997
|
devUrl: string,
|
|
688
|
-
beforeScreenshotUrl?: string | null
|
|
998
|
+
beforeScreenshotUrl?: string | null,
|
|
999
|
+
gitDiff?: string | null
|
|
689
1000
|
) {
|
|
690
1001
|
"use step"
|
|
691
1002
|
|
|
@@ -693,6 +1004,9 @@ export async function uploadToBlob(
|
|
|
693
1004
|
if (beforeScreenshotUrl) {
|
|
694
1005
|
console.log(`[Step 3] Including before screenshot: ${beforeScreenshotUrl}`)
|
|
695
1006
|
}
|
|
1007
|
+
if (gitDiff) {
|
|
1008
|
+
console.log(`[Step 3] Including git diff (${gitDiff.length} chars)`)
|
|
1009
|
+
}
|
|
696
1010
|
|
|
697
1011
|
// Create screenshot section if we have a screenshot
|
|
698
1012
|
const screenshotSection = beforeScreenshotUrl
|
|
@@ -704,6 +1018,21 @@ This screenshot was captured when the sandbox dev server first loaded, proving t
|
|
|
704
1018
|
|
|
705
1019
|
---
|
|
706
1020
|
|
|
1021
|
+
`
|
|
1022
|
+
: ""
|
|
1023
|
+
|
|
1024
|
+
// Create git diff section if we have a diff from the sandbox
|
|
1025
|
+
const gitDiffSection = gitDiff
|
|
1026
|
+
? `## Actual Git Diff from Sandbox
|
|
1027
|
+
|
|
1028
|
+
The following diff shows the actual changes made by d3k in the sandbox environment:
|
|
1029
|
+
|
|
1030
|
+
\`\`\`diff
|
|
1031
|
+
${gitDiff}
|
|
1032
|
+
\`\`\`
|
|
1033
|
+
|
|
1034
|
+
---
|
|
1035
|
+
|
|
707
1036
|
`
|
|
708
1037
|
: ""
|
|
709
1038
|
|
|
@@ -712,12 +1041,14 @@ This screenshot was captured when the sandbox dev server first loaded, proving t
|
|
|
712
1041
|
const enhancedMarkdown = `# Fix Proposal for ${projectName}
|
|
713
1042
|
|
|
714
1043
|
**Generated**: ${timestamp}
|
|
1044
|
+
|
|
715
1045
|
**Powered by**: [dev3000](https://github.com/vercel-labs/dev3000) with Claude Code
|
|
1046
|
+
|
|
716
1047
|
**Dev Server**: ${devUrl}
|
|
717
1048
|
|
|
718
1049
|
---
|
|
719
1050
|
|
|
720
|
-
${screenshotSection}## Original Log Analysis
|
|
1051
|
+
${screenshotSection}${gitDiffSection}## Original Log Analysis
|
|
721
1052
|
|
|
722
1053
|
\`\`\`
|
|
723
1054
|
${logAnalysis}
|
|
@@ -57,13 +57,16 @@ export async function cloudFixWorkflow(params: {
|
|
|
57
57
|
console.log(`[Workflow] VERCEL_OIDC_TOKEN available: ${!!vercelOidcToken}`)
|
|
58
58
|
|
|
59
59
|
// Step 0: Create d3k sandbox if repoUrl provided
|
|
60
|
-
// This step also captures CLS data from inside the sandbox
|
|
60
|
+
// This step also captures CLS data, "before" screenshot, and git diff from inside the sandbox
|
|
61
61
|
let sandboxInfo: {
|
|
62
62
|
mcpUrl: string
|
|
63
63
|
devUrl: string
|
|
64
64
|
bypassToken?: string
|
|
65
65
|
clsData?: unknown
|
|
66
66
|
mcpError?: string | null
|
|
67
|
+
beforeScreenshotUrl?: string | null
|
|
68
|
+
chromiumPath?: string
|
|
69
|
+
gitDiff?: string | null
|
|
67
70
|
} | null = null
|
|
68
71
|
if (repoUrl) {
|
|
69
72
|
sandboxInfo = await createD3kSandbox(repoUrl, repoBranch || "main", projectName, vercelToken, vercelOidcToken)
|
|
@@ -72,26 +75,29 @@ export async function cloudFixWorkflow(params: {
|
|
|
72
75
|
// Step 1: Fetch real logs (using sandbox MCP if available, otherwise devUrl directly)
|
|
73
76
|
// If we got CLS data from Step 0, pass it to Step 1 to avoid re-fetching
|
|
74
77
|
// Use bypass token from sandbox if available, otherwise use provided one
|
|
78
|
+
// Also pass the beforeScreenshotUrl from Step 0 if available
|
|
75
79
|
const effectiveBypassToken = sandboxInfo?.bypassToken || bypassToken
|
|
76
80
|
const step1Result = await fetchRealLogs(
|
|
77
81
|
sandboxInfo?.mcpUrl || devUrl,
|
|
78
82
|
effectiveBypassToken,
|
|
79
83
|
sandboxInfo?.devUrl,
|
|
80
84
|
sandboxInfo?.clsData,
|
|
81
|
-
sandboxInfo?.mcpError
|
|
85
|
+
sandboxInfo?.mcpError,
|
|
86
|
+
sandboxInfo?.beforeScreenshotUrl
|
|
82
87
|
)
|
|
83
88
|
const { logAnalysis, beforeScreenshotUrl } = step1Result
|
|
84
89
|
|
|
85
90
|
// Step 2: Invoke AI agent to analyze logs and create fix
|
|
86
91
|
const fixProposal = await analyzeLogsWithAgent(logAnalysis, sandboxInfo?.devUrl || devUrl)
|
|
87
92
|
|
|
88
|
-
// Step 3: Upload to blob storage with full context and
|
|
93
|
+
// Step 3: Upload to blob storage with full context, screenshot, and git diff
|
|
89
94
|
const blobResult = await uploadToBlob(
|
|
90
95
|
fixProposal,
|
|
91
96
|
projectName,
|
|
92
97
|
logAnalysis,
|
|
93
98
|
sandboxInfo?.devUrl || devUrl,
|
|
94
|
-
beforeScreenshotUrl
|
|
99
|
+
beforeScreenshotUrl,
|
|
100
|
+
sandboxInfo?.gitDiff
|
|
95
101
|
)
|
|
96
102
|
|
|
97
103
|
// Step 4: Create GitHub PR if repo info provided AND there are actual fixes to apply
|
|
@@ -130,11 +136,12 @@ async function fetchRealLogs(
|
|
|
130
136
|
bypassToken?: string,
|
|
131
137
|
sandboxDevUrl?: string,
|
|
132
138
|
clsData?: unknown,
|
|
133
|
-
mcpError?: string | null
|
|
139
|
+
mcpError?: string | null,
|
|
140
|
+
beforeScreenshotUrlFromStep0?: string | null
|
|
134
141
|
): Promise<{ logAnalysis: string; beforeScreenshotUrl: string | null }> {
|
|
135
142
|
"use step"
|
|
136
143
|
const { fetchRealLogs } = await import("./steps")
|
|
137
|
-
return fetchRealLogs(mcpUrlOrDevUrl, bypassToken, sandboxDevUrl, clsData, mcpError)
|
|
144
|
+
return fetchRealLogs(mcpUrlOrDevUrl, bypassToken, sandboxDevUrl, clsData, mcpError, beforeScreenshotUrlFromStep0)
|
|
138
145
|
}
|
|
139
146
|
|
|
140
147
|
async function analyzeLogsWithAgent(logAnalysis: string, devUrl: string) {
|
|
@@ -148,11 +155,12 @@ async function uploadToBlob(
|
|
|
148
155
|
projectName: string,
|
|
149
156
|
logAnalysis: string,
|
|
150
157
|
devUrl: string,
|
|
151
|
-
beforeScreenshotUrl?: string | null
|
|
158
|
+
beforeScreenshotUrl?: string | null,
|
|
159
|
+
gitDiff?: string | null
|
|
152
160
|
) {
|
|
153
161
|
"use step"
|
|
154
162
|
const { uploadToBlob } = await import("./steps")
|
|
155
|
-
return uploadToBlob(fixProposal, projectName, logAnalysis, devUrl, beforeScreenshotUrl)
|
|
163
|
+
return uploadToBlob(fixProposal, projectName, logAnalysis, devUrl, beforeScreenshotUrl, gitDiff)
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
async function createGitHubPR(
|
|
@@ -132,12 +132,12 @@ export async function POST(request: Request) {
|
|
|
132
132
|
userId,
|
|
133
133
|
projectName,
|
|
134
134
|
timestamp: new Date().toISOString(),
|
|
135
|
-
status: "
|
|
135
|
+
status: "done",
|
|
136
136
|
reportBlobUrl: result.blobUrl,
|
|
137
137
|
prUrl: result.pr?.prUrl,
|
|
138
138
|
beforeScreenshotUrl: result.beforeScreenshotUrl || undefined
|
|
139
139
|
})
|
|
140
|
-
console.log(`[Start Fix] Updated workflow run metadata to
|
|
140
|
+
console.log(`[Start Fix] Updated workflow run metadata to done: ${runId}`)
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
return Response.json(
|
|
@@ -3,61 +3,60 @@ import { NextResponse } from "next/server"
|
|
|
3
3
|
// This endpoint extracts MCP tools documentation by parsing the route handler
|
|
4
4
|
export async function GET() {
|
|
5
5
|
try {
|
|
6
|
-
// Streamlined tool set - reduced from 10 tools to 2 for zero authorization friction!
|
|
7
6
|
const tools = [
|
|
8
7
|
{
|
|
9
8
|
name: "fix_my_app",
|
|
10
9
|
description:
|
|
11
|
-
"
|
|
12
|
-
category: "
|
|
10
|
+
"Diagnoses application errors from dev3000 logs. Returns prioritized issues requiring fixes.\n\n**CRITICAL: Use in a loop until all errors are resolved:**\n1. DIAGNOSE: Call fix_my_app to get errors\n2. FIX: Fix the highest-priority error\n3. VERIFY: Call fix_my_app again to confirm fix worked\n4. REPEAT: Loop until no errors remain\n\n**This tool does NOT fix anything automatically.** You must read the output, fix issues, and call again to verify.\n\n**What it analyzes:** Server logs, browser console, network requests. Prioritizes by severity (build > server > browser > network > warnings).",
|
|
11
|
+
category: "Diagnostics",
|
|
13
12
|
parameters: [
|
|
14
13
|
{
|
|
15
14
|
name: "focusArea",
|
|
16
15
|
type: "string",
|
|
17
16
|
optional: true,
|
|
18
|
-
description: "
|
|
17
|
+
description: "Area to analyze: 'build', 'runtime', 'network', 'ui', 'performance', 'all' (default: 'all')"
|
|
19
18
|
},
|
|
20
19
|
{
|
|
21
20
|
name: "mode",
|
|
22
21
|
type: "enum",
|
|
23
22
|
optional: true,
|
|
24
|
-
description: "
|
|
23
|
+
description: "Analysis mode: 'snapshot', 'bisect', 'monitor'"
|
|
25
24
|
},
|
|
26
25
|
{
|
|
27
26
|
name: "waitForUserInteraction",
|
|
28
27
|
type: "boolean",
|
|
29
28
|
optional: true,
|
|
30
|
-
description: "In bisect mode:
|
|
29
|
+
description: "In bisect mode: wait for user testing before analyzing (default: false)"
|
|
31
30
|
},
|
|
32
31
|
{
|
|
33
32
|
name: "timeRangeMinutes",
|
|
34
33
|
type: "number",
|
|
35
34
|
optional: true,
|
|
36
|
-
description: "Minutes to analyze
|
|
35
|
+
description: "Minutes to analyze (default: 10)"
|
|
37
36
|
},
|
|
38
37
|
{
|
|
39
|
-
name: "
|
|
38
|
+
name: "createPR",
|
|
40
39
|
type: "boolean",
|
|
41
40
|
optional: true,
|
|
42
|
-
description: "
|
|
41
|
+
description: "Create a PR branch for the highest-priority issue (default: false)"
|
|
43
42
|
}
|
|
44
43
|
]
|
|
45
44
|
},
|
|
46
45
|
{
|
|
47
46
|
name: "execute_browser_action",
|
|
48
47
|
description:
|
|
49
|
-
"
|
|
48
|
+
"Executes browser actions in the dev3000-managed Chrome instance.\n\n**Actions:**\n• click: Click at coordinates {x, y}\n• navigate: Go to a URL\n• scroll: Scroll by {x, y} pixels\n• type: Type text into focused element\n• evaluate: Execute JavaScript (read-only recommended)\n• screenshot: Capture current page\n\n**Use cases:**\n• Reproducing user interactions that triggered errors\n• Verifying fixes work correctly\n• Testing UI workflows\n\n**Note:** Screenshots are auto-captured on navigation and errors. Use this for interaction reproduction, not manual screenshots.",
|
|
50
49
|
category: "Browser Automation",
|
|
51
50
|
parameters: [
|
|
52
51
|
{
|
|
53
52
|
name: "action",
|
|
54
53
|
type: "enum",
|
|
55
|
-
description: "Action
|
|
54
|
+
description: "Action: 'click', 'navigate', 'screenshot', 'evaluate', 'scroll', 'type'"
|
|
56
55
|
},
|
|
57
56
|
{
|
|
58
57
|
name: "params",
|
|
59
58
|
type: "object",
|
|
60
|
-
description: "
|
|
59
|
+
description: "Action parameters (coordinates, URL, text, expression, etc.)"
|
|
61
60
|
}
|
|
62
61
|
]
|
|
63
62
|
}
|