jjb-cmd 2.5.6 → 2.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/ai-pull.js +99 -67
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "env": "prod",
5
5
  "httpMethod": "http",
6
6
  "pushMessage": "yes",
7
- "version": "2.5.6",
7
+ "version": "2.5.7",
8
8
  "description": "jjb-cmd命令行工具",
9
9
  "main": "index.js",
10
10
  "scripts": {
package/src/ai-pull.js CHANGED
@@ -18,7 +18,7 @@ const CURSOR_DB_PATH = path.join(
18
18
  // Git 仓库地址
19
19
  const AI_REPO_URL = 'http://192.168.1.242:10985/root/jjb-ai.git';
20
20
  // Git 分支/标签(默认值)
21
- const DEFAULT_BRANCH = 'v_1.0.0';
21
+ const DEFAULT_BRANCH = 'v_2.0.0';
22
22
 
23
23
  /**
24
24
  * 删除目录(回调方式,使用递归删除)
@@ -241,40 +241,72 @@ module.exports = (branch) => {
241
241
  });
242
242
  console.log(`✓ 仓库代码拉取成功(分支: ${targetBranch})`);
243
243
 
244
- // 步骤2: 复制 .ai 文件夹到当前项目
245
- console.log('步骤2: 正在复制 .ai 文件夹...');
246
- const aiSourcePath = path.join(cloneDir, '.ai');
247
- const aiTargetPath = path.join(root_path, '.ai');
244
+ // 步骤2: 将仓库 admin 下所有子文件夹同步到当前项目 .cursor/(与 admin 同名的子目录)
245
+ console.log('步骤2: 正在复制 admin 下的文件夹到 .cursor/...');
246
+ const adminPath = path.join(cloneDir, 'admin');
247
+ const cursorDir = path.join(root_path, '.cursor');
248
248
 
249
- if (!fs.existsSync(aiSourcePath)) {
250
- console.log('【Warning】:仓库中未找到 .ai 文件夹');
249
+ if (!fs.existsSync(adminPath)) {
250
+ console.log('【Warning】:仓库中未找到 admin 文件夹');
251
251
  step3();
252
252
  } else {
253
- // 如果目标目录已存在,先删除
254
- if (fs.existsSync(aiTargetPath)) {
255
- deleteDir(aiTargetPath, () => {
256
- // 复制 .ai 文件夹
257
- copyFolder(aiSourcePath, aiTargetPath, (err) => {
253
+ let subdirs;
254
+ try {
255
+ subdirs = fs.readdirSync(adminPath).filter((name) => {
256
+ const p = path.join(adminPath, name);
257
+ try {
258
+ return fs.statSync(p).isDirectory();
259
+ } catch (e) {
260
+ return false;
261
+ }
262
+ });
263
+ } catch (e) {
264
+ console.error('【Error】:读取 admin 目录失败', e.message);
265
+ cleanupAndExit(1);
266
+ return;
267
+ }
268
+
269
+ if (subdirs.length === 0) {
270
+ console.log('【Warning】:admin 下没有子文件夹可同步');
271
+ step3();
272
+ } else {
273
+ try {
274
+ if (!fs.existsSync(cursorDir)) {
275
+ fs.mkdirSync(cursorDir, { recursive: true });
276
+ }
277
+ } catch (e) {
278
+ console.error('【Error】:创建 .cursor 目录失败', e.message);
279
+ cleanupAndExit(1);
280
+ return;
281
+ }
282
+
283
+ function copyAdminDirAt(i) {
284
+ if (i >= subdirs.length) {
285
+ console.log(`✓ 已将 admin 下 ${subdirs.length} 个文件夹复制到 .cursor/(${subdirs.join(', ')})`);
286
+ step3();
287
+ return;
288
+ }
289
+ const name = subdirs[i];
290
+ const srcPath = path.join(adminPath, name);
291
+ const destPath = path.join(cursorDir, name);
292
+ const afterCopy = (err) => {
258
293
  if (err) {
259
- console.error('【Error】:复制 .ai 文件夹失败', err.message);
294
+ console.error(`【Error】:复制 admin/${name} 失败`, err.message);
260
295
  cleanupAndExit(1);
261
296
  return;
262
297
  }
263
- console.log('✓ .ai 文件夹复制成功');
264
- step3();
265
- });
266
- });
267
- } else {
268
- // 复制 .ai 文件夹
269
- copyFolder(aiSourcePath, aiTargetPath, (err) => {
270
- if (err) {
271
- console.error('【Error】:复制 .ai 文件夹失败', err.message);
272
- cleanupAndExit(1);
273
- return;
298
+ copyAdminDirAt(i + 1);
299
+ };
300
+ if (fs.existsSync(destPath)) {
301
+ deleteDir(destPath, () => {
302
+ copyFolder(srcPath, destPath, afterCopy);
303
+ });
304
+ } else {
305
+ copyFolder(srcPath, destPath, afterCopy);
274
306
  }
275
- console.log('✓ .ai 文件夹复制成功');
276
- step3();
277
- });
307
+ }
308
+
309
+ copyAdminDirAt(0);
278
310
  }
279
311
  }
280
312
  } catch (error) {
@@ -283,26 +315,26 @@ module.exports = (branch) => {
283
315
  }
284
316
  });
285
317
 
286
- // 步骤3: 复制 prompt.md Cursor user rules (SQLite 数据库)
318
+ // 步骤3: admin/rules/PROJECT.md 写入 Cursor user rules (SQLite 数据库)
287
319
  function step3() {
288
320
  console.log('步骤3: 正在更新 Cursor user rules (SQLite 数据库)...');
289
- const promptSourcePath = path.join(cloneDir, 'prompt.md');
321
+ const projectRulesPath = path.join(cloneDir, 'admin', 'rules', 'PROJECT.md');
290
322
 
291
323
  try {
292
- if (!fs.existsSync(promptSourcePath)) {
293
- console.log('【Warning】:仓库中未找到 prompt.md 文件');
324
+ if (!fs.existsSync(projectRulesPath)) {
325
+ console.log('【Warning】:仓库中未找到 admin/rules/PROJECT.md 文件');
294
326
  step4();
295
327
  return;
296
328
  }
297
329
 
298
- // 读取 prompt.md 内容
299
- const promptContent = fs.readFileSync(promptSourcePath, 'utf8');
330
+ // 读取 PROJECT.md 内容
331
+ const rulesContent = fs.readFileSync(projectRulesPath, 'utf8');
300
332
 
301
333
  // 检查数据库文件是否存在
302
334
  if (!fs.existsSync(CURSOR_DB_PATH)) {
303
335
  console.log('【Warning】:Cursor 数据库文件不存在,可能 Cursor 未安装或路径不正确');
304
336
  console.log(`【路径】:${CURSOR_DB_PATH}`);
305
- console.log('【建议】:请确保已安装 Cursor 编辑器,或手动复制 prompt.md 内容');
337
+ console.log('【建议】:请确保已安装 Cursor 编辑器,或手动复制 admin/rules/PROJECT.md 内容');
306
338
  step4();
307
339
  return;
308
340
  }
@@ -348,7 +380,7 @@ module.exports = (branch) => {
348
380
  try {
349
381
  const sqlite3 = require('sqlite3');
350
382
  // sqlite3 是异步的,需要使用回调或 Promise
351
- console.log(`【调试】:准备更新数据库,内容长度: ${promptContent.length} 字符`);
383
+ console.log(`【调试】:准备更新数据库,内容长度: ${rulesContent.length} 字符`);
352
384
 
353
385
  const db = new sqlite3.Database(CURSOR_DB_PATH, (err) => {
354
386
  if (err) {
@@ -379,8 +411,8 @@ module.exports = (branch) => {
379
411
  oldContent = String(row.value);
380
412
  }
381
413
 
382
- if (oldContent === promptContent) {
383
- console.log('✓ prompt.md 内容未变化,无需更新');
414
+ if (oldContent === rulesContent) {
415
+ console.log('✓ admin/rules/PROJECT.md 内容未变化,无需更新');
384
416
  console.log('【提示】:请重启 Cursor 编辑器以使规则生效');
385
417
  db.close();
386
418
  step4();
@@ -388,7 +420,7 @@ module.exports = (branch) => {
388
420
  }
389
421
 
390
422
  // 更新现有记录
391
- db.run("UPDATE ItemTable SET value = ? WHERE key = ?", [promptContent, 'aicontext.personalContext'], function(err) {
423
+ db.run("UPDATE ItemTable SET value = ? WHERE key = ?", [rulesContent, 'aicontext.personalContext'], function(err) {
392
424
  if (err) {
393
425
  console.error('【Error】:更新数据库失败', err.message);
394
426
  if (err.code === 'SQLITE_BUSY' || err.message.includes('locked')) {
@@ -422,15 +454,15 @@ module.exports = (branch) => {
422
454
  verifyContent = String(verifyRow.value);
423
455
  }
424
456
 
425
- if (verifyContent === promptContent) {
426
- console.log(`✓ prompt.md 已更新到 Cursor user rules (${verifyRow.len} 字节)`);
457
+ if (verifyContent === rulesContent) {
458
+ console.log(`✓ PROJECT.md 已更新到 Cursor user rules (${verifyRow.len} 字节)`);
427
459
  // 显示前几行内容确认
428
460
  const previewLines = verifyContent.split('\n').slice(0, 3).join('\n');
429
461
  console.log(`【预览】:内容前3行:\n${previewLines}${verifyContent.split('\n').length > 3 ? '...' : ''}`);
430
462
  } else {
431
463
  console.error(`【Error】:更新后内容不匹配!`);
432
- console.error(` 期望长度: ${promptContent.length}, 实际长度: ${verifyContent.length}`);
433
- console.error(` 期望前100字符: ${promptContent.substring(0, 100)}`);
464
+ console.error(` 期望长度: ${rulesContent.length}, 实际长度: ${verifyContent.length}`);
465
+ console.error(` 期望前100字符: ${rulesContent.substring(0, 100)}`);
434
466
  console.error(` 实际前100字符: ${verifyContent.substring(0, 100)}`);
435
467
  }
436
468
  } else {
@@ -445,7 +477,7 @@ module.exports = (branch) => {
445
477
  } else {
446
478
  console.log('【调试】:记录不存在,将插入新记录');
447
479
  // 插入新记录
448
- db.run("INSERT INTO ItemTable (key, value) VALUES (?, ?)", ['aicontext.personalContext', promptContent], function(err) {
480
+ db.run("INSERT INTO ItemTable (key, value) VALUES (?, ?)", ['aicontext.personalContext', rulesContent], function(err) {
449
481
  if (err) {
450
482
  console.error('【Error】:插入数据库失败', err.message);
451
483
  if (err.code === 'SQLITE_BUSY' || err.message.includes('locked')) {
@@ -478,14 +510,14 @@ module.exports = (branch) => {
478
510
  verifyContent = String(verifyRow.value);
479
511
  }
480
512
 
481
- if (verifyContent === promptContent) {
482
- console.log(`✓ prompt.md 已添加到 Cursor user rules (${verifyRow.len} 字节)`);
513
+ if (verifyContent === rulesContent) {
514
+ console.log(`✓ PROJECT.md 已添加到 Cursor user rules (${verifyRow.len} 字节)`);
483
515
  // 显示前几行内容确认
484
516
  const previewLines = verifyContent.split('\n').slice(0, 3).join('\n');
485
517
  console.log(`【预览】:内容前3行:\n${previewLines}${verifyContent.split('\n').length > 3 ? '...' : ''}`);
486
518
  } else {
487
519
  console.error(`【Error】:插入后内容不匹配!`);
488
- console.error(` 期望长度: ${promptContent.length}, 实际长度: ${verifyContent.length}`);
520
+ console.error(` 期望长度: ${rulesContent.length}, 实际长度: ${verifyContent.length}`);
489
521
  }
490
522
  } else {
491
523
  console.error('【Error】:插入后验证失败,值为空');
@@ -513,7 +545,7 @@ module.exports = (branch) => {
513
545
  const db = new Database(CURSOR_DB_PATH, { readonly: false });
514
546
 
515
547
  try {
516
- console.log(`【调试】:准备更新数据库,内容长度: ${promptContent.length} 字符`);
548
+ console.log(`【调试】:准备更新数据库,内容长度: ${rulesContent.length} 字符`);
517
549
 
518
550
  // 先查询是否存在该键
519
551
  const row = db.prepare("SELECT value, length(value) as len FROM ItemTable WHERE key = ?").get('aicontext.personalContext');
@@ -529,8 +561,8 @@ module.exports = (branch) => {
529
561
  oldContent = String(row.value);
530
562
  }
531
563
 
532
- if (oldContent === promptContent) {
533
- console.log('✓ prompt.md 内容未变化,无需更新');
564
+ if (oldContent === rulesContent) {
565
+ console.log('✓ admin/rules/PROJECT.md 内容未变化,无需更新');
534
566
  console.log('【提示】:请重启 Cursor 编辑器以使规则生效');
535
567
  db.close();
536
568
  step4();
@@ -539,7 +571,7 @@ module.exports = (branch) => {
539
571
 
540
572
  // 更新现有记录
541
573
  const updateStmt = db.prepare("UPDATE ItemTable SET value = ? WHERE key = ?");
542
- const result = updateStmt.run(promptContent, 'aicontext.personalContext');
574
+ const result = updateStmt.run(rulesContent, 'aicontext.personalContext');
543
575
  console.log(`【调试】:更新影响行数: ${result.changes}`);
544
576
 
545
577
  if (result.changes === 0) {
@@ -560,15 +592,15 @@ module.exports = (branch) => {
560
592
  verifyContent = String(verifyRow.value);
561
593
  }
562
594
 
563
- if (verifyContent === promptContent) {
564
- console.log(`✓ prompt.md 已更新到 Cursor user rules (${verifyRow.len} 字节)`);
595
+ if (verifyContent === rulesContent) {
596
+ console.log(`✓ PROJECT.md 已更新到 Cursor user rules (${verifyRow.len} 字节)`);
565
597
  // 显示前几行内容确认
566
598
  const previewLines = verifyContent.split('\n').slice(0, 3).join('\n');
567
599
  console.log(`【预览】:内容前3行:\n${previewLines}${verifyContent.split('\n').length > 3 ? '...' : ''}`);
568
600
  } else {
569
601
  console.error(`【Error】:更新后内容不匹配!`);
570
- console.error(` 期望长度: ${promptContent.length}, 实际长度: ${verifyContent.length}`);
571
- console.error(` 期望前100字符: ${promptContent.substring(0, 100)}`);
602
+ console.error(` 期望长度: ${rulesContent.length}, 实际长度: ${verifyContent.length}`);
603
+ console.error(` 期望前100字符: ${rulesContent.substring(0, 100)}`);
572
604
  console.error(` 实际前100字符: ${verifyContent.substring(0, 100)}`);
573
605
  }
574
606
  } else {
@@ -578,7 +610,7 @@ module.exports = (branch) => {
578
610
  console.log('【调试】:记录不存在,将插入新记录');
579
611
  // 插入新记录
580
612
  const insertStmt = db.prepare("INSERT INTO ItemTable (key, value) VALUES (?, ?)");
581
- const result = insertStmt.run('aicontext.personalContext', promptContent);
613
+ const result = insertStmt.run('aicontext.personalContext', rulesContent);
582
614
  console.log(`【调试】:插入结果,最后插入ID: ${result.lastInsertRowid}`);
583
615
 
584
616
  if (!result.lastInsertRowid) {
@@ -598,14 +630,14 @@ module.exports = (branch) => {
598
630
  verifyContent = String(verifyRow.value);
599
631
  }
600
632
 
601
- if (verifyContent === promptContent) {
602
- console.log(`✓ prompt.md 已添加到 Cursor user rules (${verifyRow.len} 字节)`);
633
+ if (verifyContent === rulesContent) {
634
+ console.log(`✓ PROJECT.md 已添加到 Cursor user rules (${verifyRow.len} 字节)`);
603
635
  // 显示前几行内容确认
604
636
  const previewLines = verifyContent.split('\n').slice(0, 3).join('\n');
605
637
  console.log(`【预览】:内容前3行:\n${previewLines}${verifyContent.split('\n').length > 3 ? '...' : ''}`);
606
638
  } else {
607
639
  console.error(`【Error】:插入后内容不匹配!`);
608
- console.error(` 期望长度: ${promptContent.length}, 实际长度: ${verifyContent.length}`);
640
+ console.error(` 期望长度: ${rulesContent.length}, 实际长度: ${verifyContent.length}`);
609
641
  }
610
642
  } else {
611
643
  console.error('【Error】:插入后验证失败,值为空');
@@ -630,8 +662,8 @@ module.exports = (branch) => {
630
662
 
631
663
  step4();
632
664
  } catch (error) {
633
- console.error('【Error】:处理 prompt.md 失败', error.message);
634
- console.log('【Warning】:可能 Cursor 未安装或路径不正确,请手动复制 prompt.md');
665
+ console.error('【Error】:处理 admin/rules/PROJECT.md 失败', error.message);
666
+ console.log('【Warning】:可能 Cursor 未安装或路径不正确,请手动复制 admin/rules/PROJECT.md 内容');
635
667
  step4();
636
668
  }
637
669
  }
@@ -644,23 +676,23 @@ module.exports = (branch) => {
644
676
  try {
645
677
  if (fs.existsSync(gitignorePath)) {
646
678
  let gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
647
- const aiIgnorePattern = /^\.ai\s*$/m;
679
+ const cursorIgnorePattern = /^\.cursor\/?\s*$/m;
648
680
 
649
- if (!aiIgnorePattern.test(gitignoreContent)) {
681
+ if (!cursorIgnorePattern.test(gitignoreContent)) {
650
682
  // 如果文件末尾没有换行,先添加换行
651
683
  if (!gitignoreContent.endsWith('\n')) {
652
684
  gitignoreContent += '\n';
653
685
  }
654
- gitignoreContent += '.ai\n';
686
+ gitignoreContent += '.cursor/\n';
655
687
  fs.writeFileSync(gitignorePath, gitignoreContent, 'utf8');
656
- console.log('✓ 已在 .gitignore 中添加 .ai 忽略规则');
688
+ console.log('✓ 已在 .gitignore 中添加 .cursor/ 忽略规则');
657
689
  } else {
658
- console.log('✓ .gitignore 中已存在 .ai 忽略规则');
690
+ console.log('✓ .gitignore 中已存在 .cursor 忽略规则');
659
691
  }
660
692
  } else {
661
693
  // 如果 .gitignore 不存在,创建它
662
- fs.writeFileSync(gitignorePath, '.ai\n', 'utf8');
663
- console.log('✓ 已创建 .gitignore 并添加 .ai 忽略规则');
694
+ fs.writeFileSync(gitignorePath, '.cursor/\n', 'utf8');
695
+ console.log('✓ 已创建 .gitignore 并添加 .cursor/ 忽略规则');
664
696
  }
665
697
  } catch (error) {
666
698
  console.error('【Error】:更新 .gitignore 失败', error.message);