dev3000 0.0.151 → 0.0.154

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 (169) hide show
  1. package/README.md +121 -103
  2. package/bin/dev3000 +10 -5
  3. package/dist/cdp-monitor.d.ts.map +1 -1
  4. package/dist/cdp-monitor.js +2 -3
  5. package/dist/cdp-monitor.js.map +1 -1
  6. package/dist/cli.js +301 -75
  7. package/dist/cli.js.map +1 -1
  8. package/dist/commands/cloud-check-pr.d.ts +1 -0
  9. package/dist/commands/cloud-check-pr.d.ts.map +1 -1
  10. package/dist/commands/cloud-check-pr.js +18 -6
  11. package/dist/commands/cloud-check-pr.js.map +1 -1
  12. package/dist/commands/crawl.d.ts +12 -0
  13. package/dist/commands/crawl.d.ts.map +1 -0
  14. package/dist/commands/crawl.js +140 -0
  15. package/dist/commands/crawl.js.map +1 -0
  16. package/dist/commands/errors.d.ts +14 -0
  17. package/dist/commands/errors.d.ts.map +1 -0
  18. package/dist/commands/errors.js +295 -0
  19. package/dist/commands/errors.js.map +1 -0
  20. package/dist/commands/find-component.d.ts +8 -0
  21. package/dist/commands/find-component.d.ts.map +1 -0
  22. package/dist/commands/find-component.js +182 -0
  23. package/dist/commands/find-component.js.map +1 -0
  24. package/dist/commands/fix.d.ts +13 -0
  25. package/dist/commands/fix.d.ts.map +1 -0
  26. package/dist/commands/fix.js +288 -0
  27. package/dist/commands/fix.js.map +1 -0
  28. package/dist/commands/logs.d.ts +13 -0
  29. package/dist/commands/logs.d.ts.map +1 -0
  30. package/dist/commands/logs.js +195 -0
  31. package/dist/commands/logs.js.map +1 -0
  32. package/dist/commands/restart.d.ts +8 -0
  33. package/dist/commands/restart.d.ts.map +1 -0
  34. package/dist/commands/restart.js +92 -0
  35. package/dist/commands/restart.js.map +1 -0
  36. package/dist/components/PackageSelector.d.ts +12 -0
  37. package/dist/components/PackageSelector.d.ts.map +1 -0
  38. package/dist/components/PackageSelector.js +74 -0
  39. package/dist/components/PackageSelector.js.map +1 -0
  40. package/dist/dev-environment.d.ts +0 -7
  41. package/dist/dev-environment.d.ts.map +1 -1
  42. package/dist/dev-environment.js +108 -674
  43. package/dist/dev-environment.js.map +1 -1
  44. package/dist/screencast-manager.d.ts.map +1 -1
  45. package/dist/screencast-manager.js +7 -8
  46. package/dist/screencast-manager.js.map +1 -1
  47. package/dist/services/parsers/output-processor.js +2 -2
  48. package/dist/services/parsers/output-processor.js.map +1 -1
  49. package/dist/skills/d3k/SKILL.md +38 -27
  50. package/dist/skills/index.d.ts +10 -14
  51. package/dist/skills/index.d.ts.map +1 -1
  52. package/dist/skills/index.js +47 -77
  53. package/dist/skills/index.js.map +1 -1
  54. package/dist/skills/index.test.ts +13 -55
  55. package/dist/skills/index.ts +48 -81
  56. package/dist/src/tui-interface-impl.tsx +6 -15
  57. package/dist/tui-interface-impl.d.ts.map +1 -1
  58. package/dist/tui-interface-impl.js +4 -4
  59. package/dist/tui-interface-impl.js.map +1 -1
  60. package/dist/tui-interface-opentui.d.ts.map +1 -1
  61. package/dist/tui-interface-opentui.js +227 -100
  62. package/dist/tui-interface-opentui.js.map +1 -1
  63. package/dist/utils/agent-browser.d.ts +2 -0
  64. package/dist/utils/agent-browser.d.ts.map +1 -1
  65. package/dist/utils/agent-browser.js +46 -8
  66. package/dist/utils/agent-browser.js.map +1 -1
  67. package/dist/utils/agent-selection.d.ts.map +1 -1
  68. package/dist/utils/agent-selection.js +9 -2
  69. package/dist/utils/agent-selection.js.map +1 -1
  70. package/dist/utils/skill-installer.d.ts +55 -29
  71. package/dist/utils/skill-installer.d.ts.map +1 -1
  72. package/dist/utils/skill-installer.js +118 -229
  73. package/dist/utils/skill-installer.js.map +1 -1
  74. package/dist/utils/tmux-helpers.d.ts +1 -2
  75. package/dist/utils/tmux-helpers.d.ts.map +1 -1
  76. package/dist/utils/tmux-helpers.js +17 -18
  77. package/dist/utils/tmux-helpers.js.map +1 -1
  78. package/dist/utils/version-check.d.ts +2 -1
  79. package/dist/utils/version-check.d.ts.map +1 -1
  80. package/dist/utils/version-check.js +9 -0
  81. package/dist/utils/version-check.js.map +1 -1
  82. package/mcp-server/.next/BUILD_ID +1 -1
  83. package/mcp-server/.next/build-manifest.json +2 -2
  84. package/mcp-server/.next/fallback-build-manifest.json +2 -2
  85. package/mcp-server/.next/prerender-manifest.json +3 -3
  86. package/mcp-server/.next/server/app/_global-error/page.js +1 -1
  87. package/mcp-server/.next/server/app/_global-error/page.js.nft.json +1 -1
  88. package/mcp-server/.next/server/app/_global-error.html +2 -2
  89. package/mcp-server/.next/server/app/_global-error.rsc +1 -1
  90. package/mcp-server/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  91. package/mcp-server/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/mcp-server/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  93. package/mcp-server/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  94. package/mcp-server/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  95. package/mcp-server/.next/server/app/_not-found/page.js +1 -1
  96. package/mcp-server/.next/server/app/_not-found/page.js.nft.json +1 -1
  97. package/mcp-server/.next/server/app/_not-found.html +1 -1
  98. package/mcp-server/.next/server/app/_not-found.rsc +1 -1
  99. package/mcp-server/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  100. package/mcp-server/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  101. package/mcp-server/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  102. package/mcp-server/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  103. package/mcp-server/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  104. package/mcp-server/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  105. package/mcp-server/.next/server/app/api/screenshots/capture/route.js +2 -2
  106. package/mcp-server/.next/server/app/api/screenshots/capture/route.js.nft.json +1 -1
  107. package/mcp-server/.next/server/app/index.html +1 -1
  108. package/mcp-server/.next/server/app/index.rsc +2 -2
  109. package/mcp-server/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  110. package/mcp-server/.next/server/app/index.segments/_full.segment.rsc +2 -2
  111. package/mcp-server/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/mcp-server/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/mcp-server/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/mcp-server/.next/server/app/logs/page.js +1 -1
  115. package/mcp-server/.next/server/app/logs/page.js.nft.json +1 -1
  116. package/mcp-server/.next/server/app/mcp/route.js +4 -4
  117. package/mcp-server/.next/server/app/mcp/route.js.nft.json +1 -1
  118. package/mcp-server/.next/server/app/page.js +1 -1
  119. package/mcp-server/.next/server/app/page.js.nft.json +1 -1
  120. package/mcp-server/.next/server/app/page_client-reference-manifest.js +1 -1
  121. package/mcp-server/.next/server/app/video/[session]/page.js +1 -1
  122. package/mcp-server/.next/server/app/video/[session]/page.js.nft.json +1 -1
  123. package/mcp-server/.next/server/chunks/[root-of-the-server]__2f95edf0._.js +3 -3
  124. package/mcp-server/.next/server/chunks/[root-of-the-server]__2f95edf0._.js.map +1 -1
  125. package/mcp-server/.next/server/chunks/[root-of-the-server]__69e6dfb7._.js +3 -0
  126. package/mcp-server/.next/server/chunks/{[root-of-the-server]__444592aa._.js.map → [root-of-the-server]__69e6dfb7._.js.map} +1 -1
  127. package/mcp-server/.next/server/chunks/[root-of-the-server]__6baff21e._.js +4 -0
  128. package/mcp-server/.next/server/chunks/{[root-of-the-server]__130a5f58._.js.map → [root-of-the-server]__6baff21e._.js.map} +1 -1
  129. package/mcp-server/.next/server/chunks/[root-of-the-server]__6f790e1f._.js +1 -1
  130. package/mcp-server/.next/server/chunks/[root-of-the-server]__6f790e1f._.js.map +1 -1
  131. package/mcp-server/.next/server/chunks/[root-of-the-server]__c8cf5b23._.js +3 -0
  132. package/mcp-server/.next/server/chunks/[root-of-the-server]__e6a83e60._.js +4 -0
  133. package/mcp-server/.next/server/chunks/{[root-of-the-server]__b71c83ed._.js.map → [root-of-the-server]__e6a83e60._.js.map} +1 -1
  134. package/mcp-server/.next/server/chunks/mcp-server_app_mcp_tools_ts_faf6d7df._.js +32 -66
  135. package/mcp-server/.next/server/chunks/mcp-server_app_mcp_tools_ts_faf6d7df._.js.map +1 -1
  136. package/mcp-server/.next/server/chunks/src_utils_agent-browser_ts_cc00e0d8._.js +1 -1
  137. package/mcp-server/.next/server/chunks/src_utils_agent-browser_ts_cc00e0d8._.js.map +1 -1
  138. package/mcp-server/.next/server/chunks/src_utils_project-name_ts_1fab1dd5._.js +3 -0
  139. package/mcp-server/.next/server/chunks/src_utils_project-name_ts_1fab1dd5._.js.map +1 -0
  140. package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__f66148e5._.js → [root-of-the-server]__b17d4048._.js} +2 -2
  141. package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__50eb2eba._.js → [root-of-the-server]__dcf84f77._.js} +2 -2
  142. package/mcp-server/.next/server/chunks/ssr/mcp-server_app_page_tsx_9fc46577._.js +1 -1
  143. package/mcp-server/.next/server/chunks/ssr/mcp-server_app_page_tsx_9fc46577._.js.map +1 -1
  144. package/mcp-server/.next/server/pages/404.html +1 -1
  145. package/mcp-server/.next/server/pages/500.html +2 -2
  146. package/mcp-server/.next/server/server-reference-manifest.js +1 -1
  147. package/mcp-server/.next/server/server-reference-manifest.json +1 -1
  148. package/mcp-server/.next/static/chunks/{2422ea9ed874427b.js → 3f3f8e7d16ba3bf4.js} +1 -1
  149. package/mcp-server/app/api/tools/route.ts +5 -4
  150. package/mcp-server/app/mcp/route.ts +8 -63
  151. package/mcp-server/app/mcp/tools.ts +71 -445
  152. package/mcp-server/app/page.tsx +1 -1
  153. package/mcp-server/package.json +2 -0
  154. package/package.json +6 -5
  155. package/src/tui-interface-impl.tsx +6 -15
  156. package/dist/components/SkillSelector.d.ts +0 -10
  157. package/dist/components/SkillSelector.d.ts.map +0 -1
  158. package/dist/components/SkillSelector.js +0 -87
  159. package/dist/components/SkillSelector.js.map +0 -1
  160. package/mcp-server/.next/server/chunks/[root-of-the-server]__130a5f58._.js +0 -4
  161. package/mcp-server/.next/server/chunks/[root-of-the-server]__444592aa._.js +0 -3
  162. package/mcp-server/.next/server/chunks/[root-of-the-server]__8f84b4cc._.js +0 -3
  163. package/mcp-server/.next/server/chunks/[root-of-the-server]__b71c83ed._.js +0 -4
  164. /package/mcp-server/.next/server/chunks/{[root-of-the-server]__8f84b4cc._.js.map → [root-of-the-server]__c8cf5b23._.js.map} +0 -0
  165. /package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__f66148e5._.js.map → [root-of-the-server]__b17d4048._.js.map} +0 -0
  166. /package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__50eb2eba._.js.map → [root-of-the-server]__dcf84f77._.js.map} +0 -0
  167. /package/mcp-server/.next/static/{HVxg1xsmhVm6VO2KBlH_- → MfA6U1EFS31sVuHA4xDF_}/_buildManifest.js +0 -0
  168. /package/mcp-server/.next/static/{HVxg1xsmhVm6VO2KBlH_- → MfA6U1EFS31sVuHA4xDF_}/_clientMiddlewareManifest.json +0 -0
  169. /package/mcp-server/.next/static/{HVxg1xsmhVm6VO2KBlH_- → MfA6U1EFS31sVuHA4xDF_}/_ssgManifest.js +0 -0
@@ -26,13 +26,12 @@ function isInSandbox(): boolean {
26
26
  export const TOOL_DESCRIPTIONS = {
27
27
  // Meta-description for MCP coordination - Claude should see this when listing tools
28
28
  _mcp_coordination:
29
- "**dev3000 is an MCP orchestrator for web development.** When both dev3000 and chrome-devtools-mcp are available, prefer dev3000's browser tools (execute_browser_action) as they provide:\n Unified error context from server logs + browser console + network\n• Automatic screenshots on errors\n• Framework-aware diagnostics (Next.js, Svelte)\n• Coordinated Chrome connection management\n\ndev3000 automatically detects other MCP configurations and avoids conflicts.",
29
+ "**dev3000 is an MCP orchestrator for web development.** For browser automation, use the d3k CLI:\n```bash\nd3k agent-browser --cdp 9222 <command>\n```\nThis connects to d3k's existing Chrome browser. NEVER install Playwright or Chromium - d3k already has a browser open.\n\ndev3000 provides unified error context from server logs + browser console + network, automatic screenshots on errors, and framework-aware diagnostics (Next.js, Svelte).",
30
30
 
31
31
  fix_my_app:
32
32
  "Diagnoses application errors from dev3000 logs. Returns a prioritized list of issues requiring fixes.\n\n**CRITICAL: You MUST use this tool in a loop until all errors are resolved:**\n\n```\nwhile (errors exist) {\n 1. DIAGNOSE: Call fix_my_app to get current errors\n 2. FIX: Implement a fix for the highest-priority error\n 3. VERIFY: Call fix_my_app again to confirm the error is gone\n 4. REPEAT: Continue until no errors remain\n}\n```\n\n**This tool does NOT fix anything automatically.** It returns diagnostic data. You must:\n- Read the error output\n- Investigate and fix each issue\n- Call this tool again to verify your fix worked\n- Keep looping until the app is healthy\n\n**What it analyzes:**\n• Server logs, browser console, network requests\n• Categorizes: build errors, server crashes, browser errors, network issues, warnings\n• Prioritizes by severity (fix build errors first, then server, then browser, etc.)\n• Shows user interactions that triggered each error\n\n**Parameters:**\n• focusArea: 'build', 'runtime', 'network', 'ui', 'performance', or 'all' (default)\n• mode: 'snapshot' (current state), 'bisect' (before/after comparison), 'monitor' (continuous)\n• timeRangeMinutes: How far back to analyze (default: 10)\n• createPR: If true, creates a PR branch for the highest-priority issue\n\n**Framework support:** Auto-detects Next.js for framework-specific analysis.\n\n**Attribution for commits/PRs:**\n```\nGenerated with Claude Code using d3k (https://d3k.dev)\nCo-Authored-By: Claude <noreply@anthropic.com>\n```",
33
33
 
34
- execute_browser_action:
35
- "Executes browser actions (click, navigate, scroll, type, reload, evaluate JS) in the dev3000-managed Chrome instance.\n\n**PREFER THIS over standalone chrome-devtools-mcp tools.** dev3000 manages the Chrome connection and avoids CDP conflicts.\n\n**Available actions:**\n• screenshot: Capture current page state\n• navigate: Go to a URL\n• reload: Refresh the current page (triggers CLS recapture)\n• click: Click at coordinates {x, y} or selector\n• scroll: Scroll by {x, y} pixels\n• type: Type text into focused element\n• evaluate: Execute JavaScript (read-only operations recommended)\n\n**Use cases:**\n• Reproducing user interactions that triggered errors\n• Verifying fixes by replaying the error scenario\n• Testing specific UI workflows\n• Taking screenshots for visual verification",
34
+ // execute_browser_action removed - use agent_browser_action instead
36
35
 
37
36
  analyze_visual_diff:
38
37
  "Compares two screenshots and returns analysis instructions for identifying visual differences.\n\n**What it provides:**\n• Instructions to load both images for comparison\n• Context about what visual changes to look for\n• Guidance on identifying layout shift causes\n\n**Use cases:**\n• Analyzing before/after frames from CLS detection\n• Identifying elements that appeared, moved, or resized\n• Debugging visual regressions",
@@ -41,7 +40,7 @@ export const TOOL_DESCRIPTIONS = {
41
40
  "Maps a DOM element to its React component source code location.\n\n**How it works:**\n1. Inspects the element via Chrome DevTools Protocol\n2. Extracts the React component function source\n3. Identifies unique code patterns (JSX, classNames, etc.)\n4. Returns grep patterns to locate the source file\n\n**Use cases:**\n• Finding which file contains a specific UI element\n• Locating components responsible for layout shifts\n• Tracing DOM elements back to source code",
42
41
 
43
42
  restart_dev_server:
44
- "Restarts the development server while preserving dev3000's monitoring infrastructure.\n\n**Restart process:**\n1. Tries nextjs-dev MCP restart if available\n2. Falls back to killing and respawning the server process\n3. Preserves: MCP server, browser connection, log capture, screenshots\n\n**When to use:**\n• After modifying config files (next.config.js, middleware, .env)\n• To clear persistent server state\n• For changes that HMR cannot handle\n\n**Important:**\n• Do NOT manually kill the dev server with pkill/kill commands\n• Do NOT manually start the server with npm/pnpm/yarn\n• Server will be offline briefly during restart\n• Most code changes are handled by HMR - only restart when necessary",
43
+ "⚠️ DANGEROUS: Restarts the development server. This is RARELY needed and often causes d3k to crash.\n\n**BEFORE using this tool, consider:**\n• HMR handles most code changes automatically - just wait a moment\n• Browser reload (Cmd+R) clears most cached state\n• 'use cache' in Next.js auto-invalidates when source files change\n• Restarting often fails and causes d3k to exit, disrupting the user's session\n\n**Only use for:**\n• Changes to next.config.js/ts (rare)\n• Changes to middleware.ts (rare)\n• Changes to .env files (rare)\n\n**DO NOT use for:**\n• Clearing RSC cache (HMR handles this)\n• Testing if a fix worked (just reload the page)\n• Any regular code changes\n\n**Ask the user first** before using this tool. They may prefer to manually restart d3k themselves.",
45
44
 
46
45
  crawl_app:
47
46
  "Discovers URLs in the application by crawling links from the homepage.\n\n**Parameters:**\n• depth: How many link levels to follow (1, 2, 3, or 'all')\n• limit: Max links per page (default: 3)\n\n**Behavior:**\n• Starts at localhost homepage\n• Follows same-origin links only\n• Deduplicates discovered URLs\n• Returns list of all found pages\n\n**Use cases:**\n• Discovering all routes before running diagnostics\n• Site-wide testing coverage\n• Verifying all pages load without errors",
@@ -49,8 +48,10 @@ export const TOOL_DESCRIPTIONS = {
49
48
  get_skill:
50
49
  "Get the content of a d3k/Claude Code skill. Skills are prompt templates that provide specialized instructions for specific tasks.\n\n**Parameters:**\n• name: The skill name (e.g., 'vercel-design-guidelines', 'd3k')\n\n**Returns:**\nThe full SKILL.md content which contains instructions on how to perform the skill's task.\n\n**Available skills:**\n• vercel-design-guidelines - Audit web interfaces against Vercel's design guidelines\n• d3k - Core d3k development assistant skill\n\n**Use cases:**\n• Loading design guidelines audit instructions\n• Getting specialized workflow instructions",
51
50
 
52
- agent_browser_action:
53
- "Execute browser actions using agent-browser (Playwright-based CLI). More reliable than raw CDP in sandbox environments.\n\n**Actions:**\n• open: Open URL {url: string}\n• click: Click element {target: '@ref' or 'selector'}\n• type: Type into focused element {text: string}\n• fill: Fill input field {target, value}\n• scroll: Scroll page {direction: up/down/left/right, amount?}\n• screenshot: Capture screenshot {fullPage?: boolean}\n• snapshot: Get accessibility tree with refs for clicking\n• close: Close browser\n• reload: Reload page\n• back: Navigate back\n\n**Options:**\n• session: Session name for isolation\n• headed: Run with visible browser (default: false)\n\n**Ref-based clicking:**\nSnapshot returns elements with refs like @e1, @e2. Use these refs in click action for reliable element targeting."
51
+ // agent_browser_action: REMOVED - Use d3k CLI instead: `d3k agent-browser --cdp 9222 <command>`
52
+ // This avoids browser installation issues and connects to d3k's existing Chrome
53
+ _deprecated_agent_browser_action:
54
+ "REMOVED - Use d3k CLI: `d3k agent-browser --cdp 9222 <command>` instead. This connects to d3k's existing Chrome browser without needing to install anything."
54
55
  }
55
56
 
56
57
  // Types
@@ -81,10 +82,7 @@ export interface CreateIntegratedWorkflowParams {
81
82
  errorContext?: string
82
83
  }
83
84
 
84
- export interface ExecuteBrowserActionParams {
85
- action: string
86
- params?: Record<string, unknown>
87
- }
85
+ // ExecuteBrowserActionParams removed - use AgentBrowserActionParams instead
88
86
 
89
87
  export interface GetMcpCapabilitiesParams {
90
88
  mcpName?: string // Optional - if not provided, shows all available MCPs
@@ -1759,7 +1757,7 @@ async function canDelegateToNextjs(): Promise<boolean> {
1759
1757
  /**
1760
1758
  * Delegate browser action to chrome-devtools MCP
1761
1759
  */
1762
- async function delegateToChromeDevtools(
1760
+ async function _delegateToChromeDevtools(
1763
1761
  action: string,
1764
1762
  params: Record<string, unknown>
1765
1763
  ): Promise<{ content: Array<{ type: "text"; text: string }> }> {
@@ -1833,436 +1831,9 @@ ${availableFunctions}
1833
1831
  }
1834
1832
  }
1835
1833
 
1836
- export async function executeBrowserAction({
1837
- action,
1838
- params = {}
1839
- }: ExecuteBrowserActionParams): Promise<{ content: Array<{ type: "text"; text: string }> }> {
1840
- try {
1841
- // 🎯 INTELLIGENT DELEGATION: Check if chrome-devtools MCP can handle this action
1842
- const canDelegate = await canDelegateToChromeDevtools(action)
1843
- if (canDelegate) {
1844
- logToDevFile(`Browser Action Delegation: Routing '${action}' to chrome-devtools MCP`)
1845
- return await delegateToChromeDevtools(action, params)
1846
- }
1847
-
1848
- // Log fallback to dev3000's own implementation
1849
- logToDevFile(`Browser Action Fallback: Using dev3000's execute_browser_action for '${action}'`)
1850
-
1851
- // First, find active session to get CDP URL
1852
- const sessions = findActiveSessions()
1853
- if (sessions.length === 0) {
1854
- return {
1855
- content: [
1856
- {
1857
- type: "text",
1858
- text: "❌ No active dev3000 sessions found. Make sure dev3000 is running with a browser!"
1859
- }
1860
- ]
1861
- }
1862
- }
1863
-
1864
- // Get the most recent session's CDP URL (stored in session data)
1865
- const sessionData = JSON.parse(readFileSync(sessions[0].sessionFile, "utf-8"))
1866
- let cdpUrl = sessionData.cdpUrl
1867
-
1868
- if (!cdpUrl) {
1869
- // Try to get CDP URL from Chrome debugging port as fallback
1870
- try {
1871
- const response = await fetch("http://localhost:9222/json")
1872
- const pages = await response.json()
1873
- const activePage = pages.find(
1874
- (page: { type: string; url: string }) => page.type === "page" && !page.url.startsWith("chrome://")
1875
- )
1876
- if (activePage) {
1877
- cdpUrl = activePage.webSocketDebuggerUrl
1878
- logToDevFile(`CDP Discovery: Found fallback CDP URL ${cdpUrl}`, sessions[0].projectName)
1879
- }
1880
- } catch (error) {
1881
- logToDevFile(`CDP Discovery: Failed to find fallback CDP URL - ${error}`, sessions[0].projectName)
1882
- }
1883
- }
1884
-
1885
- if (!cdpUrl) {
1886
- return {
1887
- content: [
1888
- {
1889
- type: "text",
1890
- text: `❌ No Chrome DevTools Protocol URL found. Make sure dev3000 is running with browser monitoring enabled (not --servers-only mode). Session CDP URL: ${sessionData.cdpUrl || "null"}`
1891
- }
1892
- ]
1893
- }
1894
- }
1895
-
1896
- // Connect to Chrome DevTools Protocol with timeout
1897
- const result = await new Promise<Record<string, unknown>>((resolve, reject) => {
1898
- const ws = new WebSocket(cdpUrl)
1899
-
1900
- // Overall timeout for the entire browser action (60 seconds)
1901
- const overallTimeout = setTimeout(() => {
1902
- ws.close()
1903
- reject(
1904
- new Error(
1905
- `Browser action '${action}' timed out after 60 seconds. This may indicate an issue with the browser or invalid parameters.`
1906
- )
1907
- )
1908
- }, 60000)
1909
-
1910
- ws.on("open", async () => {
1911
- try {
1912
- // Get the first page target
1913
- ws.send(JSON.stringify({ id: 1, method: "Target.getTargets", params: {} }))
1914
-
1915
- let targetId: string | null = null
1916
- let _sessionId: string | null = null
1917
- let messageId = 2
1918
-
1919
- ws.on("message", async (data) => {
1920
- try {
1921
- const message = JSON.parse(data.toString())
1922
-
1923
- // Handle getting targets
1924
- if (message.id === 1) {
1925
- // Check for CDP protocol errors (e.g., "Not allowed" in sandboxed environments)
1926
- if (message.error) {
1927
- clearTimeout(overallTimeout)
1928
- ws.close()
1929
- reject(
1930
- new Error(
1931
- `Browser protocol error: ${message.error.message || JSON.stringify(message.error)}. This may occur in sandboxed browser environments where certain CDP commands are restricted.`
1932
- )
1933
- )
1934
- return
1935
- }
1936
-
1937
- const pageTarget = message.result?.targetInfos?.find((t: Record<string, unknown>) => t.type === "page")
1938
- if (!pageTarget) {
1939
- clearTimeout(overallTimeout)
1940
- ws.close()
1941
- reject(new Error("No page targets found"))
1942
- return
1943
- }
1944
-
1945
- targetId = pageTarget.targetId
1946
-
1947
- // Attach to the target
1948
- ws.send(
1949
- JSON.stringify({
1950
- id: messageId++,
1951
- method: "Target.attachToTarget",
1952
- params: { targetId, flatten: true }
1953
- })
1954
- )
1955
- return
1956
- }
1957
-
1958
- // Handle session creation
1959
- if (message.method === "Target.attachedToTarget") {
1960
- _sessionId = message.params.sessionId
1961
-
1962
- // Now execute the requested action
1963
- let cdpResult: Record<string, unknown>
1964
-
1965
- switch (action) {
1966
- case "click": {
1967
- let clickX: number
1968
- let clickY: number
1969
-
1970
- // Support both coordinate-based and selector-based clicks
1971
- if (typeof params.selector === "string") {
1972
- // Get element coordinates from selector and ensure we click in the center
1973
- const selectorResult = (await sendCDPCommand(ws, messageId++, "Runtime.evaluate", {
1974
- expression: `(() => {
1975
- const el = document.querySelector(${JSON.stringify(params.selector)});
1976
- if (!el) return { found: false };
1977
- const rect = el.getBoundingClientRect();
1978
- // Calculate center point, rounding to avoid fractional pixels
1979
- const centerX = Math.round(rect.left + rect.width / 2);
1980
- const centerY = Math.round(rect.top + rect.height / 2);
1981
- // Verify what element is at this point
1982
- const elementAtPoint = document.elementFromPoint(centerX, centerY);
1983
- const isCorrectElement = elementAtPoint === el || el.contains(elementAtPoint);
1984
- return {
1985
- found: true,
1986
- x: centerX,
1987
- y: centerY,
1988
- width: rect.width,
1989
- height: rect.height,
1990
- elementAtPoint: elementAtPoint?.tagName + (elementAtPoint?.className ? '.' + elementAtPoint.className : ''),
1991
- isCorrectElement: isCorrectElement
1992
- };
1993
- })()`,
1994
- returnByValue: true
1995
- })) as {
1996
- result?: {
1997
- value?: {
1998
- found: boolean
1999
- x?: number
2000
- y?: number
2001
- width?: number
2002
- height?: number
2003
- elementAtPoint?: string
2004
- isCorrectElement?: boolean
2005
- }
2006
- }
2007
- }
2008
-
2009
- if (
2010
- selectorResult.result?.value?.found === true &&
2011
- typeof selectorResult.result.value.x === "number" &&
2012
- typeof selectorResult.result.value.y === "number"
2013
- ) {
2014
- clickX = selectorResult.result.value.x
2015
- clickY = selectorResult.result.value.y
2016
-
2017
- // Log diagnostic info if element at point doesn't match
2018
- if (selectorResult.result.value.isCorrectElement === false) {
2019
- console.warn(
2020
- `[execute_browser_action] Warning: Center point (${clickX}, ${clickY}) is over ${selectorResult.result.value.elementAtPoint}, not the target element. ` +
2021
- `This may cause unexpected click behavior. Element size: ${selectorResult.result.value.width}x${selectorResult.result.value.height}`
2022
- )
2023
- }
2024
- } else {
2025
- throw new Error(`Element not found for selector: ${params.selector}`)
2026
- }
2027
- } else if (typeof params.x === "number" && typeof params.y === "number") {
2028
- clickX = params.x
2029
- clickY = params.y
2030
- } else {
2031
- throw new Error("Click action requires either {x, y} coordinates or a {selector} CSS selector")
2032
- }
2033
-
2034
- cdpResult = await sendCDPCommand(ws, messageId++, "Input.dispatchMouseEvent", {
2035
- type: "mousePressed",
2036
- x: clickX,
2037
- y: clickY,
2038
- button: "left",
2039
- clickCount: 1
2040
- })
2041
- await sendCDPCommand(ws, messageId++, "Input.dispatchMouseEvent", {
2042
- type: "mouseReleased",
2043
- x: clickX,
2044
- y: clickY,
2045
- button: "left",
2046
- clickCount: 1
2047
- })
2048
- break
2049
- }
2050
-
2051
- case "navigate":
2052
- if (typeof params.url !== "string") {
2053
- throw new Error("Navigate action requires url parameter as string")
2054
- }
2055
- cdpResult = await sendCDPCommand(ws, messageId++, "Page.navigate", { url: params.url })
2056
- break
2057
-
2058
- case "reload":
2059
- // Use CDP Page.reload for reliable page refresh that triggers CLS capture
2060
- cdpResult = await sendCDPCommand(ws, messageId++, "Page.reload", {})
2061
- break
2062
-
2063
- case "screenshot":
2064
- ws.close()
2065
- resolve({
2066
- warning: "Screenshot action is not recommended!",
2067
- advice:
2068
- "Dev3000 automatically captures screenshots during interactions. Instead of manual screenshots, use click/navigate/scroll/type actions to reproduce user workflows, and dev3000 will capture screenshots at optimal times.",
2069
- suggestion: "Run fix_my_app to see all auto-captured screenshots from your session."
2070
- })
2071
- return
2072
-
2073
- case "evaluate": {
2074
- if (typeof params.expression !== "string") {
2075
- throw new Error("Evaluate action requires expression parameter as string")
2076
- }
2077
- const expression = params.expression
2078
- // Validate that the expression is safe (read-only DOM queries)
2079
- // Block dangerous patterns
2080
- const dangerousPatterns = [
2081
- /eval\s*\(/,
2082
- /Function\s*\(/,
2083
- /setTimeout/,
2084
- /setInterval/,
2085
- /\.innerHTML\s*=/,
2086
- /\.outerHTML\s*=/,
2087
- /document\.write/,
2088
- /document\.cookie\s*=/,
2089
- /localStorage\.setItem/,
2090
- /sessionStorage\.setItem/,
2091
- /\.src\s*=/,
2092
- /\.href\s*=/,
2093
- /location\s*=/,
2094
- /\.addEventListener/,
2095
- /\.removeEventListener/,
2096
- /new\s+Function/,
2097
- /import\s*\(/,
2098
- /fetch\s*\(/,
2099
- /XMLHttpRequest/
2100
- ]
2101
-
2102
- if (dangerousPatterns.some((regex) => regex.test(expression))) {
2103
- throw new Error(
2104
- "Expression contains dangerous patterns. Only safe read-only expressions allowed."
2105
- )
2106
- }
2107
-
2108
- cdpResult = await sendCDPCommand(ws, messageId++, "Runtime.evaluate", {
2109
- expression: expression,
2110
- returnByValue: true
2111
- })
2112
- break
2113
- }
2114
-
2115
- case "scroll": {
2116
- const scrollX = typeof params.deltaX === "number" ? params.deltaX : 0
2117
- const scrollY = typeof params.deltaY === "number" ? params.deltaY : 0
2118
- cdpResult = await sendCDPCommand(ws, messageId++, "Input.dispatchMouseEvent", {
2119
- type: "mouseWheel",
2120
- x: typeof params.x === "number" ? params.x : 500,
2121
- y: typeof params.y === "number" ? params.y : 500,
2122
- deltaX: scrollX,
2123
- deltaY: scrollY
2124
- })
2125
- break
2126
- }
2127
-
2128
- case "type":
2129
- if (typeof params.text !== "string") {
2130
- throw new Error("Type action requires text parameter as string")
2131
- }
2132
- // Type each character
2133
- for (const char of params.text) {
2134
- await sendCDPCommand(ws, messageId++, "Input.dispatchKeyEvent", {
2135
- type: "char",
2136
- text: char
2137
- })
2138
- }
2139
- cdpResult = { action: "type", text: params.text }
2140
- break
2141
-
2142
- default:
2143
- throw new Error(`Unsupported action: ${action}`)
2144
- }
2145
-
2146
- ws.close()
2147
- clearTimeout(overallTimeout)
2148
- resolve(cdpResult)
2149
- }
2150
- } catch (error) {
2151
- // Catch any errors that occur during message handling
2152
- ws.close()
2153
- clearTimeout(overallTimeout)
2154
- reject(
2155
- error instanceof Error
2156
- ? error
2157
- : new Error(`Browser action failed: ${error instanceof Error ? error.message : String(error)}`)
2158
- )
2159
- }
2160
- })
2161
-
2162
- ws.on("error", (error) => {
2163
- clearTimeout(overallTimeout)
2164
- reject(error)
2165
- })
2166
-
2167
- // Helper function to send CDP commands
2168
- async function sendCDPCommand(
2169
- ws: WebSocket,
2170
- id: number,
2171
- method: string,
2172
- params: Record<string, unknown>
2173
- ): Promise<Record<string, unknown>> {
2174
- return new Promise((cmdResolve, cmdReject) => {
2175
- const command = { id, method, params }
2176
-
2177
- const messageHandler = (data: Buffer) => {
2178
- const message = JSON.parse(data.toString())
2179
- if (message.id === id) {
2180
- ws.removeListener("message", messageHandler)
2181
- if (message.error) {
2182
- cmdReject(new Error(message.error.message))
2183
- } else {
2184
- cmdResolve(message.result)
2185
- }
2186
- }
2187
- }
2188
-
2189
- ws.on("message", messageHandler)
2190
- ws.send(JSON.stringify(command))
2191
-
2192
- // Command timeout (30 seconds for complex evaluate expressions)
2193
- setTimeout(() => {
2194
- ws.removeListener("message", messageHandler)
2195
- cmdReject(new Error(`CDP command timeout after 30s: ${method}`))
2196
- }, 30000)
2197
- })
2198
- }
2199
- } catch (error) {
2200
- ws.close()
2201
- clearTimeout(overallTimeout)
2202
- reject(error)
2203
- }
2204
- })
2205
-
2206
- ws.on("error", (error) => {
2207
- clearTimeout(overallTimeout)
2208
- reject(error)
2209
- })
2210
- })
2211
-
2212
- // Build success message with augmented suggestions
2213
- let successMessage = `Browser action '${action}' executed successfully. Result: ${JSON.stringify(result, null, 2)}`
2214
-
2215
- // Add augmented suggestions for enhanced capabilities
2216
- const canDelegateChrome = await canDelegateToChromeDevtools("inspect_element")
2217
- if (canDelegateChrome) {
2218
- successMessage += "\n\n🔗 **ENHANCED BROWSER ANALYSIS AVAILABLE**"
2219
- successMessage +=
2220
- "\n\ndev3000 completed the basic browser action above. For deeper browser insights, consider also:"
2221
-
2222
- // Generate dynamic suggestions based on the action and available capabilities
2223
- const dynamicSuggestions = await generateChromeDevtoolsSuggestions(action)
2224
- const actionRelevantSuggestions = dynamicSuggestions.filter((suggestion) => {
2225
- const funcName = suggestion.function.toLowerCase()
2226
- const actionName = action.toLowerCase()
2227
-
2228
- // Match suggestions to specific actions
2229
- if (actionName === "screenshot" && (funcName.includes("inspect") || funcName.includes("performance")))
2230
- return true
2231
- if (actionName === "evaluate" && (funcName.includes("console") || funcName.includes("inspect"))) return true
2232
- if (actionName === "navigate" && (funcName.includes("network") || funcName.includes("performance"))) return true
2233
- if (actionName === "click" && (funcName.includes("console") || funcName.includes("inspect"))) return true
2234
-
2235
- // Include high-priority suggestions regardless
2236
- return suggestion.priority === "high"
2237
- })
2238
-
2239
- actionRelevantSuggestions.slice(0, 2).forEach((suggestion) => {
2240
- successMessage += `\n• \`dev3000-chrome-devtools:${suggestion.function}()\` - ${suggestion.reason}`
2241
- })
2242
-
2243
- successMessage +=
2244
- "\n\n💡 **Augmented approach:** Use dev3000 for basic automation, chrome-devtools for detailed analysis and debugging."
2245
- }
2246
-
2247
- return {
2248
- content: [
2249
- {
2250
- type: "text",
2251
- text: successMessage
2252
- }
2253
- ]
2254
- }
2255
- } catch (error) {
2256
- return {
2257
- content: [
2258
- {
2259
- type: "text",
2260
- text: `Browser action failed: ${error instanceof Error ? error.message : String(error)}`
2261
- }
2262
- ]
2263
- }
2264
- }
2265
- }
1834
+ // executeBrowserAction removed - use executeAgentBrowserAction directly
1835
+ // The legacy execute_browser_action MCP tool has been removed
1836
+ // All browser automation now goes through agent_browser_action
2266
1837
 
2267
1838
  // MCP Integration and Workflow Orchestration Functions
2268
1839
 
@@ -4381,10 +3952,22 @@ export async function getSkill(params: GetSkillParams) {
4381
3952
  // ============================================================
4382
3953
 
4383
3954
  export interface AgentBrowserActionParams {
4384
- action: "open" | "click" | "type" | "fill" | "scroll" | "screenshot" | "snapshot" | "close" | "reload" | "back"
3955
+ action:
3956
+ | "open"
3957
+ | "click"
3958
+ | "type"
3959
+ | "fill"
3960
+ | "scroll"
3961
+ | "screenshot"
3962
+ | "snapshot"
3963
+ | "close"
3964
+ | "reload"
3965
+ | "back"
3966
+ | "evaluate"
4385
3967
  params?: Record<string, unknown>
4386
3968
  session?: string // Session name for isolation
4387
3969
  headed?: boolean // Run with visible browser window
3970
+ profile?: string // Path to persistent browser profile directory (stores cookies, localStorage, etc.)
4388
3971
  }
4389
3972
 
4390
3973
  /**
@@ -4395,7 +3978,8 @@ export async function executeAgentBrowserAction({
4395
3978
  action,
4396
3979
  params = {},
4397
3980
  session,
4398
- headed = false
3981
+ headed = false,
3982
+ profile
4399
3983
  }: AgentBrowserActionParams): Promise<{ content: Array<{ type: "text"; text: string }> }> {
4400
3984
  try {
4401
3985
  // Dynamic import of agent-browser wrapper
@@ -4413,10 +3997,45 @@ export async function executeAgentBrowserAction({
4413
3997
  }
4414
3998
  }
4415
3999
 
4416
- // Build common options
4000
+ // Use project-specific profile path if not specified - this enables persistent sessions
4001
+ // (cookies, localStorage, login state) across browser restarts, per-project
4002
+ // Import getProjectDir to get the same profile path that d3k uses for Chrome
4003
+ const { getProjectDir } = await import("../../../src/utils/project-name")
4004
+ const defaultProfile = profile ?? join(getProjectDir(), "chrome-profile")
4005
+
4006
+ // Extract CDP port to connect to existing browser that d3k launched
4007
+ // CDP_URL format: ws://localhost:9222/devtools/browser/...
4008
+ // Try env var first, then fall back to session file (MCP server starts before CDP is ready)
4009
+ let cdpPort: number | undefined
4010
+ let cdpUrl = process.env.CDP_URL
4011
+
4012
+ // If env var is empty, read from session file
4013
+ if (!cdpUrl) {
4014
+ try {
4015
+ const { existsSync, readFileSync } = await import("fs")
4016
+ const sessionFile = join(getProjectDir(), "session.json")
4017
+ if (existsSync(sessionFile)) {
4018
+ const sessionInfo = JSON.parse(readFileSync(sessionFile, "utf8"))
4019
+ cdpUrl = sessionInfo.cdpUrl
4020
+ }
4021
+ } catch {
4022
+ // Ignore errors reading session file
4023
+ }
4024
+ }
4025
+
4026
+ if (cdpUrl) {
4027
+ const match = cdpUrl.match(/:(\d+)\//)
4028
+ if (match) {
4029
+ cdpPort = parseInt(match[1], 10)
4030
+ }
4031
+ }
4032
+
4033
+ // Build common options - include cdpPort to connect to existing browser
4417
4034
  const options = {
4418
4035
  session,
4419
- headed
4036
+ headed,
4037
+ profile: defaultProfile,
4038
+ cdpPort
4420
4039
  }
4421
4040
 
4422
4041
  let result: unknown
@@ -4500,6 +4119,13 @@ export async function executeAgentBrowserAction({
4500
4119
  break
4501
4120
  }
4502
4121
 
4122
+ case "evaluate": {
4123
+ const expression = typeof params.expression === "string" ? params.expression : ""
4124
+ const evalResult = await agentBrowser.evaluate(expression, options)
4125
+ result = evalResult
4126
+ break
4127
+ }
4128
+
4503
4129
  default:
4504
4130
  return {
4505
4131
  content: [
@@ -358,7 +358,7 @@ export default function HomePage() {
358
358
  </div>
359
359
  <h3 className="font-semibold mb-3 text-lg">AI Verifies Fixes</h3>
360
360
  <p className="text-muted-foreground leading-relaxed">
361
- execute_browser_action tests the fixes in real-time with screenshots
361
+ agent_browser_action tests the fixes in real-time with screenshots
362
362
  </p>
363
363
  </div>
364
364
  </div>
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@modelcontextprotocol/sdk": "1.18.1",
15
+ "agent-browser": "^0.6.0",
15
16
  "@radix-ui/react-slot": "1.2.4",
16
17
  "@types/pixelmatch": "^5.2.6",
17
18
  "@types/pngjs": "^6.0.5",
@@ -21,6 +22,7 @@
21
22
  "mcp-handler": "1.0.2",
22
23
  "ms": "^2.1.3",
23
24
  "next": "16.1.0",
25
+ "styled-jsx": "5.1.6",
24
26
  "pixelmatch": "^7.1.0",
25
27
  "pngjs": "^7.0.0",
26
28
  "react": "19.3.0-canary-09f05694-20251201",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dev3000",
3
- "version": "0.0.151",
3
+ "version": "0.0.154",
4
4
  "description": "AI-powered development tools with browser monitoring and MCP server integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -64,9 +64,9 @@
64
64
  ],
65
65
  "dependencies": {
66
66
  "@biomejs/biome": "^2.2.4",
67
- "@opentui/core": "^0.1.71",
67
+ "@opentui/core": "^0.1.75",
68
68
  "@vercel/sandbox": "^1.1.8",
69
- "agent-browser": "^0.4.4",
69
+ "agent-browser": "^0.6.0",
70
70
  "ai": "^5.0.87",
71
71
  "chalk": "^5.3.0",
72
72
  "commander": "^14.0.1",
@@ -95,8 +95,9 @@
95
95
  "vitest": "^3.2.4"
96
96
  },
97
97
  "optionalDependencies": {
98
- "@d3k/darwin-arm64": "0.0.151",
99
- "@d3k/linux-x64": "0.0.151",
98
+ "@d3k/darwin-arm64": "0.0.154",
99
+ "@d3k/linux-x64": "0.0.154",
100
+ "@d3k/windows-x64": "0.0.154",
100
101
  "@opentui/core-linux-x64": "^0.1.71"
101
102
  },
102
103
  "engines": {