cc-viewer 1.6.292 → 1.6.294

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 (99) hide show
  1. package/cli.js +91 -8
  2. package/dist/assets/App-C66LoBEz.js +2 -0
  3. package/dist/assets/App-eFrjLzF_.css +1 -0
  4. package/dist/assets/{MdxEditorPanel-DZyDzHVy.js → MdxEditorPanel-B8xrlDZJ.js} +1 -1
  5. package/dist/assets/{Mobile-Blo3o6S7.js → Mobile-fsi8-Lpb.js} +1 -1
  6. package/dist/assets/{_baseUniq-Bbls6LNZ.js → _baseUniq-r3p3rodd.js} +1 -1
  7. package/dist/assets/{arc-Dxdkihpv.js → arc-CjTV5gxc.js} +1 -1
  8. package/dist/assets/{architectureDiagram-Q4EWVU46-DZEl5ue8.js → architectureDiagram-Q4EWVU46-BqzjXpCq.js} +1 -1
  9. package/dist/assets/{blockDiagram-DXYQGD6D-CqlYS2ns.js → blockDiagram-DXYQGD6D-CLyFfeHh.js} +1 -1
  10. package/dist/assets/{c4Diagram-AHTNJAMY-Jxp541Qe.js → c4Diagram-AHTNJAMY-BaO-0tuc.js} +1 -1
  11. package/dist/assets/{channel-CyTjYjAe.js → channel-yOyhvOLV.js} +1 -1
  12. package/dist/assets/{chunk-4BX2VUAB-BaHtjjCx.js → chunk-4BX2VUAB-CMTnvZkS.js} +1 -1
  13. package/dist/assets/{chunk-4TB4RGXK-DjCpyfxt.js → chunk-4TB4RGXK-QI41m9WP.js} +1 -1
  14. package/dist/assets/{chunk-55IACEB6-LkM5KZyD.js → chunk-55IACEB6-C4ZO8bM3.js} +1 -1
  15. package/dist/assets/{chunk-EDXVE4YY-CTwZjamm.js → chunk-EDXVE4YY-Bo8P4o65.js} +1 -1
  16. package/dist/assets/{chunk-FMBD7UC4-BMGbfhBg.js → chunk-FMBD7UC4-CTHLGcHh.js} +1 -1
  17. package/dist/assets/{chunk-OYMX7WX6-CL9bBWYk.js → chunk-OYMX7WX6-D0OHxKGd.js} +1 -1
  18. package/dist/assets/{chunk-QZHKN3VN-B_htBFcu.js → chunk-QZHKN3VN-CoYnjUpS.js} +1 -1
  19. package/dist/assets/{chunk-YZCP3GAM-C2sEYgGN.js → chunk-YZCP3GAM-BY71mTXM.js} +1 -1
  20. package/dist/assets/classDiagram-6PBFFD2Q-C9o5ip5q.js +1 -0
  21. package/dist/assets/classDiagram-v2-HSJHXN6E-C9o5ip5q.js +1 -0
  22. package/dist/assets/clone-GDqN3kwT.js +1 -0
  23. package/dist/assets/{cose-bilkent-S5V4N54A-B2QExtqQ.js → cose-bilkent-S5V4N54A-DUNsA_MT.js} +1 -1
  24. package/dist/assets/{dagre-KV5264BT-DMrP1-R5.js → dagre-KV5264BT-BzlT2Exr.js} +1 -1
  25. package/dist/assets/{diagram-5BDNPKRD-DmnnioaR.js → diagram-5BDNPKRD-CiqQK3Ci.js} +1 -1
  26. package/dist/assets/{diagram-G4DWMVQ6-BznBn-DT.js → diagram-G4DWMVQ6-BciK18tQ.js} +1 -1
  27. package/dist/assets/{diagram-MMDJMWI5-CCtZmcc-.js → diagram-MMDJMWI5-C1WH1vfU.js} +1 -1
  28. package/dist/assets/{diagram-TYMM5635-DwrE4PW2.js → diagram-TYMM5635-CR5RzJ6u.js} +1 -1
  29. package/dist/assets/{erDiagram-SMLLAGMA-C-ksosE7.js → erDiagram-SMLLAGMA-NJQKXu51.js} +1 -1
  30. package/dist/assets/{flowDiagram-DWJPFMVM-BJVpW7EG.js → flowDiagram-DWJPFMVM-Cjx5t_1H.js} +1 -1
  31. package/dist/assets/{ganttDiagram-T4ZO3ILL-BMXdFiqN.js → ganttDiagram-T4ZO3ILL-YFTDBBiU.js} +1 -1
  32. package/dist/assets/{gitGraphDiagram-UUTBAWPF-DBTPkZc9.js → gitGraphDiagram-UUTBAWPF-C2muKahz.js} +1 -1
  33. package/dist/assets/{graph-B8CBUW3s.js → graph-I1olozIg.js} +1 -1
  34. package/dist/assets/{index-C_7Sqw3d.js → index-7vxIrUNA.js} +1 -1
  35. package/dist/assets/index-BTZqk5O5.js +2 -0
  36. package/dist/assets/{index-BJ8yRdWs.css → index-Be9T-kDq.css} +1 -1
  37. package/dist/assets/{index-DhDblkcm.js → index-C1RNAzAB.js} +1 -1
  38. package/dist/assets/{index-DBeeKbJt.js → index-Cf4FBg-V.js} +1 -1
  39. package/dist/assets/{index-CHdOT_E7.js → index-D-HPuqxB.js} +1 -1
  40. package/dist/assets/{index-xT0MApQE.js → index-D2QUxu18.js} +1 -1
  41. package/dist/assets/{index-DEXzVXu7.js → index-DhzoJ5wE.js} +1 -1
  42. package/dist/assets/{index-B-KwaWha.js → index-fhI0i2p3.js} +1 -1
  43. package/dist/assets/{infoDiagram-42DDH7IO-K_Tx4lQN.js → infoDiagram-42DDH7IO-C9bza97c.js} +1 -1
  44. package/dist/assets/{ishikawaDiagram-UXIWVN3A-kxQMq1sT.js → ishikawaDiagram-UXIWVN3A-BtZGipfW.js} +1 -1
  45. package/dist/assets/{journeyDiagram-VCZTEJTY-D73gF_Pb.js → journeyDiagram-VCZTEJTY-CKTp590c.js} +1 -1
  46. package/dist/assets/{jszip.min-CuShp3Z_.js → jszip.min-DDU-_oA-.js} +1 -1
  47. package/dist/assets/{kanban-definition-6JOO6SKY-BauEKrut.js → kanban-definition-6JOO6SKY-BHLNWfr5.js} +1 -1
  48. package/dist/assets/{layout-BMLto1IX.js → layout-DBmqcl9N.js} +1 -1
  49. package/dist/assets/{linear-D2Qb161Z.js → linear-Br9n7mCI.js} +1 -1
  50. package/dist/assets/{mermaid.core-IJXp8OCw.js → mermaid.core-BV3ugHFm.js} +2 -2
  51. package/dist/assets/{min-PfweEw_8.js → min-D-YA3MGY.js} +1 -1
  52. package/dist/assets/{mindmap-definition-QFDTVHPH-CbFxa-Zo.js → mindmap-definition-QFDTVHPH-CzrYj3cB.js} +1 -1
  53. package/dist/assets/{pieDiagram-DEJITSTG-DKeJuPU5.js → pieDiagram-DEJITSTG-BAvtfiT3.js} +1 -1
  54. package/dist/assets/{quadrantDiagram-34T5L4WZ-5VHUtwyi.js → quadrantDiagram-34T5L4WZ-i4zhnBJq.js} +1 -1
  55. package/dist/assets/{requirementDiagram-MS252O5E-SToTOJlA.js → requirementDiagram-MS252O5E-Cb2wX9Sk.js} +1 -1
  56. package/dist/assets/{sankeyDiagram-XADWPNL6-BdJHEZA8.js → sankeyDiagram-XADWPNL6-CcpbP6z5.js} +1 -1
  57. package/dist/assets/seqResourceLoaders-6k4uXcNn.js +2 -0
  58. package/dist/assets/{seqResourceLoaders-DWKAvGtj.css → seqResourceLoaders-De_-fYhE.css} +2 -2
  59. package/dist/assets/{sequenceDiagram-FGHM5R23-D1KEiigh.js → sequenceDiagram-FGHM5R23-BcbUxMmI.js} +1 -1
  60. package/dist/assets/{stateDiagram-FHFEXIEX-CbSD6ZEY.js → stateDiagram-FHFEXIEX-CpIa1qoO.js} +1 -1
  61. package/dist/assets/{stateDiagram-v2-QKLJ7IA2-Cf2M_W2L.js → stateDiagram-v2-QKLJ7IA2-d3GoyW9S.js} +1 -1
  62. package/dist/assets/{timeline-definition-GMOUNBTQ-DEcX1h4h.js → timeline-definition-GMOUNBTQ-BfQPSOuT.js} +1 -1
  63. package/dist/assets/{vendor-antd-CAcFBnhC.js → vendor-antd-Bur5ZxWE.js} +1 -1
  64. package/dist/assets/{vendor-codemirror-gWcsCyZl.js → vendor-codemirror-Si44UqBp.js} +1 -1
  65. package/dist/assets/{vendor-mdxeditor-2Gql6yhw.js → vendor-mdxeditor-Cco3AQJS.js} +2 -2
  66. package/dist/assets/{vendor-qrcode-BZBwE21F.js → vendor-qrcode-Dn3GYC4l.js} +1 -1
  67. package/dist/assets/{vendor-virtuoso-CIzhrc1B.js → vendor-virtuoso-CW9EqKMt.js} +1 -1
  68. package/dist/assets/{vennDiagram-DHZGUBPP-nSXsYxfo.js → vennDiagram-DHZGUBPP-hTgiYDQL.js} +1 -1
  69. package/dist/assets/{wardley-RL74JXVD-BQ_e66gQ.js → wardley-RL74JXVD-ByDpAPp1.js} +1 -1
  70. package/dist/assets/{wardleyDiagram-NUSXRM2D-BU_Pk5MC.js → wardleyDiagram-NUSXRM2D-D7LJTuWq.js} +1 -1
  71. package/dist/assets/{xychartDiagram-5P7HB3ND-D0K8r6CO.js → xychartDiagram-5P7HB3ND-MW_KOomO.js} +1 -1
  72. package/dist/index.html +5 -5
  73. package/package.json +1 -1
  74. package/server/i18n.js +60 -0
  75. package/server/interceptor.js +7 -0
  76. package/server/lib/adapters/dingtalk-adapter.js +7 -0
  77. package/server/lib/adapters/discord-adapter.js +9 -1
  78. package/server/lib/adapters/feishu-adapter.js +19 -0
  79. package/server/lib/adapters/wecom-adapter.js +4 -0
  80. package/server/lib/im-bridge-core.js +68 -11
  81. package/server/lib/im-claude-md.js +118 -0
  82. package/server/lib/im-deny.js +100 -0
  83. package/server/lib/im-lock.js +184 -0
  84. package/server/lib/im-process-manager.js +161 -0
  85. package/server/lib/im-senders.js +73 -0
  86. package/server/lib/interceptor-core.js +3 -1
  87. package/server/lib/perm-bridge.js +17 -0
  88. package/server/pty-manager.js +24 -3
  89. package/server/routes/dingtalk.js +38 -13
  90. package/server/routes/im.js +235 -36
  91. package/server/routes/skills.js +180 -165
  92. package/server/server.js +49 -21
  93. package/dist/assets/App-BIHUxfib.css +0 -1
  94. package/dist/assets/App-CG3B88Gg.js +0 -1
  95. package/dist/assets/classDiagram-6PBFFD2Q-D_SztMqP.js +0 -1
  96. package/dist/assets/classDiagram-v2-HSJHXN6E-D_SztMqP.js +0 -1
  97. package/dist/assets/clone-BQLytaFZ.js +0 -1
  98. package/dist/assets/index-BSMKfstl.js +0 -2
  99. package/dist/assets/seqResourceLoaders-IL0QIxz1.js +0 -2
package/cli.js CHANGED
@@ -312,9 +312,11 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
312
312
 
313
313
  const workingDir = cwd || process.cwd();
314
314
 
315
- // 注册工作区
316
- const { registerWorkspace } = await import('./server/workspace-registry.js');
317
- registerWorkspace(workingDir);
315
+ // 注册工作区(IM worker 跳过:避免把 IM_<id>/ 目录塞进工作区选择器)
316
+ if (!process.env.CCV_IM_PLATFORM) {
317
+ const { registerWorkspace } = await import('./server/workspace-registry.js');
318
+ registerWorkspace(workingDir);
319
+ }
318
320
 
319
321
  // 确保 AskUserQuestion hook 已注册到 ~/.claude/settings.json
320
322
  ensureHooks();
@@ -338,19 +340,38 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
338
340
  // 3. 启动 HTTP 服务器
339
341
  const serverMod = await import('./server/server.js');
340
342
 
341
- // 等待服务器启动完成
342
- await new Promise(resolve => {
343
+ // 等待服务器启动完成。IM worker 加 30s 死线:端口段(7050-7099)耗尽时 getPort() 恒为 0,
344
+ // 否则 worker 会永久空转并占着 im.lock(port:null)。超时则退出(exit 钩子释放锁),让用户快速看到失败、
345
+ // manager 也能据此判死。普通 ccv 保持原有无限轮询行为不变。
346
+ const _imPortDeadline = process.env.CCV_IM_PLATFORM ? Date.now() + 30000 : null;
347
+ await new Promise((resolve, reject) => {
343
348
  const check = () => {
344
349
  const port = serverMod.getPort();
345
- if (port) resolve(port);
346
- else setTimeout(check, 100);
350
+ if (port) return resolve(port);
351
+ if (_imPortDeadline && Date.now() > _imPortDeadline) {
352
+ return reject(new Error('no free port in 7050-7099 within 30s'));
353
+ }
354
+ setTimeout(check, 100);
347
355
  };
348
356
  setTimeout(check, 200);
357
+ }).catch((e) => {
358
+ console.error('[CC Viewer] IM worker could not bind a port:', e.message);
359
+ process.exit(1); // process.on('exit') 会按身份释放 im.lock
349
360
  });
350
361
 
351
362
  const port = serverMod.getPort();
352
363
  const serverProtocol = serverMod.getProtocol();
353
364
 
365
+ // IM worker:服务器监听成功后把真实端口回填进 im.lock(manager 据此做 HTTP 身份探测)
366
+ if (process.env.CCV_IM_PLATFORM) {
367
+ try {
368
+ const { updateImLockPort } = await import('./server/lib/im-lock.js');
369
+ updateImLockPort(process.env.CCV_IM_PLATFORM, port);
370
+ } catch (e) {
371
+ console.error('[CC Viewer] updateImLockPort failed:', e.message);
372
+ }
373
+ }
374
+
354
375
  // 3. 启动 PTY 中的 claude
355
376
  const { spawnClaude, killPty } = await import('./server/pty-manager.js');
356
377
  try {
@@ -403,6 +424,47 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
403
424
  process.on('SIGTERM', cleanup);
404
425
  }
405
426
 
427
+ // 启动一个独立常驻 IM worker。本质是「在 IM_<id>/ 工作目录、绑 127.0.0.1、skip-permissions」的 runCliMode,
428
+ // 外加:全局唯一锁、CLAUDE.md 预置、IM 专属 env。由 im-process-manager 以 detached 子进程拉起,
429
+ // 也可手动 `ccv --im <id>` 启动。
430
+ async function runImMode(platformId) {
431
+ const { getDescriptor } = await import('./server/lib/im-config.js');
432
+ if (!getDescriptor(platformId)) {
433
+ console.error(t('cli.imUnknownPlatform', { id: platformId }));
434
+ process.exit(1);
435
+ }
436
+
437
+ const { acquireImLock, releaseImLock, imDir } = await import('./server/lib/im-lock.js');
438
+ const { ensureImClaudeMd } = await import('./server/lib/im-claude-md.js');
439
+
440
+ const dir = imDir(platformId);
441
+ mkdirSync(dir, { recursive: true });
442
+
443
+ // 全局唯一:被活进程持有则拒绝启动(loser 退出,manager 会观察到子进程秒退)
444
+ const lockRes = acquireImLock(platformId);
445
+ if (!lockRes.ok) {
446
+ console.error(t('cli.imAlreadyRunning', { id: platformId, pid: lockRes.holder?.pid ?? '?' }));
447
+ process.exit(3);
448
+ }
449
+ // 退出时按身份释放锁(exit 同步钩子在 process.exit()/SIGINT/SIGTERM→cleanup 后仍执行;
450
+ // SIGKILL 不触发,由 manager 的 getImLiveness 兜底清理陈旧锁)
451
+ process.on('exit', () => { try { releaseImLock(platformId, process.pid); } catch { /* noop */ } });
452
+
453
+ // 首次缺失则生成默认 CLAUDE.md(行为约束,建议层)
454
+ try { ensureImClaudeMd(platformId, dir); }
455
+ catch (e) { console.error('[CC Viewer] ensureImClaudeMd failed:', e.message); }
456
+
457
+ // 以下 env 必须在 import server.js(runCliMode 内)之前设置:server 顶层读 START_PORT/MAX_PORT/HOST。
458
+ process.env.CCV_IM_PLATFORM = platformId;
459
+ process.env.CCV_START_PORT = process.env.CCV_START_PORT || '7050'; // IM 端口段从 7050 起
460
+ process.env.CCV_MAX_PORT = process.env.CCV_MAX_PORT || '7099';
461
+ process.env.CCV_HOST = '127.0.0.1'; // 仅 loopback:不把 skip-perms 端点暴露到局域网
462
+ process.env.CCV_IM_DENY = '1'; // 启用 perm-bridge 的 IM 硬拦截层
463
+
464
+ // worker 全自动:skip-permissions + 不开浏览器,工作目录设为 IM_<id>/
465
+ return runCliMode(['--dangerously-skip-permissions'], dir, true);
466
+ }
467
+
406
468
  async function runSdkMode(extraClaudeArgs = [], cwd, noOpen = false) {
407
469
  // 检查 SDK 是否可用
408
470
  let sdkManager;
@@ -675,6 +737,21 @@ if (usePwdIdx !== -1) {
675
737
  args.splice(usePwdIdx, 1);
676
738
  }
677
739
 
740
+ // Extract --im <platformId> — 启动一个独立常驻 IM worker:工作目录 IM_<id>/、绑 127.0.0.1、
741
+ // skip-permissions、全局唯一锁。必须在动态 import 之前提取(runImMode 会在 import server.js 前设 env)。
742
+ let imPlatform = null;
743
+ const imIdx = args.indexOf('--im');
744
+ if (imIdx !== -1) {
745
+ const val = args[imIdx + 1];
746
+ if (val && !val.startsWith('-')) {
747
+ imPlatform = val;
748
+ args.splice(imIdx, 2);
749
+ } else {
750
+ console.error(t('cli.imRequiresId'));
751
+ process.exit(1);
752
+ }
753
+ }
754
+
678
755
  // ccv 自有命令判断
679
756
  const isLogger = args.includes('-logger');
680
757
  const isUninstall = args.includes('--uninstall') || args.includes('-uninstall');
@@ -827,7 +904,13 @@ if (isLogger) {
827
904
  process.exit(0);
828
905
  }
829
906
 
830
- if (args[0] === 'run') {
907
+ if (imPlatform) {
908
+ // 独立 IM worker 模式
909
+ runImMode(imPlatform).catch(err => {
910
+ console.error('IM mode error:', err);
911
+ process.exit(1);
912
+ });
913
+ } else if (args[0] === 'run') {
831
914
  runProxyCommand(args);
832
915
  } else if (args.includes('-SDK') || args.includes('--sdk')) {
833
916
  // SDK 模式(显式 -SDK 切换)