@mumulinya167/cc-web 1.0.0 → 1.0.1
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/bin/ccm.js +25 -4
- package/bin/server.js +105 -0
- package/bin/server.ts +4533 -0
- package/dist/server.d.ts +186 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +4479 -0
- package/dist/server.js.map +1 -0
- package/package.json +21 -5
- package/public/assets/index-Bc9Qzbsh.css +1 -0
- package/public/assets/index-Cp4uGXX0.js +55 -0
- package/public/favicon.svg +1 -0
- package/public/icons.svg +24 -0
- package/public/index.html +13 -6603
- package/mcp-feishu/.env.example +0 -2
- package/mcp-feishu/package-lock.json +0 -1194
- package/mcp-feishu/package.json +0 -23
- package/mcp-feishu/src/cli.ts +0 -239
- package/mcp-feishu/src/feishu-client.ts +0 -209
- package/mcp-feishu/src/index.ts +0 -55
- package/mcp-feishu/src/tools.ts +0 -222
- package/mcp-feishu/tsconfig.json +0 -18
package/bin/ccm.js
CHANGED
|
@@ -638,6 +638,17 @@ if (args.includes("--list") || args.includes("-l")) {
|
|
|
638
638
|
console.log();
|
|
639
639
|
} else if (args[0] === "web") {
|
|
640
640
|
const port = args.includes("--port") ? parseInt(args[args.indexOf("--port") + 1]) : 3080;
|
|
641
|
+
const { startServer } = require("./server.js");
|
|
642
|
+
startServer(port);
|
|
643
|
+
} else if (args[0] === "start" && !args[1]) {
|
|
644
|
+
// ccm start → 启动 Web 控制台(前端 + 后端,前端由 server.js 从 public/ 目录直接 serve)
|
|
645
|
+
const port = args.includes("--port") ? parseInt(args[args.indexOf("--port") + 1]) : 3080;
|
|
646
|
+
|
|
647
|
+
console.log("\n╔══════════════════════════════════════╗");
|
|
648
|
+
console.log("║ cc-web 控制台 ║");
|
|
649
|
+
console.log("╚══════════════════════════════════════╝\n");
|
|
650
|
+
console.log(`访问: http://localhost:${port}\n`);
|
|
651
|
+
|
|
641
652
|
const { startServer } = require("./server.js");
|
|
642
653
|
startServer(port);
|
|
643
654
|
} else if (args[0] === "start" && args[1]) {
|
|
@@ -673,8 +684,18 @@ if (args.includes("--list") || args.includes("-l")) {
|
|
|
673
684
|
if (config) startProject(config, args[1]);
|
|
674
685
|
else console.log(`项目 "${args[0]}" 不存在,用 cc-web --list 查看`);
|
|
675
686
|
} else {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
687
|
+
console.log("\n╔══════════════════════════════════════╗");
|
|
688
|
+
console.log("║ cc-web - cc-connect 管理工具 ║");
|
|
689
|
+
console.log("╚══════════════════════════════════════╝\n");
|
|
690
|
+
console.log("用法:");
|
|
691
|
+
console.log(" ccm start 启动 Web 控制台(前端 + 后端)");
|
|
692
|
+
console.log(" ccm start <项目名> 启动指定项目");
|
|
693
|
+
console.log(" ccm start all 启动所有项目");
|
|
694
|
+
console.log(" ccm stop <项目名> 停止指定项目");
|
|
695
|
+
console.log(" ccm stop all 停止所有项目");
|
|
696
|
+
console.log(" ccm web 仅启动后端 API 服务");
|
|
697
|
+
console.log(" ccm status 查看运行状态");
|
|
698
|
+
console.log(" ccm --list 列出所有配置");
|
|
699
|
+
console.log(" ccm --init 初始化新项目");
|
|
700
|
+
console.log(" ccm agents 查看支持的 Agent\n");
|
|
680
701
|
}
|
package/bin/server.js
CHANGED
|
@@ -1595,6 +1595,13 @@ function handleRequest(req, res) {
|
|
|
1595
1595
|
if (pathname.startsWith("/public/")) {
|
|
1596
1596
|
return sendFile(res, path.join(PUBLIC_DIR, pathname.replace("/public/", "")));
|
|
1597
1597
|
}
|
|
1598
|
+
// CSS 和 JS 文件
|
|
1599
|
+
if (pathname.startsWith("/css/") || pathname.startsWith("/js/")) {
|
|
1600
|
+
const filePath = path.join(PUBLIC_DIR, pathname);
|
|
1601
|
+
if (fs.existsSync(filePath)) {
|
|
1602
|
+
return sendFile(res, filePath);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1598
1605
|
|
|
1599
1606
|
// API 路由
|
|
1600
1607
|
const apiRoutes = {
|
|
@@ -2032,6 +2039,104 @@ command = "/projects"
|
|
|
2032
2039
|
return;
|
|
2033
2040
|
}
|
|
2034
2041
|
|
|
2042
|
+
// === 文件浏览器 API ===
|
|
2043
|
+
if (pathname === "/api/filesystem/browse" && req.method === "GET") {
|
|
2044
|
+
const dir = parsed.query.dir || os.homedir();
|
|
2045
|
+
try {
|
|
2046
|
+
const items = fs.readdirSync(dir, { withFileTypes: true })
|
|
2047
|
+
.filter(item => !item.name.startsWith('.'))
|
|
2048
|
+
.map(item => ({
|
|
2049
|
+
name: item.name,
|
|
2050
|
+
path: path.join(dir, item.name),
|
|
2051
|
+
isDirectory: item.isDirectory(),
|
|
2052
|
+
isFile: item.isFile()
|
|
2053
|
+
}))
|
|
2054
|
+
.sort((a, b) => {
|
|
2055
|
+
if (a.isDirectory && !b.isDirectory) return -1;
|
|
2056
|
+
if (!a.isDirectory && b.isDirectory) return 1;
|
|
2057
|
+
return a.name.localeCompare(b.name);
|
|
2058
|
+
})
|
|
2059
|
+
.slice(0, 100);
|
|
2060
|
+
|
|
2061
|
+
sendJson(res, { success: true, path: dir, items });
|
|
2062
|
+
} catch (e) {
|
|
2063
|
+
sendJson(res, { success: false, error: e.message }, 400);
|
|
2064
|
+
}
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
// 获取系统磁盘列表
|
|
2069
|
+
if (pathname === "/api/filesystem/drives" && req.method === "GET") {
|
|
2070
|
+
try {
|
|
2071
|
+
let drives = [];
|
|
2072
|
+
if (process.platform === 'win32') {
|
|
2073
|
+
// Windows: 检查 A-Z 盘符
|
|
2074
|
+
for (let i = 65; i <= 90; i++) {
|
|
2075
|
+
const letter = String.fromCharCode(i);
|
|
2076
|
+
const drivePath = `${letter}:\\`;
|
|
2077
|
+
try {
|
|
2078
|
+
fs.accessSync(drivePath);
|
|
2079
|
+
drives.push({ name: letter, path: drivePath });
|
|
2080
|
+
} catch {}
|
|
2081
|
+
}
|
|
2082
|
+
} else {
|
|
2083
|
+
// Linux/Mac: 返回根目录
|
|
2084
|
+
drives.push({ name: '/', path: '/' });
|
|
2085
|
+
}
|
|
2086
|
+
sendJson(res, { success: true, drives, home: os.homedir() });
|
|
2087
|
+
} catch (e) {
|
|
2088
|
+
sendJson(res, { success: false, error: e.message }, 400);
|
|
2089
|
+
}
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// === 终端 API ===
|
|
2094
|
+
if (pathname === "/api/terminal/exec" && req.method === "POST") {
|
|
2095
|
+
let body = "";
|
|
2096
|
+
req.on("data", (chunk) => body += chunk);
|
|
2097
|
+
req.on("end", () => {
|
|
2098
|
+
try {
|
|
2099
|
+
const { command, cwd } = JSON.parse(body);
|
|
2100
|
+
if (!command) return sendJson(res, { error: "命令不能为空" }, 400);
|
|
2101
|
+
|
|
2102
|
+
const workDir = cwd || os.homedir();
|
|
2103
|
+
console.log(`[终端] 执行命令: ${command} (目录: ${workDir})`);
|
|
2104
|
+
|
|
2105
|
+
try {
|
|
2106
|
+
const output = execSync(command, {
|
|
2107
|
+
encoding: "utf-8",
|
|
2108
|
+
cwd: workDir,
|
|
2109
|
+
timeout: 30000,
|
|
2110
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
2111
|
+
shell: true
|
|
2112
|
+
});
|
|
2113
|
+
sendJson(res, { success: true, output: output, cwd: workDir });
|
|
2114
|
+
} catch (e) {
|
|
2115
|
+
sendJson(res, {
|
|
2116
|
+
success: true,
|
|
2117
|
+
output: (e.stdout || "") + (e.stderr || e.message),
|
|
2118
|
+
cwd: workDir,
|
|
2119
|
+
error: e.status ? `Exit code: ${e.status}` : e.message
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
} catch (e) { sendJson(res, { error: e.message }, 400); }
|
|
2123
|
+
});
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
// 获取当前系统信息
|
|
2128
|
+
if (pathname === "/api/terminal/info" && req.method === "GET") {
|
|
2129
|
+
sendJson(res, {
|
|
2130
|
+
success: true,
|
|
2131
|
+
platform: process.platform,
|
|
2132
|
+
home: os.homedir(),
|
|
2133
|
+
cwd: process.cwd(),
|
|
2134
|
+
user: os.userInfo().username,
|
|
2135
|
+
shell: process.platform === 'win32' ? 'powershell' : 'bash'
|
|
2136
|
+
});
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2035
2140
|
// === 任务派发 API ===
|
|
2036
2141
|
if (pathname === "/api/tasks" && req.method === "GET") {
|
|
2037
2142
|
return sendJson(res, { tasks: loadTasks() });
|