dev3000 0.0.153 → 0.0.155
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/README.md +121 -103
- package/dist/cdp-monitor.d.ts.map +1 -1
- package/dist/cdp-monitor.js +2 -3
- package/dist/cdp-monitor.js.map +1 -1
- package/dist/cli.js +301 -75
- package/dist/cli.js.map +1 -1
- package/dist/commands/cloud-check-pr.d.ts +1 -0
- package/dist/commands/cloud-check-pr.d.ts.map +1 -1
- package/dist/commands/cloud-check-pr.js +18 -6
- package/dist/commands/cloud-check-pr.js.map +1 -1
- package/dist/commands/crawl.d.ts +12 -0
- package/dist/commands/crawl.d.ts.map +1 -0
- package/dist/commands/crawl.js +140 -0
- package/dist/commands/crawl.js.map +1 -0
- package/dist/commands/errors.d.ts +14 -0
- package/dist/commands/errors.d.ts.map +1 -0
- package/dist/commands/errors.js +295 -0
- package/dist/commands/errors.js.map +1 -0
- package/dist/commands/find-component.d.ts +8 -0
- package/dist/commands/find-component.d.ts.map +1 -0
- package/dist/commands/find-component.js +182 -0
- package/dist/commands/find-component.js.map +1 -0
- package/dist/commands/fix.d.ts +13 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +288 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/logs.d.ts +13 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +195 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/restart.d.ts +8 -0
- package/dist/commands/restart.d.ts.map +1 -0
- package/dist/commands/restart.js +92 -0
- package/dist/commands/restart.js.map +1 -0
- package/dist/components/PackageSelector.d.ts +12 -0
- package/dist/components/PackageSelector.d.ts.map +1 -0
- package/dist/components/PackageSelector.js +74 -0
- package/dist/components/PackageSelector.js.map +1 -0
- package/dist/dev-environment.d.ts +0 -7
- package/dist/dev-environment.d.ts.map +1 -1
- package/dist/dev-environment.js +108 -674
- package/dist/dev-environment.js.map +1 -1
- package/dist/screencast-manager.d.ts.map +1 -1
- package/dist/screencast-manager.js +7 -8
- package/dist/screencast-manager.js.map +1 -1
- package/dist/skills/d3k/SKILL.md +38 -27
- package/dist/skills/index.d.ts +10 -14
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +56 -75
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/index.test.ts +13 -55
- package/dist/skills/index.ts +59 -80
- package/dist/src/tui-interface-impl.tsx +6 -15
- package/dist/tui-interface-impl.d.ts.map +1 -1
- package/dist/tui-interface-impl.js +4 -4
- package/dist/tui-interface-impl.js.map +1 -1
- package/dist/tui-interface-opentui.d.ts.map +1 -1
- package/dist/tui-interface-opentui.js +211 -80
- package/dist/tui-interface-opentui.js.map +1 -1
- package/dist/utils/agent-browser.d.ts +2 -0
- package/dist/utils/agent-browser.d.ts.map +1 -1
- package/dist/utils/agent-browser.js +46 -8
- package/dist/utils/agent-browser.js.map +1 -1
- package/dist/utils/agent-selection.d.ts.map +1 -1
- package/dist/utils/agent-selection.js +9 -2
- package/dist/utils/agent-selection.js.map +1 -1
- package/dist/utils/skill-installer.d.ts +55 -29
- package/dist/utils/skill-installer.d.ts.map +1 -1
- package/dist/utils/skill-installer.js +118 -229
- package/dist/utils/skill-installer.js.map +1 -1
- package/dist/utils/tmux-helpers.d.ts +1 -2
- package/dist/utils/tmux-helpers.d.ts.map +1 -1
- package/dist/utils/tmux-helpers.js +17 -18
- package/dist/utils/tmux-helpers.js.map +1 -1
- package/dist/utils/version-check.d.ts +2 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +9 -0
- package/dist/utils/version-check.js.map +1 -1
- package/mcp-server/.next/BUILD_ID +1 -1
- package/mcp-server/.next/build-manifest.json +2 -2
- package/mcp-server/.next/fallback-build-manifest.json +2 -2
- package/mcp-server/.next/prerender-manifest.json +3 -3
- package/mcp-server/.next/server/app/_global-error/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.html +2 -2
- package/mcp-server/.next/server/app/_global-error.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found/page.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.html +1 -1
- package/mcp-server/.next/server/app/_not-found.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/mcp-server/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/mcp-server/.next/server/app/api/screenshots/capture/route.js +2 -2
- package/mcp-server/.next/server/app/api/screenshots/capture/route.js.nft.json +1 -1
- package/mcp-server/.next/server/app/index.html +1 -1
- package/mcp-server/.next/server/app/index.rsc +2 -2
- package/mcp-server/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/mcp-server/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/mcp-server/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/mcp-server/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/mcp-server/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- 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/mcp/route.js +4 -4
- package/mcp-server/.next/server/app/mcp/route.js.nft.json +1 -1
- 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.js +1 -1
- package/mcp-server/.next/server/app/video/[session]/page.js.nft.json +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__2f95edf0._.js +3 -3
- package/mcp-server/.next/server/chunks/[root-of-the-server]__2f95edf0._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__69e6dfb7._.js +3 -0
- package/mcp-server/.next/server/chunks/{[root-of-the-server]__444592aa._.js.map → [root-of-the-server]__69e6dfb7._.js.map} +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__6baff21e._.js +4 -0
- package/mcp-server/.next/server/chunks/{[root-of-the-server]__130a5f58._.js.map → [root-of-the-server]__6baff21e._.js.map} +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__6f790e1f._.js +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__6f790e1f._.js.map +1 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__c8cf5b23._.js +3 -0
- package/mcp-server/.next/server/chunks/[root-of-the-server]__e6a83e60._.js +4 -0
- package/mcp-server/.next/server/chunks/{[root-of-the-server]__b71c83ed._.js.map → [root-of-the-server]__e6a83e60._.js.map} +1 -1
- package/mcp-server/.next/server/chunks/mcp-server_app_mcp_tools_ts_faf6d7df._.js +32 -66
- package/mcp-server/.next/server/chunks/mcp-server_app_mcp_tools_ts_faf6d7df._.js.map +1 -1
- package/mcp-server/.next/server/chunks/src_utils_agent-browser_ts_cc00e0d8._.js +1 -1
- package/mcp-server/.next/server/chunks/src_utils_agent-browser_ts_cc00e0d8._.js.map +1 -1
- package/mcp-server/.next/server/chunks/src_utils_project-name_ts_1fab1dd5._.js +3 -0
- package/mcp-server/.next/server/chunks/src_utils_project-name_ts_1fab1dd5._.js.map +1 -0
- package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__f66148e5._.js → [root-of-the-server]__b17d4048._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__50eb2eba._.js → [root-of-the-server]__dcf84f77._.js} +2 -2
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_page_tsx_9fc46577._.js +1 -1
- package/mcp-server/.next/server/chunks/ssr/mcp-server_app_page_tsx_9fc46577._.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/server/server-reference-manifest.js +1 -1
- package/mcp-server/.next/server/server-reference-manifest.json +1 -1
- package/mcp-server/.next/static/chunks/{2422ea9ed874427b.js → 3f3f8e7d16ba3bf4.js} +1 -1
- package/mcp-server/app/api/tools/route.ts +5 -4
- package/mcp-server/app/mcp/route.ts +8 -63
- package/mcp-server/app/mcp/tools.ts +71 -445
- package/mcp-server/app/page.tsx +1 -1
- package/mcp-server/package.json +1 -0
- package/package.json +6 -6
- package/src/tui-interface-impl.tsx +6 -15
- package/dist/components/SkillSelector.d.ts +0 -10
- package/dist/components/SkillSelector.d.ts.map +0 -1
- package/dist/components/SkillSelector.js +0 -87
- package/dist/components/SkillSelector.js.map +0 -1
- package/mcp-server/.next/server/chunks/[root-of-the-server]__130a5f58._.js +0 -4
- package/mcp-server/.next/server/chunks/[root-of-the-server]__444592aa._.js +0 -3
- package/mcp-server/.next/server/chunks/[root-of-the-server]__8f84b4cc._.js +0 -3
- package/mcp-server/.next/server/chunks/[root-of-the-server]__b71c83ed._.js +0 -4
- /package/mcp-server/.next/server/chunks/{[root-of-the-server]__8f84b4cc._.js.map → [root-of-the-server]__c8cf5b23._.js.map} +0 -0
- /package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__f66148e5._.js.map → [root-of-the-server]__b17d4048._.js.map} +0 -0
- /package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__50eb2eba._.js.map → [root-of-the-server]__dcf84f77._.js.map} +0 -0
- /package/mcp-server/.next/static/{Mseg7iY2pocGklcPCObqM → uxzBYIUkyXehXbe9VuXKp}/_buildManifest.js +0 -0
- /package/mcp-server/.next/static/{Mseg7iY2pocGklcPCObqM → uxzBYIUkyXehXbe9VuXKp}/_clientMiddlewareManifest.json +0 -0
- /package/mcp-server/.next/static/{Mseg7iY2pocGklcPCObqM → uxzBYIUkyXehXbe9VuXKp}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,85 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
// Intercept agent-browser command early, before Commander parses args
|
|
3
|
+
// This allows passing all args directly to agent-browser without Commander interference
|
|
4
|
+
const agentBrowserIndex = process.argv.indexOf("agent-browser");
|
|
5
|
+
if (agentBrowserIndex >= 0 && (process.argv[1]?.includes("d3k") || process.argv[1]?.includes("dev3000"))) {
|
|
6
|
+
// Use require for synchronous execution before other imports
|
|
7
|
+
const { spawnSync } = require("child_process");
|
|
8
|
+
const { existsSync } = require("fs");
|
|
9
|
+
const { join } = require("path");
|
|
10
|
+
const args = process.argv.slice(agentBrowserIndex + 1);
|
|
11
|
+
// Intercept "errors" and "console" subcommands - redirect to d3k's superior commands
|
|
12
|
+
// These d3k commands show BOTH browser AND server logs, unlike agent-browser which only shows browser
|
|
13
|
+
const subcommandIndex = args.findIndex((arg) => !arg.startsWith("-") && !arg.startsWith("@") && arg !== "9222");
|
|
14
|
+
const subcommand = subcommandIndex >= 0 ? args[subcommandIndex] : null;
|
|
15
|
+
if (subcommand === "errors") {
|
|
16
|
+
console.log("\x1b[33m💡 Tip: Using `d3k errors` instead (shows browser + server errors)\x1b[0m\n");
|
|
17
|
+
const d3kBin = process.argv[1];
|
|
18
|
+
const result = spawnSync(d3kBin, ["errors"], { stdio: "inherit", shell: false });
|
|
19
|
+
process.exit(result.status ?? 0);
|
|
20
|
+
}
|
|
21
|
+
if (subcommand === "console") {
|
|
22
|
+
console.log("\x1b[33m💡 Tip: Using `d3k logs` instead (shows browser + server logs)\x1b[0m\n");
|
|
23
|
+
const d3kBin = process.argv[1];
|
|
24
|
+
const result = spawnSync(d3kBin, ["logs", "--type", "browser"], { stdio: "inherit", shell: false });
|
|
25
|
+
process.exit(result.status ?? 0);
|
|
26
|
+
}
|
|
27
|
+
// Find agent-browser native binary directly (avoids shell wrapper that needs node)
|
|
28
|
+
function findAgentBrowser() {
|
|
29
|
+
const os = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "win32" : "linux";
|
|
30
|
+
const arch = process.arch === "arm64" ? "arm64" : "x64";
|
|
31
|
+
const nativeName = `agent-browser-${os}-${arch}`;
|
|
32
|
+
const platformPkg = `${os}-${arch}`;
|
|
33
|
+
const cwd = process.cwd();
|
|
34
|
+
const home = require("os").homedir();
|
|
35
|
+
// Prefer native binary to avoid shell wrapper needing node in PATH
|
|
36
|
+
const searchPaths = [
|
|
37
|
+
// Bun global install paths (native binary) - use homedir since compiled binary has virtual path
|
|
38
|
+
join(home, ".bun", "install", "global", "node_modules", "@d3k", platformPkg, "mcp-server", "node_modules", ".bin", nativeName),
|
|
39
|
+
// Local development paths (native binary)
|
|
40
|
+
join(cwd, "mcp-server", "node_modules", ".bin", nativeName),
|
|
41
|
+
join(cwd, "node_modules", ".bin", nativeName),
|
|
42
|
+
// Fallback to wrapper script (needs node in PATH)
|
|
43
|
+
join(home, ".bun", "install", "global", "node_modules", "@d3k", platformPkg, "mcp-server", "node_modules", ".bin", "agent-browser"),
|
|
44
|
+
join(cwd, "mcp-server", "node_modules", ".bin", "agent-browser"),
|
|
45
|
+
join(cwd, "node_modules", ".bin", "agent-browser")
|
|
46
|
+
];
|
|
47
|
+
for (const p of searchPaths) {
|
|
48
|
+
if (existsSync(p))
|
|
49
|
+
return p;
|
|
50
|
+
}
|
|
51
|
+
return "agent-browser"; // fallback to PATH
|
|
52
|
+
}
|
|
53
|
+
const binaryPath = findAgentBrowser();
|
|
54
|
+
// Ensure PATH is set for child process (Claude Code can have empty PATH)
|
|
55
|
+
const env = { ...process.env };
|
|
56
|
+
if (!env.PATH || env.PATH === "") {
|
|
57
|
+
env.PATH = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
58
|
+
}
|
|
59
|
+
// Capture output so we can show errors if command fails
|
|
60
|
+
const result = spawnSync(binaryPath, args, {
|
|
61
|
+
stdio: "pipe",
|
|
62
|
+
shell: false,
|
|
63
|
+
env
|
|
64
|
+
});
|
|
65
|
+
// Show output
|
|
66
|
+
if (result.stdout?.length > 0) {
|
|
67
|
+
process.stdout.write(result.stdout);
|
|
68
|
+
}
|
|
69
|
+
if (result.stderr?.length > 0) {
|
|
70
|
+
process.stderr.write(result.stderr);
|
|
71
|
+
}
|
|
72
|
+
// If spawn failed (e.g., binary not found), show the error
|
|
73
|
+
if (result.error) {
|
|
74
|
+
console.error(`\nError spawning agent-browser: ${result.error.message}`);
|
|
75
|
+
console.error(`Binary path: ${binaryPath}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
process.exit(result.status ?? 1);
|
|
79
|
+
}
|
|
2
80
|
import chalk from "chalk";
|
|
3
81
|
import { Command } from "commander";
|
|
4
|
-
import { existsSync, readFileSync } from "fs";
|
|
82
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "fs";
|
|
5
83
|
import { homedir, tmpdir } from "os";
|
|
6
84
|
import { detect } from "package-manager-detector";
|
|
7
85
|
import { dirname, join } from "path";
|
|
@@ -14,10 +92,38 @@ import { detectAIAgent } from "./utils/agent-detection.js";
|
|
|
14
92
|
import { getAvailableAgents } from "./utils/agent-selection.js";
|
|
15
93
|
import { formatMcpConfigTargets, parseDisabledMcpConfigs } from "./utils/mcp-configs.js";
|
|
16
94
|
import { getProjectDir } from "./utils/project-name.js";
|
|
17
|
-
import {
|
|
95
|
+
import { checkForSkillUpdates, getApplicablePackages, installSkillPackage, isPackageInstalled, updateSkills } from "./utils/skill-installer.js";
|
|
18
96
|
import { DEFAULT_TMUX_CONFIG, generateSessionName, generateTmuxCommands, getTmuxInstallInstructions, isTmuxInstalled } from "./utils/tmux-helpers.js";
|
|
19
97
|
import { loadUserConfig, saveUserConfig } from "./utils/user-config.js";
|
|
20
98
|
import { checkForUpdates, getUpgradeCommand, performUpgrade } from "./utils/version-check.js";
|
|
99
|
+
// Global error handlers to log crashes
|
|
100
|
+
const crashLogPath = join(homedir(), ".d3k", "crash.log");
|
|
101
|
+
function logCrash(type, error) {
|
|
102
|
+
try {
|
|
103
|
+
const crashDir = join(homedir(), ".d3k");
|
|
104
|
+
if (!existsSync(crashDir)) {
|
|
105
|
+
mkdirSync(crashDir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
const timestamp = new Date().toISOString();
|
|
108
|
+
const errorStr = error instanceof Error ? `${error.message}\n${error.stack}` : String(error);
|
|
109
|
+
const logEntry = `[${timestamp}] ${type}: ${errorStr}\n\n`;
|
|
110
|
+
appendFileSync(crashLogPath, logEntry);
|
|
111
|
+
console.error(chalk.red(`\n💥 d3k crashed: ${error instanceof Error ? error.message : error}`));
|
|
112
|
+
console.error(chalk.gray(` Details logged to: ${crashLogPath}`));
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// If we can't log, at least print to stderr
|
|
116
|
+
console.error(`d3k crashed: ${error}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
process.on("uncaughtException", (error) => {
|
|
120
|
+
logCrash("Uncaught Exception", error);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
});
|
|
123
|
+
process.on("unhandledRejection", (reason) => {
|
|
124
|
+
logCrash("Unhandled Promise Rejection", reason);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
});
|
|
21
127
|
/**
|
|
22
128
|
* Build the d3k command string with forwarded options.
|
|
23
129
|
*/
|
|
@@ -55,7 +161,7 @@ function buildD3kCommandWithOptions(options) {
|
|
|
55
161
|
* Launch d3k with an agent using tmux for proper terminal multiplexing.
|
|
56
162
|
* This creates a split-screen with the agent on the left and d3k logs on the right.
|
|
57
163
|
*/
|
|
58
|
-
async function launchWithTmux(agentCommand,
|
|
164
|
+
async function launchWithTmux(agentCommand, forwardedOptions = {}) {
|
|
59
165
|
const { execSync } = await import("child_process");
|
|
60
166
|
const { appendFileSync, writeFileSync } = await import("fs");
|
|
61
167
|
// Log file for debugging crashes
|
|
@@ -94,7 +200,6 @@ async function launchWithTmux(agentCommand, mcpPort = DEFAULT_TMUX_CONFIG.mcpPor
|
|
|
94
200
|
sessionName,
|
|
95
201
|
d3kCommand,
|
|
96
202
|
agentCommand,
|
|
97
|
-
mcpPort,
|
|
98
203
|
paneWidthPercent: DEFAULT_TMUX_CONFIG.paneWidthPercent
|
|
99
204
|
});
|
|
100
205
|
// Create a shell script that sets up tmux and attaches
|
|
@@ -198,25 +303,22 @@ async function promptAgentSelection(defaultAgentName) {
|
|
|
198
303
|
* Show interactive skill selection prompt using Ink.
|
|
199
304
|
* Returns the selected skills and install location, or empty array if user skipped.
|
|
200
305
|
*/
|
|
201
|
-
async function
|
|
306
|
+
async function promptPackageSelection(packages) {
|
|
202
307
|
const { render } = await import("ink");
|
|
203
308
|
const React = await import("react");
|
|
204
|
-
const {
|
|
205
|
-
let
|
|
309
|
+
const { PackageSelector } = await import("./components/PackageSelector.js");
|
|
310
|
+
let selectedPackages = [];
|
|
206
311
|
let installLocation = "project";
|
|
207
|
-
let skipped = false;
|
|
208
312
|
try {
|
|
209
|
-
const { unmount, waitUntilExit, clear } = render(React.createElement(
|
|
210
|
-
|
|
211
|
-
initiallySelected,
|
|
313
|
+
const { unmount, waitUntilExit, clear } = render(React.createElement(PackageSelector, {
|
|
314
|
+
packages,
|
|
212
315
|
onComplete: (selected, location) => {
|
|
213
|
-
|
|
316
|
+
selectedPackages = selected;
|
|
214
317
|
installLocation = location;
|
|
215
318
|
clear();
|
|
216
319
|
unmount();
|
|
217
320
|
},
|
|
218
321
|
onSkip: () => {
|
|
219
|
-
skipped = true;
|
|
220
322
|
clear();
|
|
221
323
|
unmount();
|
|
222
324
|
}
|
|
@@ -226,14 +328,10 @@ async function promptSkillSelection(skills, initiallySelected) {
|
|
|
226
328
|
process.stdout.write("\x1b[2J\x1b[H\x1b[3J");
|
|
227
329
|
}
|
|
228
330
|
catch (error) {
|
|
229
|
-
console.error(chalk.red("Error in
|
|
230
|
-
return {
|
|
231
|
-
}
|
|
232
|
-
// If user skipped, mark skills as seen so we don't ask again
|
|
233
|
-
if (skipped) {
|
|
234
|
-
markSkillsAsSeen(skills);
|
|
331
|
+
console.error(chalk.red("Error in package selection:"), error);
|
|
332
|
+
return { packages: [], location: "project" };
|
|
235
333
|
}
|
|
236
|
-
return {
|
|
334
|
+
return { packages: selectedPackages, location: installLocation };
|
|
237
335
|
}
|
|
238
336
|
function detectPythonCommand(debug = false) {
|
|
239
337
|
// Check if we're in a virtual environment
|
|
@@ -466,7 +564,6 @@ program
|
|
|
466
564
|
program
|
|
467
565
|
.description("AI-powered development tools with browser monitoring and MCP server")
|
|
468
566
|
.option("-p, --port <port>", "Development server port (auto-detected by project type)")
|
|
469
|
-
.option("-m, --port-mcp <port>", "MCP server port", "3684")
|
|
470
567
|
.option("-s, --script <script>", "Script to run (e.g. dev, main.py) - auto-detected by project type")
|
|
471
568
|
.option("-c, --command <command>", "Custom command to run (overrides auto-detection and --script)")
|
|
472
569
|
.option("--profile-dir <dir>", "Chrome profile directory", join(tmpdir(), "dev3000-chrome-profile"))
|
|
@@ -480,7 +577,6 @@ program
|
|
|
480
577
|
.option("--disable-mcp-configs <targets>", "Comma or space separated list of MCP config files to skip (.mcp.json, .cursor/mcp.json, opencode.json). Use 'all' to disable all.")
|
|
481
578
|
.option("--no-chrome-devtools-mcp", "Disable chrome-devtools MCP integration (enabled by default)")
|
|
482
579
|
.option("--headless", "Run Chrome in headless mode (for serverless/CI environments)")
|
|
483
|
-
.option("--kill-mcp", "Kill the MCP server on port 3684 and exit")
|
|
484
580
|
.option("--with-agent <command>", 'Run an agent (e.g. claude) in split-screen mode using tmux. Example: --with-agent "claude"')
|
|
485
581
|
.option("--no-agent", "Skip agent selection prompt and run d3k standalone")
|
|
486
582
|
.action(async (options) => {
|
|
@@ -490,7 +586,7 @@ program
|
|
|
490
586
|
const browserOption = options.browser || userConfig.browser;
|
|
491
587
|
// Handle --with-agent by spawning tmux with split panes
|
|
492
588
|
if (options.withAgent) {
|
|
493
|
-
await launchWithTmux(options.withAgent,
|
|
589
|
+
await launchWithTmux(options.withAgent, {
|
|
494
590
|
port: options.port,
|
|
495
591
|
portMcp: options.portMcp,
|
|
496
592
|
script: options.script,
|
|
@@ -506,70 +602,97 @@ program
|
|
|
506
602
|
});
|
|
507
603
|
return;
|
|
508
604
|
}
|
|
509
|
-
// Handle --kill-mcp option
|
|
510
|
-
if (options.killMcp) {
|
|
511
|
-
console.log(chalk.yellow("🛑 Killing MCP server on port 3684..."));
|
|
512
|
-
try {
|
|
513
|
-
const { spawn } = require("child_process");
|
|
514
|
-
await new Promise((resolve) => {
|
|
515
|
-
const killProcess = spawn("sh", ["-c", "lsof -ti:3684 | xargs kill -9"], { stdio: "inherit" });
|
|
516
|
-
killProcess.on("exit", () => resolve());
|
|
517
|
-
});
|
|
518
|
-
console.log(chalk.green("✅ MCP server killed"));
|
|
519
|
-
}
|
|
520
|
-
catch (_error) {
|
|
521
|
-
console.log(chalk.gray("⚠️ No MCP server found on port 3684"));
|
|
522
|
-
}
|
|
523
|
-
process.exit(0);
|
|
524
|
-
}
|
|
525
605
|
// Handle agent selection for split-screen mode (default behavior in TTY)
|
|
526
606
|
// Skip if --no-agent, --no-tui, --debug flags are used, or if already inside tmux (to avoid nested prompts)
|
|
527
607
|
const insideTmux = !!process.env.TMUX;
|
|
528
608
|
if (process.stdin.isTTY && options.agent !== false && options.tui !== false && !options.debug && !insideTmux) {
|
|
529
609
|
// Clear the terminal so d3k UI starts at the top of the screen
|
|
530
610
|
process.stdout.write("\x1B[2J\x1B[0f");
|
|
531
|
-
//
|
|
532
|
-
process.stdout.write(chalk.gray(" Checking for skill updates...\r"));
|
|
533
|
-
// Check for new/updated skills from vercel-labs/agent-skills
|
|
611
|
+
// Check for skill updates and offer new packages
|
|
534
612
|
try {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
if (
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
console.log(chalk.
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
console.log(chalk.
|
|
613
|
+
// Show loading message
|
|
614
|
+
process.stdout.write(chalk.gray(" Checking for skills...\r"));
|
|
615
|
+
// 1. Check for updates to existing skills
|
|
616
|
+
const { hasUpdates } = await checkForSkillUpdates();
|
|
617
|
+
// Clear the loading message line
|
|
618
|
+
process.stdout.write("\x1B[2K\r");
|
|
619
|
+
if (hasUpdates) {
|
|
620
|
+
// Show which packages have updates (use applicable packages since lock file may not exist)
|
|
621
|
+
const applicablePackages = getApplicablePackages();
|
|
622
|
+
console.log(chalk.cyan("📦 Skill updates available"));
|
|
623
|
+
for (const pkg of applicablePackages) {
|
|
624
|
+
console.log(chalk.gray(` • ${pkg.repo}`));
|
|
625
|
+
}
|
|
626
|
+
const { default: readline } = await import("readline");
|
|
627
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
628
|
+
const answer = await new Promise((resolve) => {
|
|
629
|
+
rl.question(chalk.white(" Update now? (Y/n) "), resolve);
|
|
630
|
+
});
|
|
631
|
+
rl.close();
|
|
632
|
+
if (answer.toLowerCase() !== "n") {
|
|
633
|
+
console.log(chalk.gray(" Updating skills..."));
|
|
634
|
+
const updateResult = await updateSkills();
|
|
635
|
+
if (updateResult.success) {
|
|
636
|
+
console.log(chalk.green(" ✓ Skills updated"));
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
console.log(chalk.yellow(" ⚠ Some skills failed to update"));
|
|
562
640
|
}
|
|
563
|
-
|
|
564
|
-
|
|
641
|
+
}
|
|
642
|
+
console.log("");
|
|
643
|
+
}
|
|
644
|
+
// 2. Show all applicable packages with install status
|
|
645
|
+
// Skip if we just handled updates
|
|
646
|
+
if (!hasUpdates) {
|
|
647
|
+
const applicablePackages = getApplicablePackages();
|
|
648
|
+
const packagesWithStatus = applicablePackages.map((pkg) => ({
|
|
649
|
+
...pkg,
|
|
650
|
+
installed: isPackageInstalled(pkg)
|
|
651
|
+
}));
|
|
652
|
+
const hasUninstalled = packagesWithStatus.some((p) => !p.installed);
|
|
653
|
+
// Only show package selector if there are packages to install
|
|
654
|
+
if (packagesWithStatus.length > 0 && hasUninstalled) {
|
|
655
|
+
const { packages: selectedPackages, location } = await promptPackageSelection(packagesWithStatus);
|
|
656
|
+
if (selectedPackages.length > 0) {
|
|
657
|
+
const locationLabel = location === "global" ? "globally" : "to project";
|
|
658
|
+
console.log(chalk.cyan(`Installing ${selectedPackages.length} skill package(s) ${locationLabel}...`));
|
|
659
|
+
const results = { success: [], failed: [] };
|
|
660
|
+
for (let i = 0; i < selectedPackages.length; i++) {
|
|
661
|
+
const pkg = selectedPackages[i];
|
|
662
|
+
console.log(chalk.gray(` [${i + 1}/${selectedPackages.length}] ${pkg.displayName}...`));
|
|
663
|
+
const result = await installSkillPackage(pkg, location);
|
|
664
|
+
if (result.success) {
|
|
665
|
+
results.success.push(pkg.displayName);
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
results.failed.push(pkg.displayName);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
if (results.success.length > 0) {
|
|
672
|
+
console.log(chalk.green(`✓ Installed: ${results.success.join(", ")}`));
|
|
673
|
+
}
|
|
674
|
+
if (results.failed.length > 0) {
|
|
675
|
+
console.log(chalk.yellow(`⚠ Failed: ${results.failed.join(", ")}`));
|
|
676
|
+
}
|
|
677
|
+
console.log("");
|
|
565
678
|
}
|
|
679
|
+
else {
|
|
680
|
+
// User skipped package installation, show skills are up to date
|
|
681
|
+
console.log(chalk.green("✓ Skills up to date"));
|
|
682
|
+
console.log("");
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
// No updates and no new packages - show success
|
|
687
|
+
console.log(chalk.green("✓ Skills up to date"));
|
|
566
688
|
console.log("");
|
|
567
689
|
}
|
|
568
690
|
}
|
|
569
691
|
}
|
|
570
692
|
catch {
|
|
571
|
-
//
|
|
572
|
-
|
|
693
|
+
// Show error briefly, then continue
|
|
694
|
+
console.log(chalk.yellow("⚠ Could not check for skill updates"));
|
|
695
|
+
console.log("");
|
|
573
696
|
}
|
|
574
697
|
// Check if tmux is available before showing prompt
|
|
575
698
|
if (!(await isTmuxInstalled())) {
|
|
@@ -592,7 +715,7 @@ program
|
|
|
592
715
|
}
|
|
593
716
|
// Clear screen and scrollback before launching tmux so when tmux exits, terminal is clean
|
|
594
717
|
process.stdout.write("\x1b[2J\x1b[H\x1b[3J");
|
|
595
|
-
await launchWithTmux(selectedAgent.command,
|
|
718
|
+
await launchWithTmux(selectedAgent.command, {
|
|
596
719
|
port: options.port,
|
|
597
720
|
portMcp: options.portMcp,
|
|
598
721
|
script: options.script,
|
|
@@ -779,6 +902,7 @@ cloud
|
|
|
779
902
|
.command("check-pr [pr-number]")
|
|
780
903
|
.description("Verify a PR's changes work as expected using Vercel preview deployment")
|
|
781
904
|
.option("--repo <url>", "Repository URL (optional, auto-detected from git)")
|
|
905
|
+
.option("--url <preview-url>", "Preview deployment URL (optional, auto-detected from Vercel)")
|
|
782
906
|
.option("--debug", "Enable debug logging")
|
|
783
907
|
.action(async (prNumber, options) => {
|
|
784
908
|
try {
|
|
@@ -828,6 +952,12 @@ program
|
|
|
828
952
|
process.exit(1);
|
|
829
953
|
}
|
|
830
954
|
});
|
|
955
|
+
// Agent-browser command - registered for --help display only
|
|
956
|
+
// Actual handling happens at the top of the file before Commander runs
|
|
957
|
+
program
|
|
958
|
+
.command("agent-browser [args...]")
|
|
959
|
+
.description("Run the bundled agent-browser CLI (e.g., d3k agent-browser screenshot /tmp/foo.png)")
|
|
960
|
+
.allowUnknownOption(true);
|
|
831
961
|
// Skill command - get skill content for use in prompts/workflows
|
|
832
962
|
program
|
|
833
963
|
.command("skill [name]")
|
|
@@ -842,7 +972,7 @@ program
|
|
|
842
972
|
if (skills.length === 0) {
|
|
843
973
|
console.log(chalk.yellow("No skills found."));
|
|
844
974
|
console.log(chalk.gray("\nSkills are loaded from:"));
|
|
845
|
-
console.log(chalk.gray(" • .
|
|
975
|
+
console.log(chalk.gray(" • .agents/skills/ (project-local)"));
|
|
846
976
|
console.log(chalk.gray(" • d3k built-in skills"));
|
|
847
977
|
process.exit(0);
|
|
848
978
|
}
|
|
@@ -883,5 +1013,101 @@ program
|
|
|
883
1013
|
// Output skill content to stdout (no formatting, for piping/parsing)
|
|
884
1014
|
console.log(result.content);
|
|
885
1015
|
});
|
|
1016
|
+
// Errors command - quick view of recent errors
|
|
1017
|
+
program
|
|
1018
|
+
.command("errors")
|
|
1019
|
+
.description("Show recent errors from d3k logs (browser + server)")
|
|
1020
|
+
.option("-n, --count <count>", "Number of errors to show", "10")
|
|
1021
|
+
.option("-a, --all", "Show all errors, not just recent")
|
|
1022
|
+
.option("-c, --context", "Show interactions before each error (for replay)")
|
|
1023
|
+
.option("--json", "Output as JSON for parsing")
|
|
1024
|
+
.action(async (options) => {
|
|
1025
|
+
const { showErrors } = await import("./commands/errors.js");
|
|
1026
|
+
await showErrors(options);
|
|
1027
|
+
});
|
|
1028
|
+
// Logs command - view recent logs
|
|
1029
|
+
program
|
|
1030
|
+
.command("logs")
|
|
1031
|
+
.description("Show recent logs from d3k (browser + server)")
|
|
1032
|
+
.option("-n, --count <count>", "Number of lines to show", "50")
|
|
1033
|
+
.option("-t, --type <type>", "Filter by type: browser, server, network, all", "all")
|
|
1034
|
+
.option("--json", "Output as JSON for parsing")
|
|
1035
|
+
.action(async (options) => {
|
|
1036
|
+
const { showLogs } = await import("./commands/logs.js");
|
|
1037
|
+
await showLogs(options);
|
|
1038
|
+
});
|
|
1039
|
+
// Fix command - diagnose application errors from logs
|
|
1040
|
+
program
|
|
1041
|
+
.command("fix")
|
|
1042
|
+
.description("Diagnose application errors from d3k logs")
|
|
1043
|
+
.option("-f, --focus <area>", "Focus area: build, runtime, network, ui, all", "all")
|
|
1044
|
+
.option("-t, --time <minutes>", "Minutes to analyze back", "10")
|
|
1045
|
+
.option("--json", "Output as JSON for parsing")
|
|
1046
|
+
.action(async (options) => {
|
|
1047
|
+
const { fixMyApp } = await import("./commands/fix.js");
|
|
1048
|
+
await fixMyApp(options);
|
|
1049
|
+
});
|
|
1050
|
+
// Crawl command - discover app URLs
|
|
1051
|
+
program
|
|
1052
|
+
.command("crawl")
|
|
1053
|
+
.description("Discover URLs by crawling the app")
|
|
1054
|
+
.option("-d, --depth <depth>", "Crawl depth (1, 2, 3, or 'all')", "1")
|
|
1055
|
+
.option("-l, --limit <limit>", "Max links per page to follow", "3")
|
|
1056
|
+
.action(async (options) => {
|
|
1057
|
+
const { crawlApp } = await import("./commands/crawl.js");
|
|
1058
|
+
await crawlApp(options);
|
|
1059
|
+
});
|
|
1060
|
+
// Find-component command - map DOM to React source
|
|
1061
|
+
program
|
|
1062
|
+
.command("find-component <selector>")
|
|
1063
|
+
.description("Find React component source for a DOM selector")
|
|
1064
|
+
.action(async (selector) => {
|
|
1065
|
+
const { findComponent } = await import("./commands/find-component.js");
|
|
1066
|
+
await findComponent(selector);
|
|
1067
|
+
});
|
|
1068
|
+
// Restart command - restart the dev server
|
|
1069
|
+
program
|
|
1070
|
+
.command("restart")
|
|
1071
|
+
.description("Restart the development server (rarely needed - HMR handles most changes)")
|
|
1072
|
+
.action(async () => {
|
|
1073
|
+
const { restartServer } = await import("./commands/restart.js");
|
|
1074
|
+
await restartServer();
|
|
1075
|
+
});
|
|
1076
|
+
// CDP port command - get the CDP port from the session file
|
|
1077
|
+
program
|
|
1078
|
+
.command("cdp-port")
|
|
1079
|
+
.description("Output the CDP port for the current d3k session (for use in scripts)")
|
|
1080
|
+
.action(async () => {
|
|
1081
|
+
const sessionDir = join(homedir(), ".d3k");
|
|
1082
|
+
const projectDir = getProjectDir();
|
|
1083
|
+
const projectName = projectDir.split("/").pop() || "unknown";
|
|
1084
|
+
// Try to find session.json in ~/.d3k/{project-name}/
|
|
1085
|
+
const entries = existsSync(sessionDir)
|
|
1086
|
+
? await import("fs").then((fs) => fs.readdirSync(sessionDir, { withFileTypes: true }))
|
|
1087
|
+
: [];
|
|
1088
|
+
for (const entry of entries) {
|
|
1089
|
+
if (entry.isDirectory() && entry.name.startsWith(projectName.substring(0, 20))) {
|
|
1090
|
+
const sessionFile = join(sessionDir, entry.name, "session.json");
|
|
1091
|
+
if (existsSync(sessionFile)) {
|
|
1092
|
+
try {
|
|
1093
|
+
const content = JSON.parse(readFileSync(sessionFile, "utf-8"));
|
|
1094
|
+
if (content.cdpUrl) {
|
|
1095
|
+
// Extract port from URL like "ws://localhost:9223/devtools/browser/..."
|
|
1096
|
+
const match = content.cdpUrl.match(/:(\d+)/);
|
|
1097
|
+
if (match) {
|
|
1098
|
+
console.log(match[1]);
|
|
1099
|
+
process.exit(0);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
catch {
|
|
1104
|
+
// Continue searching
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
// Default to 9222 if no session found
|
|
1110
|
+
console.log("9222");
|
|
1111
|
+
});
|
|
886
1112
|
program.parse();
|
|
887
1113
|
//# sourceMappingURL=cli.js.map
|