@kody-ade/kody-engine-lite 0.1.142 → 0.1.143
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/bin/cli.js +75 -39
- package/kody.config.schema.json +29 -1
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -252,7 +252,9 @@ function getProjectConfig() {
|
|
|
252
252
|
...raw.mcp,
|
|
253
253
|
// Auto-enable when devServer is configured (user can still set enabled: false to override)
|
|
254
254
|
enabled: raw.mcp.enabled ?? !!raw.mcp.devServer
|
|
255
|
-
} : void 0
|
|
255
|
+
} : void 0,
|
|
256
|
+
// Top-level devServer takes precedence; fall back to mcp.devServer for backward compat
|
|
257
|
+
devServer: raw.devServer ?? raw.mcp?.devServer ?? void 0
|
|
256
258
|
};
|
|
257
259
|
} catch {
|
|
258
260
|
logger.warn("kody.config.json is invalid JSON \u2014 using defaults");
|
|
@@ -4943,7 +4945,7 @@ function taskHasUI(taskDir) {
|
|
|
4943
4945
|
}
|
|
4944
4946
|
function getDevServerInfo(taskDir) {
|
|
4945
4947
|
const config = getProjectConfig();
|
|
4946
|
-
const ds = config.
|
|
4948
|
+
const ds = config.devServer;
|
|
4947
4949
|
if (!ds) return void 0;
|
|
4948
4950
|
return {
|
|
4949
4951
|
command: ds.command,
|
|
@@ -5011,13 +5013,9 @@ done
|
|
|
5011
5013
|
\`\`\`
|
|
5012
5014
|
If the dev server fails to start (e.g. DB connection issues), skip browser verification and proceed with code-only changes. Do NOT hang waiting for it.
|
|
5013
5015
|
After you are done browsing, kill the dev server: \`kill $DEV_PID 2>/dev/null || true\``;
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
This task involves UI changes. You MUST visually verify your implementation using the browser tools.
|
|
5018
|
-
${devServerBlock}
|
|
5019
|
-
|
|
5020
|
-
### Available Browser Tools
|
|
5016
|
+
const config = getProjectConfig();
|
|
5017
|
+
const hasMcpPlaywright = isMcpEnabledForStage(stageName, config.mcp);
|
|
5018
|
+
const mcpTools = `### Available Browser Tools
|
|
5021
5019
|
- \`mcp__playwright__browser_navigate\` \u2014 go to a URL
|
|
5022
5020
|
- \`mcp__playwright__browser_snapshot\` \u2014 capture accessibility tree (shows all elements, text, roles)
|
|
5023
5021
|
- \`mcp__playwright__browser_take_screenshot\` \u2014 take a visual screenshot
|
|
@@ -5029,14 +5027,50 @@ ${devServerBlock}
|
|
|
5029
5027
|
- \`mcp__playwright__browser_press_key\` \u2014 press keyboard keys (Enter, Escape, Tab, etc.)
|
|
5030
5028
|
- \`mcp__playwright__browser_resize\` \u2014 resize viewport (test responsive layouts)
|
|
5031
5029
|
- \`mcp__playwright__browser_wait_for\` \u2014 wait for text to appear/disappear
|
|
5032
|
-
- \`mcp__playwright__browser_evaluate\` \u2014 run JavaScript on the page
|
|
5030
|
+
- \`mcp__playwright__browser_evaluate\` \u2014 run JavaScript on the page`;
|
|
5031
|
+
const cliTools = `### Browser Verification via Playwright CLI
|
|
5032
|
+
Use the \`playwright-cli\` commands in your bash tool to interact with the browser:
|
|
5033
|
+
\`\`\`bash
|
|
5034
|
+
# Take a screenshot of a page
|
|
5035
|
+
playwright-cli screenshot ${serverUrl ?? "http://localhost:3000"} --output /tmp/screenshot.png
|
|
5036
|
+
|
|
5037
|
+
# Navigate and interact
|
|
5038
|
+
playwright-cli open ${serverUrl ?? "http://localhost:3000"}
|
|
5039
|
+
|
|
5040
|
+
# Run a quick verification script
|
|
5041
|
+
npx playwright test --grep "homepage" --reporter=list
|
|
5042
|
+
\`\`\`
|
|
5043
|
+
|
|
5044
|
+
Alternatively, write and run a short Playwright script to verify the UI:
|
|
5045
|
+
\`\`\`bash
|
|
5046
|
+
node -e "
|
|
5047
|
+
const { chromium } = require('playwright');
|
|
5048
|
+
(async () => {
|
|
5049
|
+
const browser = await chromium.launch();
|
|
5050
|
+
const page = await browser.newPage();
|
|
5051
|
+
await page.goto('${serverUrl ?? "http://localhost:3000"}');
|
|
5052
|
+
await page.screenshot({ path: '/tmp/verify.png', fullPage: true });
|
|
5053
|
+
console.log('Title:', await page.title());
|
|
5054
|
+
await browser.close();
|
|
5055
|
+
})();
|
|
5056
|
+
"
|
|
5057
|
+
\`\`\`
|
|
5058
|
+
Use the screenshot output and page title to verify the UI is rendering correctly.`;
|
|
5059
|
+
const toolsBlock = hasMcpPlaywright ? mcpTools : cliTools;
|
|
5060
|
+
if (stageName === "build" || stageName === "review-fix") {
|
|
5061
|
+
return `## Browser Visual Verification (MANDATORY for UI tasks)
|
|
5062
|
+
|
|
5063
|
+
This task involves UI changes. You MUST visually verify your implementation using the browser tools.
|
|
5064
|
+
${devServerBlock}
|
|
5065
|
+
|
|
5066
|
+
${toolsBlock}
|
|
5033
5067
|
|
|
5034
5068
|
### Verification Steps (DO ALL OF THESE)
|
|
5035
5069
|
1. Start the dev server (see above)
|
|
5036
|
-
2.
|
|
5037
|
-
3.
|
|
5038
|
-
4. **Test interactions**: if the task involves buttons, forms, search, toggles, or any interactive elements \u2014 click them, type into them, and verify the result
|
|
5039
|
-
5. If the task mentions responsive behavior,
|
|
5070
|
+
2. Navigate to the affected page(s)
|
|
5071
|
+
3. Take a screenshot or snapshot to verify elements are present
|
|
5072
|
+
4. **Test interactions**: if the task involves buttons, forms, search, toggles, or any interactive elements \u2014 click them, type into them, and verify the result
|
|
5073
|
+
5. If the task mentions responsive behavior, test at different viewport widths (e.g., 1200px, 768px, 480px)
|
|
5040
5074
|
6. Kill the dev server when done
|
|
5041
5075
|
|
|
5042
5076
|
Do NOT skip the browser verification. The visual check AND interaction testing are required parts of implementing UI changes.`;
|
|
@@ -5047,22 +5081,14 @@ Do NOT skip the browser verification. The visual check AND interaction testing a
|
|
|
5047
5081
|
This task involves UI changes. You MUST visually verify the implementation using the browser tools before giving your verdict.
|
|
5048
5082
|
${devServerBlock}
|
|
5049
5083
|
|
|
5050
|
-
|
|
5051
|
-
- \`mcp__playwright__browser_navigate\` \u2014 go to a URL
|
|
5052
|
-
- \`mcp__playwright__browser_snapshot\` \u2014 capture accessibility tree (shows all elements, text, roles)
|
|
5053
|
-
- \`mcp__playwright__browser_take_screenshot\` \u2014 take a visual screenshot
|
|
5054
|
-
- \`mcp__playwright__browser_click\` \u2014 click an element
|
|
5055
|
-
- \`mcp__playwright__browser_type\` \u2014 type text into an input
|
|
5056
|
-
- \`mcp__playwright__browser_hover\` \u2014 hover over an element
|
|
5057
|
-
- \`mcp__playwright__browser_resize\` \u2014 resize viewport
|
|
5058
|
-
- \`mcp__playwright__browser_wait_for\` \u2014 wait for text to appear/disappear
|
|
5084
|
+
${toolsBlock}
|
|
5059
5085
|
|
|
5060
5086
|
### Review Verification Steps (DO ALL OF THESE)
|
|
5061
5087
|
1. Start the dev server (see above)
|
|
5062
|
-
2.
|
|
5063
|
-
3.
|
|
5088
|
+
2. Navigate to the affected page(s)
|
|
5089
|
+
3. Take a screenshot or snapshot to verify elements, layout, and text content
|
|
5064
5090
|
4. **Test interactions**: click buttons, fill forms, test search \u2014 verify the UI responds correctly
|
|
5065
|
-
5. If the task mentions responsive behavior,
|
|
5091
|
+
5. If the task mentions responsive behavior, test at different viewport widths
|
|
5066
5092
|
6. Include your browser verification findings in the review (what you saw, what you interacted with, what worked/failed)
|
|
5067
5093
|
7. Kill the dev server when done
|
|
5068
5094
|
|
|
@@ -5070,10 +5096,12 @@ Do NOT skip the browser verification. A review of UI changes without visual AND
|
|
|
5070
5096
|
}
|
|
5071
5097
|
return `## Browser Tools Available
|
|
5072
5098
|
|
|
5073
|
-
You have access to
|
|
5099
|
+
You have access to browser tools for visual verification.
|
|
5074
5100
|
${devServerBlock}
|
|
5075
5101
|
|
|
5076
|
-
|
|
5102
|
+
${toolsBlock}
|
|
5103
|
+
|
|
5104
|
+
Use browser tools to navigate to pages and take screenshots to verify UI output.`;
|
|
5077
5105
|
}
|
|
5078
5106
|
function buildFullPrompt(stageName, taskId, taskDir, projectDir, feedback) {
|
|
5079
5107
|
const config = getProjectConfig();
|
|
@@ -5089,7 +5117,9 @@ function buildFullPrompt(stageName, taskId, taskDir, projectDir, feedback) {
|
|
|
5089
5117
|
|
|
5090
5118
|
${prompt}` : prompt;
|
|
5091
5119
|
}
|
|
5092
|
-
|
|
5120
|
+
const browserStages = ["build", "review", "review-fix"];
|
|
5121
|
+
const hasBrowserTools = isMcpEnabledForStage(stageName, config.mcp) || config.devServer && browserStages.includes(stageName);
|
|
5122
|
+
if (hasBrowserTools && taskHasUI(taskDir)) {
|
|
5093
5123
|
assembled = assembled + "\n\n" + getBrowserToolGuidance(stageName, taskDir);
|
|
5094
5124
|
const qaGuidePath = path21.join(projectDir, ".kody", "qa-guide.md");
|
|
5095
5125
|
if (fs23.existsSync(qaGuidePath)) {
|
|
@@ -5337,9 +5367,10 @@ async function executeAgentStage(ctx, def) {
|
|
|
5337
5367
|
if (mcpConfigJson) {
|
|
5338
5368
|
logger.info(` MCP servers enabled for ${def.name}`);
|
|
5339
5369
|
}
|
|
5370
|
+
const devServerStages = ["build", "review", "review-fix"];
|
|
5340
5371
|
let devServerHandle = null;
|
|
5341
|
-
const ds = config.
|
|
5342
|
-
if (
|
|
5372
|
+
const ds = config.devServer;
|
|
5373
|
+
if (ds && devServerStages.includes(def.name) && taskHasUI(ctx.taskDir)) {
|
|
5343
5374
|
logger.info(` Starting dev server: ${ds.command}`);
|
|
5344
5375
|
const envVars = {};
|
|
5345
5376
|
for (const varName of ds.env ?? []) {
|
|
@@ -8262,28 +8293,33 @@ function buildConfig(cwd, basic) {
|
|
|
8262
8293
|
};
|
|
8263
8294
|
const mcp = detectMcpConfig(cwd, basic.pm, pkg);
|
|
8264
8295
|
if (mcp) config.mcp = mcp;
|
|
8296
|
+
const devServer = detectDevServer(basic.pm, pkg);
|
|
8297
|
+
if (devServer) config.devServer = devServer;
|
|
8265
8298
|
return config;
|
|
8266
8299
|
}
|
|
8267
|
-
function
|
|
8300
|
+
function detectDevServer(pm, pkg) {
|
|
8268
8301
|
const allDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
8269
8302
|
const hasFrontend = FRONTEND_DEPS.some((dep) => dep in allDeps);
|
|
8270
8303
|
if (!hasFrontend) return void 0;
|
|
8271
8304
|
const scripts = pkg.scripts ?? {};
|
|
8272
|
-
|
|
8305
|
+
if (!scripts.dev) return void 0;
|
|
8273
8306
|
const isNext = "next" in allDeps || "nuxt" in allDeps;
|
|
8274
8307
|
const isVite = "vite" in allDeps;
|
|
8275
8308
|
const defaultPort = isNext ? 3e3 : isVite ? 5173 : 3e3;
|
|
8309
|
+
return {
|
|
8310
|
+
command: `${pm} dev`,
|
|
8311
|
+
url: `http://localhost:${defaultPort}`
|
|
8312
|
+
};
|
|
8313
|
+
}
|
|
8314
|
+
function detectMcpConfig(cwd, pm, pkg) {
|
|
8315
|
+
const allDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
8316
|
+
const hasFrontend = FRONTEND_DEPS.some((dep) => dep in allDeps);
|
|
8317
|
+
if (!hasFrontend) return void 0;
|
|
8276
8318
|
const mcp = {
|
|
8277
8319
|
enabled: true,
|
|
8278
8320
|
servers: {},
|
|
8279
8321
|
stages: ["build", "review"]
|
|
8280
8322
|
};
|
|
8281
|
-
if (hasDevScript) {
|
|
8282
|
-
mcp.devServer = {
|
|
8283
|
-
command: `${pm} dev`,
|
|
8284
|
-
url: `http://localhost:${defaultPort}`
|
|
8285
|
-
};
|
|
8286
|
-
}
|
|
8287
8323
|
return mcp;
|
|
8288
8324
|
}
|
|
8289
8325
|
|
package/kody.config.schema.json
CHANGED
|
@@ -241,7 +241,7 @@
|
|
|
241
241
|
},
|
|
242
242
|
"devServer": {
|
|
243
243
|
"type": "object",
|
|
244
|
-
"description": "
|
|
244
|
+
"description": "DEPRECATED: Use top-level devServer instead. Kept for backward compatibility.",
|
|
245
245
|
"properties": {
|
|
246
246
|
"command": {
|
|
247
247
|
"type": "string",
|
|
@@ -270,6 +270,34 @@
|
|
|
270
270
|
},
|
|
271
271
|
"required": ["enabled", "servers"],
|
|
272
272
|
"additionalProperties": false
|
|
273
|
+
},
|
|
274
|
+
"devServer": {
|
|
275
|
+
"type": "object",
|
|
276
|
+
"description": "Dev server configuration for browser tool verification. Works with any provider (MCP or CLI-based).",
|
|
277
|
+
"properties": {
|
|
278
|
+
"command": {
|
|
279
|
+
"type": "string",
|
|
280
|
+
"description": "Command to start the dev server (e.g., 'pnpm dev')"
|
|
281
|
+
},
|
|
282
|
+
"url": {
|
|
283
|
+
"type": "string",
|
|
284
|
+
"description": "URL where the dev server will be accessible (e.g., 'http://localhost:3000')"
|
|
285
|
+
},
|
|
286
|
+
"readyPattern": {
|
|
287
|
+
"type": "string",
|
|
288
|
+
"description": "Regex pattern to match in stdout when server is ready. Default: 'Ready in|compiled|started server|Local:'"
|
|
289
|
+
},
|
|
290
|
+
"readyTimeout": {
|
|
291
|
+
"type": "number",
|
|
292
|
+
"description": "Seconds to wait for the server to be ready. Default: 30"
|
|
293
|
+
},
|
|
294
|
+
"env": {
|
|
295
|
+
"type": "array",
|
|
296
|
+
"items": { "type": "string" },
|
|
297
|
+
"description": "List of GitHub secret names to forward as environment variables for the dev server process (e.g., ['BLOB_READ_WRITE_TOKEN', 'DATABASE_URL']). These are injected into the workflow env block during 'kody init'."
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": ["command", "url"]
|
|
273
301
|
}
|
|
274
302
|
},
|
|
275
303
|
"additionalProperties": false
|