dev3000 0.0.84 → 0.0.85
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/dev-environment.d.ts.map +1 -1
- package/dist/dev-environment.js +31 -186
- package/dist/dev-environment.js.map +1 -1
- package/dist/src/tui-interface-impl.tsx +1 -1
- package/dist/tui-interface-impl.js +1 -1
- package/dist/tui-interface-impl.js.map +1 -1
- package/mcp-server/.next/BUILD_ID +1 -1
- package/mcp-server/.next/app-path-routes-manifest.json +1 -0
- package/mcp-server/.next/build-manifest.json +5 -6
- package/mcp-server/.next/fallback-build-manifest.json +2 -2
- package/mcp-server/.next/next-server.js.nft.json +1 -1
- package/mcp-server/.next/prerender-manifest.json +3 -3
- package/mcp-server/.next/server/app/_global-error/page/build-manifest.json +3 -4
- package/mcp-server/.next/server/app/_global-error/page.js +1 -1
- package/mcp-server/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/build-manifest.json +3 -4
- package/mcp-server/.next/server/app/_not-found/page.js +1 -1
- package/mcp-server/.next/server/app/_not-found/page.js.nft.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/api/jank/[session]/route.js +1 -1
- package/mcp-server/.next/server/app/api/jank/[session]/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/logs/head/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/logs/list/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/logs/rotate/route.js +1 -1
- package/mcp-server/.next/server/app/api/logs/rotate/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/logs/stream/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/logs/tail/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/orchestrator/route/app-paths-manifest.json +3 -0
- package/mcp-server/.next/server/app/api/orchestrator/route/build-manifest.json +11 -0
- package/mcp-server/.next/server/app/api/orchestrator/route/server-reference-manifest.json +4 -0
- package/mcp-server/.next/server/app/api/orchestrator/route.js +8 -0
- package/mcp-server/.next/server/app/api/orchestrator/route.js.map +5 -0
- package/mcp-server/.next/server/app/api/orchestrator/route.js.nft.json +1 -0
- package/mcp-server/.next/server/app/api/orchestrator/route_client-reference-manifest.js +2 -0
- package/mcp-server/.next/server/app/api/screenshots/[filename]/route.js +1 -1
- package/mcp-server/.next/server/app/api/screenshots/[filename]/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/api/screenshots/list/route.js +1 -1
- package/mcp-server/.next/server/app/api/screenshots/list/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/index.html +1 -1
- package/mcp-server/.next/server/app/index.rsc +3 -3
- package/mcp-server/.next/server/app/logs/page/build-manifest.json +3 -4
- package/mcp-server/.next/server/app/logs/page.js +1 -1
- 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 +4 -3
- package/mcp-server/.next/server/app/mcp/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/page/build-manifest.json +3 -4
- package/mcp-server/.next/server/app/page.js +1 -1
- package/mcp-server/.next/server/app/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app/video/[session]/page/build-manifest.json +3 -4
- package/mcp-server/.next/server/app/video/[session]/page.js +1 -1
- package/mcp-server/.next/server/app/video/[session]/page.js.nft.json +1 -1
- package/mcp-server/.next/server/app/video/[session]/page_client-reference-manifest.js +1 -1
- package/mcp-server/.next/server/app-paths-manifest.json +1 -0
- package/mcp-server/.next/server/chunks/[externals]_node:crypto_c20cce38._.js +3 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__05e38acd._.js +3 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__05e38acd._.js.map +1 -0
- package/mcp-server/.next/server/chunks/{[root-of-the-server]__6ee9a99f._.js → [root-of-the-server]__3130ceec._.js} +2 -2
- package/mcp-server/.next/server/chunks/[root-of-the-server]__4637d3dd._.js +3 -0
- package/mcp-server/.next/server/chunks/{[root-of-the-server]__bc773251._.js → [root-of-the-server]__5114419d._.js} +2 -2
- package/mcp-server/.next/server/chunks/[root-of-the-server]__5248c9ff._.js +3 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__5248c9ff._.js.map +1 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__94037b23._.js +7 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__94037b23._.js.map +1 -0
- package/mcp-server/.next/server/chunks/{[root-of-the-server]__55c04517._.js → [root-of-the-server]__a004a307._.js} +2 -2
- package/mcp-server/.next/server/chunks/[root-of-the-server]__ae49815f._.js +91 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__ae49815f._.js.map +1 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__cc74dbef._.js +7 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__cc74dbef._.js.map +1 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__dc0b0022._.js +17 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__dc0b0022._.js.map +1 -0
- package/mcp-server/.next/server/chunks/mcp-server__next-internal_server_app_api_orchestrator_route_actions_c6fba9ec.js +3 -0
- package/mcp-server/.next/server/chunks/mcp-server__next-internal_server_app_api_orchestrator_route_actions_c6fba9ec.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__61c905ce._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__bf771f7e._.js.map → [root-of-the-server]__61c905ce._.js.map} +1 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__8863b0f6._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__8863b0f6._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__9bc632fa._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__c4e78a20._.js.map → [root-of-the-server]__9bc632fa._.js.map} +1 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__a4bb31a6._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__a4bb31a6._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__cf17e26a._.js → [root-of-the-server]__aed64cd3._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__aed64cd3._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__cf030fda._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__cf030fda._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/{_96ba1d8e._.js → _74bf5366._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/_74bf5366._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_page_tsx_9fc46577._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_page_tsx_9fc46577._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/mcp-server_components_dark-mode-toggle_tsx_f31dd15d._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/mcp-server_components_dark-mode-toggle_tsx_f31dd15d._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_3d10aa72._.js +3 -0
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_3d10aa72._.js.map +1 -0
- package/mcp-server/.next/server/middleware-build-manifest.js +3 -4
- package/mcp-server/.next/server/server-reference-manifest.js +1 -1
- package/mcp-server/.next/server/server-reference-manifest.json +1 -1
- package/mcp-server/.next/static/chunks/{55cedb1a993e951c.js → 1d2676338b51bbcf.js} +1 -1
- package/mcp-server/.next/static/chunks/312a4c1c7f6436ef.js +1 -0
- package/mcp-server/.next/static/chunks/8364b81221aabb64.js +1 -0
- package/mcp-server/.next/static/chunks/a42830291751fe48.js +1 -0
- package/mcp-server/.next/static/chunks/bb2e6ac36794beea.css +1 -0
- package/mcp-server/.next/static/chunks/c578923146856601.js +1 -0
- package/mcp-server/.next/static/chunks/turbopack-22a9e2c19fd12b04.js +3 -0
- package/mcp-server/app/api/orchestrator/route.ts +73 -0
- package/mcp-server/app/globals.css +0 -1
- package/mcp-server/app/logs/LogsClient.infinite-loop.test.tsx +1 -1
- package/mcp-server/app/mcp/client-manager.ts +281 -0
- package/mcp-server/app/mcp/route.ts +166 -0
- package/mcp-server/app/mcp/tools.ts +71 -18
- package/mcp-server/app/page.tsx +79 -65
- package/mcp-server/package.json +7 -9
- package/package.json +3 -8
- package/src/tui-interface-impl.tsx +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__00592d3f._.js +0 -91
- package/mcp-server/.next/server/chunks/[root-of-the-server]__00592d3f._.js.map +0 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__177c72c6._.js +0 -17
- package/mcp-server/.next/server/chunks/[root-of-the-server]__177c72c6._.js.map +0 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__2942c072._.js +0 -3
- package/mcp-server/.next/server/chunks/[root-of-the-server]__e6dcd8bf._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__22d96eb1._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__22d96eb1._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__63dd19ce._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__63dd19ce._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__94d8e211._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__94d8e211._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__bf771f7e._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__c4e78a20._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__cf17e26a._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/_28084f73._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/_28084f73._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/_96ba1d8e._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/_aa32a659._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/_aa32a659._.js.map +0 -1
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_b2368b47._.js +0 -3
- package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_b2368b47._.js.map +0 -1
- package/mcp-server/.next/static/chunks/0cf268b98f36b0b5.css +0 -1
- package/mcp-server/.next/static/chunks/571fbcba7786c174.js +0 -1
- package/mcp-server/.next/static/chunks/5fdb882fe407a798.js +0 -1
- package/mcp-server/.next/static/chunks/98e04adc8a00688a.js +0 -1
- package/mcp-server/.next/static/chunks/db42008ac1e97815.js +0 -1
- package/mcp-server/.next/static/chunks/dbbdc51e76f4cea4.js +0 -1
- package/mcp-server/.next/static/chunks/turbopack-7112e6b6aee1d84f.js +0 -3
- /package/mcp-server/.next/server/chunks/{[root-of-the-server]__2942c072._.js.map → [externals]_node:crypto_c20cce38._.js.map} +0 -0
- /package/mcp-server/.next/server/chunks/{[root-of-the-server]__6ee9a99f._.js.map → [root-of-the-server]__3130ceec._.js.map} +0 -0
- /package/mcp-server/.next/server/chunks/{[root-of-the-server]__e6dcd8bf._.js.map → [root-of-the-server]__4637d3dd._.js.map} +0 -0
- /package/mcp-server/.next/server/chunks/{[root-of-the-server]__bc773251._.js.map → [root-of-the-server]__5114419d._.js.map} +0 -0
- /package/mcp-server/.next/server/chunks/{[root-of-the-server]__55c04517._.js.map → [root-of-the-server]__a004a307._.js.map} +0 -0
- /package/mcp-server/.next/static/{xBA_-Bho-qV9WoLREZ2m_ → 5ZNPgBUtuG6HhHaBXqChL}/_buildManifest.js +0 -0
- /package/mcp-server/.next/static/{xBA_-Bho-qV9WoLREZ2m_ → 5ZNPgBUtuG6HhHaBXqChL}/_clientMiddlewareManifest.json +0 -0
- /package/mcp-server/.next/static/{xBA_-Bho-qV9WoLREZ2m_ → 5ZNPgBUtuG6HhHaBXqChL}/_ssgManifest.js +0 -0
|
@@ -1,9 +1,175 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
1
4
|
import { createMcpHandler } from "mcp-handler"
|
|
2
5
|
import { z } from "zod"
|
|
6
|
+
import { getMCPClientManager } from "./client-manager"
|
|
3
7
|
import { executeBrowserAction, findComponentSource, fixMyApp, TOOL_DESCRIPTIONS } from "./tools"
|
|
4
8
|
|
|
9
|
+
// Detect available package runner (npx, pnpm dlx, or fail)
|
|
10
|
+
const getPackageRunner = (): { command: string; args: string[] } | null => {
|
|
11
|
+
try {
|
|
12
|
+
const { execSync } = require("node:child_process")
|
|
13
|
+
|
|
14
|
+
// Try npx first (most common)
|
|
15
|
+
try {
|
|
16
|
+
execSync("npx --version", { stdio: "ignore" })
|
|
17
|
+
return { command: "npx", args: ["-y"] }
|
|
18
|
+
} catch {
|
|
19
|
+
// npx not available or is aliased to pnpm dlx
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Try pnpm dlx as fallback
|
|
23
|
+
try {
|
|
24
|
+
execSync("pnpm --version", { stdio: "ignore" })
|
|
25
|
+
return { command: "pnpm", args: ["dlx"] }
|
|
26
|
+
} catch {
|
|
27
|
+
// pnpm not available
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.error("[MCP Orchestrator] Neither npx nor pnpm found - cannot spawn chrome-devtools MCP")
|
|
31
|
+
return null
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error("[MCP Orchestrator] Failed to detect package runner:", error)
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Initialize MCP client manager for orchestration
|
|
39
|
+
// This will connect to chrome-devtools and nextjs-dev MCPs when available
|
|
40
|
+
const initializeOrchestration = async () => {
|
|
41
|
+
const clientManager = getMCPClientManager()
|
|
42
|
+
|
|
43
|
+
// Helper to get config from session files in ~/.d3k/
|
|
44
|
+
const getConfigFromSessions = () => {
|
|
45
|
+
const config: Parameters<typeof clientManager.initialize>[0] = {}
|
|
46
|
+
const sessionDir = join(homedir(), ".d3k")
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// Read all *.json session files
|
|
50
|
+
const { readdirSync, existsSync } = require("node:fs")
|
|
51
|
+
if (!existsSync(sessionDir)) return config
|
|
52
|
+
|
|
53
|
+
const sessionFiles = readdirSync(sessionDir).filter((f: string) => f.endsWith(".json"))
|
|
54
|
+
|
|
55
|
+
// Use the most recent session with CDP URL
|
|
56
|
+
for (const file of sessionFiles) {
|
|
57
|
+
try {
|
|
58
|
+
const sessionPath = join(sessionDir, file)
|
|
59
|
+
const sessionData = JSON.parse(readFileSync(sessionPath, "utf-8"))
|
|
60
|
+
|
|
61
|
+
// Configure chrome-devtools MCP if CDP URL is available
|
|
62
|
+
if (sessionData.cdpUrl && !config.chromeDevtools) {
|
|
63
|
+
const cdpUrl = sessionData.cdpUrl.replace("ws://", "http://") // Convert ws:// to http:// for browser URL
|
|
64
|
+
const runner = getPackageRunner()
|
|
65
|
+
|
|
66
|
+
if (runner) {
|
|
67
|
+
config.chromeDevtools = {
|
|
68
|
+
command: runner.command,
|
|
69
|
+
args: [...runner.args, "chrome-devtools-mcp@latest", "--browserUrl", cdpUrl],
|
|
70
|
+
enabled: true
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
console.warn("[MCP Orchestrator] Cannot configure chrome-devtools MCP: no package runner available")
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Configure nextjs-dev MCP if app port is available
|
|
78
|
+
if (sessionData.appPort && !config.nextjsDev) {
|
|
79
|
+
config.nextjsDev = {
|
|
80
|
+
url: `http://localhost:${sessionData.appPort}/_next/mcp`,
|
|
81
|
+
enabled: true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Break if we have both MCPs
|
|
86
|
+
if (config.chromeDevtools && config.nextjsDev) break
|
|
87
|
+
} catch {
|
|
88
|
+
// Skip invalid session files
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.warn("[MCP Orchestrator] Failed to read session files:", error)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return config
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
// Initial attempt to connect
|
|
100
|
+
const config = getConfigFromSessions()
|
|
101
|
+
if (Object.keys(config).length > 0) {
|
|
102
|
+
await clientManager.initialize(config)
|
|
103
|
+
console.log(`[MCP Orchestrator] Initialized with ${Object.keys(config).join(", ")}`)
|
|
104
|
+
} else {
|
|
105
|
+
console.log("[MCP Orchestrator] No downstream MCPs found yet (will retry)")
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Since MCP server starts before Chrome, periodically retry connection
|
|
109
|
+
// This allows late-binding to chrome-devtools MCP after Chrome launches
|
|
110
|
+
let retryCount = 0
|
|
111
|
+
const maxRetries = 10
|
|
112
|
+
const retryInterval = setInterval(async () => {
|
|
113
|
+
retryCount++
|
|
114
|
+
|
|
115
|
+
const newConfig = getConfigFromSessions()
|
|
116
|
+
const hasChromeDevtools = !!newConfig.chromeDevtools
|
|
117
|
+
const hasNextjs = !!newConfig.nextjsDev
|
|
118
|
+
const alreadyConnectedChrome = clientManager.isConnected("chrome-devtools")
|
|
119
|
+
const alreadyConnectedNextjs = clientManager.isConnected("nextjs-dev")
|
|
120
|
+
|
|
121
|
+
// Check if we have new MCPs to connect to
|
|
122
|
+
const needsChrome = hasChromeDevtools && !alreadyConnectedChrome
|
|
123
|
+
const needsNextjs = hasNextjs && !alreadyConnectedNextjs
|
|
124
|
+
|
|
125
|
+
if (needsChrome || needsNextjs) {
|
|
126
|
+
const toConnect = [needsChrome && "chrome-devtools", needsNextjs && "nextjs-dev"].filter(Boolean)
|
|
127
|
+
console.log(`[MCP Orchestrator] Retry ${retryCount}: Attempting to connect to ${toConnect.join(", ")}`)
|
|
128
|
+
try {
|
|
129
|
+
await clientManager.initialize(newConfig)
|
|
130
|
+
console.log("[MCP Orchestrator] Successfully connected to downstream MCPs")
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.warn(`[MCP Orchestrator] Retry ${retryCount} failed:`, error)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Stop retrying after max attempts or when both are connected
|
|
137
|
+
if (retryCount >= maxRetries || (alreadyConnectedChrome && alreadyConnectedNextjs)) {
|
|
138
|
+
clearInterval(retryInterval)
|
|
139
|
+
const connected = clientManager.getConnectedMCPs()
|
|
140
|
+
console.log(`[MCP Orchestrator] Stopped retry loop (connected: ${connected.join(", ") || "none"})`)
|
|
141
|
+
}
|
|
142
|
+
}, 2000) // Retry every 2 seconds
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.warn("[MCP Orchestrator] Failed to initialize downstream MCPs:", error)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Initialize on module load
|
|
149
|
+
initializeOrchestration().catch(console.error)
|
|
150
|
+
|
|
5
151
|
const handler = createMcpHandler(
|
|
6
152
|
(server) => {
|
|
153
|
+
// Dynamically register proxied tools from downstream MCPs
|
|
154
|
+
const clientManager = getMCPClientManager()
|
|
155
|
+
const downstreamTools = clientManager.getAllTools()
|
|
156
|
+
|
|
157
|
+
for (const { mcpName, tool } of downstreamTools) {
|
|
158
|
+
// Add prefix to avoid conflicts with dev3000's own tools
|
|
159
|
+
const proxiedToolName = `${mcpName}_${tool.name}`
|
|
160
|
+
|
|
161
|
+
server.tool(
|
|
162
|
+
proxiedToolName,
|
|
163
|
+
`[${mcpName}] ${tool.description || ""}`,
|
|
164
|
+
tool.inputSchema as any,
|
|
165
|
+
async (params: Record<string, unknown>) => {
|
|
166
|
+
// Proxy the call to the downstream MCP
|
|
167
|
+
return clientManager.callTool(mcpName, tool.name, params)
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Dev3000's own tools below:
|
|
7
173
|
// Enhanced fix_my_app - the ultimate error fixing tool
|
|
8
174
|
server.tool(
|
|
9
175
|
"fix_my_app",
|
|
@@ -181,7 +181,27 @@ export async function fixMyApp({
|
|
|
181
181
|
integrateChromeDevtools = false,
|
|
182
182
|
returnRawData = false
|
|
183
183
|
}: FixMyAppParams): Promise<{ content: Array<{ type: "text"; text: string }> }> {
|
|
184
|
-
// 🎯
|
|
184
|
+
// 🎯 MCP ORCHESTRATION: Check which downstream MCPs are available
|
|
185
|
+
const { getMCPClientManager } = await import("./client-manager")
|
|
186
|
+
const clientManager = getMCPClientManager()
|
|
187
|
+
const connectedMCPs = clientManager.getConnectedMCPs()
|
|
188
|
+
|
|
189
|
+
const hasNextjsDev = connectedMCPs.includes("nextjs-dev")
|
|
190
|
+
const hasChromeDevtools = connectedMCPs.includes("chrome-devtools")
|
|
191
|
+
|
|
192
|
+
if (connectedMCPs.length > 0) {
|
|
193
|
+
logToDevFile(`Fix My App: Connected to downstream MCPs: ${connectedMCPs.join(", ")}`)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Auto-detect integration flags based on connected MCPs
|
|
197
|
+
if (hasNextjsDev && integrateNextjs === false) {
|
|
198
|
+
integrateNextjs = true
|
|
199
|
+
}
|
|
200
|
+
if (hasChromeDevtools && integrateChromeDevtools === false) {
|
|
201
|
+
integrateChromeDevtools = true
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Legacy delegation check (keeping for backwards compatibility)
|
|
185
205
|
const canDelegateNextjs = await canDelegateToNextjs()
|
|
186
206
|
if (canDelegateNextjs) {
|
|
187
207
|
logToDevFile(`Fix My App: Recommending dev3000-nextjs-dev MCP for Next.js-specific analysis`)
|
|
@@ -619,6 +639,9 @@ export async function fixMyApp({
|
|
|
619
639
|
results.push(`• ${match[1]}`)
|
|
620
640
|
}
|
|
621
641
|
})
|
|
642
|
+
results.push("")
|
|
643
|
+
results.push("💡 **TIP**: Use analyze_visual_diff tool to compare screenshots and identify changes")
|
|
644
|
+
results.push(" (Advanced: screenshots are also accessible via curl if needed)")
|
|
622
645
|
}
|
|
623
646
|
|
|
624
647
|
// Jank/Layout Shift Detection (from ScreencastManager passive captures)
|
|
@@ -711,6 +734,11 @@ export async function fixMyApp({
|
|
|
711
734
|
results.push("• Check for web fonts causing text reflow (font-display: swap)")
|
|
712
735
|
results.push(`• Raw screenshots: ${jankResult.screenshotDir}`)
|
|
713
736
|
results.push("")
|
|
737
|
+
results.push("📸 **ANALYZING SCREENSHOTS:**")
|
|
738
|
+
results.push("• RECOMMENDED: Use analyze_visual_diff tool with before/after URLs (shown above)")
|
|
739
|
+
results.push("• The tool provides structured instructions for comparing frames")
|
|
740
|
+
results.push("• Advanced: Screenshots are also accessible via curl if needed")
|
|
741
|
+
results.push("")
|
|
714
742
|
results.push(`🎬 **IMPORTANT**: Share this frame sequence link with the user: ${videoUrl}`)
|
|
715
743
|
}
|
|
716
744
|
}
|
|
@@ -2148,7 +2176,8 @@ async function detectJankFromScreenshots(_projectName?: string): Promise<{
|
|
|
2148
2176
|
if (existsSync(metadataPath)) {
|
|
2149
2177
|
try {
|
|
2150
2178
|
const metadata = JSON.parse(readFileSync(metadataPath, "utf-8"))
|
|
2151
|
-
if
|
|
2179
|
+
// Set realCLSData even if there are zero shifts - this tells us Chrome ran and found nothing
|
|
2180
|
+
if (metadata.layoutShifts !== undefined) {
|
|
2152
2181
|
realCLSData = {
|
|
2153
2182
|
score: metadata.totalCLS || 0,
|
|
2154
2183
|
grade: metadata.clsGrade || "unknown",
|
|
@@ -2182,22 +2211,33 @@ async function detectJankFromScreenshots(_projectName?: string): Promise<{
|
|
|
2182
2211
|
|
|
2183
2212
|
// Look for CLS entries with Before/After URLs
|
|
2184
2213
|
// Format: [BROWSER] [CDP] CLS #N (score: X, time: Yms):
|
|
2185
|
-
// [BROWSER] [CDP] - <ELEMENT> shifted...
|
|
2214
|
+
// [BROWSER] [CDP] - <ELEMENT> shifted... (variable number of these)
|
|
2186
2215
|
// [BROWSER] [CDP] Before: http://...
|
|
2187
2216
|
// [BROWSER] [CDP] After: http://...
|
|
2188
2217
|
for (let i = 0; i < lines.length; i++) {
|
|
2189
2218
|
const clsMatch = lines[i].match(/\[CDP\] CLS #\d+ \(score: [\d.]+, time: (\d+)ms\):/)
|
|
2190
2219
|
if (clsMatch) {
|
|
2191
2220
|
const timestamp = parseInt(clsMatch[1], 10)
|
|
2192
|
-
// Look ahead for Before and After URLs (
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2221
|
+
// Look ahead for Before and After URLs (scan next 10 lines for them)
|
|
2222
|
+
let beforeUrl: string | null = null
|
|
2223
|
+
let afterUrl: string | null = null
|
|
2224
|
+
|
|
2225
|
+
for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
|
|
2226
|
+
if (!beforeUrl) {
|
|
2227
|
+
const beforeMatch = lines[j].match(/Before:\s+(http:\/\/\S+)/)
|
|
2228
|
+
if (beforeMatch) beforeUrl = beforeMatch[1]
|
|
2229
|
+
}
|
|
2230
|
+
if (!afterUrl) {
|
|
2231
|
+
const afterMatch = lines[j].match(/After:\s+(http:\/\/\S+)/)
|
|
2232
|
+
if (afterMatch) afterUrl = afterMatch[1]
|
|
2233
|
+
}
|
|
2234
|
+
// Stop if we found both
|
|
2235
|
+
if (beforeUrl && afterUrl) {
|
|
2197
2236
|
frameUrlMap.set(timestamp, {
|
|
2198
|
-
before:
|
|
2199
|
-
after:
|
|
2237
|
+
before: beforeUrl,
|
|
2238
|
+
after: afterUrl
|
|
2200
2239
|
})
|
|
2240
|
+
break
|
|
2201
2241
|
}
|
|
2202
2242
|
}
|
|
2203
2243
|
}
|
|
@@ -2207,8 +2247,21 @@ async function detectJankFromScreenshots(_projectName?: string): Promise<{
|
|
|
2207
2247
|
// Ignore log parsing errors
|
|
2208
2248
|
}
|
|
2209
2249
|
|
|
2210
|
-
// If we have real CLS data
|
|
2211
|
-
if (realCLSData
|
|
2250
|
+
// If we have real CLS data from Chrome's PerformanceObserver, trust it completely
|
|
2251
|
+
if (realCLSData) {
|
|
2252
|
+
// If Chrome says there are no shifts, return immediately - don't fall back to pixel diff
|
|
2253
|
+
if (realCLSData.shifts.length === 0) {
|
|
2254
|
+
return {
|
|
2255
|
+
detections: [],
|
|
2256
|
+
sessionId: latestSessionId,
|
|
2257
|
+
totalFrames: sessionFiles.length,
|
|
2258
|
+
screenshotDir,
|
|
2259
|
+
realCLS: { score: 0, grade: realCLSData.grade }
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
// Process actual layout shifts detected by Chrome
|
|
2264
|
+
// Trust Chrome's Layout Instability API completely - if Chrome reports it, it's real
|
|
2212
2265
|
realCLSData.shifts.forEach((shift) => {
|
|
2213
2266
|
const element = shift.sources?.[0]?.node || "unknown"
|
|
2214
2267
|
const isCriticalElement = ["NAV", "HEADER", "BUTTON", "A"].includes(element.toUpperCase())
|
|
@@ -2742,11 +2795,13 @@ export async function analyzeVisualDiff(params: {
|
|
|
2742
2795
|
results.push("")
|
|
2743
2796
|
results.push("To analyze the visual differences between these two screenshots:")
|
|
2744
2797
|
results.push("")
|
|
2745
|
-
results.push("**Step 1:
|
|
2746
|
-
results.push(`Use
|
|
2798
|
+
results.push("**Step 1: Fetch and analyze the BEFORE image**")
|
|
2799
|
+
results.push(`Use WebFetch with URL: \`${beforeImageUrl}\``)
|
|
2800
|
+
results.push(`Prompt: "Describe this screenshot in detail, focusing on layout and visible elements"`)
|
|
2747
2801
|
results.push("")
|
|
2748
|
-
results.push("**Step 2:
|
|
2749
|
-
results.push(`Use
|
|
2802
|
+
results.push("**Step 2: Fetch and analyze the AFTER image**")
|
|
2803
|
+
results.push(`Use WebFetch with URL: \`${afterImageUrl}\``)
|
|
2804
|
+
results.push(`Prompt: "Describe this screenshot in detail, focusing on layout and visible elements"`)
|
|
2750
2805
|
results.push("")
|
|
2751
2806
|
results.push("**Step 3: Compare and describe the differences**")
|
|
2752
2807
|
|
|
@@ -2767,8 +2822,6 @@ export async function analyzeVisualDiff(params: {
|
|
|
2767
2822
|
results.push("• Which element(s) changed")
|
|
2768
2823
|
results.push("• What appeared/moved/resized")
|
|
2769
2824
|
results.push("• Why this caused other elements to shift")
|
|
2770
|
-
results.push("")
|
|
2771
|
-
results.push("💡 **TIP:** Load both images first, then describe the differences in detail.")
|
|
2772
2825
|
|
|
2773
2826
|
return {
|
|
2774
2827
|
content: [{ type: "text", text: results.join("\n") }]
|
package/mcp-server/app/page.tsx
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import Link from "next/link"
|
|
4
4
|
import { useEffect, useState } from "react"
|
|
5
5
|
import { DarkModeToggle } from "@/components/dark-mode-toggle"
|
|
6
|
+
import { ChromeIcon, NextJsIcon } from "@/components/mcp-icons"
|
|
6
7
|
import { useDarkMode } from "@/hooks/use-dark-mode"
|
|
7
8
|
|
|
8
9
|
interface MCPTool {
|
|
@@ -24,6 +25,22 @@ interface ToolsResponse {
|
|
|
24
25
|
categories: string[]
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
interface OrchestratorResponse {
|
|
29
|
+
orchestratorEnabled: boolean
|
|
30
|
+
connectedMCPs: string[]
|
|
31
|
+
totalConnections: number
|
|
32
|
+
mcpDetails: Array<{
|
|
33
|
+
name: string
|
|
34
|
+
connected: boolean
|
|
35
|
+
toolCount: number
|
|
36
|
+
tools: string[]
|
|
37
|
+
projects: string[]
|
|
38
|
+
}>
|
|
39
|
+
totalProjects: number
|
|
40
|
+
projects: string[]
|
|
41
|
+
message: string
|
|
42
|
+
}
|
|
43
|
+
|
|
27
44
|
// Format tool descriptions by parsing markdown-style sections
|
|
28
45
|
function formatToolDescription(description: string) {
|
|
29
46
|
const slugify = (value: string) =>
|
|
@@ -46,18 +63,19 @@ function formatToolDescription(description: string) {
|
|
|
46
63
|
const normalizedKey = getUniqueKey(slugify(rawSection) || "section")
|
|
47
64
|
let section = rawSection
|
|
48
65
|
|
|
66
|
+
// Remove markdown formatting
|
|
67
|
+
section = section.replace(/\*\*/g, "").trim()
|
|
68
|
+
|
|
49
69
|
// Remove excessive emojis
|
|
50
|
-
// Simple emoji reduction - just remove most emojis except the first in sequences
|
|
51
70
|
section = section.replace(/(\u{1F300}-\u{1F9FF}|\u{2600}-\u{26FF}|\u{1F900}-\u{1F9FF})+/gu, (match) => {
|
|
52
|
-
// Keep only the first emoji in a sequence
|
|
53
71
|
return match.charAt(0)
|
|
54
72
|
})
|
|
55
73
|
|
|
56
74
|
// Handle different section types
|
|
57
|
-
if (section.includes("
|
|
75
|
+
if (section.includes(":")) {
|
|
58
76
|
// This is a header with content
|
|
59
77
|
const [header, ...contentParts] = section.split(":")
|
|
60
|
-
const cleanHeader = header.
|
|
78
|
+
const cleanHeader = header.trim()
|
|
61
79
|
const content = contentParts.join(":").trim()
|
|
62
80
|
|
|
63
81
|
// Check if content has bullet points
|
|
@@ -96,7 +114,6 @@ function formatToolDescription(description: string) {
|
|
|
96
114
|
return (
|
|
97
115
|
<ol className="space-y-1 ml-4" key={`${normalizedKey}-steps`}>
|
|
98
116
|
{items.map((item, itemIdx) => {
|
|
99
|
-
// Clean up the item text
|
|
100
117
|
const cleanItem = item
|
|
101
118
|
.replace(/^\d+[\ud83c-\ud83e][\udc00-\udfff]\s*/, "")
|
|
102
119
|
.replace(/^\d+\.\s*/, "")
|
|
@@ -125,14 +142,17 @@ function formatToolDescription(description: string) {
|
|
|
125
142
|
|
|
126
143
|
export default function HomePage() {
|
|
127
144
|
const [tools, setTools] = useState<ToolsResponse | null>(null)
|
|
145
|
+
const [orchestrator, setOrchestrator] = useState<OrchestratorResponse | null>(null)
|
|
128
146
|
const [loading, setLoading] = useState(true)
|
|
129
147
|
const [darkMode, setDarkMode] = useDarkMode()
|
|
130
148
|
|
|
131
149
|
useEffect(() => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
.then((
|
|
135
|
-
|
|
150
|
+
// Fetch both tools and orchestrator status in parallel
|
|
151
|
+
Promise.all([fetch("/api/tools"), fetch("/api/orchestrator")])
|
|
152
|
+
.then(([toolsRes, orchRes]) => Promise.all([toolsRes.json(), orchRes.json()]))
|
|
153
|
+
.then(([toolsData, orchData]) => {
|
|
154
|
+
setTools(toolsData)
|
|
155
|
+
setOrchestrator(orchData)
|
|
136
156
|
setLoading(false)
|
|
137
157
|
})
|
|
138
158
|
.catch(() => {
|
|
@@ -165,12 +185,6 @@ export default function HomePage() {
|
|
|
165
185
|
</div>
|
|
166
186
|
</div>
|
|
167
187
|
<div className="flex items-center gap-4">
|
|
168
|
-
<Link
|
|
169
|
-
href="/logs"
|
|
170
|
-
className="inline-flex items-center gap-2 px-5 py-3 bg-primary text-primary-foreground text-sm font-medium rounded hover:bg-primary/90 transition-colors"
|
|
171
|
-
>
|
|
172
|
-
📊 View Logs
|
|
173
|
-
</Link>
|
|
174
188
|
<a
|
|
175
189
|
href="https://github.com/vercel-labs/dev3000#setup"
|
|
176
190
|
target="_blank"
|
|
@@ -187,56 +201,59 @@ export default function HomePage() {
|
|
|
187
201
|
|
|
188
202
|
{/* Main Content - no sidebar needed with only 2 tools */}
|
|
189
203
|
<main className="max-w-7xl mx-auto px-6 py-8">
|
|
190
|
-
{/*
|
|
191
|
-
|
|
192
|
-
<
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
className="text-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
204
|
+
{/* MCP Connections Status */}
|
|
205
|
+
{!loading && orchestrator && (
|
|
206
|
+
<section className="mb-16">
|
|
207
|
+
<div className="bg-accent/10 border border-accent/20 rounded p-8">
|
|
208
|
+
<h2 className="text-xl font-semibold mb-4">🔌 MCP Connections</h2>
|
|
209
|
+
<p className="text-sm text-muted-foreground mb-4">{orchestrator.message}</p>
|
|
210
|
+
|
|
211
|
+
{orchestrator.totalConnections > 0 ? (
|
|
212
|
+
<>
|
|
213
|
+
<div className="flex flex-wrap gap-3 mb-4">
|
|
214
|
+
{orchestrator.mcpDetails.map((mcp) => {
|
|
215
|
+
const Icon =
|
|
216
|
+
mcp.name === "chrome-devtools" ? ChromeIcon : mcp.name === "nextjs-dev" ? NextJsIcon : null
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
key={mcp.name}
|
|
220
|
+
className="inline-flex items-center gap-2 bg-background/50 border border-border rounded px-3 py-2"
|
|
221
|
+
>
|
|
222
|
+
{Icon && <Icon className="shrink-0" />}
|
|
223
|
+
<span className="font-semibold font-mono text-sm">{mcp.name}</span>
|
|
224
|
+
<span className="w-2 h-2 bg-green-500 rounded-full"></span>
|
|
225
|
+
</div>
|
|
226
|
+
)
|
|
227
|
+
})}
|
|
228
|
+
</div>
|
|
229
|
+
{orchestrator.totalProjects > 0 && (
|
|
230
|
+
<div className="text-sm text-muted-foreground">
|
|
231
|
+
<span className="font-medium">Active projects:</span>{" "}
|
|
232
|
+
{orchestrator.projects.map((project, idx) => (
|
|
233
|
+
<span key={project}>
|
|
234
|
+
<code className="text-foreground bg-background/50 px-1.5 py-0.5 rounded">{project}</code>
|
|
235
|
+
{idx < orchestrator.projects.length - 1 && ", "}
|
|
236
|
+
</span>
|
|
237
|
+
))}
|
|
238
|
+
</div>
|
|
239
|
+
)}
|
|
240
|
+
</>
|
|
241
|
+
) : (
|
|
242
|
+
<div className="text-sm text-muted-foreground bg-background/50 border border-border rounded p-4">
|
|
243
|
+
<p className="mb-2">⏳ Waiting for downstream MCPs to become available...</p>
|
|
244
|
+
<p className="text-xs">
|
|
245
|
+
dev3000 will automatically connect to <code className="text-foreground">chrome-devtools</code> and{" "}
|
|
246
|
+
<code className="text-foreground">nextjs-dev</code> MCPs when Chrome and your dev server start.
|
|
247
|
+
</p>
|
|
220
248
|
</div>
|
|
221
|
-
|
|
249
|
+
)}
|
|
222
250
|
</div>
|
|
223
|
-
</
|
|
224
|
-
|
|
251
|
+
</section>
|
|
252
|
+
)}
|
|
225
253
|
|
|
226
254
|
{/* Tools Documentation */}
|
|
227
|
-
<section>
|
|
228
|
-
<
|
|
229
|
-
<div>
|
|
230
|
-
<h2 className="text-3xl font-bold mb-3">Available Tools</h2>
|
|
231
|
-
<p className="text-muted-foreground text-lg">
|
|
232
|
-
{loading
|
|
233
|
-
? "Loading MCP tools..."
|
|
234
|
-
: `${tools?.totalTools || 0} tools across ${
|
|
235
|
-
tools?.categories.length || 0
|
|
236
|
-
} categories for AI-powered development debugging`}
|
|
237
|
-
</p>
|
|
238
|
-
</div>
|
|
239
|
-
</div>
|
|
255
|
+
<section className="bg-accent/10 border border-accent/20 rounded p-8">
|
|
256
|
+
<h2 className="text-xl font-semibold mb-4">🛠️ dev3000 Tools</h2>
|
|
240
257
|
|
|
241
258
|
{loading ? (
|
|
242
259
|
<div className="text-center py-16">
|
|
@@ -249,7 +266,7 @@ export default function HomePage() {
|
|
|
249
266
|
<div
|
|
250
267
|
key={tool.name}
|
|
251
268
|
id={tool.name}
|
|
252
|
-
className="border border-border rounded-lg p-6 hover:border-muted-foreground/50 transition-colors"
|
|
269
|
+
className="bg-background/50 border border-border rounded-lg p-6 hover:border-muted-foreground/50 transition-colors"
|
|
253
270
|
>
|
|
254
271
|
<div className="mb-4">
|
|
255
272
|
<h4 className="text-xl font-semibold font-mono mb-3">{tool.name}</h4>
|
|
@@ -352,9 +369,6 @@ export default function HomePage() {
|
|
|
352
369
|
>
|
|
353
370
|
Homepage
|
|
354
371
|
</a>
|
|
355
|
-
<Link href="/logs" className="hover:text-gray-900 transition-colors">
|
|
356
|
-
Logs
|
|
357
|
-
</Link>
|
|
358
372
|
</div>
|
|
359
373
|
</div>
|
|
360
374
|
</div>
|
package/mcp-server/package.json
CHANGED
|
@@ -11,11 +11,10 @@
|
|
|
11
11
|
"tools": "tsx tools-cli.ts"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@modelcontextprotocol/sdk": "
|
|
14
|
+
"@modelcontextprotocol/sdk": "catalog:",
|
|
15
15
|
"@radix-ui/react-slot": "^1.1.1",
|
|
16
16
|
"@types/pixelmatch": "^5.2.6",
|
|
17
17
|
"@types/pngjs": "^6.0.5",
|
|
18
|
-
"autoprefixer": "^10.4.20",
|
|
19
18
|
"class-variance-authority": "^0.7.1",
|
|
20
19
|
"clsx": "^2.1.1",
|
|
21
20
|
"commander": "^14.0.1",
|
|
@@ -31,15 +30,14 @@
|
|
|
31
30
|
"zod": "^3.22.4"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
|
-
"@tailwindcss/postcss": "
|
|
33
|
+
"@tailwindcss/postcss": "catalog:",
|
|
35
34
|
"@types/node": "^24.5.2",
|
|
36
35
|
"@types/react": "19.1.13",
|
|
37
|
-
"
|
|
38
|
-
"@types/ws": "^8.5.12",
|
|
36
|
+
"autoprefixer": "catalog:",
|
|
39
37
|
"babel-plugin-react-compiler": "^19.1.0-rc.3",
|
|
40
|
-
"postcss": "
|
|
41
|
-
"tailwindcss": "
|
|
42
|
-
"
|
|
43
|
-
"
|
|
38
|
+
"postcss": "catalog:",
|
|
39
|
+
"tailwindcss": "catalog:",
|
|
40
|
+
"typescript": "^5.0.0",
|
|
41
|
+
"vitest": "^3.2.4"
|
|
44
42
|
}
|
|
45
43
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dev3000",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.85",
|
|
4
4
|
"description": "AI-powered development tools with browser monitoring and MCP server integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -59,29 +59,23 @@
|
|
|
59
59
|
"claude"
|
|
60
60
|
],
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@antfu/ni": "^26.0.1",
|
|
63
62
|
"@biomejs/biome": "^2.2.4",
|
|
64
63
|
"chalk": "^5.3.0",
|
|
65
|
-
"cli-progress": "^3.12.0",
|
|
66
64
|
"commander": "^14.0.1",
|
|
67
65
|
"ink": "^6.3.1",
|
|
68
|
-
"mcp-handler": "^1.0.2",
|
|
69
66
|
"next": "15.5.1-canary.30",
|
|
70
67
|
"ora": "^9.0.0",
|
|
71
68
|
"package-manager-detector": "^1.3.0",
|
|
72
69
|
"react": "^19.1.1",
|
|
73
70
|
"react-dom": "^19.1.1",
|
|
74
71
|
"ws": "^8.18.3",
|
|
75
|
-
"zod": "^3.22.4",
|
|
76
72
|
"typescript": "^5.0.0"
|
|
77
73
|
},
|
|
78
74
|
"devDependencies": {
|
|
79
|
-
"@types/cli-progress": "^3.11.6",
|
|
80
75
|
"@types/node": "^24.5.2",
|
|
81
76
|
"@types/react": "^19.0.0",
|
|
82
77
|
"@types/ws": "^8.5.12",
|
|
83
78
|
"husky": "^9.0.0",
|
|
84
|
-
"js-yaml": "^4.1.0",
|
|
85
79
|
"tsx": "^4.20.3",
|
|
86
80
|
"vitest": "^3.2.4"
|
|
87
81
|
},
|
|
@@ -99,5 +93,6 @@
|
|
|
99
93
|
"url": "git+https://github.com/vercel-labs/dev3000.git"
|
|
100
94
|
},
|
|
101
95
|
"author": "Lindsey Simon <lindsey@vercel.com>",
|
|
102
|
-
"license": "MIT"
|
|
96
|
+
"license": "MIT",
|
|
97
|
+
"packageManager": "pnpm@10.15.0+sha512.486ebc259d3e999a4e8691ce03b5cac4a71cbeca39372a9b762cb500cfdf0873e2cb16abe3d951b1ee2cf012503f027b98b6584e4df22524e0c7450d9ec7aa7b"
|
|
103
98
|
}
|
|
@@ -307,7 +307,7 @@ const TUIApp = ({
|
|
|
307
307
|
{/* Info on the right */}
|
|
308
308
|
<Box flexDirection="column" flexGrow={1}>
|
|
309
309
|
<Text color="cyan">🌐 App: http://localhost:{appPort}</Text>
|
|
310
|
-
<Text color="cyan">🤖 MCP: http://localhost:{mcpPort}
|
|
310
|
+
<Text color="cyan">🤖 MCP: http://localhost:{mcpPort}</Text>
|
|
311
311
|
<Text color="cyan">
|
|
312
312
|
📸 Logs: http://localhost:{mcpPort}/logs
|
|
313
313
|
{projectName ? `?project=${encodeURIComponent(projectName)}` : ""}
|