@chatbi-v/cli 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/bin/chatbi-cli.js +1 -2
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +2645 -189
  4. package/package.json +6 -3
  5. package/templates/app/package.json.hbs +6 -2
  6. package/templates/app/src/features/settings/PluginList.tsx.hbs +7 -1
  7. package/templates/plugin/package.json.hbs +3 -3
  8. package/templates/sandbox/.npmrc.hbs +2 -0
  9. package/templates/sandbox/package.json.hbs +6 -0
  10. package/dist/bench-NMQTZVQF.mjs +0 -77
  11. package/dist/build-66EM7X52.mjs +0 -11
  12. package/dist/chunk-2IR4PJIP.mjs +0 -2255
  13. package/dist/chunk-2REG4NIZ.mjs +0 -9577
  14. package/dist/chunk-6YO7P2EG.mjs +0 -55
  15. package/dist/chunk-7DA7PT2X.mjs +0 -271
  16. package/dist/chunk-AQNFMKFL.mjs +0 -5292
  17. package/dist/chunk-B6J5VVNN.mjs +0 -52
  18. package/dist/chunk-BMUJH4OW.mjs +0 -255
  19. package/dist/chunk-DRBLMVU7.mjs +0 -6368
  20. package/dist/chunk-WUWYFYMG.mjs +0 -89
  21. package/dist/commands/add.js +0 -182
  22. package/dist/commands/bench.js +0 -100
  23. package/dist/commands/build.js +0 -297
  24. package/dist/commands/dev.js +0 -8
  25. package/dist/commands/discover.js +0 -25
  26. package/dist/commands/doctor.js +0 -231
  27. package/dist/commands/fetch.js +0 -41
  28. package/dist/commands/gl.js +0 -151
  29. package/dist/commands/init.js +0 -253
  30. package/dist/commands/install.js +0 -85
  31. package/dist/commands/ls.js +0 -46
  32. package/dist/commands/sync.js +0 -78
  33. package/dist/commands/use.js +0 -31
  34. package/dist/config.js +0 -70
  35. package/dist/corekit.js +0 -371
  36. package/dist/execa-GD72AH35.mjs +0 -17
  37. package/dist/fetch-4EUKQD7S.mjs +0 -10
  38. package/dist/index.cjs +0 -27287
  39. package/dist/index.mjs +0 -2769
  40. package/dist/init-P2UCTRNH.mjs +0 -12
  41. package/dist/sandbox.js +0 -522
  42. package/dist/sync-JWHGYK34.mjs +0 -11
  43. package/dist/utils.js +0 -99
package/dist/index.js CHANGED
@@ -1,201 +1,2657 @@
1
- "use strict";
2
- /**
3
- * @file index.ts
4
- * @description CLI 入口文件,定义所有命令行指令及交互逻辑
5
- * @author ChatBI Team
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- var __importDefault = (this && this.__importDefault) || function (mod) {
41
- return (mod && mod.__esModule) ? mod : { "default": mod };
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
42
11
  };
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- const cac_1 = __importDefault(require("cac"));
45
- const picocolors_1 = __importDefault(require("picocolors"));
46
- const figlet_1 = __importDefault(require("figlet"));
47
- const gradient_string_1 = __importDefault(require("gradient-string"));
48
- const boxen_1 = __importDefault(require("boxen"));
49
- const build_1 = require("./commands/build");
50
- const dev_1 = require("./commands/dev");
51
- const init_1 = require("./commands/init");
52
- const add_1 = require("./commands/add");
53
- const gl_1 = require("./commands/gl");
54
- const sync_1 = require("./commands/sync");
55
- const doctor_1 = require("./commands/doctor");
56
- const discover_1 = require("./commands/discover");
57
- const ls_1 = require("./commands/ls");
58
- const use_1 = require("./commands/use");
59
- const fetch_1 = require("./commands/fetch");
60
- const install_1 = require("./commands/install");
61
- const package_json_1 = __importDefault(require("../package.json"));
62
- const utils_1 = require("./utils");
63
- const cli = (0, cac_1.default)('chatbi-cli');
64
- // 打印漂亮的 Header
65
- const showHeader = () => {
66
- const title = figlet_1.default.textSync('ChatBI-V CLI', { font: 'Standard' });
67
- console.log(gradient_string_1.default.pastel.multiline(title));
68
- console.log((0, boxen_1.default)(picocolors_1.default.cyan(`ChatBI-V 统一开发工具 v${package_json_1.default.version}`), {
69
- padding: 0,
70
- margin: { top: 1, bottom: 1 },
71
- borderStyle: 'round',
72
- borderColor: 'cyan',
73
- title: 'CoreKit Enabled',
74
- titleAlignment: 'center'
75
- }));
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
76
15
  };
77
- /**
78
- * 包装命令 Action,统一错误处理
79
- */
80
- const wrapAction = (action, commandName) => {
81
- return async (...args) => {
82
- showHeader();
16
+
17
+ // ../../../chatbi-v/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js
18
+ import path from "path";
19
+ import { fileURLToPath } from "url";
20
+ var getFilename, getDirname, __dirname;
21
+ var init_esm_shims = __esm({
22
+ "../../../chatbi-v/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
23
+ "use strict";
24
+ getFilename = () => fileURLToPath(import.meta.url);
25
+ getDirname = () => path.dirname(getFilename());
26
+ __dirname = /* @__PURE__ */ getDirname();
27
+ }
28
+ });
29
+
30
+ // src/utils.ts
31
+ import path2 from "path";
32
+ import fs from "fs-extra";
33
+ import pc from "picocolors";
34
+ import ora from "ora";
35
+ import boxen from "boxen";
36
+ var _require, _dirname, logger, createSpinner, printBox, findPackageRoot, getCliRoot;
37
+ var init_utils = __esm({
38
+ "src/utils.ts"() {
39
+ "use strict";
40
+ init_esm_shims();
41
+ _require = __require;
42
+ _dirname = __dirname;
43
+ logger = {
44
+ info: (msg) => console.log(pc.cyan(`\u2139 ${msg}`)),
45
+ success: (msg) => console.log(pc.green(`\u2714 ${msg}`)),
46
+ warn: (msg) => console.log(pc.yellow(`\u26A0 ${msg}`)),
47
+ error: (msg, err) => {
48
+ console.error(pc.red(`
49
+ \u274C ${msg}`));
50
+ if (err) {
51
+ if (err instanceof Error) {
52
+ console.error(pc.gray(err.stack || err.message));
53
+ } else {
54
+ console.error(pc.gray(String(err)));
55
+ }
56
+ }
57
+ },
58
+ bold: (msg) => pc.bold(msg),
59
+ cyan: (msg) => pc.cyan(msg),
60
+ green: (msg) => pc.green(msg),
61
+ yellow: (msg) => pc.yellow(msg),
62
+ red: (msg) => pc.red(msg),
63
+ gray: (msg) => pc.gray(msg)
64
+ };
65
+ createSpinner = (msg) => ora({
66
+ text: pc.cyan(msg),
67
+ color: "cyan"
68
+ });
69
+ printBox = (msg, title, options = {}) => {
70
+ console.log("\n" + boxen(msg, {
71
+ padding: 1,
72
+ borderStyle: "round",
73
+ borderColor: "cyan",
74
+ title,
75
+ titleAlignment: "center",
76
+ ...options
77
+ }));
78
+ };
79
+ findPackageRoot = (pkgName) => {
80
+ try {
81
+ const pkgPath = _require.resolve(`${pkgName}/package.json`);
82
+ return path2.dirname(pkgPath);
83
+ } catch (e) {
84
+ if (pkgName === "@chatbi-v/cli") {
85
+ return path2.resolve(_dirname, "../../");
86
+ }
87
+ return null;
88
+ }
89
+ };
90
+ getCliRoot = async () => {
91
+ let myCliRoot = "";
92
+ let checkDir = _dirname;
93
+ while (checkDir !== path2.parse(checkDir).root) {
94
+ if (fs.existsSync(path2.join(checkDir, "package.json"))) {
95
+ const pkg = await fs.readJson(path2.join(checkDir, "package.json"));
96
+ if (pkg.name === "@chatbi-v/cli") {
97
+ myCliRoot = checkDir;
98
+ break;
99
+ }
100
+ }
101
+ checkDir = path2.dirname(checkDir);
102
+ }
103
+ if (!myCliRoot) {
104
+ myCliRoot = findPackageRoot("@chatbi-v/cli") || "";
105
+ }
106
+ return myCliRoot;
107
+ };
108
+ }
109
+ });
110
+
111
+ // src/constants.ts
112
+ import path3 from "path";
113
+ import os from "os";
114
+ var SANDBOX_CONFIG, GLOBAL_PATHS, DEPENDENCY_VERSIONS, DEFAULT_CONFIG;
115
+ var init_constants = __esm({
116
+ "src/constants.ts"() {
117
+ "use strict";
118
+ init_esm_shims();
119
+ SANDBOX_CONFIG = {
120
+ /** 用户主目录下的沙箱根目录名 */
121
+ BASE_NAME: ".chatbi-v-core",
122
+ /** 内部子目录结构 */
123
+ DIRS: {
124
+ VERSIONS: "versions",
125
+ CURRENT: "current",
126
+ CACHE: ".chatbi"
127
+ },
128
+ /** 关键标识文件 */
129
+ LOCK_FILE: ".chatbi-version"
130
+ };
131
+ GLOBAL_PATHS = {
132
+ /** 沙箱根路径 */
133
+ BASE_DIR: path3.join(os.homedir(), SANDBOX_CONFIG.BASE_NAME),
134
+ /** Monorepo 扫描目录 */
135
+ MONOREPO_ROOTS: ["apps", "plugins", "packages"]
136
+ };
137
+ DEPENDENCY_VERSIONS = {
138
+ // 基础框架
139
+ "react": "^18.3.1",
140
+ "react-dom": "^18.3.1",
141
+ "antd": "^5.20.0",
142
+ // 构建工具
143
+ "vite": "^5.0.8",
144
+ "typescript": "^5.3.3",
145
+ "tailwindcss": "^3.4.1",
146
+ "autoprefixer": "^10.4.17",
147
+ "postcss": "^8.4.35",
148
+ "less": "^4.2.0",
149
+ // 类型定义
150
+ "@types/react": "^18.3.1",
151
+ "@types/react-dom": "^18.3.1",
152
+ "@types/node": "^20.11.20",
153
+ "@vitejs/plugin-react": "^4.2.1"
154
+ };
155
+ DEFAULT_CONFIG = {
156
+ /** 支持的配置文件名 */
157
+ CONFIG_FILES: [
158
+ "chatbi.config.ts",
159
+ "chatbi.config.js",
160
+ "chatbi.config.json",
161
+ ".chatbirc"
162
+ ],
163
+ /** 默认 UI 主题 */
164
+ THEME: "standard"
165
+ };
166
+ }
167
+ });
168
+
169
+ // src/sandbox/SandboxPath.ts
170
+ import path4 from "path";
171
+ import fs2 from "fs-extra";
172
+ var SandboxPath;
173
+ var init_SandboxPath = __esm({
174
+ "src/sandbox/SandboxPath.ts"() {
175
+ "use strict";
176
+ init_esm_shims();
177
+ init_constants();
178
+ SandboxPath = class {
179
+ static {
180
+ /**
181
+ * 沙箱的基础存储目录,通常位于用户主目录下的 .chatbi-v-core
182
+ */
183
+ this.BASE_DIR = GLOBAL_PATHS.BASE_DIR;
184
+ }
185
+ /**
186
+ * 获取沙箱根目录
187
+ * @returns 沙箱根目录的绝对路径
188
+ */
189
+ static getRoot() {
190
+ return this.BASE_DIR;
191
+ }
192
+ /**
193
+ * 获取存储所有版本的根目录
194
+ * @returns versions 目录的绝对路径
195
+ */
196
+ static getVersionRoot() {
197
+ return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS);
198
+ }
199
+ /**
200
+ * 获取指定版本的沙箱路径
201
+ * @param version 版本号,或者 'current' 表示当前激活版本
202
+ * @returns 对应版本的绝对路径
203
+ */
204
+ static getVersionPath(version) {
205
+ if (version === SANDBOX_CONFIG.DIRS.CURRENT) {
206
+ return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS, SANDBOX_CONFIG.DIRS.CURRENT);
207
+ }
208
+ return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS, version);
209
+ }
210
+ /**
211
+ * 递归向上查找工作区根目录
212
+ * 识别标准:包含 pnpm-workspace.yaml 或 package.json 中定义了 workspaces
213
+ * @param cwd 起始查找目录
214
+ * @returns 查找到的工作区根目录路径,若未找到则返回 cwd
215
+ */
216
+ static async getWorkspaceRoot(cwd) {
217
+ let current = cwd;
218
+ while (current !== path4.parse(current).root) {
219
+ const pkgPath = path4.join(current, "package.json");
220
+ const pnpmWorkspacePath = path4.join(current, "pnpm-workspace.yaml");
221
+ if (fs2.existsSync(pnpmWorkspacePath)) return current;
222
+ if (fs2.existsSync(pkgPath)) {
223
+ try {
224
+ const pkg = await fs2.readJson(pkgPath);
225
+ if (pkg.workspaces) return current;
226
+ } catch (e) {
227
+ }
228
+ }
229
+ current = path4.dirname(current);
230
+ }
231
+ return cwd;
232
+ }
233
+ };
234
+ }
235
+ });
236
+
237
+ // src/sandbox/SandboxRenderer.ts
238
+ import fs3 from "fs-extra";
239
+ import path5 from "path";
240
+ import Handlebars from "handlebars";
241
+ var SandboxRenderer;
242
+ var init_SandboxRenderer = __esm({
243
+ "src/sandbox/SandboxRenderer.ts"() {
244
+ "use strict";
245
+ init_esm_shims();
246
+ Handlebars.registerHelper("json", (obj) => JSON.stringify(obj, null, 2));
247
+ Handlebars.registerHelper("eq", (a, b) => a === b);
248
+ SandboxRenderer = class {
249
+ static {
250
+ /**
251
+ * 需要转义的模板关键字列表
252
+ * 只有匹配这些关键字的 {{ }} 才会被 Handlebars 处理,其余(如 React 的 {{ style }})将被转义跳过
253
+ */
254
+ this.TEMPLATE_KEYWORDS = [
255
+ "name",
256
+ "version",
257
+ "projectName",
258
+ "projectTitle",
259
+ "projectVersion",
260
+ "cliVersion",
261
+ "tsconfigPath",
262
+ "theme",
263
+ "isNebula",
264
+ "isGlass",
265
+ "isBusiness",
266
+ "isApp",
267
+ "isShell",
268
+ "pluginName",
269
+ "pluginPackageName",
270
+ "pluginVersion",
271
+ "pluginDisplayName",
272
+ "pluginDescription",
273
+ "pluginClassName",
274
+ "pluginPath",
275
+ "pluginFolderName",
276
+ "pluginType",
277
+ "pluginId",
278
+ "className",
279
+ "dependencies",
280
+ "devDependencies",
281
+ "json"
282
+ ];
283
+ }
284
+ /**
285
+ * 递归渲染目录模板
286
+ * @param srcDir 模板源目录
287
+ * @param destDir 目标输出目录
288
+ * @param data 渲染模板所需的变量上下文
289
+ */
290
+ static async renderDirectory(srcDir, destDir, data) {
291
+ if (!fs3.existsSync(srcDir)) return;
292
+ const entries = await fs3.readdir(srcDir, { withFileTypes: true });
293
+ for (const entry of entries) {
294
+ const srcPath = path5.join(srcDir, entry.name);
295
+ const destPath = path5.join(destDir, entry.name.replace(/\.hbs$/, ""));
296
+ if (entry.isDirectory()) {
297
+ await fs3.ensureDir(destPath);
298
+ await this.renderDirectory(srcPath, destPath, data);
299
+ } else {
300
+ await this.renderFile(srcPath, destPath, data);
301
+ }
302
+ }
303
+ }
304
+ /**
305
+ * 渲染单个文件
306
+ */
307
+ static async renderFile(srcPath, destPath, data) {
308
+ const isTemplate = srcPath.endsWith(".hbs");
309
+ if (!isTemplate) {
310
+ await fs3.copy(srcPath, destPath);
311
+ return;
312
+ }
313
+ const content = await fs3.readFile(srcPath, "utf-8");
314
+ if (!content.includes("{{")) {
315
+ await fs3.outputFile(destPath, content);
316
+ return;
317
+ }
83
318
  try {
84
- await action(...args);
319
+ const keywordsPattern = this.TEMPLATE_KEYWORDS.join("|");
320
+ const safeContent = content.replace(
321
+ new RegExp(`\\{\\{(?!\\{)(?!\\s*([#/]?(?:${keywordsPattern}))\\b)`, "g"),
322
+ "\\{{"
323
+ );
324
+ const template = Handlebars.compile(safeContent);
325
+ const result = template(data);
326
+ await fs3.outputFile(destPath, result);
327
+ } catch (e) {
328
+ let result = content;
329
+ for (const [key, val] of Object.entries(data)) {
330
+ const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, "g");
331
+ result = result.replace(regex, typeof val === "object" ? JSON.stringify(val) : String(val));
332
+ }
333
+ await fs3.outputFile(destPath, result);
85
334
  }
86
- catch (e) {
87
- utils_1.logger.error(`${commandName} 执行失败`, e);
88
- process.exit(1);
335
+ }
336
+ };
337
+ }
338
+ });
339
+
340
+ // src/sandbox/SandboxContext.ts
341
+ import fs4 from "fs-extra";
342
+ import path6 from "path";
343
+ var SandboxContext;
344
+ var init_SandboxContext = __esm({
345
+ "src/sandbox/SandboxContext.ts"() {
346
+ "use strict";
347
+ init_esm_shims();
348
+ init_SandboxPath();
349
+ init_constants();
350
+ SandboxContext = class {
351
+ /**
352
+ * 注入项目虚拟上下文
353
+ * 包括:
354
+ * 1. 确定集中式 .chatbi 存放位置并处理子包软链
355
+ * 2. 生成适配沙箱的 tsconfig.json (配置路径别名)
356
+ * 3. 软链接沙箱的 node_modules 到项目 .chatbi 目录下
357
+ * 4. 确保 .chatbi 被加入 .gitignore
358
+ *
359
+ * @param projectRoot 当前项目根目录
360
+ * @param version 内核版本号
361
+ * @param corePackages 核心包名列表
362
+ * @param runtimeDeps 运行时依赖包名列表
363
+ */
364
+ static async inject(projectRoot, version, corePackages, runtimeDeps) {
365
+ const workspaceRoot = await SandboxPath.getWorkspaceRoot(projectRoot);
366
+ const chatbiDir = path6.join(workspaceRoot, SANDBOX_CONFIG.DIRS.CACHE);
367
+ await fs4.ensureDir(chatbiDir);
368
+ if (workspaceRoot !== projectRoot) {
369
+ const localChatbi = path6.join(projectRoot, SANDBOX_CONFIG.DIRS.CACHE);
370
+ try {
371
+ const stats = await fs4.lstat(localChatbi).catch(() => null);
372
+ if (stats) {
373
+ if (stats.isSymbolicLink()) {
374
+ const linkTarget = await fs4.readlink(localChatbi);
375
+ if (linkTarget !== chatbiDir) {
376
+ await fs4.remove(localChatbi);
377
+ await fs4.symlink(chatbiDir, localChatbi, "dir");
378
+ }
379
+ } else {
380
+ await fs4.remove(localChatbi);
381
+ await fs4.symlink(chatbiDir, localChatbi, "dir");
382
+ }
383
+ } else {
384
+ await fs4.symlink(chatbiDir, localChatbi, "dir");
385
+ }
386
+ } catch (e) {
387
+ }
388
+ }
389
+ const versionPath = SandboxPath.getVersionPath(version);
390
+ const sandboxNodeModules = path6.join(versionPath, "node_modules");
391
+ const corePaths = {};
392
+ for (const pkgName of corePackages) {
393
+ corePaths[pkgName] = [`./node_modules/${pkgName}`];
394
+ corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
89
395
  }
396
+ for (const pkgName of runtimeDeps) {
397
+ corePaths[pkgName] = [`./node_modules/${pkgName}`];
398
+ corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
399
+ if (["react", "react-dom", "node"].includes(pkgName)) {
400
+ const typeName = pkgName === "node" ? "node" : pkgName;
401
+ corePaths[`@types/${typeName}`] = [`./node_modules/@types/${typeName}`];
402
+ corePaths[`@types/${typeName}/*`] = [`./node_modules/@types/${typeName}/*`];
403
+ }
404
+ }
405
+ corePaths["@types/*"] = ["./node_modules/@types/*"];
406
+ corePaths["vite/client"] = ["./node_modules/vite/client.d.ts"];
407
+ const baseConfigPath = path6.join(sandboxNodeModules, "@chatbi-v/tsconfig/base.json");
408
+ const tsConfig = {
409
+ extends: baseConfigPath,
410
+ compilerOptions: {
411
+ baseUrl: ".",
412
+ moduleResolution: "bundler",
413
+ skipLibCheck: true,
414
+ typeRoots: ["./node_modules/@types"],
415
+ preserveSymlinks: true,
416
+ paths: {
417
+ ...corePaths,
418
+ "@/*": ["../src/*"],
419
+ "*": ["./node_modules/*"]
420
+ }
421
+ }
422
+ };
423
+ await fs4.writeJson(path6.join(chatbiDir, "tsconfig.json"), tsConfig, { spaces: 2 });
424
+ await fs4.writeJson(path6.join(chatbiDir, "tsconfig.paths.json"), { compilerOptions: tsConfig.compilerOptions }, { spaces: 2 });
425
+ const virtualNodeModules = path6.join(chatbiDir, "node_modules");
426
+ if (fs4.existsSync(sandboxNodeModules)) {
427
+ try {
428
+ await fs4.remove(virtualNodeModules).catch(() => {
429
+ });
430
+ await fs4.ensureSymlink(sandboxNodeModules, virtualNodeModules, "dir");
431
+ } catch (e) {
432
+ }
433
+ }
434
+ const gitignorePath = path6.join(workspaceRoot, ".gitignore");
435
+ if (fs4.existsSync(gitignorePath)) {
436
+ let content = await fs4.readFile(gitignorePath, "utf-8");
437
+ if (!content.includes(SANDBOX_CONFIG.DIRS.CACHE)) {
438
+ await fs4.appendFile(gitignorePath, `
439
+ # ChatBI
440
+ ${SANDBOX_CONFIG.DIRS.CACHE}
441
+ `);
442
+ }
443
+ }
444
+ }
90
445
  };
91
- };
92
- cli
93
- .command('dev', '启动开发服务器')
94
- .alias('d')
95
- .option('--port <port>', '端口号')
96
- .action(wrapAction(dev_1.dev, 'dev'));
97
- cli
98
- .command('build', '构建当前项目')
99
- .alias('b')
100
- .option('--watch', '开启监听模式')
101
- .action(wrapAction(build_1.build, 'build'));
102
- cli
103
- .command('fetch <version>', '获取指定版本的内核 (支持打包)')
104
- .option('--pack', '打包为离线安装包 (.tgz)')
105
- .action(wrapAction(fetch_1.fetch, 'fetch'));
106
- cli
107
- .command('install <target>', '安装内核 (支持版本号或离线包路径)')
108
- .action(wrapAction(install_1.install, 'install'));
109
- cli
110
- .command('init [name]', '初始化一个新的业务插件项目')
111
- .alias('create')
112
- .alias('i')
113
- .option('--project-type <type>', '项目类型 (monorepo | app | plugin)')
114
- .option('--include-app', 'Monorepo 中包含 App')
115
- .option('--no-include-app', 'Monorepo 中不包含 App')
116
- .option('--include-plugin', 'Monorepo 中包含 Plugin')
117
- .option('--no-include-plugin', 'Monorepo 中不包含 Plugin')
118
- .option('--plugin-type <type>', '插件类型 (business | system)')
119
- .option('--theme <theme>', '主题 (standard | nebula | glass)')
120
- .action(wrapAction(async (name, options) => {
121
- await (0, init_1.init)({
122
- name,
123
- projectType: options.projectType,
124
- includeApp: options.includeApp,
125
- includePlugin: options.includePlugin,
126
- pluginType: options.pluginType,
127
- theme: options.theme
446
+ }
447
+ });
448
+
449
+ // src/sandbox/SandboxPkgManager.ts
450
+ import fs5 from "fs-extra";
451
+ import path7 from "path";
452
+ import pc2 from "picocolors";
453
+ import fg from "fast-glob";
454
+ var SandboxPkgManager;
455
+ var init_SandboxPkgManager = __esm({
456
+ "src/sandbox/SandboxPkgManager.ts"() {
457
+ "use strict";
458
+ init_esm_shims();
459
+ init_utils();
460
+ init_SandboxPath();
461
+ SandboxPkgManager = class {
462
+ /**
463
+ * 尝试将本地开发环境的包 Link 到沙箱中 (模拟安装)
464
+ * 用于 Monorepo 场景下,让沙箱直接使用最新的本地源码
465
+ * @param versionPath 沙箱版本的存储路径
466
+ * @param corePackages 核心包名列表
467
+ * @param runtimeDeps 运行时依赖包名列表
468
+ * @returns 是否成功 Link 了至少一个包
469
+ */
470
+ static async tryLinkLocalPackages(versionPath, corePackages, runtimeDeps) {
471
+ try {
472
+ const cliRoot = await getCliRoot();
473
+ const projectRoot = await SandboxPath.getWorkspaceRoot(cliRoot);
474
+ if (projectRoot === cliRoot && !fs5.existsSync(path7.join(projectRoot, "pnpm-workspace.yaml"))) {
475
+ return false;
476
+ }
477
+ const possiblePackagesDirs = [
478
+ path7.join(projectRoot, "packages"),
479
+ // 兼容旧版或其他可能的路径结构
480
+ path7.resolve(projectRoot, "../chatbi-v/packages")
481
+ ];
482
+ const localPackages = {};
483
+ const patterns = possiblePackagesDirs.filter((dir) => fs5.existsSync(dir)).map((dir) => path7.join(dir, "**/package.json"));
484
+ if (patterns.length > 0) {
485
+ const pkgJsonFiles = await fg(patterns, {
486
+ ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
487
+ absolute: true,
488
+ deep: 5
489
+ });
490
+ for (const pkgJsonPath of pkgJsonFiles) {
491
+ try {
492
+ const pkgJson = await fs5.readJson(pkgJsonPath);
493
+ if (corePackages.includes(pkgJson.name) || runtimeDeps.includes(pkgJson.name)) {
494
+ localPackages[pkgJson.name] = path7.dirname(pkgJsonPath);
495
+ }
496
+ } catch (e) {
497
+ }
498
+ }
499
+ }
500
+ if (Object.keys(localPackages).length === 0) return false;
501
+ const linkSummary = Object.entries(localPackages).map(([name, pkgPath]) => `${pc2.cyan(name.padEnd(30))} -> ${pc2.gray(pkgPath)}`).join("\n");
502
+ printBox(
503
+ pc2.green("\u{1F517} \u5DF2\u68C0\u6D4B\u5230\u672C\u5730\u5F00\u53D1\u73AF\u5883\uFF0C\u5C06\u94FE\u63A5\u4EE5\u4E0B\u6838\u5FC3\u5305\uFF1A\n\n") + linkSummary,
504
+ "Monorepo Link Mode"
505
+ );
506
+ const sandboxNodeModules = path7.join(versionPath, "node_modules");
507
+ await fs5.ensureDir(sandboxNodeModules);
508
+ for (const [name, pkgPath] of Object.entries(localPackages)) {
509
+ const targetLinkPath = path7.join(sandboxNodeModules, name);
510
+ await fs5.ensureDir(path7.dirname(targetLinkPath));
511
+ try {
512
+ const stats = await fs5.lstat(targetLinkPath).catch(() => null);
513
+ if (stats) await fs5.remove(targetLinkPath);
514
+ } catch (e) {
515
+ }
516
+ await fs5.symlink(pkgPath, targetLinkPath, "dir");
517
+ }
518
+ const sandboxPkgJsonPath = path7.join(versionPath, "package.json");
519
+ const sandboxPkgJson = await fs5.readJson(sandboxPkgJsonPath);
520
+ const sections = ["dependencies", "devDependencies"];
521
+ let modified = false;
522
+ for (const section of sections) {
523
+ if (sandboxPkgJson[section]) {
524
+ for (const [name, pkgPath] of Object.entries(localPackages)) {
525
+ if (sandboxPkgJson[section][name]) {
526
+ sandboxPkgJson[section][name] = `link:${pkgPath}`;
527
+ modified = true;
528
+ }
529
+ }
530
+ }
531
+ }
532
+ if (modified) await fs5.writeJson(sandboxPkgJsonPath, sandboxPkgJson, { spaces: 2 });
533
+ return true;
534
+ } catch (e) {
535
+ console.warn(pc2.yellow(` \u26A0\uFE0F Link \u672C\u5730\u6E90\u7801\u5931\u8D25\uFF0C\u5C06\u5C1D\u8BD5\u4ECE NPM \u5B89\u88C5: ${e.message}`));
536
+ return false;
537
+ }
538
+ }
539
+ };
540
+ }
541
+ });
542
+
543
+ // src/sandbox.ts
544
+ import fs6 from "fs-extra";
545
+ import path8 from "path";
546
+ import pc3 from "picocolors";
547
+ import fg2 from "fast-glob";
548
+ import { execa } from "execa";
549
+ var Sandbox;
550
+ var init_sandbox = __esm({
551
+ "src/sandbox.ts"() {
552
+ "use strict";
553
+ init_esm_shims();
554
+ init_utils();
555
+ init_SandboxPath();
556
+ init_SandboxRenderer();
557
+ init_SandboxContext();
558
+ init_SandboxPkgManager();
559
+ init_constants();
560
+ Sandbox = class {
561
+ static {
562
+ /** 核心源码包列表 */
563
+ this.CORE_PACKAGES = [
564
+ "@chatbi-v/core",
565
+ "@chatbi-v/mocks",
566
+ "@chatbi-v/tsconfig",
567
+ "@chatbi-v/tailwind-config",
568
+ "@chatbi-v/plugin-theme-manager",
569
+ "@chatbi-v/plugin-layout-transform",
570
+ "@chatbi-v/plugin-system-monitor"
571
+ ];
572
+ }
573
+ static {
574
+ /** 运行时必须依赖 */
575
+ this.RUNTIME_DEPS = [
576
+ "@ant-design/x",
577
+ "@ant-design/icons",
578
+ "antd",
579
+ "react",
580
+ "react-dom",
581
+ "lucide-react",
582
+ "framer-motion",
583
+ "clsx",
584
+ "tailwind-merge",
585
+ "react-router-dom",
586
+ "zustand",
587
+ "axios",
588
+ "less",
589
+ "vite"
590
+ ];
591
+ }
592
+ /** 获取沙箱根目录 */
593
+ static getRoot() {
594
+ return SandboxPath.getRoot();
595
+ }
596
+ /** 获取所有版本的根目录 */
597
+ static getVersionRoot() {
598
+ return SandboxPath.getVersionRoot();
599
+ }
600
+ /** 获取指定版本的沙箱路径 */
601
+ static getVersionPath(version) {
602
+ return SandboxPath.getVersionPath(version);
603
+ }
604
+ /** 获取项目的工作区根目录 (Monorepo 支持) */
605
+ static async getWorkspaceRoot(cwd) {
606
+ return SandboxPath.getWorkspaceRoot(cwd);
607
+ }
608
+ /** 清理指定版本的沙箱物理文件 */
609
+ static async cleanVersion(version) {
610
+ const versionPath = this.getVersionPath(version);
611
+ if (fs6.existsSync(versionPath)) {
612
+ await fs6.remove(versionPath);
613
+ }
614
+ }
615
+ /**
616
+ * 优雅清理缓存环境
617
+ * @param cwd 当前项目路径
618
+ * @param deep 是否执行深度清理
619
+ */
620
+ static async clean(cwd, deep = false) {
621
+ const spinner = createSpinner("\u6B63\u5728\u6E05\u7406\u7F13\u5B58\u76EE\u5F55...").start();
622
+ try {
623
+ const workspaceRoot = await this.getWorkspaceRoot(cwd);
624
+ let cleanedCount = 0;
625
+ const cachePatterns = [
626
+ path8.join(workspaceRoot, `**/${SANDBOX_CONFIG.DIRS.CACHE}`)
627
+ ];
628
+ const cacheDirs = await fg2(cachePatterns, {
629
+ onlyFiles: false,
630
+ // 允许匹配文件和符号链接
631
+ absolute: true,
632
+ ignore: ["**/node_modules/**"],
633
+ dot: true
634
+ // 确保能匹配到以 . 开头的目录
635
+ });
636
+ for (const dir of cacheDirs) {
637
+ const stats = await fs6.lstat(dir).catch(() => null);
638
+ if (stats) {
639
+ await fs6.remove(dir);
640
+ cleanedCount++;
641
+ }
642
+ }
643
+ if (deep) {
644
+ const distPatterns = [
645
+ path8.join(workspaceRoot, "**/dist")
646
+ ];
647
+ const distDirs = await fg2(distPatterns, {
648
+ onlyFiles: false,
649
+ absolute: true,
650
+ ignore: [
651
+ "**/node_modules/**",
652
+ "**/packages/cli/dist/**",
653
+ // 保护 CLI 自身构建产物
654
+ "**/.git/**"
655
+ ]
656
+ });
657
+ for (const dir of distDirs) {
658
+ const stats = await fs6.lstat(dir).catch(() => null);
659
+ if (stats) {
660
+ const hasPkg = fs6.existsSync(path8.join(path8.dirname(dir), "package.json"));
661
+ if (hasPkg) {
662
+ await fs6.remove(dir);
663
+ cleanedCount++;
664
+ }
665
+ }
666
+ }
667
+ const globalRoot = this.getRoot();
668
+ if (fs6.existsSync(globalRoot)) {
669
+ await fs6.remove(globalRoot);
670
+ cleanedCount++;
671
+ }
672
+ }
673
+ spinner.succeed(pc3.green(`\u6E05\u7406\u5B8C\u6210\uFF0C\u5171\u6E05\u7406 ${cleanedCount} \u4E2A\u9879\u76EE/\u7F13\u5B58\u76EE\u5F55`));
674
+ } catch (e) {
675
+ spinner.fail(pc3.red(`\u6E05\u7406\u5931\u8D25: ${e.message}`));
676
+ }
677
+ }
678
+ /**
679
+ * 准备内核沙箱环境 (安装/更新)
680
+ */
681
+ static async prepare(version, force = false) {
682
+ const versionPath = this.getVersionPath(version);
683
+ if (!force && fs6.existsSync(path8.join(versionPath, "node_modules/tailwindcss"))) {
684
+ return versionPath;
685
+ }
686
+ if (fs6.existsSync(versionPath)) {
687
+ await fs6.remove(path8.join(versionPath, "node_modules"));
688
+ }
689
+ await fs6.ensureDir(versionPath);
690
+ const spinner = createSpinner(`\u6B63\u5728\u521D\u59CB\u5316\u5185\u6838\u6C99\u7BB1 ${pc3.cyan(version)}...`).start();
691
+ try {
692
+ const cliRoot = await getCliRoot();
693
+ const dependencies = {};
694
+ for (const pkg of this.RUNTIME_DEPS) {
695
+ dependencies[pkg] = DEPENDENCY_VERSIONS[pkg] || "latest";
696
+ }
697
+ for (const pkg of this.CORE_PACKAGES) {
698
+ dependencies[pkg] = pkg === "@chatbi-v/core" ? version : "latest";
699
+ }
700
+ const templateData = {
701
+ version,
702
+ dependencies,
703
+ devDependencies: DEPENDENCY_VERSIONS
704
+ };
705
+ await SandboxRenderer.renderDirectory(
706
+ path8.join(cliRoot, "templates/sandbox"),
707
+ versionPath,
708
+ templateData
709
+ );
710
+ spinner.text = pc3.gray(" \u{1F50D} \u68C0\u67E5\u672C\u5730\u5F00\u53D1\u73AF\u5883...");
711
+ const isLocalDev = await SandboxPkgManager.tryLinkLocalPackages(versionPath, this.CORE_PACKAGES, this.RUNTIME_DEPS);
712
+ const installArgs = isLocalDev ? ["install", "--no-frozen-lockfile"] : ["install"];
713
+ spinner.text = pc3.gray(` \u23F3 \u6267\u884C pnpm ${installArgs.join(" ")}...`);
714
+ await execa("pnpm", installArgs, { cwd: versionPath });
715
+ spinner.text = pc3.gray(" \u{1F3A8} \u540C\u6B65 Shell \u6A21\u677F...");
716
+ await this.ensureShell(version, force);
717
+ spinner.succeed(pc3.green(`\u5185\u6838\u6C99\u7BB1 ${version} \u521D\u59CB\u5316\u6210\u529F`));
718
+ } catch (e) {
719
+ spinner.fail(pc3.red(`\u5185\u6838\u6C99\u7BB1\u521D\u59CB\u5316\u5931\u8D25: ${e.message}`));
720
+ throw e;
721
+ }
722
+ return versionPath;
723
+ }
724
+ /**
725
+ * 确保 Shell 模板已同步到沙箱
726
+ */
727
+ static async ensureShell(version, force = false) {
728
+ const versionPath = this.getVersionPath(version);
729
+ const shellDestDir = path8.join(versionPath, "shell");
730
+ if (!force && fs6.existsSync(path8.join(shellDestDir, "tsconfig.paths.json"))) {
731
+ return shellDestDir;
732
+ }
733
+ const cliRoot = await getCliRoot();
734
+ const shellTemplateDir = path8.join(cliRoot, "templates/app");
735
+ if (fs6.existsSync(shellTemplateDir)) {
736
+ await fs6.remove(shellDestDir);
737
+ const templateData = {
738
+ name: "chatbi-shell",
739
+ version,
740
+ cliVersion: version,
741
+ theme: DEFAULT_CONFIG.THEME,
742
+ isShell: true,
743
+ isBusiness: true,
744
+ tsconfigPath: "./tsconfig.paths.json"
745
+ };
746
+ await SandboxRenderer.renderDirectory(shellTemplateDir, shellDestDir, templateData);
747
+ await fs6.writeJson(path8.join(shellDestDir, "tsconfig.paths.json"), {
748
+ compilerOptions: { baseUrl: ".", paths: { "@/*": ["./src/*"] } }
749
+ }, { spaces: 2 });
750
+ }
751
+ return shellDestDir;
752
+ }
753
+ /** 注入项目虚拟上下文 */
754
+ static async injectContext(projectRoot, version) {
755
+ return SandboxContext.inject(projectRoot, version, this.CORE_PACKAGES, this.RUNTIME_DEPS);
756
+ }
757
+ /** 获取核心库的 Vite Alias 配置 */
758
+ static getCoreAlias(version) {
759
+ const versionPath = this.getVersionPath(version);
760
+ const sandboxNodeModules = path8.join(versionPath, "node_modules");
761
+ return Object.fromEntries(this.CORE_PACKAGES.map((pkg) => [pkg, path8.join(sandboxNodeModules, pkg)]));
762
+ }
763
+ /** 切换内核版本 */
764
+ static async useVersion(version) {
765
+ const versionRoot = this.getVersionRoot();
766
+ const currentLink = path8.join(versionRoot, SANDBOX_CONFIG.DIRS.CURRENT);
767
+ const targetPath = this.getVersionPath(version);
768
+ if (!fs6.existsSync(targetPath)) throw new Error(`\u7248\u672C ${version} \u4E0D\u5B58\u5728`);
769
+ if (fs6.existsSync(currentLink)) await fs6.remove(currentLink);
770
+ await fs6.ensureSymlink(targetPath, currentLink, "dir");
771
+ }
772
+ /** 解析版本号 */
773
+ static async resolveVersion(version) {
774
+ if (!version || version === "latest" || version === "current") {
775
+ const currentLink = path8.join(this.getVersionRoot(), SANDBOX_CONFIG.DIRS.CURRENT);
776
+ if (fs6.existsSync(currentLink)) {
777
+ return path8.basename(await fs6.readlink(currentLink));
778
+ }
779
+ const versions = await this.listVersions();
780
+ return versions[0] || "1.0.0";
781
+ }
782
+ return version;
783
+ }
784
+ /** 列出所有已安装版本 */
785
+ static async listVersions() {
786
+ const versionRoot = this.getVersionRoot();
787
+ if (!fs6.existsSync(versionRoot)) return [];
788
+ const dirs = await fs6.readdir(versionRoot);
789
+ return dirs.filter((d) => d !== SANDBOX_CONFIG.DIRS.CURRENT && !d.startsWith(".")).sort().reverse();
790
+ }
791
+ /** 可视化展示沙箱状态 */
792
+ static async visualizeStatus(cwd) {
793
+ const workspaceRoot = await this.getWorkspaceRoot(cwd);
794
+ const isMonorepo = workspaceRoot !== cwd;
795
+ const currentVersion = await this.resolveVersion("current");
796
+ const versions = await this.listVersions();
797
+ const statusInfo = [
798
+ `${pc3.bold("\u9879\u76EE\u8DEF\u5F84:")} ${pc3.cyan(cwd)}`,
799
+ `${pc3.bold("\u67B6\u6784\u6A21\u5F0F:")} ${isMonorepo ? pc3.yellow("Monorepo") : pc3.green("Standalone")}`,
800
+ `${pc3.bold("\u5F53\u524D\u5185\u6838:")} ${pc3.green(currentVersion)}`,
801
+ `${pc3.bold("\u5DF2\u88C5\u7248\u672C:")} ${pc3.gray(versions.join(", ") || "none")}`,
802
+ `${pc3.bold("\u6C99\u7BB1\u6839\u76EE\u5F55:")} ${pc3.gray(this.getRoot())}`
803
+ ].join("\n");
804
+ printBox(statusInfo, "ChatBI Sandbox Status");
805
+ }
806
+ };
807
+ }
808
+ });
809
+
810
+ // src/config.ts
811
+ import fs7 from "fs-extra";
812
+ import path9 from "path";
813
+ import { createJiti } from "jiti";
814
+ var ConfigManager;
815
+ var init_config = __esm({
816
+ "src/config.ts"() {
817
+ "use strict";
818
+ init_esm_shims();
819
+ init_utils();
820
+ init_constants();
821
+ init_utils();
822
+ ConfigManager = class {
823
+ static {
824
+ this.CONFIG_FILES = DEFAULT_CONFIG.CONFIG_FILES;
825
+ }
826
+ /**
827
+ * 加载项目配置
828
+ * @param cwd 项目根目录
829
+ */
830
+ static async loadConfig(cwd = process.cwd()) {
831
+ const config = {};
832
+ const versionFilePath = path9.join(cwd, SANDBOX_CONFIG.LOCK_FILE);
833
+ if (fs7.existsSync(versionFilePath)) {
834
+ try {
835
+ const version = (await fs7.readFile(versionFilePath, "utf-8")).trim();
836
+ if (version) {
837
+ config.coreVersion = version;
838
+ }
839
+ } catch (e) {
840
+ }
841
+ }
842
+ const jiti = createJiti(cwd);
843
+ for (const file of this.CONFIG_FILES) {
844
+ const configPath = path9.join(cwd, file);
845
+ if (fs7.existsSync(configPath)) {
846
+ try {
847
+ let projectConfig = {};
848
+ if (file.endsWith(".ts") || file.endsWith(".js")) {
849
+ const mod = await jiti.import(configPath, { default: true });
850
+ projectConfig = mod.default || mod || {};
851
+ } else if (file.endsWith(".json") || file.startsWith(".chatbirc")) {
852
+ projectConfig = await fs7.readJson(configPath);
853
+ }
854
+ return {
855
+ ...projectConfig,
856
+ ...config
857
+ };
858
+ } catch (e) {
859
+ logger.error(`\u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6 ${file} \u5931\u8D25`, e);
860
+ }
861
+ }
862
+ }
863
+ return config;
864
+ }
865
+ /**
866
+ * 解析核心依赖的具体路径或版本号
867
+ * @param config 项目配置
868
+ * @param relativeTo 相对路径(用于 local 模式下的 file: 协议生成)
869
+ */
870
+ static async resolveCoreDependency(config, relativeTo = ".") {
871
+ const { coreSource = "local", coreVersion } = config;
872
+ if (coreSource === "npm") {
873
+ if (coreVersion) return coreVersion;
874
+ const cliRoot = await getCliRoot();
875
+ const cliPkg = await fs7.readJson(path9.join(cliRoot, "package.json"));
876
+ return cliPkg.version;
877
+ }
878
+ const sandboxCorePath = path9.join(SANDBOX_CONFIG.DIRS.CACHE, "core");
879
+ const cwd = process.cwd();
880
+ const absoluteRelativeTo = path9.isAbsolute(relativeTo) ? relativeTo : path9.resolve(cwd, relativeTo);
881
+ const absoluteProjectRoot = cwd;
882
+ const relativePath = path9.relative(absoluteRelativeTo, path9.join(absoluteProjectRoot, sandboxCorePath));
883
+ return `file:${relativePath}`;
884
+ }
885
+ /**
886
+ * 加载 tsup 配置
887
+ * @param cwd 项目根目录
888
+ */
889
+ static async loadTsupConfig(cwd = process.cwd()) {
890
+ const TSUP_CONFIG_FILES = [
891
+ "tsup.config.ts",
892
+ "tsup.config.js",
893
+ "tsup.config.cjs",
894
+ "tsup.config.mjs",
895
+ "tsup.config.json"
896
+ ];
897
+ const jiti = createJiti(cwd);
898
+ for (const file of TSUP_CONFIG_FILES) {
899
+ const configPath = path9.join(cwd, file);
900
+ if (fs7.existsSync(configPath)) {
901
+ try {
902
+ if (file.endsWith(".json")) {
903
+ return await fs7.readJson(configPath);
904
+ } else {
905
+ const mod = await jiti.import(configPath, { default: true });
906
+ return mod.default || mod || {};
907
+ }
908
+ } catch (e) {
909
+ logger.warn(`\u52A0\u8F7D tsup \u914D\u7F6E\u6587\u4EF6 ${file} \u5931\u8D25: ${e.message}`);
910
+ }
911
+ }
912
+ }
913
+ const pkgPath = path9.join(cwd, "package.json");
914
+ if (fs7.existsSync(pkgPath)) {
915
+ try {
916
+ const pkg = await fs7.readJson(pkgPath);
917
+ if (pkg.tsup) {
918
+ return pkg.tsup;
919
+ }
920
+ } catch (e) {
921
+ }
922
+ }
923
+ return {};
924
+ }
925
+ };
926
+ }
927
+ });
928
+
929
+ // src/corekit.ts
930
+ import path10 from "path";
931
+ import fs8 from "fs-extra";
932
+ import pc4 from "picocolors";
933
+ import prompts from "prompts";
934
+ import fg3 from "fast-glob";
935
+ var CoreKit;
936
+ var init_corekit = __esm({
937
+ "src/corekit.ts"() {
938
+ "use strict";
939
+ init_esm_shims();
940
+ init_utils();
941
+ init_sandbox();
942
+ init_config();
943
+ CoreKit = class {
944
+ /**
945
+ * 解析项目模式
946
+ */
947
+ static async detectMode(cwd) {
948
+ const pkgPath = path10.join(cwd, "package.json");
949
+ if (!fs8.existsSync(pkgPath)) return "app";
950
+ const pkg = await fs8.readJson(pkgPath);
951
+ if (pkg.workspaces || fs8.existsSync(path10.join(cwd, "pnpm-workspace.yaml"))) {
952
+ return "monorepo";
953
+ }
954
+ if (pkg.chatbi?.type === "plugin" || pkg.plugin === true) return "plugin";
955
+ if (pkg.chatbi?.type === "app") return "app";
956
+ const pluginEntries = await fg3(["index.plugin.{ts,js}", "src/index.plugin.{ts,js}"], { cwd });
957
+ if (pluginEntries.length > 0) return "plugin";
958
+ if (fs8.existsSync(path10.join(cwd, "index.html"))) {
959
+ return "app";
960
+ }
961
+ if (fs8.existsSync(path10.join(cwd, "src/index.ts")) || fs8.existsSync(path10.join(cwd, "src/index.tsx"))) {
962
+ if (pkg.bin) return "lib";
963
+ if (pkg.peerDependencies?.react && !pkg.dependencies?.react) return "plugin";
964
+ return "lib";
965
+ }
966
+ return "app";
967
+ }
968
+ /**
969
+ * 获取当前生效的内核版本
970
+ * 优先序:项目配置 > 全局 current 软链 > 最新安装的版本
971
+ */
972
+ static async resolveVersion(projectRoot) {
973
+ if (projectRoot) {
974
+ const config = await ConfigManager.loadConfig(projectRoot);
975
+ if (config.coreVersion) return config.coreVersion;
976
+ }
977
+ try {
978
+ const cliRoot = await getCliRoot();
979
+ const cliVersionFile = path10.join(cliRoot, ".chatbi-version");
980
+ if (fs8.existsSync(cliVersionFile)) {
981
+ const version = (await fs8.readFile(cliVersionFile, "utf-8")).trim();
982
+ if (version) return version;
983
+ }
984
+ } catch (e) {
985
+ }
986
+ const currentLinkPath = path10.join(Sandbox.getVersionRoot(), "current");
987
+ if (fs8.existsSync(currentLinkPath)) {
988
+ try {
989
+ const realPath = await fs8.realpath(currentLinkPath);
990
+ return path10.basename(realPath);
991
+ } catch (e) {
992
+ }
993
+ }
994
+ const versions = await this.listVersions();
995
+ return versions[0] || "latest";
996
+ }
997
+ /**
998
+ * 列出所有已安装版本
999
+ */
1000
+ static async listVersions() {
1001
+ const versionsDir = Sandbox.getVersionRoot();
1002
+ if (!fs8.existsSync(versionsDir)) return [];
1003
+ const dirs = await fg3("*", {
1004
+ cwd: versionsDir,
1005
+ onlyDirectories: true,
1006
+ deep: 1
1007
+ });
1008
+ return dirs.filter((d) => d !== "current").sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
1009
+ }
1010
+ /**
1011
+ * 自动发现项目中的插件
1012
+ */
1013
+ static async discoverPlugins(rootDir) {
1014
+ const pluginsDir = path10.join(rootDir, "plugins");
1015
+ if (!fs8.existsSync(pluginsDir)) return [];
1016
+ const pkgFiles = await fg3("*/package.json", { cwd: pluginsDir, absolute: true });
1017
+ const plugins = [];
1018
+ for (const pkgPath of pkgFiles) {
1019
+ try {
1020
+ const pkg = await fs8.readJson(pkgPath);
1021
+ const pluginPath = path10.dirname(pkgPath);
1022
+ plugins.push({
1023
+ name: pkg.name || path10.basename(pluginPath),
1024
+ path: pluginPath,
1025
+ id: path10.basename(pluginPath)
1026
+ });
1027
+ } catch (e) {
1028
+ }
1029
+ }
1030
+ return plugins;
1031
+ }
1032
+ /**
1033
+ * 启动开发环境 (统一入口)
1034
+ */
1035
+ static async startDev(cwd, options = {}) {
1036
+ const mode = await this.detectMode(cwd);
1037
+ const version = await this.resolveVersion(cwd);
1038
+ printBox(
1039
+ `${pc4.cyan(pc4.bold("\u{1F680} ChatBI Dev Server"))}
1040
+
1041
+ ${pc4.gray("Mode: ")} ${pc4.yellow(mode)}
1042
+ ${pc4.gray("Kernel: ")} ${pc4.green(version)}
1043
+ ${pc4.gray("Root: ")} ${pc4.white(cwd)}`,
1044
+ "Dev Server"
1045
+ );
1046
+ const spinner = createSpinner("\u6B63\u5728\u51C6\u5907\u6C99\u7BB1\u73AF\u5883...").start();
1047
+ try {
1048
+ await Sandbox.prepare(version);
1049
+ spinner.text = pc4.cyan("\u6B63\u5728\u6CE8\u5165\u865A\u62DF\u4E0A\u4E0B\u6587...");
1050
+ await Sandbox.injectContext(cwd, version);
1051
+ spinner.succeed(pc4.green("\u73AF\u5883\u5C31\u7EEA"));
1052
+ if (mode === "plugin") {
1053
+ await this.startPluginDevServer(cwd, version, options.port);
1054
+ } else if (mode === "app") {
1055
+ await this.startAppDevServer(cwd, version, options.port);
1056
+ } else {
1057
+ await this.startMonorepoDevServer(cwd, version, options.port);
1058
+ }
1059
+ } catch (e) {
1060
+ spinner.fail(pc4.red(`\u542F\u52A8\u5931\u8D25: ${e.message}`));
1061
+ }
1062
+ }
1063
+ /**
1064
+ * 启动 Monorepo 开发服务器
1065
+ */
1066
+ static async startMonorepoDevServer(rootDir, version, customPort) {
1067
+ const appsDir = path10.join(rootDir, "apps");
1068
+ if (!fs8.existsSync(appsDir)) {
1069
+ logger.warn("\u5F53\u524D Monorepo \u4E0B\u672A\u627E\u5230 apps/ \u76EE\u5F55");
1070
+ return;
1071
+ }
1072
+ const pkgFiles = await fg3("*/package.json", { cwd: appsDir, absolute: true });
1073
+ const apps = pkgFiles.map((pkgPath) => ({
1074
+ name: path10.basename(path10.dirname(pkgPath)),
1075
+ path: path10.dirname(pkgPath)
1076
+ }));
1077
+ if (apps.length === 0) {
1078
+ logger.warn("\u5F53\u524D Monorepo \u4E0B\u672A\u627E\u5230\u4EFB\u4F55\u5E94\u7528 (apps/)");
1079
+ return;
1080
+ }
1081
+ const response = await prompts({
1082
+ type: "select",
1083
+ name: "appPath",
1084
+ message: "\u8BF7\u9009\u62E9\u8981\u542F\u52A8\u7684\u5E94\u7528:",
1085
+ choices: apps.map((app) => ({ title: app.name, value: app.path })),
1086
+ initial: 0
1087
+ });
1088
+ if (!response.appPath) {
1089
+ logger.info("\u5DF2\u53D6\u6D88");
1090
+ return;
1091
+ }
1092
+ await this.startAppDevServer(response.appPath, version, customPort);
1093
+ }
1094
+ /**
1095
+ * 启动插件开发服务器 (Hosted Mode)
1096
+ */
1097
+ static async startPluginDevServer(pluginDir, version, customPort) {
1098
+ logger.info("\u6B63\u5728\u542F\u52A8\u6258\u7BA1\u5F0F Shell...");
1099
+ const shellPort = customPort || 5173;
1100
+ const sandboxRoot = Sandbox.getRoot();
1101
+ const versionPath = Sandbox.getVersionPath(version);
1102
+ const sandboxNodeModules = path10.join(versionPath, "node_modules");
1103
+ const shellDir = await Sandbox.ensureShell(version);
1104
+ const coreAlias = Sandbox.getCoreAlias(version);
1105
+ const tailwindPath = path10.join(sandboxNodeModules, "tailwindcss");
1106
+ const autoprefixerPath = path10.join(sandboxNodeModules, "autoprefixer");
1107
+ let pluginEntry = path10.join(pluginDir, "src/index.tsx");
1108
+ if (!fs8.existsSync(pluginEntry)) {
1109
+ pluginEntry = path10.join(pluginDir, "src/index.ts");
1110
+ }
1111
+ const define = {
1112
+ "process.env.CHATBI_PLUGIN_PATH": JSON.stringify(pluginDir)
1113
+ };
1114
+ const { createServer } = await import("vite");
1115
+ try {
1116
+ const server = await createServer({
1117
+ root: shellDir,
1118
+ configFile: false,
1119
+ css: {
1120
+ postcss: {
1121
+ plugins: [
1122
+ __require(tailwindPath)({
1123
+ presets: [__require(path10.join(sandboxNodeModules, "@chatbi-v/tailwind-config"))],
1124
+ darkMode: "class",
1125
+ content: [
1126
+ path10.join(shellDir, "index.html"),
1127
+ path10.join(shellDir, "src/**/*.{ts,tsx}"),
1128
+ path10.join(pluginDir, "src/**/*.{ts,tsx}")
1129
+ ]
1130
+ }),
1131
+ __require(autoprefixerPath)
1132
+ ]
1133
+ }
1134
+ },
1135
+ server: {
1136
+ port: shellPort,
1137
+ host: true,
1138
+ watch: {
1139
+ // 关键:排除沙箱和软链目录,防止 Vite 挂起
1140
+ ignored: [
1141
+ "**/.chatbi/**",
1142
+ "**/node_modules/**",
1143
+ Sandbox.getRoot()
1144
+ ]
1145
+ },
1146
+ fs: {
1147
+ allow: [
1148
+ sandboxRoot,
1149
+ pluginDir,
1150
+ path10.resolve(pluginDir, "../../")
1151
+ ]
1152
+ }
1153
+ },
1154
+ resolve: {
1155
+ alias: {
1156
+ ...coreAlias,
1157
+ "react": path10.join(sandboxNodeModules, "react"),
1158
+ "react-dom": path10.join(sandboxNodeModules, "react-dom"),
1159
+ "@": path10.join(shellDir, "src"),
1160
+ // 关键:将虚拟模块指向用户插件
1161
+ "virtual:user-plugin": pluginEntry,
1162
+ // 防止 glob 报错,提供空的映射
1163
+ "@chatbi-plugins": path10.join(shellDir, "empty"),
1164
+ "@chatbi-apps": path10.join(shellDir, "empty")
1165
+ }
1166
+ },
1167
+ define
1168
+ });
1169
+ await server.listen();
1170
+ const localUrl = `http://localhost:${shellPort}/`;
1171
+ printBox(
1172
+ `${pc4.green(pc4.bold("\u2705 \u6258\u7BA1\u5F0F Shell \u5DF2\u542F\u52A8"))}
1173
+
1174
+ ${pc4.white("Local: ")} ${pc4.cyan(pc4.underline(localUrl))}`,
1175
+ "Shell Success"
1176
+ );
1177
+ } catch (e) {
1178
+ logger.error("Shell \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25", e);
1179
+ }
1180
+ }
1181
+ /**
1182
+ * 启动应用开发服务器 (Integrated Mode)
1183
+ */
1184
+ static async startAppDevServer(appDir, version, customPort) {
1185
+ logger.info("\u6B63\u5728\u542F\u52A8\u5E94\u7528...");
1186
+ const versionPath = Sandbox.getVersionPath(version);
1187
+ const sandboxNodeModules = path10.join(versionPath, "node_modules");
1188
+ const coreAlias = Sandbox.getCoreAlias(version);
1189
+ const { createServer, loadConfigFromFile } = await import("vite");
1190
+ try {
1191
+ const configContext = { command: "serve", mode: "development" };
1192
+ const userConfig = await loadConfigFromFile(configContext, void 0, appDir).catch(() => null);
1193
+ const server = await createServer({
1194
+ root: appDir,
1195
+ // 这里我们允许用户有自己的 vite config,但我们会 merge alias
1196
+ // 实际场景中可能需要写一个 Vite 插件来做这件事,这里简单处理
1197
+ resolve: {
1198
+ alias: {
1199
+ ...coreAlias,
1200
+ // 补充常用的基础依赖映射,防止用户 vite.config.ts 中的插件找不到依赖
1201
+ "react": path10.join(sandboxNodeModules, "react"),
1202
+ "react-dom": path10.join(sandboxNodeModules, "react-dom"),
1203
+ "@vitejs/plugin-react": path10.join(sandboxNodeModules, "@vitejs/plugin-react")
1204
+ }
1205
+ },
1206
+ server: {
1207
+ port: customPort || 3e3,
1208
+ host: true,
1209
+ watch: {
1210
+ // 关键:排除沙箱和软链目录,防止 Vite 挂起
1211
+ ignored: [
1212
+ "**/.chatbi/**",
1213
+ "**/node_modules/**",
1214
+ Sandbox.getRoot()
1215
+ ]
1216
+ },
1217
+ fs: {
1218
+ allow: [
1219
+ Sandbox.getRoot(),
1220
+ appDir,
1221
+ // 允许访问沙箱中的所有依赖
1222
+ sandboxNodeModules
1223
+ ]
1224
+ }
1225
+ }
1226
+ });
1227
+ await server.listen();
1228
+ const localUrl = `http://localhost:${server.config.server.port}/`;
1229
+ printBox(
1230
+ `${pc4.green(pc4.bold("\u2705 \u5E94\u7528\u5DF2\u6210\u529F\u542F\u52A8"))}
1231
+
1232
+ ${pc4.white("Local: ")} ${pc4.cyan(pc4.underline(localUrl))}`,
1233
+ "App Success"
1234
+ );
1235
+ } catch (e) {
1236
+ logger.error("\u5E94\u7528\u542F\u52A8\u5931\u8D25", e);
1237
+ }
1238
+ }
1239
+ };
1240
+ }
1241
+ });
1242
+
1243
+ // src/commands/build.ts
1244
+ var build_exports = {};
1245
+ __export(build_exports, {
1246
+ build: () => build
1247
+ });
1248
+ import { execa as execa2 } from "execa";
1249
+ import fs9 from "fs-extra";
1250
+ import path11 from "path";
1251
+ import pc5 from "picocolors";
1252
+ import { build as tsupBuild } from "tsup";
1253
+ async function build(options) {
1254
+ const cwd = process.cwd();
1255
+ const pkgPath = path11.join(cwd, "package.json");
1256
+ if (!fs9.existsSync(pkgPath)) {
1257
+ logger.error(`\u5728 ${cwd} \u4E2D\u672A\u627E\u5230 package.json`);
1258
+ return;
1259
+ }
1260
+ const pkg = await fs9.readJson(pkgPath);
1261
+ if (options.force) {
1262
+ const spinnerClean = createSpinner("\u6B63\u5728\u6E05\u7406\u7F13\u5B58\u73AF\u5883...").start();
1263
+ try {
1264
+ await Sandbox.clean(cwd, true);
1265
+ spinnerClean.succeed("\u7F13\u5B58\u73AF\u5883\u6E05\u7406\u5B8C\u6210");
1266
+ } catch (e) {
1267
+ spinnerClean.fail("\u7F13\u5B58\u6E05\u7406\u5931\u8D25");
1268
+ logger.error("\u6E05\u7406\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF", e);
1269
+ }
1270
+ }
1271
+ const version = await CoreKit.resolveVersion(cwd);
1272
+ logger.info(`\u6B63\u5728\u6784\u5EFA\u9879\u76EE: ${pc5.bold(pkg.name || "unnamed")} (\u5185\u6838\u7248\u672C: ${version})
1273
+ `);
1274
+ const spinner = createSpinner("\u6B63\u5728\u51C6\u5907\u6784\u5EFA\u73AF\u5883...").start();
1275
+ spinner.text = "\u6B63\u5728\u540C\u6B65\u6C99\u7BB1\u5185\u6838...";
1276
+ await Sandbox.prepare(version, options.force);
1277
+ if (pkg.workspaces || fs9.existsSync(path11.join(cwd, "pnpm-workspace.yaml"))) {
1278
+ spinner.text = "\u68C0\u6D4B\u5230 Monorepo\uFF0C\u6B63\u5728\u521D\u59CB\u5316\u6839\u76EE\u5F55\u4E0A\u4E0B\u6587...";
1279
+ await Sandbox.injectContext(cwd, version);
1280
+ spinner.text = "\u6B63\u5728\u540C\u6B65\u5B50\u5305\u4E0A\u4E0B\u6587...";
1281
+ const subDirs = ["apps", "plugins", "packages"];
1282
+ for (const dir of subDirs) {
1283
+ const dirPath = path11.join(cwd, dir);
1284
+ if (fs9.existsSync(dirPath)) {
1285
+ const entries = await fs9.readdir(dirPath, { withFileTypes: true });
1286
+ for (const entry2 of entries) {
1287
+ if (entry2.isDirectory()) {
1288
+ const subPkgPath = path11.join(dirPath, entry2.name);
1289
+ if (fs9.existsSync(path11.join(subPkgPath, "package.json"))) {
1290
+ await Sandbox.injectContext(subPkgPath, version);
1291
+ }
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+ } else {
1297
+ await Sandbox.injectContext(cwd, version);
1298
+ }
1299
+ spinner.succeed("\u6784\u5EFA\u73AF\u5883\u5C31\u7EEA");
1300
+ if (pkg.scripts && pkg.scripts.build && !process.env.CHATBI_CLI_INTERNAL) {
1301
+ const buildScript = pkg.scripts.build;
1302
+ if (!buildScript.includes("chatbi-cli build") && !buildScript.includes("chatbi build")) {
1303
+ logger.info(`\u68C0\u6D4B\u5230\u81EA\u5B9A\u4E49 build \u811A\u672C\uFF0C\u6B63\u5728\u6267\u884C: ${pc5.cyan("npm run build")}`);
1304
+ const args = ["run", "build"];
1305
+ if (options.watch) {
1306
+ args.push("--", "--watch");
1307
+ }
1308
+ await execa2("npm", args, {
1309
+ stdio: "inherit",
1310
+ env: { ...process.env, CHATBI_CLI_INTERNAL: "true" }
1311
+ });
1312
+ return;
1313
+ }
1314
+ }
1315
+ const mode = await CoreKit.detectMode(cwd);
1316
+ if (mode === "monorepo") {
1317
+ logger.info("\u68C0\u6D4B\u5230 Monorepo \u9879\u76EE\uFF0C\u6B63\u5728\u9012\u5F52\u6784\u5EFA\u5B50\u5305...");
1318
+ await execa2("pnpm", ["-r", "build"], { stdio: "inherit", cwd });
1319
+ return;
1320
+ }
1321
+ if (mode === "app") {
1322
+ logger.info("\u6B63\u5728\u6784\u5EFA\u5E94\u7528 (Vite)...");
1323
+ const { build: viteBuild } = await import("vite");
1324
+ const coreAlias = Sandbox.getCoreAlias(version);
1325
+ await viteBuild({
1326
+ root: cwd,
1327
+ configFile: fs9.existsSync(path11.join(cwd, "vite.config.ts")) ? void 0 : false,
1328
+ resolve: {
1329
+ alias: {
1330
+ ...coreAlias
1331
+ }
1332
+ },
1333
+ build: {
1334
+ watch: options.watch ? {} : null,
1335
+ outDir: "dist",
1336
+ emptyOutDir: true,
1337
+ minify: !options.watch ? "esbuild" : false
1338
+ // 生产环境开启压缩混淆
1339
+ },
1340
+ server: {
1341
+ fs: {
1342
+ allow: [
1343
+ Sandbox.getRoot(),
1344
+ cwd
1345
+ ]
1346
+ }
1347
+ }
128
1348
  });
129
- }, 'init'));
130
- cli
131
- .command('add [name]', '在当前项目中添加一个新插件')
132
- .option('-t, --type <type>', '插件类型 (business | system)')
133
- .option('--display-name <name>', '插件显示名称')
134
- .option('--desc <description>', '插件描述')
135
- .action(wrapAction(async (name, options) => {
136
- await (0, add_1.add)({
137
- name,
138
- type: options.type,
139
- displayName: options.displayName,
140
- description: options.desc
1349
+ if (!options.watch) {
1350
+ printBox(
1351
+ pc5.green(pc5.bold("\u2728 \u5E94\u7528\u6784\u5EFA\u6210\u529F!")) + "\n\n" + pc5.white("\u4EA7\u7269\u76EE\u5F55: ") + pc5.cyan("dist"),
1352
+ "Build Success"
1353
+ );
1354
+ }
1355
+ return;
1356
+ }
1357
+ let entry = ["src/index.ts"];
1358
+ if (fs9.existsSync(path11.join(cwd, "src/index.tsx"))) {
1359
+ entry = ["src/index.tsx"];
1360
+ } else if (!fs9.existsSync(path11.join(cwd, "src/index.ts"))) {
1361
+ logger.error("\u672A\u627E\u5230\u5165\u53E3\u6587\u4EF6\u3002\u671F\u671B src/index.ts \u6216 src/index.tsx");
1362
+ return;
1363
+ }
1364
+ const isPlugin = mode === "plugin";
1365
+ const userConfig = await ConfigManager.loadTsupConfig(cwd);
1366
+ if (Object.keys(userConfig).length > 0) {
1367
+ logger.info(`\u5DF2\u52A0\u8F7D\u672C\u5730\u6784\u5EFA\u914D\u7F6E`);
1368
+ }
1369
+ if (!options.watch) {
1370
+ await fs9.remove(path11.join(cwd, "dist"));
1371
+ const tsbuildinfo = path11.join(cwd, "tsconfig.tsbuildinfo");
1372
+ if (fs9.existsSync(tsbuildinfo)) {
1373
+ await fs9.remove(tsbuildinfo);
1374
+ }
1375
+ }
1376
+ if (isPlugin) {
1377
+ }
1378
+ const commonConfig = {
1379
+ entry,
1380
+ dts: false,
1381
+ clean: false,
1382
+ sourcemap: false,
1383
+ target: "esnext",
1384
+ platform: isPlugin ? "browser" : "node",
1385
+ ...userConfig,
1386
+ // 合并用户配置
1387
+ external: [
1388
+ .../* @__PURE__ */ new Set([
1389
+ "react",
1390
+ "react-dom",
1391
+ "react/jsx-runtime",
1392
+ "react-is",
1393
+ "antd",
1394
+ "@ant-design/icons",
1395
+ "@ant-design/x",
1396
+ ...Object.keys(pkg.dependencies || {}),
1397
+ ...Object.keys(pkg.peerDependencies || {}),
1398
+ ...isPlugin ? Sandbox.CORE_PACKAGES : [],
1399
+ ...Array.isArray(userConfig.external) ? userConfig.external : []
1400
+ ])
1401
+ ],
1402
+ minify: userConfig.minify !== void 0 ? userConfig.minify : !options.watch,
1403
+ // 优先使用用户配置
1404
+ watch: options.watch,
1405
+ silent: true,
1406
+ esbuildOptions(esbuildOpts) {
1407
+ esbuildOpts.logOverride = {
1408
+ "empty-import-meta": "silent"
1409
+ };
1410
+ esbuildOpts.external = esbuildOpts.external || [];
1411
+ const forceExternal = [
1412
+ "react",
1413
+ "react-dom",
1414
+ "antd",
1415
+ "@ant-design/icons",
1416
+ "@ant-design/x",
1417
+ ...Sandbox.CORE_PACKAGES
1418
+ ];
1419
+ forceExternal.forEach((dep) => {
1420
+ if (!esbuildOpts.external.includes(dep)) {
1421
+ esbuildOpts.external.push(dep);
1422
+ }
1423
+ });
1424
+ if (typeof userConfig.esbuildOptions === "function") {
1425
+ userConfig.esbuildOptions(esbuildOpts);
1426
+ }
1427
+ }
1428
+ };
1429
+ const buildSpinner = createSpinner("\u6B63\u5728\u7F16\u8BD1\u6E90\u7801...").start();
1430
+ if (isPlugin) {
1431
+ buildSpinner.text = "\u6B63\u5728\u6784\u5EFA ESM \u683C\u5F0F...";
1432
+ await tsupBuild({
1433
+ ...commonConfig,
1434
+ format: ["esm"],
1435
+ outExtension: () => ({ js: ".mjs" })
141
1436
  });
142
- }, 'add'));
143
- cli
144
- .command('update [targetVersion]', '更新内核版本')
145
- .alias('up')
146
- .action(wrapAction(async (targetVersion) => {
147
- const { sync } = await Promise.resolve().then(() => __importStar(require('./commands/sync')));
148
- await sync({ version: targetVersion, force: true });
149
- utils_1.logger.success('更新完成!');
150
- }, 'update'));
151
- cli
152
- .command('sync', '同步内核依赖与规范')
153
- .alias('s')
154
- .option('-v, --core-version <version>', '指定内核版本')
155
- .option('-f, --force', '强制重新初始化内核沙箱')
156
- .option('--clean', '清理并重置沙箱')
157
- .action(wrapAction(async (options) => {
158
- await (0, sync_1.sync)({ ...options, version: options.coreVersion });
159
- console.log('');
160
- await (0, doctor_1.doctor)({ fix: false });
161
- }, 'sync'));
162
- cli
163
- .command('doctor', '诊断项目健康状况并修复')
164
- .alias('dr')
165
- .option('--fix', '自动修复发现的问题')
166
- .action(wrapAction(doctor_1.doctor, 'doctor'));
167
- cli
168
- .command('list', '列出所有已安装的内核沙箱版本')
169
- .alias('ls')
170
- .action(wrapAction(ls_1.ls, 'ls'));
171
- cli
172
- .command('use <version>', '切换当前项目使用的内核版本')
173
- .alias('u')
174
- .option('--global', '切换全局默认内核版本')
175
- .action(wrapAction(use_1.use, 'use'));
176
- cli
177
- .command('gl', '使用 AI 脚手架生成代码或文档')
178
- .option('-t, --type <type>', '生成类型 (plugin|util|doc|component)')
179
- .option('-p, --prompt <prompt>', 'AI 需求描述')
180
- .action(wrapAction(gl_1.gl, 'gl'));
181
- cli
182
- .command('discover', '扫描并发现当前项目中的插件')
183
- .action(wrapAction(discover_1.discover, 'discover'));
184
- cli
185
- .command('bench', '运行 CLI 性能基准测试')
186
- .action(wrapAction(async () => {
187
- const { bench } = await Promise.resolve().then(() => __importStar(require('./commands/bench')));
188
- await bench();
189
- }, 'bench'));
190
- cli.help((sections) => {
1437
+ buildSpinner.text = "\u6B63\u5728\u6784\u5EFA IIFE \u683C\u5F0F (Plugin)...";
1438
+ await tsupBuild({
1439
+ ...commonConfig,
1440
+ format: ["iife"],
1441
+ globalName: pkg.name.replace(/[^a-zA-Z0-9]/g, "_"),
1442
+ outExtension: () => ({ js: ".plugin.js" }),
1443
+ platform: "browser",
1444
+ define: {
1445
+ "import.meta.env": "process.env"
1446
+ },
1447
+ esbuildOptions: commonConfig.esbuildOptions
1448
+ });
1449
+ } else {
1450
+ buildSpinner.text = "\u6B63\u5728\u7F16\u8BD1\u6E90\u7801...";
1451
+ await tsupBuild({
1452
+ ...commonConfig,
1453
+ format: ["cjs", "esm"],
1454
+ outExtension({ format }) {
1455
+ return { js: format === "esm" ? ".mjs" : ".cjs" };
1456
+ }
1457
+ });
1458
+ }
1459
+ buildSpinner.succeed("\u6E90\u7801\u7F16\u8BD1\u5B8C\u6210");
1460
+ if (!options.watch) {
1461
+ const dtsSpinner = createSpinner("\u6B63\u5728\u751F\u6210\u7C7B\u578B\u5B9A\u4E49...").start();
1462
+ try {
1463
+ const localTsc = path11.join(cwd, "node_modules/.bin/tsc");
1464
+ const sandboxTsc = path11.join(Sandbox.getVersionPath(version), "node_modules/.bin/tsc");
1465
+ let tscBin = "tsc";
1466
+ if (fs9.existsSync(localTsc)) {
1467
+ tscBin = localTsc;
1468
+ } else if (fs9.existsSync(sandboxTsc)) {
1469
+ tscBin = sandboxTsc;
1470
+ } else {
1471
+ if (fs9.existsSync(path11.join(cwd, "pnpm-lock.yaml"))) {
1472
+ await execa2("pnpm", ["exec", "tsc", "--build", "tsconfig.json"]);
1473
+ dtsSpinner.succeed("\u7C7B\u578B\u5B9A\u4E49\u751F\u6210\u5B8C\u6210");
1474
+ } else {
1475
+ await execa2("npx", ["-p", "typescript", "tsc", "--build", "tsconfig.json"]);
1476
+ dtsSpinner.succeed("\u7C7B\u578B\u5B9A\u4E49\u751F\u6210\u5B8C\u6210");
1477
+ }
1478
+ }
1479
+ if (tscBin !== "tsc") {
1480
+ await execa2(tscBin, ["--build", "tsconfig.json"]);
1481
+ dtsSpinner.succeed("\u7C7B\u578B\u5B9A\u4E49\u751F\u6210\u5B8C\u6210");
1482
+ }
1483
+ } catch (e) {
1484
+ dtsSpinner.warn("\u7C7B\u578B\u751F\u6210\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u4E2D\u7684 tsconfig.json \u914D\u7F6E");
1485
+ }
1486
+ printBox(
1487
+ pc5.green(pc5.bold("\u2728 \u6784\u5EFA\u5B8C\u6210!")) + "\n\n" + pc5.white("\u4EA7\u7269\u76EE\u5F55: ") + pc5.cyan("dist") + "\n" + pc5.white("\u6784\u5EFA\u6A21\u5F0F: ") + pc5.cyan(isPlugin ? "Plugin" : "Library"),
1488
+ "Build Success"
1489
+ );
1490
+ }
1491
+ }
1492
+ var init_build = __esm({
1493
+ "src/commands/build.ts"() {
1494
+ "use strict";
1495
+ init_esm_shims();
1496
+ init_sandbox();
1497
+ init_corekit();
1498
+ init_config();
1499
+ init_utils();
1500
+ }
1501
+ });
1502
+
1503
+ // src/commands/sync.ts
1504
+ var sync_exports = {};
1505
+ __export(sync_exports, {
1506
+ sync: () => sync
1507
+ });
1508
+ import fs10 from "fs-extra";
1509
+ import path12 from "path";
1510
+ import pc6 from "picocolors";
1511
+ async function sync(options = {}) {
1512
+ const cwd = options.cwd || process.cwd();
1513
+ const pkgPath = path12.join(cwd, "package.json");
1514
+ if (!fs10.existsSync(pkgPath)) {
1515
+ logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u3002");
1516
+ return;
1517
+ }
1518
+ const pkg = await fs10.readJson(pkgPath);
1519
+ let version = options.version;
1520
+ if (!version) {
1521
+ version = await CoreKit.resolveVersion(cwd);
1522
+ }
1523
+ if (options.clean) {
1524
+ const cleanSpinner = createSpinner(`\u6B63\u5728\u6E05\u7406\u6C99\u7BB1\u7248\u672C ${version}...`).start();
1525
+ await Sandbox.cleanVersion(version);
1526
+ cleanSpinner.succeed(`\u6C99\u7BB1\u7248\u672C ${version} \u5DF2\u6E05\u7406`);
1527
+ }
1528
+ const mainSpinner = createSpinner(`\u6B63\u5728\u540C\u6B65\u5185\u6838\u4F9D\u8D56 (\u7248\u672C: ${version})...`).start();
1529
+ mainSpinner.text = "\u6B63\u5728\u540C\u6B65\u6C99\u7BB1\u5185\u6838...";
1530
+ await Sandbox.prepare(version, options.force);
1531
+ mainSpinner.text = "\u6B63\u5728\u751F\u6210\u865A\u62DF\u4E0A\u4E0B\u6587...";
1532
+ if (options.version) {
1533
+ const versionFilePath = path12.join(cwd, ".chatbi-version");
1534
+ await fs10.writeFile(versionFilePath, version, "utf-8");
1535
+ }
1536
+ await Sandbox.injectContext(cwd, version);
1537
+ let modified = false;
1538
+ const deps = pkg.dependencies || {};
1539
+ const devDeps = pkg.devDependencies || {};
1540
+ const isVirtualMode = true;
1541
+ if (isVirtualMode) {
1542
+ for (const pkgName of Sandbox.CORE_PACKAGES) {
1543
+ if (deps[pkgName]) {
1544
+ delete deps[pkgName];
1545
+ modified = true;
1546
+ }
1547
+ if (devDeps[pkgName]) {
1548
+ delete devDeps[pkgName];
1549
+ modified = true;
1550
+ }
1551
+ }
1552
+ }
1553
+ if (modified) {
1554
+ pkg.dependencies = deps;
1555
+ pkg.devDependencies = devDeps;
1556
+ await fs10.writeJson(pkgPath, pkg, { spaces: 2 });
1557
+ mainSpinner.succeed("\u5185\u6838\u540C\u6B65\u5B8C\u6210 (\u4F9D\u8D56\u5DF2\u4F18\u5316)");
1558
+ } else {
1559
+ mainSpinner.succeed("\u5185\u6838\u540C\u6B65\u5B8C\u6210");
1560
+ }
1561
+ if (!options.silent) {
1562
+ printBox(
1563
+ `${pc6.green(pc6.bold("\u2728 \u5185\u6838\u540C\u6B65\u6210\u529F!"))}
1564
+
1565
+ ${pc6.white("\u5F53\u524D\u7248\u672C: ")} ${pc6.cyan(version)}
1566
+ ${pc6.white("\u6C99\u7BB1\u8DEF\u5F84: ")} ${pc6.gray(Sandbox.getVersionPath(version))}
1567
+
1568
+ ${pc6.white("\u63D0\u793A: ")} \u9879\u76EE\u73B0\u5728\u901A\u8FC7\u865A\u62DF\u522B\u540D\u5F15\u7528\u6838\u5FC3\u5305\uFF0C\u65E0\u9700\u663E\u5F0F\u5B89\u88C5\u4F9D\u8D56\u3002`,
1569
+ "Sync Success"
1570
+ );
1571
+ }
1572
+ }
1573
+ var init_sync = __esm({
1574
+ "src/commands/sync.ts"() {
1575
+ "use strict";
1576
+ init_esm_shims();
1577
+ init_utils();
1578
+ init_sandbox();
1579
+ init_corekit();
1580
+ }
1581
+ });
1582
+
1583
+ // src/commands/init.ts
1584
+ var init_exports = {};
1585
+ __export(init_exports, {
1586
+ init: () => init
1587
+ });
1588
+ import fs11 from "fs-extra";
1589
+ import path13 from "path";
1590
+ import pc7 from "picocolors";
1591
+ import prompts2 from "prompts";
1592
+ async function init(options) {
1593
+ let { name, pluginType = "business", theme = DEFAULT_CONFIG.THEME, projectType, includeApp, includePlugin, cwd } = options;
1594
+ const response = await prompts2([
1595
+ // ... (prompts remain the same)
1596
+ {
1597
+ type: name ? null : "text",
1598
+ name: "projectName",
1599
+ message: "\u8BF7\u8F93\u5165\u9879\u76EE\u540D\u79F0:",
1600
+ initial: "my-chatbi-workspace"
1601
+ },
1602
+ {
1603
+ type: projectType ? null : "select",
1604
+ name: "projectType",
1605
+ message: "\u8BF7\u9009\u62E9\u9879\u76EE\u7C7B\u578B:",
1606
+ choices: [
1607
+ { title: "Monorepo Workspace (\u5B8C\u6574\u5DE5\u4F5C\u7A7A\u95F4)", value: "monorepo", description: "\u5305\u542B Apps \u548C Plugins \u7684\u591A\u5305\u7BA1\u7406\u7ED3\u6784" },
1608
+ { title: "Host App (\u72EC\u7ACB\u5BBF\u4E3B\u5E94\u7528)", value: "app", description: "\u72EC\u7ACB\u7684 ChatBI \u5E94\u7528\u6846\u67B6" },
1609
+ { title: "Plugin (\u72EC\u7ACB\u63D2\u4EF6)", value: "plugin", description: "\u72EC\u7ACB\u7684\u4E1A\u52A1\u6216\u7CFB\u7EDF\u63D2\u4EF6" }
1610
+ ],
1611
+ initial: 0
1612
+ },
1613
+ // Monorepo specific questions
1614
+ {
1615
+ type: (prev) => (projectType === "monorepo" || prev === "monorepo") && includeApp === void 0 ? "confirm" : null,
1616
+ name: "includeApp",
1617
+ message: "\u662F\u5426\u521D\u59CB\u5316\u9ED8\u8BA4 Host App?",
1618
+ initial: true
1619
+ },
1620
+ {
1621
+ type: (prev) => (projectType === "monorepo" || prev === "monorepo") && includePlugin === void 0 ? "confirm" : null,
1622
+ name: "includePlugin",
1623
+ message: "\u662F\u5426\u521D\u59CB\u5316\u793A\u4F8B Plugin?",
1624
+ initial: true
1625
+ },
1626
+ // Plugin specific questions
1627
+ {
1628
+ type: (prev, values) => (projectType === "plugin" || values.projectType === "plugin" || (includePlugin || values.includePlugin)) && !pluginType ? "select" : null,
1629
+ name: "pluginType",
1630
+ message: "\u8BF7\u9009\u62E9\u63D2\u4EF6\u7C7B\u578B:",
1631
+ choices: [
1632
+ { title: "Business (\u4E1A\u52A1\u63D2\u4EF6)", value: "business", description: "\u4FA7\u91CD\u4E8E\u4E1A\u52A1\u903B\u8F91\u548C UI \u5C55\u793A" },
1633
+ { title: "System (\u7CFB\u7EDF\u63D2\u4EF6)", value: "system", description: "\u4FA7\u91CD\u4E8E\u7CFB\u7EDF\u80FD\u529B\u548C\u5E95\u5C42\u6269\u5C55" }
1634
+ ],
1635
+ initial: 0
1636
+ },
1637
+ // Theme selection (for App)
1638
+ {
1639
+ type: (prev, values) => (projectType === "app" || values.projectType === "app" || (includeApp || values.includeApp)) && !theme ? "select" : null,
1640
+ name: "theme",
1641
+ message: "\u8BF7\u9009\u62E9\u5E94\u7528\u9ED8\u8BA4\u4E3B\u9898:",
1642
+ choices: [
1643
+ { title: "Standard (\u7ECF\u5178\u84DD)", value: "standard" },
1644
+ { title: "Nebula (\u661F\u4E91\u7D2B)", value: "nebula" },
1645
+ { title: "Glass (\u6BDB\u73BB\u7483)", value: "glass" }
1646
+ ],
1647
+ initial: 0
1648
+ }
1649
+ ], {
1650
+ onCancel: () => {
1651
+ logger.warn("\u5DF2\u53D6\u6D88\u521D\u59CB\u5316");
1652
+ process.exit(0);
1653
+ }
1654
+ });
1655
+ name = name || response.projectName;
1656
+ projectType = projectType || response.projectType || "monorepo";
1657
+ pluginType = pluginType || response.pluginType || pluginType;
1658
+ theme = theme || response.theme || theme;
1659
+ const finalIncludeApp = includeApp !== void 0 ? includeApp : response.includeApp !== void 0 ? response.includeApp : true;
1660
+ const finalIncludePlugin = includePlugin !== void 0 ? includePlugin : response.includePlugin !== void 0 ? response.includePlugin : true;
1661
+ const isAppIncluded = finalIncludeApp;
1662
+ const isPluginIncluded = finalIncludePlugin;
1663
+ const rootDir = cwd || process.cwd();
1664
+ const targetDir = path13.resolve(rootDir, name);
1665
+ if (fs11.existsSync(targetDir)) {
1666
+ logger.error(`\u76EE\u5F55 ${name} \u5DF2\u5B58\u5728\u3002`);
1667
+ return;
1668
+ }
1669
+ logger.info(`\u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE: ${pc7.bold(name)}...`);
1670
+ logger.info(pc7.gray(`\u7C7B\u578B: ${projectType} | \u4E3B\u9898: ${theme || "N/A"}`));
1671
+ console.log("");
1672
+ try {
1673
+ const myCliRoot = await getCliRoot();
1674
+ const cliPkg = await fs11.readJson(path13.join(myCliRoot, "package.json"));
1675
+ const cliVersion = cliPkg.version;
1676
+ const config = { coreSource: "npm" };
1677
+ const kernelVersionFile = path13.join(myCliRoot, SANDBOX_CONFIG.LOCK_FILE);
1678
+ if (fs11.existsSync(kernelVersionFile)) {
1679
+ config.coreVersion = (await fs11.readFile(kernelVersionFile, "utf-8")).trim();
1680
+ }
1681
+ const kernelVersion = await ConfigManager.resolveCoreDependency(config);
1682
+ const renderTemplate = async (templateName, destDir, extraData = {}) => {
1683
+ const srcDir = path13.join(myCliRoot, "templates", templateName);
1684
+ if (!fs11.existsSync(srcDir)) {
1685
+ throw new Error(`\u627E\u4E0D\u5230\u6A21\u677F: ${templateName}\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84 ${srcDir} \u662F\u5426\u6B63\u786E\u3002`);
1686
+ }
1687
+ await fs11.ensureDir(destDir);
1688
+ const templateData = {
1689
+ name: path13.basename(destDir),
1690
+ projectName: name,
1691
+ // Original project name from CLI argument
1692
+ projectTitle: name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" "),
1693
+ projectVersion: "0.1.0",
1694
+ version: kernelVersion,
1695
+ // 使用内核版本作为依赖版本
1696
+ cliVersion,
1697
+ // CLI 自身版本
1698
+ pluginType,
1699
+ theme,
1700
+ isNebula: theme === "nebula",
1701
+ isGlass: theme === "glass",
1702
+ isBusiness: pluginType === "business",
1703
+ isApp: projectType === "app" || isAppIncluded,
1704
+ // Zero Dependency Mode: No explicit core path needed in package.json
1705
+ // tsconfig extends the virtual paths config
1706
+ tsconfigPath: projectType === "monorepo" ? `../../${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json` : `./${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json`,
1707
+ ...extraData
1708
+ };
1709
+ await SandboxRenderer.renderDirectory(srcDir, destDir, templateData);
1710
+ };
1711
+ const spinner = createSpinner("\u6B63\u5728\u751F\u6210\u9879\u76EE\u7ED3\u6784...").start();
1712
+ if (projectType === "monorepo") {
1713
+ spinner.text = "\u6B63\u5728\u751F\u6210 Monorepo \u9AA8\u67B6...";
1714
+ await renderTemplate("monorepo", targetDir, { name });
1715
+ if (isAppIncluded) {
1716
+ spinner.text = "\u6B63\u5728\u751F\u6210 Host App...";
1717
+ const appDir = path13.join(targetDir, "apps", "main");
1718
+ await renderTemplate("app", appDir, { name: "@chatbi-v/main" });
1719
+ }
1720
+ if (isPluginIncluded) {
1721
+ spinner.text = "\u6B63\u5728\u751F\u6210 Demo Plugin...";
1722
+ const pluginDir = path13.join(targetDir, "plugins", "plugin-demo");
1723
+ await renderTemplate("plugin", pluginDir, {
1724
+ name: "@chatbi-v/plugin-demo",
1725
+ pluginId: "demo",
1726
+ pluginName: "demo",
1727
+ pluginPackageName: "@chatbi-v/plugin-demo",
1728
+ pluginVersion: "0.1.0",
1729
+ pluginDisplayName: "\u793A\u4F8B\u63D2\u4EF6",
1730
+ pluginDescription: "\u8FD9\u662F\u4E00\u4E2A\u521D\u59CB\u5316\u7684\u793A\u4F8B\u63D2\u4EF6",
1731
+ pluginClassName: "DemoPlugin",
1732
+ pluginPath: "plugin-demo",
1733
+ pluginFolderName: "plugin-demo",
1734
+ className: "DemoPlugin"
1735
+ });
1736
+ }
1737
+ } else if (projectType === "app") {
1738
+ spinner.text = "\u6B63\u5728\u751F\u6210\u72EC\u7ACB\u5E94\u7528...";
1739
+ await renderTemplate("app", targetDir, { name });
1740
+ } else if (projectType === "plugin") {
1741
+ spinner.text = "\u6B63\u5728\u751F\u6210\u72EC\u7ACB\u63D2\u4EF6...";
1742
+ await renderTemplate("plugin", targetDir, {
1743
+ name: `@chatbi-v/plugin-${name}`,
1744
+ pluginId: name,
1745
+ pluginName: name,
1746
+ pluginPackageName: `@chatbi-v/plugin-${name}`,
1747
+ pluginVersion: "0.1.0",
1748
+ pluginDisplayName: name,
1749
+ pluginDescription: "A ChatBI-V Plugin",
1750
+ pluginClassName: name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(""),
1751
+ pluginPath: name,
1752
+ pluginFolderName: name,
1753
+ className: name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("")
1754
+ });
1755
+ }
1756
+ spinner.succeed("\u9879\u76EE\u7ED3\u6784\u751F\u6210\u5B8C\u6210");
1757
+ const syncSpinner = createSpinner("\u6B63\u5728\u540C\u6B65\u5185\u6838\u4F9D\u8D56...").start();
1758
+ await sync({ cwd: targetDir, silent: true });
1759
+ syncSpinner.succeed("\u5185\u6838\u4F9D\u8D56\u540C\u6B65\u5B8C\u6210");
1760
+ const configSpinner = createSpinner("\u6B63\u5728\u751F\u6210\u9879\u76EE\u914D\u7F6E...").start();
1761
+ const cliConfig = {
1762
+ coreVersion: kernelVersion
1763
+ };
1764
+ await fs11.writeJson(path13.join(targetDir, "chatbi.config.json"), cliConfig, { spaces: 2 });
1765
+ configSpinner.succeed("\u9879\u76EE\u914D\u7F6E\u751F\u6210\u5B8C\u6210");
1766
+ printBox(
1767
+ `${pc7.green(pc7.bold("\u2728 \u9879\u76EE\u5DF2\u6210\u529F\u521B\u5EFA!"))}
1768
+
1769
+ ${pc7.white("\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5:")}
1770
+ ${pc7.cyan(` cd ${name}`)}
1771
+ ${pc7.cyan(" pnpm install")}
1772
+ ${pc7.cyan(" pnpm dev")}`,
1773
+ "Success"
1774
+ );
1775
+ } catch (error) {
1776
+ logger.error("\u521D\u59CB\u5316\u5931\u8D25", error);
1777
+ throw error;
1778
+ }
1779
+ }
1780
+ var init_init = __esm({
1781
+ "src/commands/init.ts"() {
1782
+ "use strict";
1783
+ init_esm_shims();
1784
+ init_utils();
1785
+ init_sync();
1786
+ init_constants();
1787
+ init_config();
1788
+ init_SandboxRenderer();
1789
+ }
1790
+ });
1791
+
1792
+ // src/commands/fetch.ts
1793
+ var fetch_exports = {};
1794
+ __export(fetch_exports, {
1795
+ fetch: () => fetch
1796
+ });
1797
+ import path18 from "path";
1798
+ import pc13 from "picocolors";
1799
+ import { execa as execa4 } from "execa";
1800
+ async function fetch(version, options = {}) {
1801
+ const fetchSpinner = createSpinner(`\u6B63\u5728\u83B7\u53D6\u5185\u6838\u7248\u672C ${pc13.cyan(version)}...`).start();
1802
+ const versionPath = await Sandbox.prepare(version, true);
1803
+ fetchSpinner.succeed(`\u5185\u6838\u7248\u672C ${pc13.cyan(version)} \u83B7\u53D6\u6210\u529F`);
1804
+ if (options.pack) {
1805
+ const packSpinner = createSpinner("\u6B63\u5728\u6253\u5305\u79BB\u7EBF\u8D44\u6E90...").start();
1806
+ const tgzName = `chatbi-core-${version}.tgz`;
1807
+ const tgzPath = path18.resolve(process.cwd(), tgzName);
1808
+ await execa4("tar", [
1809
+ "-czf",
1810
+ tgzPath,
1811
+ "-C",
1812
+ path18.dirname(versionPath),
1813
+ path18.basename(versionPath)
1814
+ ]);
1815
+ packSpinner.succeed("\u79BB\u7EBF\u8D44\u6E90\u6253\u5305\u5B8C\u6210");
1816
+ printBox(
1817
+ `${pc13.green(pc13.bold("\u2728 \u79BB\u7EBF\u5305\u5DF2\u751F\u6210!"))}
1818
+
1819
+ ${pc13.white("\u6587\u4EF6\u8DEF\u5F84: ")} ${pc13.cyan(tgzPath)}
1820
+ ${pc13.white("\u5B89\u88C5\u547D\u4EE4: ")} ${pc13.gray(`chatbi install ${tgzName}`)}`,
1821
+ "Pack Success"
1822
+ );
1823
+ } else {
1824
+ logger.success(`\u5185\u6838\u7248\u672C ${pc13.cyan(version)} \u5DF2\u51C6\u5907\u5C31\u7EEA\u3002`);
1825
+ }
1826
+ }
1827
+ var init_fetch = __esm({
1828
+ "src/commands/fetch.ts"() {
1829
+ "use strict";
1830
+ init_esm_shims();
1831
+ init_sandbox();
1832
+ init_utils();
1833
+ }
1834
+ });
1835
+
1836
+ // src/commands/bench.ts
1837
+ var bench_exports = {};
1838
+ __export(bench_exports, {
1839
+ bench: () => bench
1840
+ });
1841
+ import pc15 from "picocolors";
1842
+ import fs17 from "fs-extra";
1843
+ import path20 from "path";
1844
+ import os2 from "os";
1845
+ async function bench() {
1846
+ logger.info("\u6B63\u5728\u542F\u52A8 CLI \u6027\u80FD\u57FA\u51C6\u6D4B\u8BD5...");
1847
+ const results = [];
1848
+ const tmpDir = path20.join(os2.tmpdir(), `chatbi-bench-${Date.now()}`);
1849
+ await fs17.ensureDir(tmpDir);
1850
+ try {
1851
+ const initSpinner = createSpinner("\u6B63\u5728\u6D4B\u8BD5: \u521D\u59CB\u5316\u63D2\u4EF6\u9879\u76EE (init)...").start();
1852
+ const startInit = Date.now();
1853
+ const { init: init2 } = await Promise.resolve().then(() => (init_init(), init_exports));
1854
+ const testProjDir = path20.join(tmpDir, "bench-proj");
1855
+ await init2({ name: "bench-proj", projectType: "plugin", cwd: tmpDir });
1856
+ const endInit = Date.now();
1857
+ const initTime = (endInit - startInit) / 1e3;
1858
+ initSpinner.succeed(`\u521D\u59CB\u5316\u5B8C\u6210: ${pc15.cyan(initTime.toFixed(2) + "s")}`);
1859
+ results.push({
1860
+ scene: "\u521D\u59CB\u5316\u63D2\u4EF6\u9879\u76EE (init)",
1861
+ target: "\u2264 5.0 s",
1862
+ actual: `${initTime.toFixed(2)} s`
1863
+ });
1864
+ const syncSpinner = createSpinner("\u6B63\u5728\u6D4B\u8BD5: \u6C99\u7BB1\u73AF\u5883\u540C\u6B65 (sync)...").start();
1865
+ const startSync = Date.now();
1866
+ const { sync: sync2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
1867
+ await sync2({ cwd: testProjDir });
1868
+ const endSync = Date.now();
1869
+ const syncTime = (endSync - startSync) / 1e3;
1870
+ syncSpinner.succeed(`\u540C\u6B65\u5B8C\u6210: ${pc15.cyan(syncTime.toFixed(2) + "s")}`);
1871
+ results.push({
1872
+ scene: "\u6C99\u7BB1\u73AF\u5883\u540C\u6B65 (sync)",
1873
+ target: "\u2264 2.0 s",
1874
+ actual: `${syncTime.toFixed(2)} s`
1875
+ });
1876
+ const buildSpinner = createSpinner("\u6B63\u5728\u6D4B\u8BD5: \u63D2\u4EF6\u9879\u76EE\u6784\u5EFA (build)...").start();
1877
+ const startBuild = Date.now();
1878
+ const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
1879
+ const originalCwd = process.cwd();
1880
+ process.chdir(testProjDir);
1881
+ await build2({ watch: false });
1882
+ process.chdir(originalCwd);
1883
+ const endBuild = Date.now();
1884
+ const buildTime = (endBuild - startBuild) / 1e3;
1885
+ buildSpinner.succeed(`\u6784\u5EFA\u5B8C\u6210: ${pc15.cyan(buildTime.toFixed(2) + "s")}`);
1886
+ results.push({
1887
+ scene: "\u63D2\u4EF6\u9879\u76EE\u6784\u5EFA (build)",
1888
+ target: "\u2264 10.0 s",
1889
+ actual: `${buildTime.toFixed(2)} s`
1890
+ });
1891
+ printBox(
1892
+ `${pc15.green(pc15.bold("\u2728 \u57FA\u51C6\u6D4B\u8BD5\u5B8C\u6210!"))}
1893
+
1894
+ ` + results.map((r) => `${pc15.white(r.scene.padEnd(20))}: ${pc15.cyan(r.actual)} (\u76EE\u6807 ${r.target})`).join("\n"),
1895
+ "Benchmark Results"
1896
+ );
1897
+ } finally {
1898
+ await fs17.remove(tmpDir);
1899
+ }
1900
+ }
1901
+ var init_bench = __esm({
1902
+ "src/commands/bench.ts"() {
1903
+ "use strict";
1904
+ init_esm_shims();
1905
+ init_utils();
1906
+ }
1907
+ });
1908
+
1909
+ // src/index.ts
1910
+ init_esm_shims();
1911
+ init_build();
1912
+ import cac from "cac";
1913
+ import pc16 from "picocolors";
1914
+ import figlet from "figlet";
1915
+ import gradient from "gradient-string";
1916
+ import boxen2 from "boxen";
1917
+
1918
+ // src/commands/dev.ts
1919
+ init_esm_shims();
1920
+ init_corekit();
1921
+ async function dev(options = {}) {
1922
+ const cwd = process.cwd();
1923
+ await CoreKit.startDev(cwd, options);
1924
+ }
1925
+
1926
+ // src/index.ts
1927
+ init_init();
1928
+
1929
+ // src/commands/add.ts
1930
+ init_esm_shims();
1931
+ init_utils();
1932
+ init_config();
1933
+ init_constants();
1934
+ init_SandboxRenderer();
1935
+ import fs12 from "fs-extra";
1936
+ import path14 from "path";
1937
+ import pc8 from "picocolors";
1938
+ import prompts3 from "prompts";
1939
+ async function add(options) {
1940
+ let { name, type, displayName, description } = options;
1941
+ const cwd = process.cwd();
1942
+ const pkgPath = path14.join(cwd, "package.json");
1943
+ if (!fs12.existsSync(pkgPath)) {
1944
+ logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728 ChatBI-V \u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u6B64\u547D\u4EE4\u3002");
1945
+ return;
1946
+ }
1947
+ const pkg = await fs12.readJson(pkgPath);
1948
+ const isMonorepo = pkg.workspaces && (pkg.workspaces.includes("plugins/*") || pkg.workspaces.packages?.includes("plugins/*"));
1949
+ if (!isMonorepo) {
1950
+ logger.error("\u5F53\u524D\u4E0D\u662F Monorepo \u9879\u76EE\uFF0C\u65E0\u6CD5\u6DFB\u52A0\u63D2\u4EF6 (\u8BF7\u5728\u5305\u542B plugins/ \u5DE5\u4F5C\u7A7A\u95F4\u7684\u9879\u76EE\u4E2D\u8FD0\u884C)");
1951
+ process.exit(1);
1952
+ }
1953
+ const response = await prompts3([
1954
+ {
1955
+ type: name ? null : "text",
1956
+ name: "pluginName",
1957
+ message: "\u8BF7\u8F93\u5165\u63D2\u4EF6\u540D\u79F0 (ID, \u5EFA\u8BAE\u5C0F\u5199\u548C\u4E2D\u5212\u7EBF):",
1958
+ initial: "my-custom-plugin",
1959
+ validate: (value) => /^[a-z0-9-]+$/.test(value) || "\u540D\u79F0\u53EA\u80FD\u5305\u542B\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E2D\u5212\u7EBF"
1960
+ },
1961
+ {
1962
+ type: displayName ? null : "text",
1963
+ name: "pluginDisplayName",
1964
+ message: "\u8BF7\u8F93\u5165\u63D2\u4EF6\u663E\u793A\u540D\u79F0 (\u4E2D\u6587):",
1965
+ initial: (prev) => prev || name
1966
+ },
1967
+ {
1968
+ type: description ? null : "text",
1969
+ name: "pluginDescription",
1970
+ message: "\u8BF7\u8F93\u5165\u63D2\u4EF6\u63CF\u8FF0:",
1971
+ initial: "\u4E00\u4E2A\u7B80\u5355\u7684 ChatBI-V \u63D2\u4EF6"
1972
+ },
1973
+ {
1974
+ type: type ? null : "select",
1975
+ name: "pluginType",
1976
+ message: "\u8BF7\u9009\u62E9\u63D2\u4EF6\u7C7B\u578B:",
1977
+ choices: [
1978
+ { title: "Business (\u4E1A\u52A1\u63D2\u4EF6)", value: "business", description: "\u5305\u542B UI \u754C\u9762\u548C\u4E1A\u52A1\u903B\u8F91" },
1979
+ { title: "System (\u7CFB\u7EDF\u63D2\u4EF6)", value: "system", description: "\u4FA7\u91CD\u4E8E\u5E95\u5C42\u80FD\u529B\u548C\u7CFB\u7EDF\u6269\u5C55" }
1980
+ ],
1981
+ initial: 0
1982
+ }
1983
+ ], {
1984
+ onCancel: () => {
1985
+ logger.warn("\u5DF2\u53D6\u6D88\u6DFB\u52A0\u63D2\u4EF6");
1986
+ process.exit(0);
1987
+ }
1988
+ });
1989
+ name = name || response.pluginName;
1990
+ type = type || response.pluginType;
1991
+ displayName = displayName || response.pluginDisplayName || name;
1992
+ description = description || response.pluginDescription || "";
1993
+ let cleanName = name;
1994
+ if (cleanName.endsWith("-plugin")) {
1995
+ cleanName = cleanName.replace(/-plugin$/, "");
1996
+ }
1997
+ const folderName = cleanName.startsWith("plugin-") ? cleanName : `plugin-${cleanName}`;
1998
+ const pluginDir = path14.resolve(cwd, "plugins", folderName);
1999
+ if (fs12.existsSync(pluginDir)) {
2000
+ logger.error(`\u63D2\u4EF6\u76EE\u5F55 ${folderName} \u5DF2\u5B58\u5728\u3002`);
2001
+ return;
2002
+ }
2003
+ const spinner = createSpinner(`\u6B63\u5728\u6DFB\u52A0\u65B0\u63D2\u4EF6: ${pc8.bold(name)}...`).start();
2004
+ const myCliRoot = await getCliRoot();
2005
+ const templateDir = path14.join(myCliRoot, "templates/plugin");
2006
+ if (!fs12.existsSync(templateDir)) {
2007
+ spinner.fail("\u627E\u4E0D\u5230\u63D2\u4EF6\u6A21\u677F");
2008
+ throw new Error(`\u627E\u4E0D\u5230\u63D2\u4EF6\u6A21\u677F: ${templateDir}`);
2009
+ }
2010
+ const targetDir = pluginDir;
2011
+ spinner.text = "\u6B63\u5728\u52A0\u8F7D\u914D\u7F6E...";
2012
+ const config = await ConfigManager.loadConfig(cwd);
2013
+ const corePath = await ConfigManager.resolveCoreDependency(config, pluginDir);
2014
+ const data = {
2015
+ // 兼容旧模板
2016
+ name: `@chatbi-v/${folderName}`,
2017
+ pluginId: cleanName,
2018
+ pluginType: type,
2019
+ className: cleanName.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(""),
2020
+ isBusiness: type === "business",
2021
+ corePath,
2022
+ // 新模板变量
2023
+ pluginName: cleanName,
2024
+ pluginPackageName: `@chatbi-v/${folderName}`,
2025
+ pluginVersion: "0.1.0",
2026
+ pluginDisplayName: displayName,
2027
+ pluginDescription: description,
2028
+ pluginClassName: cleanName.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(""),
2029
+ pluginPath: folderName,
2030
+ pluginFolderName: folderName,
2031
+ // Fix: 注入 tsconfigPath,确保 tsconfig.json 能正确 extend
2032
+ tsconfigPath: `../../${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json`
2033
+ };
2034
+ spinner.text = "\u6B63\u5728\u751F\u6210\u63D2\u4EF6\u6587\u4EF6...";
2035
+ await SandboxRenderer.renderDirectory(templateDir, targetDir, data);
2036
+ spinner.succeed(`\u63D2\u4EF6 ${pc8.bold(name)} \u6DFB\u52A0\u6210\u529F\uFF01`);
2037
+ printBox(
2038
+ `${pc8.green(pc8.bold("\u2728 \u63D2\u4EF6\u521B\u5EFA\u6210\u529F!"))}
2039
+
2040
+ ${pc8.white("\u9879\u76EE\u8DEF\u5F84: ")} ${pc8.cyan(`plugins/${folderName}`)}
2041
+ ${pc8.white("\u63D2\u4EF6 ID: ")} ${pc8.cyan(cleanName)}
2042
+ ${pc8.white("\u63D2\u4EF6\u7C7B\u578B: ")} ${pc8.cyan(type)}
2043
+
2044
+ ${pc8.white("\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5:")}
2045
+ ${pc8.cyan(" pnpm dev")} \u542F\u52A8\u5F00\u53D1\u73AF\u5883\u67E5\u770B\u6548\u679C`,
2046
+ "Plugin Created"
2047
+ );
2048
+ }
2049
+
2050
+ // src/commands/gl.ts
2051
+ init_esm_shims();
2052
+ init_utils();
2053
+ import fs13 from "fs-extra";
2054
+ import path15 from "path";
2055
+ import pc9 from "picocolors";
2056
+ import prompts4 from "prompts";
2057
+ import { execa as execa3 } from "execa";
2058
+ async function gl(options) {
2059
+ const { type: initialType, prompt: initialPrompt } = options;
2060
+ const cwd = process.cwd();
2061
+ const pkgPath = path15.join(cwd, "package.json");
2062
+ if (!fs13.existsSync(pkgPath)) {
2063
+ logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728 ChatBI-V \u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u6B64\u547D\u4EE4\u3002");
2064
+ return;
2065
+ }
2066
+ const response = await prompts4([
2067
+ {
2068
+ type: initialType ? null : "select",
2069
+ name: "genType",
2070
+ message: "\u8BF7\u9009\u62E9 AI \u811A\u624B\u67B6\u6307\u4EE4:",
2071
+ choices: [
2072
+ { title: "\u{1F916} smart", value: "smart", description: "\u667A\u80FD\u51B3\u7B56 (\u6839\u636E\u9700\u6C42\u81EA\u52A8\u9009\u62E9\u5DE5\u5177)" },
2073
+ { title: "\u{1F50C} plugin", value: "plugin", description: "\u751F\u6210\u65B0\u63D2\u4EF6" },
2074
+ { title: "\u{1F9E9} component", value: "component", description: "\u751F\u6210\u4E1A\u52A1\u7EC4\u4EF6" },
2075
+ { title: "\u{1F4E1} api", value: "api", description: "\u751F\u6210 API \u5B9A\u4E49\u4E0E\u8BF7\u6C42\u51FD\u6570" },
2076
+ { title: "\u{1F3AD} mock", value: "mock", description: "\u751F\u6210 Mock \u6D4B\u8BD5\u6570\u636E" },
2077
+ { title: "\u{1F6E0}\uFE0F util", value: "util", description: "\u751F\u6210\u5DE5\u5177\u51FD\u6570" },
2078
+ { title: "\u{1F4C4} doc", value: "doc", description: "\u751F\u6210\u9879\u76EE\u6587\u6863" },
2079
+ { title: "\u2728 chat", value: "chat", description: "\u81EA\u7531\u5BF9\u8BDD" }
2080
+ ],
2081
+ initial: 0
2082
+ },
2083
+ {
2084
+ type: (prev, values) => initialPrompt || values.genType === "chat" ? null : "text",
2085
+ name: "userPrompt",
2086
+ message: "\u8BF7\u8F93\u5165\u8BE6\u7EC6\u9700\u6C42\u63CF\u8FF0:",
2087
+ initial: initialPrompt || ""
2088
+ }
2089
+ ], {
2090
+ onCancel: () => {
2091
+ logger.warn("\u5DF2\u53D6\u6D88 AI \u751F\u6210");
2092
+ process.exit(0);
2093
+ }
2094
+ });
2095
+ const genType = initialType || response.genType;
2096
+ const userPrompt = initialPrompt || response.userPrompt;
2097
+ if (!userPrompt && genType !== "chat") {
2098
+ logger.error("\u9700\u6C42\u63CF\u8FF0\u4E0D\u80FD\u4E3A\u7A7A\u3002");
2099
+ return;
2100
+ }
2101
+ logger.info(`\u6B63\u5728\u547C\u53EB AI \u5F15\u64CE [\u6A21\u5F0F: ${pc9.bold(genType)}]...`);
2102
+ const toolsContext = `
2103
+ [Available Tools & Capabilities]
2104
+ - Tool: plugin -> For creating new feature modules. Requires: name, type (business|system).
2105
+ - Tool: component -> For UI elements. Tech: AntD5, Tailwind.
2106
+ - Tool: api -> For network requests. Structure: src/api/[name].ts, uses shared request util, defines TS interfaces.
2107
+ - Tool: mock -> For dev data. Structure: mock/[name].ts, follows Mock.js or MSW format.
2108
+ - Tool: util -> For pure functions. Structure: src/utils/[name].ts, requires unit tests.
2109
+ - Tool: doc -> For documentation. Format: Markdown, structure: docs/[type]/[name].md.
2110
+
2111
+ [Tool Functions Implementation Details]
2112
+ - API Function: Should include request method, URL, params/data types, and response type. Use '@chatbi-v/core/request'.
2113
+ - Mock Function: Should provide realistic data based on API definition.
2114
+ - Plugin Function: Should follow the Micro-Kernel architecture, registering to 'pluginManager'.
2115
+
2116
+ [Requirement Slots / Missing Info]
2117
+ If the user's request is ambiguous or missing key information, you MUST output: "SLOT_REQUIRED: [Field Name] | [Question to User]".
2118
+ `.trim();
2119
+ const templatesContext = `
2120
+ [Project Templates Structure]
2121
+ - Plugin: class extends Plugin, metadata: { id, name, version, type, routes, extensions }.
2122
+ - API: export const fetchData = (params: T) => request.get<R>('/url', { params }).
2123
+ - Mock: export default { 'GET /api/test': { code: 200, data: {} } }.
2124
+ - UI: React 18, Ant Design 5, Tailwind CSS 3.
2125
+ `.trim();
2126
+ const systemContext = `[Context: ChatBI-V System | Dir: ${cwd} | Tech: React18, AntD5, Tailwind, Micro-Kernel]
2127
+ ${toolsContext}
2128
+ ${templatesContext}
2129
+
2130
+ [Decision Logic]
2131
+ If genType is 'smart', you must first decide which tool is most appropriate.
2132
+ If the requirement is clear, proceed with generation.
2133
+ If not, use the SLOT_REQUIRED format.`.trim();
2134
+ const finalPrompt = userPrompt ? `${systemContext}
2135
+
2136
+ [User Request]: ${userPrompt}` : systemContext;
2137
+ const geminiCmd = genType === "smart" ? "chat" : genType;
2138
+ const spinner = createSpinner("AI \u5F15\u64CE\u6B63\u5728\u601D\u8003\u4E2D... (\u53EF\u80FD\u9700\u8981\u51E0\u5341\u79D2\uFF0C\u8BF7\u8010\u5FC3\u7B49\u5F85)");
2139
+ let currentPrompt = finalPrompt;
2140
+ let retry = true;
2141
+ while (retry) {
2142
+ spinner.start();
2143
+ try {
2144
+ const { stdout } = await execa3("gemini", [geminiCmd, currentPrompt], {
2145
+ stdio: "pipe"
2146
+ });
2147
+ spinner.stop();
2148
+ if (stdout.includes("SLOT_REQUIRED:")) {
2149
+ const slots = [];
2150
+ const lines = stdout.split("\n");
2151
+ for (const line of lines) {
2152
+ if (line.includes("SLOT_REQUIRED:")) {
2153
+ const match = line.match(/SLOT_REQUIRED:\s*([^|]+)\|\s*(.+)/);
2154
+ if (match) {
2155
+ slots.push({
2156
+ type: "text",
2157
+ name: match[1].trim(),
2158
+ message: match[2].trim()
2159
+ });
2160
+ }
2161
+ }
2162
+ }
2163
+ if (slots.length > 0) {
2164
+ logger.info(pc9.yellow("\n\u{1F4DD} AI \u9700\u8981\u66F4\u591A\u4FE1\u606F\u4EE5\u7EE7\u7EED:"));
2165
+ const answers = await prompts4(slots, {
2166
+ onCancel: () => process.exit(0)
2167
+ });
2168
+ const answerContext = Object.entries(answers).map(([k, v]) => `[${k}]: ${v}`).join("\n");
2169
+ currentPrompt += `
2170
+
2171
+ [User Answers]:
2172
+ ${answerContext}
2173
+
2174
+ Please proceed with generation based on these answers.`;
2175
+ logger.info("\u6B63\u5728\u6839\u636E\u60A8\u7684\u53CD\u9988\u91CD\u65B0\u547C\u53EB AI...");
2176
+ continue;
2177
+ }
2178
+ }
2179
+ console.log("\n" + stdout);
2180
+ retry = false;
2181
+ logger.success(`AI \u547D\u4EE4 [gemini ${geminiCmd}] \u6267\u884C\u5B8C\u6BD5!`);
2182
+ } catch (error) {
2183
+ spinner.stop();
2184
+ if (error.code === "ENOENT") {
2185
+ logger.error("\u672A\u5728\u7CFB\u7EDF\u4E2D\u627E\u5230 `gemini-cli` \u547D\u4EE4\u3002");
2186
+ logger.info(pc9.yellow("\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5 gemini-cli \u5E76\u5C06\u5176\u6DFB\u52A0\u5230\u7CFB\u7EDF PATH \u4E2D\u3002"));
2187
+ } else {
2188
+ logger.error(`AI \u751F\u6210\u8FC7\u7A0B\u4E2D\u51FA\u9519: ${error.message}`);
2189
+ }
2190
+ throw error;
2191
+ }
2192
+ }
2193
+ }
2194
+
2195
+ // src/index.ts
2196
+ init_sync();
2197
+
2198
+ // src/commands/doctor.ts
2199
+ init_esm_shims();
2200
+ init_utils();
2201
+ init_sandbox();
2202
+ init_corekit();
2203
+ import fs14 from "fs-extra";
2204
+ import path16 from "path";
2205
+ import pc10 from "picocolors";
2206
+ import glob from "fast-glob";
2207
+ async function doctor(options = {}) {
2208
+ logger.info("\u6B63\u5728\u8BCA\u65AD\u9879\u76EE\u5065\u5EB7\u72B6\u51B5...\n");
2209
+ const cwd = process.cwd();
2210
+ let hasIssues = false;
2211
+ const issues = [];
2212
+ logger.info(pc10.bold("Step 1: \u68C0\u67E5\u57FA\u7840\u73AF\u5883..."));
2213
+ const nodeVersion = process.version;
2214
+ if (parseInt(nodeVersion.slice(1).split(".")[0]) < 18) {
2215
+ logger.error(`Node.js \u7248\u672C\u592A\u4F4E: ${nodeVersion} (\u8981\u6C42 >=18)`);
2216
+ hasIssues = true;
2217
+ issues.push(`Node.js \u7248\u672C\u8FC7\u4F4E (${nodeVersion})`);
2218
+ } else {
2219
+ logger.success(`Node.js \u7248\u672C: ${nodeVersion}`);
2220
+ }
2221
+ try {
2222
+ const { execa: execa6 } = await import("execa");
2223
+ const { stdout: pnpmVer } = await execa6("pnpm", ["-v"]);
2224
+ logger.success(`pnpm \u7248\u672C: ${pnpmVer}`);
2225
+ } catch (e) {
2226
+ logger.warn("\u672A\u68C0\u6D4B\u5230 pnpm\uFF0C\u5EFA\u8BAE\u5B89\u88C5\u4EE5\u83B7\u5F97\u6700\u4F73\u4F53\u9A8C");
2227
+ }
2228
+ logger.info(pc10.bold("\nStep 2: \u68C0\u67E5\u5185\u6838\u6C99\u7BB1\u73AF\u5883..."));
2229
+ const version = await CoreKit.resolveVersion(cwd);
2230
+ const versionPath = Sandbox.getVersionPath(version);
2231
+ if (!fs14.existsSync(versionPath)) {
2232
+ logger.error(`\u5185\u6838\u6C99\u7BB1\u7248\u672C ${version} \u5C1A\u672A\u5B89\u88C5`);
2233
+ console.log(pc10.gray(` \u5EFA\u8BAE\u8FD0\u884C 'chatbi sync' \u6216 'chatbi use ${version}' \u8FDB\u884C\u5B89\u88C5\u3002`));
2234
+ hasIssues = true;
2235
+ issues.push(`\u5185\u6838\u6C99\u7BB1\u672A\u5B89\u88C5 (${version})`);
2236
+ } else {
2237
+ logger.success(`\u5185\u6838\u6C99\u7BB1\u5C31\u7EEA (\u7248\u672C: ${version})`);
2238
+ const sandboxNm = path16.join(versionPath, "node_modules");
2239
+ if (!fs14.existsSync(sandboxNm)) {
2240
+ logger.warn("\u6C99\u7BB1\u4F9D\u8D56\u672A\u5B89\u88C5\uFF0C\u5C06\u5BFC\u81F4\u6784\u5EFA\u5931\u8D25");
2241
+ hasIssues = true;
2242
+ issues.push("\u6C99\u7BB1\u4F9D\u8D56\u7F3A\u5931");
2243
+ }
2244
+ const missingDeps = [];
2245
+ for (const dep of Sandbox.CORE_PACKAGES) {
2246
+ if (!fs14.existsSync(path16.join(sandboxNm, dep))) {
2247
+ missingDeps.push(dep);
2248
+ }
2249
+ }
2250
+ if (missingDeps.length > 0) {
2251
+ }
2252
+ }
2253
+ logger.info(pc10.bold("\nStep 3: \u68C0\u67E5\u865A\u62DF\u4F9D\u8D56\u6620\u5C04..."));
2254
+ const chatbiDir = path16.join(cwd, ".chatbi");
2255
+ if (!fs14.existsSync(chatbiDir)) {
2256
+ logger.warn("\u672A\u53D1\u73B0\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E (.chatbi \u76EE\u5F55)");
2257
+ hasIssues = true;
2258
+ issues.push("\u7F3A\u5931 .chatbi \u76EE\u5F55");
2259
+ } else {
2260
+ const pathsJson = path16.join(chatbiDir, "tsconfig.paths.json");
2261
+ const aliasJson = path16.join(chatbiDir, "vite.alias.json");
2262
+ if (!fs14.existsSync(pathsJson) || !fs14.existsSync(aliasJson)) {
2263
+ logger.warn("\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B8C\u6574");
2264
+ hasIssues = true;
2265
+ issues.push("\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E\u4E0D\u5B8C\u6574");
2266
+ } else {
2267
+ logger.success("\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E\u5DF2\u751F\u6210");
2268
+ }
2269
+ }
2270
+ const tsConfigPath = path16.join(cwd, "tsconfig.json");
2271
+ if (fs14.existsSync(tsConfigPath)) {
2272
+ try {
2273
+ const tsConfig = await fs14.readJson(tsConfigPath);
2274
+ const extendsPath = tsConfig.extends;
2275
+ const expectedPaths = ["./.chatbi/tsconfig.paths.json", ".chatbi/tsconfig.paths.json"];
2276
+ let hasExtend = false;
2277
+ if (typeof extendsPath === "string") {
2278
+ hasExtend = expectedPaths.includes(extendsPath);
2279
+ } else if (Array.isArray(extendsPath)) {
2280
+ hasExtend = extendsPath.some((p) => expectedPaths.includes(p));
2281
+ }
2282
+ if (!hasExtend) {
2283
+ logger.warn("tsconfig.json \u672A\u7EE7\u627F\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E");
2284
+ hasIssues = true;
2285
+ issues.push("tsconfig.json \u914D\u7F6E\u7F3A\u5931");
2286
+ } else {
2287
+ logger.success("tsconfig.json \u914D\u7F6E\u6B63\u5E38");
2288
+ }
2289
+ } catch (e) {
2290
+ logger.error("\u89E3\u6790 tsconfig.json \u5931\u8D25");
2291
+ }
2292
+ }
2293
+ const viteConfigPath = path16.join(cwd, "vite.config.ts");
2294
+ if (fs14.existsSync(viteConfigPath)) {
2295
+ const content = await fs14.readFile(viteConfigPath, "utf-8");
2296
+ if (!content.includes("vite.alias.json")) {
2297
+ logger.warn("vite.config.ts \u53EF\u80FD\u672A\u52A0\u8F7D\u865A\u62DF\u522B\u540D\u914D\u7F6E");
2298
+ }
2299
+ }
2300
+ logger.info(pc10.bold("\nStep 4: \u626B\u63CF\u4EE3\u7801\u89C4\u5219..."));
2301
+ const rules = [
2302
+ {
2303
+ id: "plugin-lifecycle-init",
2304
+ description: "\u63D2\u4EF6\u751F\u547D\u5468\u671F init() \u5DF2\u53D8\u66F4\u4E3A onLoad()",
2305
+ pattern: /async\s+init\s*\(\s*context\s*:\s*PluginContext\s*\)/g,
2306
+ fix: (content) => content.replace(/async\s+init\s*\(\s*context\s*:\s*PluginContext\s*\)/g, "async onLoad(context: PluginContext)")
2307
+ },
2308
+ {
2309
+ id: "plugin-lifecycle-destroy",
2310
+ description: "\u63D2\u4EF6\u751F\u547D\u5468\u671F destroy() \u5DF2\u53D8\u66F4\u4E3A onUnload()",
2311
+ pattern: /async\s+destroy\s*\(\s*\)/g,
2312
+ fix: (content) => content.replace(/async\s+destroy\s*\(\s*\)/g, "async onUnload()")
2313
+ }
2314
+ ];
2315
+ const files = await glob(["src/**/*.{ts,tsx}"], { cwd, absolute: true });
2316
+ const codeIssues = [];
2317
+ if (files.length > 0) {
2318
+ const scanSpinner = createSpinner(`\u6B63\u5728\u626B\u63CF ${files.length} \u4E2A\u6587\u4EF6...`).start();
2319
+ for (const file of files) {
2320
+ const content = await fs14.readFile(file, "utf-8");
2321
+ for (const rule of rules) {
2322
+ if (rule.pattern.test(content)) {
2323
+ codeIssues.push({
2324
+ file,
2325
+ ruleId: rule.id,
2326
+ description: rule.description,
2327
+ rule
2328
+ });
2329
+ }
2330
+ }
2331
+ }
2332
+ if (codeIssues.length > 0) {
2333
+ scanSpinner.fail(`\u53D1\u73B0 ${codeIssues.length} \u4E2A\u4EE3\u7801\u89C4\u8303\u95EE\u9898`);
2334
+ hasIssues = true;
2335
+ codeIssues.forEach((issue) => {
2336
+ const relativePath = path16.relative(cwd, issue.file);
2337
+ issues.push(`\u4EE3\u7801\u89C4\u8303 [${issue.ruleId}]: ${relativePath}`);
2338
+ });
2339
+ } else {
2340
+ scanSpinner.succeed("\u4EE3\u7801\u89C4\u8303\u68C0\u67E5\u901A\u8FC7");
2341
+ }
2342
+ }
2343
+ if (!hasIssues) {
2344
+ printBox(
2345
+ pc10.green(pc10.bold("\u2728 \u8BCA\u65AD\u5B8C\u6210\uFF1A\u9879\u76EE\u4E00\u5207\u6B63\u5E38\uFF01")),
2346
+ "Doctor Report"
2347
+ );
2348
+ } else {
2349
+ const issueList = issues.map((i) => pc10.red(`\u2022 ${i}`)).join("\n");
2350
+ printBox(
2351
+ `${pc10.yellow(pc10.bold("\u26A0\uFE0F \u8BCA\u65AD\u5B8C\u6210\uFF1A\u53D1\u73B0\u4EE5\u4E0B\u95EE\u9898"))}
2352
+
2353
+ ${issueList}
2354
+
2355
+ ${pc10.cyan("\u5EFA\u8BAE\u6839\u636E\u63D0\u793A\u8FDB\u884C\u4FEE\u590D")}`,
2356
+ "Doctor Report"
2357
+ );
2358
+ if (options.fix) {
2359
+ if (codeIssues.length > 0) {
2360
+ const fixSpinner = createSpinner("\u6B63\u5728\u4FEE\u590D\u4EE3\u7801\u89C4\u8303\u95EE\u9898...").start();
2361
+ for (const issue of codeIssues) {
2362
+ const content = await fs14.readFile(issue.file, "utf-8");
2363
+ const newContent = issue.rule.fix(content);
2364
+ await fs14.writeFile(issue.file, newContent);
2365
+ }
2366
+ fixSpinner.succeed("\u4EE3\u7801\u4FEE\u590D\u5B8C\u6210");
2367
+ }
2368
+ logger.info("\u6B63\u5728\u4FEE\u590D\u73AF\u5883\u914D\u7F6E...");
2369
+ const { sync: sync2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
2370
+ await sync2({ force: true });
2371
+ logger.success("\u81EA\u52A8\u4FEE\u590D\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u8BCA\u65AD\u3002");
2372
+ }
2373
+ }
2374
+ }
2375
+
2376
+ // src/commands/discover.ts
2377
+ init_esm_shims();
2378
+ init_corekit();
2379
+ init_utils();
2380
+ import pc11 from "picocolors";
2381
+ async function discover() {
2382
+ const cwd = process.cwd();
2383
+ const spinner = createSpinner("\u6B63\u5728\u626B\u63CF\u9879\u76EE\u4E2D\u7684\u63D2\u4EF6...").start();
2384
+ const plugins = await CoreKit.discoverPlugins(cwd);
2385
+ if (plugins.length === 0) {
2386
+ spinner.warn("\u672A\u53D1\u73B0\u4EFB\u4F55\u63D2\u4EF6");
2387
+ logger.info(pc11.gray("\u8BF7\u786E\u4FDD\u63D2\u4EF6\u4F4D\u4E8E plugins/ \u76EE\u5F55\u4E0B\uFF0C\u4E14\u5305\u542B package.json\u3002"));
2388
+ } else {
2389
+ spinner.succeed(`\u53D1\u73B0\u4E86 ${pc11.cyan(plugins.length)} \u4E2A\u63D2\u4EF6`);
2390
+ const pluginList = plugins.map((p) => `- ${pc11.bold(p.name)} ${pc11.gray(`(${p.id})`)}
2391
+ ${pc11.gray(p.path)}`).join("\n\n");
2392
+ printBox(
2393
+ `${pc11.green(pc11.bold("\u2728 \u63D2\u4EF6\u626B\u63CF\u7ED3\u679C"))}
2394
+
2395
+ ${pluginList}`,
2396
+ "Plugin Discovery"
2397
+ );
2398
+ }
2399
+ }
2400
+
2401
+ // src/commands/ls.ts
2402
+ init_esm_shims();
2403
+ init_corekit();
2404
+ init_sandbox();
2405
+ init_utils();
2406
+ import pc12 from "picocolors";
2407
+ async function ls() {
2408
+ const versions = await CoreKit.listVersions();
2409
+ const currentVersion = await CoreKit.resolveVersion(process.cwd());
2410
+ const globalCurrentVersion = await CoreKit.resolveVersion();
2411
+ logger.info("\u5DF2\u5B89\u88C5\u7684\u5185\u6838\u6C99\u7BB1\u7248\u672C:");
2412
+ if (versions.length === 0) {
2413
+ logger.warn("\u5C1A\u672A\u5B89\u88C5\u4EFB\u4F55\u7248\u672C\uFF0C\u8BF7\u8FD0\u884C chatbi sync \u8FDB\u884C\u5B89\u88C5\u3002");
2414
+ } else {
2415
+ const list = versions.map((v) => {
2416
+ const isGlobalCurrent = v === globalCurrentVersion;
2417
+ const isProjectCurrent = v === currentVersion;
2418
+ let prefix = " ";
2419
+ if (isProjectCurrent) {
2420
+ prefix = pc12.green(" *");
2421
+ } else if (isGlobalCurrent) {
2422
+ prefix = pc12.blue(" >");
2423
+ }
2424
+ let suffix = "";
2425
+ if (isProjectCurrent && isGlobalCurrent) {
2426
+ suffix = pc12.gray(" (\u5F53\u524D\u9879\u76EE & \u5168\u5C40)");
2427
+ } else if (isProjectCurrent) {
2428
+ suffix = pc12.gray(" (\u5F53\u524D\u9879\u76EE)");
2429
+ } else if (isGlobalCurrent) {
2430
+ suffix = pc12.gray(" (\u5168\u5C40)");
2431
+ }
2432
+ return `${prefix} ${pc12.white(v)}${suffix}`;
2433
+ }).join("\n");
2434
+ printBox(
2435
+ list + pc12.gray("\n\n\u63D0\u793A: * \u5F53\u524D\u9879\u76EE\u4F7F\u7528, > \u5168\u5C40\u9ED8\u8BA4\u4F7F\u7528"),
2436
+ "Kernel Versions"
2437
+ );
2438
+ }
2439
+ await Sandbox.visualizeStatus(process.cwd());
2440
+ }
2441
+
2442
+ // src/commands/use.ts
2443
+ init_esm_shims();
2444
+ init_sandbox();
2445
+ init_corekit();
2446
+ init_sync();
2447
+ init_utils();
2448
+ import fs15 from "fs-extra";
2449
+ import path17 from "path";
2450
+ async function use(version, options = {}) {
2451
+ const versions = await CoreKit.listVersions();
2452
+ if (!versions.includes(version)) {
2453
+ logger.warn(`\u7248\u672C ${version} \u5C1A\u672A\u5B89\u88C5\uFF0C\u6B63\u5728\u5C1D\u8BD5\u5B89\u88C5...`);
2454
+ await Sandbox.prepare(version);
2455
+ }
2456
+ if (options.global) {
2457
+ await Sandbox.useVersion(version);
2458
+ logger.success(`\u5DF2\u5207\u6362\u5168\u5C40\u5185\u6838\u7248\u672C\u81F3: ${version}`);
2459
+ } else {
2460
+ const cwd = process.cwd();
2461
+ const versionFilePath = path17.join(cwd, ".chatbi-version");
2462
+ await fs15.writeFile(versionFilePath, version, "utf-8");
2463
+ logger.success(`\u5DF2\u5207\u6362\u5F53\u524D\u9879\u76EE\u5185\u6838\u7248\u672C\u4E3A: ${version}`);
2464
+ }
2465
+ await sync({ version, force: false });
2466
+ }
2467
+
2468
+ // src/index.ts
2469
+ init_fetch();
2470
+
2471
+ // src/commands/install.ts
2472
+ init_esm_shims();
2473
+ init_sandbox();
2474
+ init_utils();
2475
+ import fs16 from "fs-extra";
2476
+ import path19 from "path";
2477
+ import pc14 from "picocolors";
2478
+ import { execa as execa5 } from "execa";
2479
+ async function install(target) {
2480
+ if (target.endsWith(".tgz") && fs16.existsSync(target)) {
2481
+ const spinner = createSpinner(`\u6B63\u5728\u5B89\u88C5\u672C\u5730\u79BB\u7EBF\u5305: ${pc14.bold(target)}...`).start();
2482
+ try {
2483
+ const tgzPath = path19.resolve(target);
2484
+ const match = path19.basename(target).match(/chatbi-core-(.+)\.tgz/);
2485
+ let version = "unknown";
2486
+ if (match) {
2487
+ version = match[1];
2488
+ }
2489
+ if (version === "unknown") {
2490
+ spinner.warn("\u65E0\u6CD5\u4ECE\u6587\u4EF6\u540D\u8BC6\u522B\u7248\u672C\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u65F6\u95F4\u6233\u4F5C\u4E3A\u7248\u672C\u53F7");
2491
+ version = `local-${Date.now()}`;
2492
+ }
2493
+ const versionRoot = Sandbox.getVersionRoot();
2494
+ await fs16.ensureDir(versionRoot);
2495
+ spinner.text = "\u6B63\u5728\u89E3\u538B\u6587\u4EF6...";
2496
+ await execa5("tar", ["-xzf", tgzPath, "-C", versionRoot]);
2497
+ spinner.succeed(`\u672C\u5730\u5305\u5DF2\u5B89\u88C5\u81F3\u6C99\u7BB1: ${version}`);
2498
+ spinner.text = "\u6B63\u5728\u51C6\u5907\u5185\u6838\u73AF\u5883...";
2499
+ await Sandbox.prepare(version);
2500
+ spinner.succeed("\u5185\u6838\u73AF\u5883\u5C31\u7EEA");
2501
+ printBox(
2502
+ pc14.green(pc14.bold("\u2728 \u672C\u5730\u5185\u6838\u5B89\u88C5\u6210\u529F!")) + "\n\n" + pc14.white("\u7248\u672C: ") + pc14.cyan(version) + "\n" + pc14.white("\u8DEF\u5F84: ") + pc14.gray(Sandbox.getVersionPath(version)),
2503
+ "Install Success"
2504
+ );
2505
+ } catch (e) {
2506
+ spinner.fail("\u5B89\u88C5\u5931\u8D25");
2507
+ throw e;
2508
+ }
2509
+ } else {
2510
+ const { fetch: fetch2 } = await Promise.resolve().then(() => (init_fetch(), fetch_exports));
2511
+ await fetch2(target);
2512
+ }
2513
+ }
2514
+
2515
+ // src/commands/clean.ts
2516
+ init_esm_shims();
2517
+ init_sandbox();
2518
+ async function clean(options) {
2519
+ const cwd = process.cwd();
2520
+ await Sandbox.clean(cwd, options.deep);
2521
+ }
2522
+
2523
+ // package.json
2524
+ var package_default = {
2525
+ name: "@chatbi-v/cli",
2526
+ version: "2.0.5",
2527
+ description: "Standardized CLI tooling for ChatBI Monorepo",
2528
+ type: "module",
2529
+ main: "dist/index.js",
2530
+ module: "dist/index.js",
2531
+ types: "dist/index.d.ts",
2532
+ bin: {
2533
+ "chatbi-cli": "./bin/chatbi-cli.js"
2534
+ },
2535
+ files: [
2536
+ "dist",
2537
+ "bin",
2538
+ "templates"
2539
+ ],
2540
+ publishConfig: {
2541
+ access: "public"
2542
+ },
2543
+ scripts: {
2544
+ build: "tsup",
2545
+ dev: "tsup --watch",
2546
+ test: "vitest"
2547
+ },
2548
+ dependencies: {
2549
+ boxen: "^8.0.1",
2550
+ cac: "^6.7.14",
2551
+ execa: "^8.0.1",
2552
+ "fast-glob": "^3.3.3",
2553
+ figlet: "^1.9.4",
2554
+ "fs-extra": "^11.2.0",
2555
+ "gradient-string": "^3.0.0",
2556
+ handlebars: "^4.7.8",
2557
+ jiti: "^2.6.1",
2558
+ ora: "^7.0.1",
2559
+ picocolors: "^1.0.0",
2560
+ prompts: "^2.4.2",
2561
+ tsup: "^8.5.1",
2562
+ typescript: "^5.0.0",
2563
+ vite: "^5.4.21"
2564
+ },
2565
+ devDependencies: {
2566
+ "@types/boxen": "^3.0.5",
2567
+ "@types/figlet": "^1.7.0",
2568
+ "@types/fs-extra": "^11.0.0",
2569
+ "@types/gradient-string": "^1.1.6",
2570
+ "@types/node": "^20.0.0",
2571
+ "@types/prompts": "^2.4.9",
2572
+ "@vitest/coverage-v8": "1.6.1",
2573
+ tsup: "^8.5.1",
2574
+ vitest: "^1.0.0"
2575
+ }
2576
+ };
2577
+
2578
+ // src/index.ts
2579
+ init_utils();
2580
+ var cli = cac("chatbi-cli");
2581
+ var showHeader = () => {
2582
+ const title = figlet.textSync("ChatBI-V CLI", { font: "Standard" });
2583
+ console.log(gradient.pastel.multiline(title));
2584
+ console.log(
2585
+ boxen2(pc16.cyan(`ChatBI-V \u7EDF\u4E00\u5F00\u53D1\u5DE5\u5177 v${package_default.version}`), {
2586
+ padding: 0,
2587
+ margin: { top: 1, bottom: 1 },
2588
+ borderStyle: "round",
2589
+ borderColor: "cyan",
2590
+ title: "CoreKit Enabled",
2591
+ titleAlignment: "center"
2592
+ })
2593
+ );
2594
+ };
2595
+ var wrapAction = (action, commandName) => {
2596
+ return async (...args) => {
191
2597
  showHeader();
192
- sections[0].body = picocolors_1.default.white('ChatBI-V 开发者命令行工具,助力快速开发和构建插件。');
2598
+ try {
2599
+ await action(...args);
2600
+ } catch (e) {
2601
+ logger.error(`${commandName} \u6267\u884C\u5931\u8D25`, e);
2602
+ process.exit(1);
2603
+ }
2604
+ };
2605
+ };
2606
+ cli.command("dev", "\u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668").alias("d").option("--port <port>", "\u7AEF\u53E3\u53F7").action(wrapAction(dev, "dev"));
2607
+ cli.command("build", "\u6784\u5EFA\u5F53\u524D\u9879\u76EE").alias("b").option("--watch", "\u5F00\u542F\u76D1\u542C\u6A21\u5F0F").option("--force", "\u5F3A\u5236\u91CD\u65B0\u521D\u59CB\u5316\u73AF\u5883 (\u6E05\u7406\u7F13\u5B58)").action(wrapAction(build, "build"));
2608
+ cli.command("fetch <version>", "\u83B7\u53D6\u6307\u5B9A\u7248\u672C\u7684\u5185\u6838 (\u652F\u6301\u6253\u5305)").option("--pack", "\u6253\u5305\u4E3A\u79BB\u7EBF\u5B89\u88C5\u5305 (.tgz)").action(wrapAction(fetch, "fetch"));
2609
+ cli.command("install <target>", "\u5B89\u88C5\u5185\u6838 (\u652F\u6301\u7248\u672C\u53F7\u6216\u79BB\u7EBF\u5305\u8DEF\u5F84)").action(wrapAction(install, "install"));
2610
+ cli.command("init [name]", "\u521D\u59CB\u5316\u4E00\u4E2A\u65B0\u7684\u4E1A\u52A1\u63D2\u4EF6\u9879\u76EE").alias("create").alias("i").option("--project-type <type>", "\u9879\u76EE\u7C7B\u578B (monorepo | app | plugin)").option("--include-app", "Monorepo \u4E2D\u5305\u542B App").option("--no-include-app", "Monorepo \u4E2D\u4E0D\u5305\u542B App").option("--include-plugin", "Monorepo \u4E2D\u5305\u542B Plugin").option("--no-include-plugin", "Monorepo \u4E2D\u4E0D\u5305\u542B Plugin").option("--plugin-type <type>", "\u63D2\u4EF6\u7C7B\u578B (business | system)").option("--theme <theme>", "\u4E3B\u9898 (standard | nebula | glass)").action(wrapAction(async (name, options) => {
2611
+ await init({
2612
+ name,
2613
+ projectType: options.projectType,
2614
+ includeApp: options.includeApp,
2615
+ includePlugin: options.includePlugin,
2616
+ pluginType: options.pluginType,
2617
+ theme: options.theme
2618
+ });
2619
+ }, "init"));
2620
+ cli.command("add [name]", "\u5728\u5F53\u524D\u9879\u76EE\u4E2D\u6DFB\u52A0\u4E00\u4E2A\u65B0\u63D2\u4EF6").option("-t, --type <type>", "\u63D2\u4EF6\u7C7B\u578B (business | system)").option("--display-name <name>", "\u63D2\u4EF6\u663E\u793A\u540D\u79F0").option("--desc <description>", "\u63D2\u4EF6\u63CF\u8FF0").action(wrapAction(async (name, options) => {
2621
+ await add({
2622
+ name,
2623
+ type: options.type,
2624
+ displayName: options.displayName,
2625
+ description: options.desc
2626
+ });
2627
+ }, "add"));
2628
+ cli.command("update [targetVersion]", "\u66F4\u65B0\u5185\u6838\u7248\u672C").alias("up").action(wrapAction(async (targetVersion) => {
2629
+ const { sync: sync2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
2630
+ await sync2({ version: targetVersion, force: true });
2631
+ logger.success("\u66F4\u65B0\u5B8C\u6210\uFF01");
2632
+ }, "update"));
2633
+ cli.command("sync", "\u540C\u6B65\u5185\u6838\u4F9D\u8D56\u4E0E\u89C4\u8303").alias("s").option("-v, --core-version <version>", "\u6307\u5B9A\u5185\u6838\u7248\u672C").option("-f, --force", "\u5F3A\u5236\u91CD\u65B0\u521D\u59CB\u5316\u5185\u6838\u6C99\u7BB1").option("--clean", "\u6E05\u7406\u5E76\u91CD\u7F6E\u6C99\u7BB1").action(wrapAction(async (options) => {
2634
+ await sync({ ...options, version: options.coreVersion });
2635
+ console.log("");
2636
+ await doctor({ fix: false });
2637
+ }, "sync"));
2638
+ cli.command("doctor", "\u8BCA\u65AD\u9879\u76EE\u5065\u5EB7\u72B6\u51B5\u5E76\u4FEE\u590D").alias("dr").option("--fix", "\u81EA\u52A8\u4FEE\u590D\u53D1\u73B0\u7684\u95EE\u9898").action(wrapAction(doctor, "doctor"));
2639
+ cli.command("list", "\u5217\u51FA\u6240\u6709\u5DF2\u5B89\u88C5\u7684\u5185\u6838\u6C99\u7BB1\u7248\u672C").alias("ls").action(wrapAction(ls, "ls"));
2640
+ cli.command("use <version>", "\u5207\u6362\u5F53\u524D\u9879\u76EE\u4F7F\u7528\u7684\u5185\u6838\u7248\u672C").alias("u").option("--global", "\u5207\u6362\u5168\u5C40\u9ED8\u8BA4\u5185\u6838\u7248\u672C").action(wrapAction(use, "use"));
2641
+ cli.command("gl", "\u4F7F\u7528 AI \u811A\u624B\u67B6\u751F\u6210\u4EE3\u7801\u6216\u6587\u6863").option("-t, --type <type>", "\u751F\u6210\u7C7B\u578B (plugin|util|doc|component)").option("-p, --prompt <prompt>", "AI \u9700\u6C42\u63CF\u8FF0").action(wrapAction(gl, "gl"));
2642
+ cli.command("discover", "\u626B\u63CF\u5E76\u53D1\u73B0\u5F53\u524D\u9879\u76EE\u4E2D\u7684\u63D2\u4EF6").action(wrapAction(discover, "discover"));
2643
+ cli.command("clean", "\u6E05\u7406 CLI \u4EA7\u751F\u7684\u7F13\u5B58\u76EE\u5F55").alias("cl").option("--deep", "\u6DF1\u5EA6\u6E05\u7406 (\u5305\u542B\u6240\u6709\u5B50\u5305\u7684 .chatbi \u76EE\u5F55\u53CA\u5168\u5C40\u6C99\u7BB1\u6839\u76EE\u5F55)").action(wrapAction(clean, "clean"));
2644
+ cli.command("bench", "\u8FD0\u884C CLI \u6027\u80FD\u57FA\u51C6\u6D4B\u8BD5").action(wrapAction(async () => {
2645
+ const { bench: bench2 } = await Promise.resolve().then(() => (init_bench(), bench_exports));
2646
+ await bench2();
2647
+ }, "bench"));
2648
+ cli.help((sections) => {
2649
+ showHeader();
2650
+ sections[0].body = pc16.white("ChatBI-V \u5F00\u53D1\u8005\u547D\u4EE4\u884C\u5DE5\u5177\uFF0C\u52A9\u529B\u5FEB\u901F\u5F00\u53D1\u548C\u6784\u5EFA\u63D2\u4EF6\u3002");
193
2651
  });
194
- cli.version(package_json_1.default.version);
195
- // 处理空命令
2652
+ cli.version(package_default.version);
196
2653
  if (process.argv.length <= 2) {
197
- cli.outputHelp();
198
- }
199
- else {
200
- cli.parse();
2654
+ cli.outputHelp();
2655
+ } else {
2656
+ cli.parse();
201
2657
  }