@chatbi-v/cli 2.1.6 → 2.1.8

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