dev3000 0.0.66 → 0.0.67
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 +4 -1
- package/dist/cdp-monitor.d.ts.map +1 -1
- package/dist/cdp-monitor.js +35 -1
- package/dist/cdp-monitor.js.map +1 -1
- package/dist/cli.js +10 -5
- package/dist/cli.js.map +1 -1
- package/dist/dev-environment.d.ts +2 -0
- package/dist/dev-environment.d.ts.map +1 -1
- package/dist/dev-environment.js +44 -27
- package/dist/dev-environment.js.map +1 -1
- package/dist/services/parsers/log-parsers/base.d.ts +1 -1
- package/dist/services/parsers/log-parsers/base.d.ts.map +1 -1
- package/dist/src/tui-interface-impl.tsx +163 -48
- package/dist/tui-interface-impl.d.ts.map +1 -1
- package/dist/tui-interface-impl.js +72 -14
- package/dist/tui-interface-impl.js.map +1 -1
- package/dist/utils/project-name.d.ts +18 -0
- package/dist/utils/project-name.d.ts.map +1 -0
- package/dist/utils/project-name.js +114 -0
- package/dist/utils/project-name.js.map +1 -0
- package/dist/utils/timestamp.d.ts +8 -0
- package/dist/utils/timestamp.d.ts.map +1 -0
- package/dist/utils/timestamp.js +18 -0
- package/dist/utils/timestamp.js.map +1 -0
- package/mcp-server/.next/BUILD_ID +1 -1
- package/mcp-server/.next/app-build-manifest.json +8 -6
- package/mcp-server/.next/build-manifest.json +2 -2
- package/mcp-server/.next/cache/.tsbuildinfo +1 -1
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000005.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000006.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000007.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000008.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000009.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000010.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000011.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000013.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000014.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000016.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000017.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000018.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000021.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000022.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000023.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000025.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000027.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000028.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000029.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000030.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000031.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000032.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000034.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000035.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000037.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000038.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000039.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000040.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000041.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000042.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000044.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000045.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000047.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000048.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000049.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000050.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000051.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000052.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000054.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000055.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000057.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000058.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000059.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000060.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000061.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000062.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000064.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000065.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000066.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000067.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000069.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000070.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000071.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000072.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000073.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000074.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000075.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000076.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000077.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000078.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000079.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000080.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000081.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000082.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000083.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000084.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000085.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000086.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000087.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000088.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000089.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000090.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000091.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000092.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000093.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000094.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000095.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000096.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000097.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000098.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000099.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000100.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000101.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000102.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000103.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000104.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000105.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000106.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000107.sst +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000108.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000109.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/00000110.meta +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/CURRENT +0 -0
- package/mcp-server/.next/cache/turbopack/v15.5.1-canary.28-7-gede8d1b86/LOG +230 -0
- package/mcp-server/.next/fallback-build-manifest.json +2 -2
- package/mcp-server/.next/package.json +3 -1
- package/mcp-server/.next/required-server-files.json +1 -0
- 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/_not-found/page/app-build-manifest.json +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/index.html +1 -1
- package/mcp-server/.next/server/app/index.rsc +3 -3
- package/mcp-server/.next/server/app/logs/page/app-build-manifest.json +4 -3
- 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.nft.json +1 -1
- package/mcp-server/.next/server/app/page/app-build-manifest.json +3 -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/chunks/[root-of-the-server]__1b561deb._.js +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__1b561deb._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__38e8baae._.js +7 -8
- package/mcp-server/.next/server/chunks/[root-of-the-server]__38e8baae._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/{node_modules__pnpm_4f58b96e._.js → _188bfe33._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/_188bfe33._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/_9d670a6b._.js +2 -2
- package/mcp-server/.next/server/chunks/ssr/_9d670a6b._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/_d858c4cd._.js +1 -1
- package/mcp-server/.next/server/chunks/ssr/_d858c4cd._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/_dae9c1d5._.js +1 -1
- package/mcp-server/.next/server/chunks/ssr/_dae9c1d5._.js.map +1 -1
- package/mcp-server/.next/server/chunks/ssr/{node_modules__pnpm_87fb6266._.js → _f03e80a8._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/_f03e80a8._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_layout_tsx_afa41767._.js +1 -1
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_layout_tsx_afa41767._.js.map +1 -1
- package/mcp-server/.next/server/pages/404.html +1 -1
- package/mcp-server/.next/server/pages/500.html +2 -2
- package/mcp-server/.next/static/chunks/5a5edc75ee7e7de4.js +1 -0
- package/mcp-server/.next/static/chunks/65b18bf1ede9811a.css +1 -0
- package/mcp-server/.next/static/chunks/909033014621484e.js +1 -0
- package/mcp-server/.next/static/chunks/c5f8464bc8083ee7.js +1 -0
- package/mcp-server/.next/trace +1 -1
- package/mcp-server/app/api/tools/route.ts +22 -5
- package/mcp-server/app/layout.tsx +4 -2
- package/mcp-server/app/logs/LogsClient.infinite-loop.test.tsx +127 -0
- package/mcp-server/app/logs/LogsClient.tsx +318 -201
- package/mcp-server/app/logs/page.tsx +19 -3
- package/mcp-server/app/logs/utils.ts +15 -3
- package/mcp-server/app/mcp/route.ts +75 -509
- package/mcp-server/app/mcp/tools.ts +747 -0
- package/mcp-server/app/page.tsx +244 -169
- package/mcp-server/next.config.ts +1 -1
- package/mcp-server/package.json +9 -1
- package/mcp-server/public/favicon-16.svg +4 -0
- package/mcp-server/public/favicon-180.png +0 -0
- package/mcp-server/public/favicon-64.svg +4 -0
- package/mcp-server/public/favicon-preview.html +67 -0
- package/mcp-server/public/favicon.ico +0 -0
- package/mcp-server/public/favicon.svg +4 -0
- package/mcp-server/public/screenshots/test.txt +1 -0
- package/package.json +3 -4
- package/src/tui-interface-impl.tsx +163 -48
- package/mcp-server/.next/build/chunks/[root-of-the-server]__25374c4f._.js +0 -496
- package/mcp-server/.next/build/chunks/[root-of-the-server]__25374c4f._.js.map +0 -11
- package/mcp-server/.next/build/chunks/[root-of-the-server]__4718a9dd._.js +0 -408
- package/mcp-server/.next/build/chunks/[root-of-the-server]__4718a9dd._.js.map +0 -7
- package/mcp-server/.next/build/chunks/[root-of-the-server]__c438ef56._.js +0 -205
- package/mcp-server/.next/build/chunks/[root-of-the-server]__c438ef56._.js.map +0 -8
- package/mcp-server/.next/build/chunks/[root-of-the-server]__c7ae8543._.js +0 -496
- package/mcp-server/.next/build/chunks/[root-of-the-server]__c7ae8543._.js.map +0 -11
- package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_d723d216._.js +0 -13
- package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_d723d216._.js.map +0 -5
- package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_webpack-loaders_ts_5a40237e._.js +0 -12
- package/mcp-server/.next/build/chunks/[turbopack-node]_transforms_webpack-loaders_ts_5a40237e._.js.map +0 -5
- package/mcp-server/.next/build/chunks/[turbopack]_runtime.js +0 -770
- package/mcp-server/.next/build/chunks/[turbopack]_runtime.js.map +0 -10
- package/mcp-server/.next/build/chunks/node_modules__pnpm_806d01c0._.js +0 -6759
- package/mcp-server/.next/build/chunks/node_modules__pnpm_806d01c0._.js.map +0 -47
- package/mcp-server/.next/postcss.js +0 -6
- package/mcp-server/.next/postcss.js.map +0 -5
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_4f58b96e._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_87fb6266._.js.map +0 -1
- package/mcp-server/.next/static/chunks/11f1b53bdf7a9af0.js +0 -1
- package/mcp-server/.next/static/chunks/3d4ea64f6384f2c6.js +0 -1
- package/mcp-server/.next/static/chunks/50335dad5c51aab8.js +0 -1
- package/mcp-server/.next/static/chunks/bdd0789390bc312f.css +0 -1
- package/mcp-server/.next/webpack-loaders.js +0 -6
- package/mcp-server/.next/webpack-loaders.js.map +0 -5
- /package/mcp-server/.next/static/{mZfouQw6OHfahPQayuVeY → KrGcHKj--hSqNUOXmnA4A}/_buildManifest.js +0 -0
- /package/mcp-server/.next/static/{mZfouQw6OHfahPQayuVeY → KrGcHKj--hSqNUOXmnA4A}/_clientMiddlewareManifest.json +0 -0
- /package/mcp-server/.next/static/{mZfouQw6OHfahPQayuVeY → KrGcHKj--hSqNUOXmnA4A}/_ssgManifest.js +0 -0
|
@@ -1,70 +1,13 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "fs"
|
|
2
1
|
import { createMcpHandler } from "mcp-handler"
|
|
3
|
-
import { homedir } from "os"
|
|
4
|
-
import { join } from "path"
|
|
5
|
-
import { WebSocket } from "ws"
|
|
6
2
|
import { z } from "zod"
|
|
7
|
-
|
|
8
|
-
// Helper to find active dev3000 sessions
|
|
9
|
-
function findActiveSessions() {
|
|
10
|
-
const sessionDir = join(homedir(), ".d3k")
|
|
11
|
-
if (!existsSync(sessionDir)) {
|
|
12
|
-
return []
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const files = readdirSync(sessionDir)
|
|
17
|
-
.filter((f) => f.endsWith(".json"))
|
|
18
|
-
.map((f) => {
|
|
19
|
-
const filePath = join(sessionDir, f)
|
|
20
|
-
const content = JSON.parse(readFileSync(filePath, "utf-8"))
|
|
21
|
-
const stat = statSync(filePath)
|
|
22
|
-
return {
|
|
23
|
-
...content,
|
|
24
|
-
sessionFile: filePath,
|
|
25
|
-
lastModified: stat.mtime
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
.filter((session) => {
|
|
29
|
-
// Only show sessions from the last 24 hours
|
|
30
|
-
const age = Date.now() - new Date(session.startTime).getTime()
|
|
31
|
-
return age < 24 * 60 * 60 * 1000
|
|
32
|
-
})
|
|
33
|
-
.sort((a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime())
|
|
34
|
-
|
|
35
|
-
return files
|
|
36
|
-
} catch (_error) {
|
|
37
|
-
return []
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Helper to get log path - either from env or session
|
|
42
|
-
function getLogPath(projectName?: string): string | null {
|
|
43
|
-
// If explicit project name provided, look it up
|
|
44
|
-
if (projectName) {
|
|
45
|
-
const sessions = findActiveSessions()
|
|
46
|
-
const session = sessions.find((s) => s.projectName === projectName)
|
|
47
|
-
if (session && existsSync(session.logFilePath)) {
|
|
48
|
-
return session.logFilePath
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Fall back to environment variable
|
|
53
|
-
const envPath = process.env.LOG_FILE_PATH
|
|
54
|
-
if (envPath && existsSync(envPath)) {
|
|
55
|
-
return envPath
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// If no project specified and no env var, show available sessions
|
|
59
|
-
return null
|
|
60
|
-
}
|
|
3
|
+
import { executeBrowserAction, fixMyApp, TOOL_DESCRIPTIONS } from "./tools"
|
|
61
4
|
|
|
62
5
|
const handler = createMcpHandler(
|
|
63
6
|
(server) => {
|
|
64
|
-
// Enhanced
|
|
7
|
+
// Enhanced fix_my_app - the ultimate error fixing tool
|
|
65
8
|
server.tool(
|
|
66
|
-
"
|
|
67
|
-
|
|
9
|
+
"fix_my_app",
|
|
10
|
+
TOOL_DESCRIPTIONS.fix_my_app,
|
|
68
11
|
{
|
|
69
12
|
projectName: z
|
|
70
13
|
.string()
|
|
@@ -77,7 +20,7 @@ const handler = createMcpHandler(
|
|
|
77
20
|
mode: z
|
|
78
21
|
.enum(["snapshot", "bisect", "monitor"])
|
|
79
22
|
.optional()
|
|
80
|
-
.describe("
|
|
23
|
+
.describe("Fix mode: 'snapshot' (fix now), 'bisect' (fix regression), 'monitor' (fix continuously)"),
|
|
81
24
|
waitForUserInteraction: z
|
|
82
25
|
.boolean()
|
|
83
26
|
.optional()
|
|
@@ -88,20 +31,44 @@ const handler = createMcpHandler(
|
|
|
88
31
|
.optional()
|
|
89
32
|
.describe("Show timestamp-based debugging instructions for manual workflow (default: true)")
|
|
90
33
|
},
|
|
91
|
-
async ({
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
34
|
+
async (params) => {
|
|
35
|
+
return fixMyApp(params)
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
// Browser interaction tool
|
|
40
|
+
server.tool(
|
|
41
|
+
"execute_browser_action",
|
|
42
|
+
TOOL_DESCRIPTIONS.execute_browser_action,
|
|
43
|
+
{
|
|
44
|
+
action: z
|
|
45
|
+
.enum(["click", "navigate", "screenshot", "evaluate", "scroll", "type"])
|
|
46
|
+
.describe("The browser action to perform"),
|
|
47
|
+
params: z
|
|
48
|
+
.record(z.unknown())
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Parameters for the action (e.g., {x: 100, y: 200} for click, {url: 'https://...'} for navigate)")
|
|
51
|
+
},
|
|
52
|
+
async (params) => {
|
|
53
|
+
return executeBrowserAction(params)
|
|
54
|
+
}
|
|
55
|
+
)
|
|
102
56
|
|
|
57
|
+
// Tool that returns monitoring code for Claude to execute
|
|
58
|
+
// TODO: Commenting out for now - need to figure out the right approach for proactive monitoring
|
|
59
|
+
/*
|
|
60
|
+
server.tool(
|
|
61
|
+
"start_error_monitoring",
|
|
62
|
+
"🔍 **SIMPLE ERROR MONITORING** - Starts a lightweight background process that watches your app for errors and alerts you in real-time.\n\n⚡ **INSTANT ACTION:**\n• Claude will offer to run the monitoring script right away\n• No manual setup needed - just say yes!\n• Simple 15-line Python script\n• Alerts when errors appear in logs\n\n💡 **WHAT IT DOES:**\n• Watches for ERROR, FAIL, Exception, TypeError, CRASH keywords\n• Shows the error line when detected\n• Prompts you to let Claude debug\n• That's it - simple and effective!\n\n🎯 **PERFECT FOR:**\n• Quick error detection during development\n• Lightweight background monitoring\n• No complex features - just works",
|
|
63
|
+
{
|
|
64
|
+
projectName: z
|
|
65
|
+
.string()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Project name to monitor (if multiple dev3000 instances are running)")
|
|
68
|
+
},
|
|
69
|
+
async ({ projectName }) => {
|
|
103
70
|
try {
|
|
104
|
-
|
|
71
|
+
const logPath = getLogPath(projectName)
|
|
105
72
|
if (!logPath) {
|
|
106
73
|
const sessions = findActiveSessions()
|
|
107
74
|
if (sessions.length === 0) {
|
|
@@ -109,462 +76,60 @@ const handler = createMcpHandler(
|
|
|
109
76
|
content: [
|
|
110
77
|
{
|
|
111
78
|
type: "text",
|
|
112
|
-
text:
|
|
79
|
+
text: "❌ No active dev3000 sessions found. Make sure dev3000 is running!"
|
|
113
80
|
}
|
|
114
81
|
]
|
|
115
82
|
}
|
|
116
83
|
}
|
|
117
84
|
|
|
118
|
-
// Show available sessions
|
|
119
|
-
const sessionList = sessions
|
|
120
|
-
.map((s) => `• ${s.projectName} (port ${s.appPort}, started ${new Date(s.startTime).toLocaleString()})`)
|
|
121
|
-
.join("\n")
|
|
122
|
-
|
|
123
85
|
return {
|
|
124
86
|
content: [
|
|
125
87
|
{
|
|
126
88
|
type: "text",
|
|
127
|
-
text:
|
|
89
|
+
text: `🔍 Multiple sessions found. Please specify projectName:\n${sessions
|
|
90
|
+
.map((s) => `• ${s.projectName} (started ${new Date(s.startTime).toLocaleString()})`)
|
|
91
|
+
.join("\n")}`
|
|
128
92
|
}
|
|
129
93
|
]
|
|
130
94
|
}
|
|
131
95
|
}
|
|
132
96
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
results.push("3. 🔍 When you're done testing, run this tool again with waitForUserInteraction=false")
|
|
156
|
-
results.push("4. 📊 I'll automatically analyze all errors that occurred during your testing")
|
|
157
|
-
results.push("")
|
|
158
|
-
results.push("💡 **This eliminates the need for separate timestamp tools!**")
|
|
159
|
-
results.push("🎪 **The magic happens when you return - I'll have everything ready to fix!**")
|
|
160
|
-
|
|
161
|
-
return {
|
|
162
|
-
content: [
|
|
163
|
-
{
|
|
164
|
-
type: "text",
|
|
165
|
-
text: results.join("\n")
|
|
166
|
-
}
|
|
167
|
-
]
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Determine time range for analysis
|
|
172
|
-
const cutoffTime = new Date(Date.now() - timeRangeMinutes * 60 * 1000)
|
|
173
|
-
|
|
174
|
-
// For monitor mode, show longer time range
|
|
175
|
-
if (mode === "monitor") {
|
|
176
|
-
results.push(`🔄 **CONTINUOUS MONITORING MODE** (last ${timeRangeMinutes} minutes)`)
|
|
177
|
-
} else {
|
|
178
|
-
results.push(`🔍 **COMPREHENSIVE DEBUG ANALYSIS** (last ${timeRangeMinutes} minutes)`)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
results.push(`📊 Analysis timestamp: ${currentTimestamp}`)
|
|
182
|
-
results.push("")
|
|
183
|
-
|
|
184
|
-
// COMPREHENSIVE ERROR DETECTION - combines all previous tools
|
|
185
|
-
const errorPatterns = [
|
|
186
|
-
/ERROR/i,
|
|
187
|
-
/Exception/i,
|
|
188
|
-
/FATAL/i,
|
|
189
|
-
/CRASH/i,
|
|
190
|
-
/Failed to compile/i,
|
|
191
|
-
/Build failed/i,
|
|
192
|
-
/Type error/i,
|
|
193
|
-
/Syntax error/i,
|
|
194
|
-
/Module not found/i,
|
|
195
|
-
/500/,
|
|
196
|
-
/404/,
|
|
197
|
-
/ECONNREFUSED/i,
|
|
198
|
-
/NETWORK.*failed/i,
|
|
199
|
-
/timeout.*error/i,
|
|
200
|
-
/WARN/i,
|
|
201
|
-
/WARNING/i,
|
|
202
|
-
/deprecated/i,
|
|
203
|
-
/slow/i,
|
|
204
|
-
/retry/i
|
|
205
|
-
]
|
|
206
|
-
|
|
207
|
-
// Filter logs by time range (replaces get_logs_between_timestamps)
|
|
208
|
-
const timeFilteredLines = logLines.filter((line) => {
|
|
209
|
-
const timestampMatch = line.match(/\[(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)\]/)
|
|
210
|
-
if (timestampMatch) {
|
|
211
|
-
const logTime = new Date(timestampMatch[1])
|
|
212
|
-
return logTime >= cutoffTime
|
|
213
|
-
}
|
|
214
|
-
return false
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
// Extract ALL error types (replaces multiple error detection tools)
|
|
218
|
-
const allErrors = timeFilteredLines.filter((line) => {
|
|
219
|
-
return errorPatterns.some((pattern) => pattern.test(line))
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
// Categorize errors for better analysis
|
|
223
|
-
const categorizedErrors = {
|
|
224
|
-
serverErrors: allErrors.filter(
|
|
225
|
-
(line) => line.includes("[SERVER]") && (line.includes("ERROR") || line.includes("Exception"))
|
|
226
|
-
),
|
|
227
|
-
browserErrors: allErrors.filter(
|
|
228
|
-
(line) => line.includes("[BROWSER]") && (line.includes("ERROR") || line.includes("CONSOLE ERROR"))
|
|
229
|
-
),
|
|
230
|
-
buildErrors: allErrors.filter(
|
|
231
|
-
(line) =>
|
|
232
|
-
line.includes("Failed to compile") || line.includes("Type error") || line.includes("Build failed")
|
|
233
|
-
),
|
|
234
|
-
networkErrors: allErrors.filter(
|
|
235
|
-
(line) =>
|
|
236
|
-
line.includes("NETWORK") || line.includes("404") || line.includes("500") || line.includes("timeout")
|
|
237
|
-
),
|
|
238
|
-
warnings: allErrors.filter(
|
|
239
|
-
(line) => /WARN|WARNING|deprecated/i.test(line) && !/ERROR|Exception|FAIL/i.test(line)
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const totalErrors = allErrors.length
|
|
244
|
-
const criticalErrors = totalErrors - categorizedErrors.warnings.length
|
|
245
|
-
|
|
246
|
-
if (totalErrors === 0) {
|
|
247
|
-
results.push(`✅ **SYSTEM HEALTHY** - No errors found in last ${timeRangeMinutes} minutes`)
|
|
248
|
-
results.push("🎯 App appears to be running smoothly!")
|
|
249
|
-
|
|
250
|
-
if (includeTimestampInstructions && mode !== "monitor") {
|
|
251
|
-
results.push("")
|
|
252
|
-
results.push("💡 **PROACTIVE MONITORING TIPS:**")
|
|
253
|
-
results.push("• Use mode='bisect' with waitForUserInteraction=true before testing new features")
|
|
254
|
-
results.push("• Use mode='monitor' for continuous background monitoring")
|
|
255
|
-
results.push("• Increase timeRangeMinutes to analyze longer periods")
|
|
256
|
-
}
|
|
257
|
-
} else {
|
|
258
|
-
results.push(
|
|
259
|
-
`🚨 **${totalErrors} ISSUES DETECTED** (${criticalErrors} critical, ${categorizedErrors.warnings.length} warnings)`
|
|
260
|
-
)
|
|
261
|
-
results.push("")
|
|
262
|
-
|
|
263
|
-
// Show categorized errors (replaces individual error tools)
|
|
264
|
-
if (categorizedErrors.serverErrors.length > 0) {
|
|
265
|
-
results.push("🔥 **SERVER ERRORS:**")
|
|
266
|
-
results.push(categorizedErrors.serverErrors.slice(-5).join("\n"))
|
|
267
|
-
results.push("")
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (categorizedErrors.browserErrors.length > 0) {
|
|
271
|
-
results.push("🌐 **BROWSER/CONSOLE ERRORS:**")
|
|
272
|
-
results.push(categorizedErrors.browserErrors.slice(-5).join("\n"))
|
|
273
|
-
results.push("")
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (categorizedErrors.buildErrors.length > 0) {
|
|
277
|
-
results.push("🔨 **BUILD/COMPILATION ERRORS:**")
|
|
278
|
-
results.push(categorizedErrors.buildErrors.slice(-5).join("\n"))
|
|
279
|
-
results.push("")
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (categorizedErrors.networkErrors.length > 0) {
|
|
283
|
-
results.push("🌐 **NETWORK/API ERRORS:**")
|
|
284
|
-
results.push(categorizedErrors.networkErrors.slice(-5).join("\n"))
|
|
285
|
-
results.push("")
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (categorizedErrors.warnings.length > 0 && focusArea === "all") {
|
|
289
|
-
results.push(`⚠️ **WARNINGS** (${categorizedErrors.warnings.length} found, showing recent):`)
|
|
290
|
-
results.push(categorizedErrors.warnings.slice(-3).join("\n"))
|
|
291
|
-
results.push("")
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Show the magical dev3000 fix workflow
|
|
295
|
-
results.push("🪄 **ULTIMATE DEV3000 MAGIC READY:**")
|
|
296
|
-
results.push("🎯 **I don't just find errors - I FIX them instantly!**")
|
|
297
|
-
results.push("• Analyze error patterns and identify root causes automatically")
|
|
298
|
-
results.push("• Edit problematic code files to resolve each issue")
|
|
299
|
-
results.push("• Use execute_browser_action to reproduce user workflows")
|
|
300
|
-
results.push("• Dev3000 AUTO-CAPTURES screenshots during all interactions!")
|
|
301
|
-
results.push("• No manual screenshots needed - dev3000 handles it all!")
|
|
302
|
-
results.push("")
|
|
303
|
-
results.push("📸 **AUTO-SCREENSHOT MAGIC:**")
|
|
304
|
-
results.push("• Screenshots captured automatically on errors, page loads, scrolls")
|
|
305
|
-
results.push("• Just reproduce the user actions - screenshots happen magically")
|
|
306
|
-
results.push("• Check logs for [SCREENSHOT] entries with filenames")
|
|
307
|
-
results.push("")
|
|
308
|
-
results.push("🚀 **SAY 'FIX THESE ISSUES' TO START THE MAGIC:**")
|
|
309
|
-
results.push("• Critical errors fixed first, then warnings")
|
|
310
|
-
results.push("• Each fix tested with browser interactions (no manual screenshots!)")
|
|
311
|
-
results.push("• Real-time proof that every issue is resolved")
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Add usage instructions based on mode
|
|
315
|
-
if (includeTimestampInstructions && mode !== "monitor") {
|
|
316
|
-
results.push("")
|
|
317
|
-
results.push("📚 **ADVANCED DEBUGGING MODES:**")
|
|
318
|
-
results.push("• **Snapshot** (current): Immediate comprehensive analysis")
|
|
319
|
-
results.push("• **Bisect**: Use waitForUserInteraction=true for timestamp-based debugging")
|
|
320
|
-
results.push("• **Monitor**: Continuous monitoring mode for ongoing development")
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Show recent screenshots if any exist
|
|
324
|
-
const screenshotLines = timeFilteredLines.filter((line) => line.includes("[SCREENSHOT]"))
|
|
325
|
-
if (screenshotLines.length > 0) {
|
|
326
|
-
results.push("")
|
|
327
|
-
results.push("📸 **RECENT AUTO-CAPTURED SCREENSHOTS:**")
|
|
328
|
-
const recentScreenshots = screenshotLines.slice(-5)
|
|
329
|
-
recentScreenshots.forEach((line) => {
|
|
330
|
-
const match = line.match(/\[SCREENSHOT\]\s+([^\s]+\.png)/)
|
|
331
|
-
if (match) {
|
|
332
|
-
results.push(`• ${match[1]}`)
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
results.push("💡 Tip: Dev3000 captures these automatically during interactions!")
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
results.push("")
|
|
339
|
-
results.push(`📁 Full logs: ${logPath}`)
|
|
340
|
-
results.push(`⚡ Quick access: tail -f ${logPath}`)
|
|
341
|
-
|
|
342
|
-
if (mode === "monitor") {
|
|
343
|
-
results.push("")
|
|
344
|
-
results.push("🔄 **MONITORING ACTIVE** - Run this tool again to check for new issues")
|
|
345
|
-
}
|
|
97
|
+
// Return simple Python monitoring code
|
|
98
|
+
const monitoringCode = `import time
|
|
99
|
+
|
|
100
|
+
log_file = "${logPath}"
|
|
101
|
+
pos = 0
|
|
102
|
+
|
|
103
|
+
print("🔍 Monitoring:", log_file)
|
|
104
|
+
print("Press Ctrl+C to stop\\n")
|
|
105
|
+
|
|
106
|
+
while True:
|
|
107
|
+
with open(log_file, 'r') as f:
|
|
108
|
+
f.seek(pos)
|
|
109
|
+
new = f.read()
|
|
110
|
+
pos = f.tell()
|
|
111
|
+
|
|
112
|
+
for line in new.split('\\n'):
|
|
113
|
+
if any(err in line for err in ['ERROR', 'FAIL', 'Exception', 'TypeError', 'CRASH']):
|
|
114
|
+
print(f"\\n🚨 ERROR DETECTED:\\n{line[:200]}\\n")
|
|
115
|
+
print("💡 Tell me: 'fix my app' or 'debug my app' to fix this!\\n")
|
|
116
|
+
|
|
117
|
+
time.sleep(2)
|
|
118
|
+
`
|
|
346
119
|
|
|
347
120
|
return {
|
|
348
121
|
content: [
|
|
349
122
|
{
|
|
350
123
|
type: "text",
|
|
351
|
-
text:
|
|
352
|
-
}
|
|
353
|
-
]
|
|
354
|
-
}
|
|
355
|
-
} catch (error) {
|
|
356
|
-
return {
|
|
357
|
-
content: [
|
|
358
|
-
{
|
|
359
|
-
type: "text",
|
|
360
|
-
text: `❌ Error during debug analysis: ${error instanceof Error ? error.message : String(error)}`
|
|
361
|
-
}
|
|
362
|
-
]
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
// Tool to execute browser actions via CDP
|
|
369
|
-
server.tool(
|
|
370
|
-
"execute_browser_action",
|
|
371
|
-
"🎯 **BROWSER INTERACTION TOOL** - For testing user workflows and reproducing issues!\n\n⚡ **KEY STRATEGY:**\n🚨 **NEVER use 'screenshot' action** - dev3000 automatically captures screenshots on:\n• Page loads and navigation\n• Errors and exceptions\n• After scrolling settles\n• Network idle states\n\n✅ **CORRECT USAGE:**\n1. Use click/navigate/scroll/type to reproduce user actions\n2. Dev3000 will AUTOMATICALLY capture screenshots during these actions\n3. Check logs or use debug_my_app to see the auto-captured screenshots\n\n🔥 **AVAILABLE ACTIONS:**\n• **click** → Click buttons/links (requires x,y coordinates)\n• **navigate** → Go to URLs (requires url)\n• **scroll** → Scroll pages (optional deltaX, deltaY)\n• **type** → Type text in forms (requires text)\n• **evaluate** → Read page state with JS (limited safe expressions only)\n\n❌ **DO NOT USE:**\n• **screenshot** → This is for manual capture which dev3000 handles automatically\n\n💡 **BEST PRACTICE WORKFLOW:**\n1. Use debug_my_app to find issues and see existing screenshots\n2. Make code fixes\n3. Use click/navigate/type to reproduce the original user flow\n4. Dev3000 auto-captures new screenshots during your interactions\n5. Use debug_my_app again to verify fixes worked\n\n🎪 **WHY THIS WORKS BETTER:**\n• Screenshots are captured at optimal times automatically\n• You focus on reproducing user actions, not timing screenshots\n• Dev3000 handles all the screenshot complexity for you\n\n🛡️ **SAFETY:** Only safe operations allowed, whitelisted JavaScript expressions",
|
|
372
|
-
{
|
|
373
|
-
action: z.enum(["click", "navigate", "screenshot", "evaluate", "scroll", "type"]).describe("Action to perform"),
|
|
374
|
-
params: z
|
|
375
|
-
.object({
|
|
376
|
-
x: z.number().optional().describe("X coordinate for click/scroll"),
|
|
377
|
-
y: z.number().optional().describe("Y coordinate for click/scroll"),
|
|
378
|
-
url: z.string().optional().describe("URL for navigation"),
|
|
379
|
-
selector: z.string().optional().describe("CSS selector for element targeting"),
|
|
380
|
-
text: z.string().optional().describe("Text to type"),
|
|
381
|
-
expression: z.string().optional().describe("JavaScript expression to evaluate (safe expressions only)"),
|
|
382
|
-
deltaX: z.number().optional().describe("Horizontal scroll amount"),
|
|
383
|
-
deltaY: z.number().optional().describe("Vertical scroll amount")
|
|
384
|
-
})
|
|
385
|
-
.describe("Parameters for the action")
|
|
386
|
-
},
|
|
387
|
-
async ({ action, params }) => {
|
|
388
|
-
try {
|
|
389
|
-
// Connect to CDP on port 9222
|
|
390
|
-
const targetsResponse = await fetch("http://localhost:9222/json")
|
|
391
|
-
const targets = await targetsResponse.json()
|
|
392
|
-
|
|
393
|
-
const pageTarget = targets.find(
|
|
394
|
-
(target: { type: string; webSocketDebuggerUrl: string }) => target.type === "page"
|
|
395
|
-
)
|
|
396
|
-
if (!pageTarget) {
|
|
397
|
-
throw new Error("No browser tab found. Make sure dev3000 is running with CDP monitoring.")
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const wsUrl = pageTarget.webSocketDebuggerUrl
|
|
401
|
-
|
|
402
|
-
const result = await new Promise((resolve, reject) => {
|
|
403
|
-
// WebSocket imported at top of file
|
|
404
|
-
const ws = new WebSocket(wsUrl)
|
|
405
|
-
let messageId = 1
|
|
406
|
-
|
|
407
|
-
ws.on("open", async () => {
|
|
408
|
-
try {
|
|
409
|
-
let cdpResult: Record<string, unknown>
|
|
410
|
-
|
|
411
|
-
switch (action) {
|
|
412
|
-
case "click":
|
|
413
|
-
if (!params.x || !params.y) {
|
|
414
|
-
throw new Error("Click action requires x and y coordinates")
|
|
415
|
-
}
|
|
416
|
-
// Send mouse down and up events
|
|
417
|
-
await sendCDPCommand(ws, messageId++, "Input.dispatchMouseEvent", {
|
|
418
|
-
type: "mousePressed",
|
|
419
|
-
x: params.x,
|
|
420
|
-
y: params.y,
|
|
421
|
-
button: "left",
|
|
422
|
-
clickCount: 1
|
|
423
|
-
})
|
|
424
|
-
await sendCDPCommand(ws, messageId++, "Input.dispatchMouseEvent", {
|
|
425
|
-
type: "mouseReleased",
|
|
426
|
-
x: params.x,
|
|
427
|
-
y: params.y,
|
|
428
|
-
button: "left",
|
|
429
|
-
clickCount: 1
|
|
430
|
-
})
|
|
431
|
-
cdpResult = {
|
|
432
|
-
action: "click",
|
|
433
|
-
coordinates: { x: params.x, y: params.y }
|
|
434
|
-
}
|
|
435
|
-
break
|
|
124
|
+
text: `I'm ready to monitor your app for errors. I'll watch ${logPath} and alert you when errors occur.
|
|
436
125
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
throw new Error("Navigate action requires url parameter")
|
|
440
|
-
}
|
|
441
|
-
// Basic URL validation
|
|
442
|
-
if (!params.url.startsWith("http://") && !params.url.startsWith("https://")) {
|
|
443
|
-
throw new Error("Only http:// and https:// URLs are allowed")
|
|
444
|
-
}
|
|
445
|
-
cdpResult = await sendCDPCommand(ws, messageId++, "Page.navigate", { url: params.url })
|
|
446
|
-
break
|
|
447
|
-
|
|
448
|
-
case "screenshot":
|
|
449
|
-
// Discourage manual screenshots - dev3000 handles this automatically
|
|
450
|
-
ws.close()
|
|
451
|
-
resolve({
|
|
452
|
-
warning: "Screenshot action is not recommended!",
|
|
453
|
-
advice:
|
|
454
|
-
"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.",
|
|
455
|
-
suggestion: "Run debug_my_app to see all auto-captured screenshots from your session."
|
|
456
|
-
})
|
|
457
|
-
return
|
|
458
|
-
|
|
459
|
-
case "evaluate": {
|
|
460
|
-
if (!params.expression) {
|
|
461
|
-
throw new Error("Evaluate action requires expression parameter")
|
|
462
|
-
}
|
|
463
|
-
// Whitelist safe expressions only
|
|
464
|
-
const safeExpressions = [
|
|
465
|
-
/^document\.title$/,
|
|
466
|
-
/^window\.location\.href$/,
|
|
467
|
-
/^document\.querySelector\(['"][^'"]*['"]\)\.textContent$/,
|
|
468
|
-
/^document\.body\.scrollHeight$/,
|
|
469
|
-
/^window\.scrollY$/,
|
|
470
|
-
/^window\.scrollX$/
|
|
471
|
-
]
|
|
472
|
-
|
|
473
|
-
if (!params.expression) {
|
|
474
|
-
throw new Error("Evaluate action requires expression parameter")
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
if (!safeExpressions.some((regex) => regex.test(params.expression as string))) {
|
|
478
|
-
throw new Error("Expression not in whitelist. Only safe read-only expressions allowed.")
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
cdpResult = await sendCDPCommand(ws, messageId++, "Runtime.evaluate", {
|
|
482
|
-
expression: params.expression,
|
|
483
|
-
returnByValue: true
|
|
484
|
-
})
|
|
485
|
-
break
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
case "scroll": {
|
|
489
|
-
const scrollX = params.deltaX || 0
|
|
490
|
-
const scrollY = params.deltaY || 0
|
|
491
|
-
cdpResult = await sendCDPCommand(ws, messageId++, "Input.dispatchMouseEvent", {
|
|
492
|
-
type: "mouseWheel",
|
|
493
|
-
x: params.x || 500,
|
|
494
|
-
y: params.y || 500,
|
|
495
|
-
deltaX: scrollX,
|
|
496
|
-
deltaY: scrollY
|
|
497
|
-
})
|
|
498
|
-
break
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
case "type":
|
|
502
|
-
if (!params.text) {
|
|
503
|
-
throw new Error("Type action requires text parameter")
|
|
504
|
-
}
|
|
505
|
-
// Type each character
|
|
506
|
-
for (const char of params.text) {
|
|
507
|
-
await sendCDPCommand(ws, messageId++, "Input.dispatchKeyEvent", {
|
|
508
|
-
type: "char",
|
|
509
|
-
text: char
|
|
510
|
-
})
|
|
511
|
-
}
|
|
512
|
-
cdpResult = { action: "type", text: params.text }
|
|
513
|
-
break
|
|
514
|
-
|
|
515
|
-
default:
|
|
516
|
-
throw new Error(`Unsupported action: ${action}`)
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
ws.close()
|
|
520
|
-
resolve(cdpResult)
|
|
521
|
-
} catch (error) {
|
|
522
|
-
ws.close()
|
|
523
|
-
reject(error)
|
|
524
|
-
}
|
|
525
|
-
})
|
|
526
|
-
|
|
527
|
-
ws.on("error", reject)
|
|
528
|
-
|
|
529
|
-
// Helper function to send CDP commands
|
|
530
|
-
async function sendCDPCommand(
|
|
531
|
-
ws: WebSocket,
|
|
532
|
-
id: number,
|
|
533
|
-
method: string,
|
|
534
|
-
params: Record<string, unknown>
|
|
535
|
-
): Promise<Record<string, unknown>> {
|
|
536
|
-
return new Promise((cmdResolve, cmdReject) => {
|
|
537
|
-
const command = { id, method, params }
|
|
538
|
-
|
|
539
|
-
const messageHandler = (data: Buffer) => {
|
|
540
|
-
const message = JSON.parse(data.toString())
|
|
541
|
-
if (message.id === id) {
|
|
542
|
-
ws.removeListener("message", messageHandler)
|
|
543
|
-
if (message.error) {
|
|
544
|
-
cmdReject(new Error(message.error.message))
|
|
545
|
-
} else {
|
|
546
|
-
cmdResolve(message.result)
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
ws.on("message", messageHandler)
|
|
552
|
-
ws.send(JSON.stringify(command))
|
|
553
|
-
|
|
554
|
-
// Command timeout
|
|
555
|
-
setTimeout(() => {
|
|
556
|
-
ws.removeListener("message", messageHandler)
|
|
557
|
-
cmdReject(new Error(`CDP command timeout: ${method}`))
|
|
558
|
-
}, 5000)
|
|
559
|
-
})
|
|
560
|
-
}
|
|
561
|
-
})
|
|
562
|
-
|
|
563
|
-
return {
|
|
564
|
-
content: [
|
|
126
|
+
Should I start monitoring now?`
|
|
127
|
+
},
|
|
565
128
|
{
|
|
566
129
|
type: "text",
|
|
567
|
-
text:
|
|
130
|
+
text: `\`\`\`python
|
|
131
|
+
${monitoringCode}
|
|
132
|
+
\`\`\``
|
|
568
133
|
}
|
|
569
134
|
]
|
|
570
135
|
}
|
|
@@ -573,13 +138,14 @@ const handler = createMcpHandler(
|
|
|
573
138
|
content: [
|
|
574
139
|
{
|
|
575
140
|
type: "text",
|
|
576
|
-
text: `
|
|
141
|
+
text: `Error setting up monitoring: ${error instanceof Error ? error.message : String(error)}`
|
|
577
142
|
}
|
|
578
143
|
]
|
|
579
144
|
}
|
|
580
145
|
}
|
|
581
146
|
}
|
|
582
147
|
)
|
|
148
|
+
*/
|
|
583
149
|
},
|
|
584
150
|
{
|
|
585
151
|
// dev3000 MCP Server - Advanced development debugging tools
|