cc-viewer 1.6.92 → 1.6.94

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 (67) hide show
  1. package/cli.js +150 -16
  2. package/dist/assets/{App-D4nsyVOs.js → App-CpDREOeV.js} +16 -16
  3. package/dist/assets/AppHeader-B2WxpwwK.css +41 -0
  4. package/dist/assets/{AppHeader.module-S7b16Luh.js → AppHeader.module-CmeLfozP.js} +176 -176
  5. package/dist/assets/Mobile-dzPMTNzK.js +10 -0
  6. package/dist/assets/{_basePickBy-uFgBWU_1.js → _basePickBy-DtCw5KGL.js} +1 -1
  7. package/dist/assets/{_baseUniq-D9OrCsW-.js → _baseUniq-ImoXbuWJ.js} +1 -1
  8. package/dist/assets/{arc-B5paIHbL.js → arc-DPeHTMnU.js} +1 -1
  9. package/dist/assets/{architectureDiagram-2XIMDMQ5-CVR0S5_A.js → architectureDiagram-2XIMDMQ5-CBXj01rK.js} +1 -1
  10. package/dist/assets/{blockDiagram-WCTKOSBZ-DbExq97J.js → blockDiagram-WCTKOSBZ-D7wcf1pW.js} +1 -1
  11. package/dist/assets/{c4Diagram-IC4MRINW-CyyZQH7U.js → c4Diagram-IC4MRINW-BRPLIdn4.js} +1 -1
  12. package/dist/assets/channel-CIlWz43T.js +1 -0
  13. package/dist/assets/{chunk-4BX2VUAB-D-TxZu2j.js → chunk-4BX2VUAB-BXdgQxSh.js} +1 -1
  14. package/dist/assets/{chunk-55IACEB6-BpiK1KHs.js → chunk-55IACEB6-CGjaWrfY.js} +1 -1
  15. package/dist/assets/{chunk-FMBD7UC4-BsVETng4.js → chunk-FMBD7UC4-mMdkjRFC.js} +1 -1
  16. package/dist/assets/{chunk-JSJVCQXG-ByEZLFF3.js → chunk-JSJVCQXG-C6OK5M-I.js} +1 -1
  17. package/dist/assets/{chunk-KX2RTZJC-DGedEdfQ.js → chunk-KX2RTZJC-AEEd0Ryd.js} +1 -1
  18. package/dist/assets/{chunk-NQ4KR5QH-CVuE5E20.js → chunk-NQ4KR5QH-B-8p6H36.js} +1 -1
  19. package/dist/assets/{chunk-QZHKN3VN-BDDf3H2l.js → chunk-QZHKN3VN-B-CVp8R8.js} +1 -1
  20. package/dist/assets/{chunk-WL4C6EOR-D57kZtSM.js → chunk-WL4C6EOR-A-wxrsg9.js} +1 -1
  21. package/dist/assets/classDiagram-VBA2DB6C-CFFsxNG8.js +1 -0
  22. package/dist/assets/classDiagram-v2-RAHNMMFH-CFFsxNG8.js +1 -0
  23. package/dist/assets/clone-CKeKraNB.js +1 -0
  24. package/dist/assets/{cose-bilkent-S5V4N54A-CF2LKXX0.js → cose-bilkent-S5V4N54A-8lbzR16F.js} +1 -1
  25. package/dist/assets/{dagre-KLK3FWXG-AKm2eMFa.js → dagre-KLK3FWXG-DMayMOCq.js} +1 -1
  26. package/dist/assets/{diagram-E7M64L7V-Dy0ZpqYE.js → diagram-E7M64L7V-ChHSZyAh.js} +1 -1
  27. package/dist/assets/{diagram-IFDJBPK2-BwulOlMM.js → diagram-IFDJBPK2-BwUoLoNA.js} +1 -1
  28. package/dist/assets/{diagram-P4PSJMXO-BlGWqbdU.js → diagram-P4PSJMXO-W3hHvhQv.js} +1 -1
  29. package/dist/assets/{erDiagram-INFDFZHY-DlKoWq8q.js → erDiagram-INFDFZHY-ToaX7NX1.js} +1 -1
  30. package/dist/assets/{flowDiagram-PKNHOUZH-fbS7K31R.js → flowDiagram-PKNHOUZH-D2ZMeP7M.js} +1 -1
  31. package/dist/assets/{ganttDiagram-A5KZAMGK-CrXC6aZY.js → ganttDiagram-A5KZAMGK-B3G9qGij.js} +1 -1
  32. package/dist/assets/{gitGraphDiagram-K3NZZRJ6-DgL6ifkO.js → gitGraphDiagram-K3NZZRJ6-DVPNEMEl.js} +1 -1
  33. package/dist/assets/{graph-D8OSNuBb.js → graph-7WxqTkFG.js} +1 -1
  34. package/dist/assets/{index-vXPJvGyq.js → index-BJPMV8pJ.js} +2 -2
  35. package/dist/assets/{infoDiagram-LFFYTUFH-D-yXUDBn.js → infoDiagram-LFFYTUFH-BpGp_HF2.js} +1 -1
  36. package/dist/assets/{ishikawaDiagram-PHBUUO56-BSLzUZNI.js → ishikawaDiagram-PHBUUO56-B5VsmnNJ.js} +1 -1
  37. package/dist/assets/{journeyDiagram-4ABVD52K-BsZGTLTS.js → journeyDiagram-4ABVD52K-C2z-HVVr.js} +1 -1
  38. package/dist/assets/{kanban-definition-K7BYSVSG-qHcQ8IDf.js → kanban-definition-K7BYSVSG-BD5yr9Bu.js} +1 -1
  39. package/dist/assets/{layout-BT82KtcO.js → layout-CE4RECIN.js} +1 -1
  40. package/dist/assets/{linear-C-NY3Tys.js → linear-D1KJlzdf.js} +1 -1
  41. package/dist/assets/{mermaid.core-Iu-Haj2d.js → mermaid.core-CUfJ0HRg.js} +4 -4
  42. package/dist/assets/{mindmap-definition-YRQLILUH-bYKflbjM.js → mindmap-definition-YRQLILUH-DxHuRKwL.js} +1 -1
  43. package/dist/assets/{pieDiagram-SKSYHLDU-EBV2nFfI.js → pieDiagram-SKSYHLDU-D9WiCCJ-.js} +1 -1
  44. package/dist/assets/{quadrantDiagram-337W2JSQ-CDbCpLQ6.js → quadrantDiagram-337W2JSQ-CZ8WY2Jp.js} +1 -1
  45. package/dist/assets/{requirementDiagram-Z7DCOOCP-DTepHdzH.js → requirementDiagram-Z7DCOOCP-D0DF0apq.js} +1 -1
  46. package/dist/assets/{sankeyDiagram-WA2Y5GQK-BDGKah3z.js → sankeyDiagram-WA2Y5GQK--FyELbOO.js} +1 -1
  47. package/dist/assets/{sequenceDiagram-2WXFIKYE-DOTt340N.js → sequenceDiagram-2WXFIKYE-BCuHKjuI.js} +1 -1
  48. package/dist/assets/{stateDiagram-RAJIS63D-C-dx3ZVl.js → stateDiagram-RAJIS63D-Luke3XUg.js} +1 -1
  49. package/dist/assets/stateDiagram-v2-FVOUBMTO-BKK8D7Gx.js +1 -0
  50. package/dist/assets/{timeline-definition-YZTLITO2-CQuH8MMr.js → timeline-definition-YZTLITO2-5YJwGq5n.js} +1 -1
  51. package/dist/assets/{treemap-KZPCXAKY-Bh6K3rqD.js → treemap-KZPCXAKY-sJliY-5m.js} +1 -1
  52. package/dist/assets/{vennDiagram-LZ73GAT5-B4Avwovu.js → vennDiagram-LZ73GAT5-BU34zfK3.js} +1 -1
  53. package/dist/assets/{xychartDiagram-JWTSCODW-CNDvIAFk.js → xychartDiagram-JWTSCODW-ALa7ypHt.js} +1 -1
  54. package/dist/index.html +2 -2
  55. package/i18n.js +3 -3
  56. package/lib/perm-bridge.js +128 -0
  57. package/lib/sdk-adapter.js +77 -0
  58. package/lib/sdk-manager.js +458 -0
  59. package/package.json +5 -2
  60. package/server.js +216 -4
  61. package/dist/assets/AppHeader-q5FApoep.css +0 -41
  62. package/dist/assets/Mobile-ZoUy632Q.js +0 -10
  63. package/dist/assets/channel-Bk-jFRd9.js +0 -1
  64. package/dist/assets/classDiagram-VBA2DB6C-BIEQkv07.js +0 -1
  65. package/dist/assets/classDiagram-v2-RAHNMMFH-BIEQkv07.js +0 -1
  66. package/dist/assets/clone-CDtWj5DG.js +0 -1
  67. package/dist/assets/stateDiagram-v2-FVOUBMTO-Dn8gbgvz.js +0 -1
package/cli.js CHANGED
@@ -256,7 +256,7 @@ async function runProxyCommand(args) {
256
256
  }
257
257
  }
258
258
 
259
- function ensureAskHook() {
259
+ function ensureHooks() {
260
260
  try {
261
261
  const claudeDir = resolve(homedir(), '.claude');
262
262
  const settingsPath = resolve(claudeDir, 'settings.json');
@@ -266,28 +266,64 @@ function ensureAskHook() {
266
266
  return;
267
267
  }
268
268
 
269
- const askBridgePath = resolve(__dirname, 'lib', 'ask-bridge.js');
270
- const expectedCmd = `node "${askBridgePath}"`;
271
-
272
269
  if (!settings.hooks) settings.hooks = {};
273
270
  if (!Array.isArray(settings.hooks.PreToolUse)) settings.hooks.PreToolUse = [];
274
271
 
275
- const existing = settings.hooks.PreToolUse.find(h => h.matcher === 'AskUserQuestion');
276
- if (existing) {
277
- const cmd = existing.hooks?.[0]?.command || '';
278
- if (cmd === expectedCmd) return;
279
- existing.hooks = [{ type: 'command', command: expectedCmd }];
272
+ let changed = false;
273
+
274
+ // AskUserQuestion hook → ask-bridge.js
275
+ const askBridgePath = resolve(__dirname, 'lib', 'ask-bridge.js');
276
+ const askCmd = `node "${askBridgePath}"`;
277
+ const askExisting = settings.hooks.PreToolUse.find(h => h.matcher === 'AskUserQuestion');
278
+ if (askExisting) {
279
+ if ((askExisting.hooks?.[0]?.command || '') !== askCmd) {
280
+ askExisting.hooks = [{ type: 'command', command: askCmd }];
281
+ changed = true;
282
+ }
280
283
  } else {
281
284
  settings.hooks.PreToolUse.push({
282
285
  matcher: 'AskUserQuestion',
283
- hooks: [{ type: 'command', command: expectedCmd }]
286
+ hooks: [{ type: 'command', command: askCmd }]
287
+ });
288
+ changed = true;
289
+ }
290
+
291
+ // Permission approval hook → perm-bridge.js (matcher: "" = match all tools)
292
+ const permBridgePath = resolve(__dirname, 'lib', 'perm-bridge.js');
293
+ const permCmd = `node "${permBridgePath}"`;
294
+ const permMatcher = '';
295
+ // Clean up legacy entries: old narrow matchers, null matchers (invalid JSON)
296
+ for (let i = settings.hooks.PreToolUse.length - 1; i >= 0; i--) {
297
+ const h = settings.hooks.PreToolUse[i];
298
+ const cmd = h.hooks?.[0]?.command || '';
299
+ if (cmd.includes('perm-bridge.js') && h.matcher !== permMatcher) {
300
+ settings.hooks.PreToolUse.splice(i, 1);
301
+ changed = true;
302
+ } else if ((h.matcher === null || h.matcher === undefined) && cmd.includes('perm-bridge.js')) {
303
+ settings.hooks.PreToolUse.splice(i, 1);
304
+ changed = true;
305
+ }
306
+ }
307
+ const permExisting = settings.hooks.PreToolUse.find(h => h.matcher === permMatcher);
308
+ if (permExisting) {
309
+ if ((permExisting.hooks?.[0]?.command || '') !== permCmd) {
310
+ permExisting.hooks = [{ type: 'command', command: permCmd }];
311
+ changed = true;
312
+ }
313
+ } else {
314
+ settings.hooks.PreToolUse.push({
315
+ matcher: permMatcher,
316
+ hooks: [{ type: 'command', command: permCmd }]
284
317
  });
318
+ changed = true;
285
319
  }
286
320
 
287
- mkdirSync(claudeDir, { recursive: true });
288
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
321
+ if (changed) {
322
+ mkdirSync(claudeDir, { recursive: true });
323
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
324
+ }
289
325
  } catch (err) {
290
- console.warn('[CC Viewer] Failed to ensure AskUserQuestion hook:', err.message);
326
+ console.warn('[CC Viewer] Failed to ensure hooks:', err.message);
291
327
  }
292
328
  }
293
329
 
@@ -314,7 +350,7 @@ async function runCliMode(extraClaudeArgs = [], cwd) {
314
350
  registerWorkspace(workingDir);
315
351
 
316
352
  // 确保 AskUserQuestion hook 已注册到 ~/.claude/settings.json
317
- ensureAskHook();
353
+ ensureHooks();
318
354
 
319
355
  // 2. 设置 CLI 模式标记(必须在 import proxy.js 之前,
320
356
  // 因为 proxy.js → interceptor.js 可能触发 server.js 加载,
@@ -322,6 +358,10 @@ async function runCliMode(extraClaudeArgs = [], cwd) {
322
358
  process.env.CCV_CLI_MODE = '1';
323
359
  process.env.CCV_PROJECT_DIR = workingDir;
324
360
  process.env.CCV_PROXY_MODE = '1';
361
+ // 当 --dangerously-skip-permissions 生效时,通知 perm-bridge 不要拦截
362
+ if (extraClaudeArgs.includes('--dangerously-skip-permissions')) {
363
+ process.env.CCV_BYPASS_PERMISSIONS = '1';
364
+ }
325
365
 
326
366
  // 1. 启动代理
327
367
  const { startProxy } = await import('./proxy.js');
@@ -379,6 +419,93 @@ async function runCliMode(extraClaudeArgs = [], cwd) {
379
419
  process.on('SIGTERM', cleanup);
380
420
  }
381
421
 
422
+ async function runSdkMode(extraClaudeArgs = [], cwd) {
423
+ // 检查 SDK 是否可用
424
+ let sdkManager;
425
+ try {
426
+ sdkManager = await import('./lib/sdk-manager.js');
427
+ if (!sdkManager.isSdkAvailable()) throw new Error('query not available');
428
+ } catch {
429
+ console.warn('[CC Viewer] Agent SDK not available, falling back to PTY mode (-C)');
430
+ return runCliMode(extraClaudeArgs, cwd);
431
+ }
432
+
433
+ const workingDir = cwd || process.cwd();
434
+
435
+ // 注册工作区
436
+ const { registerWorkspace } = await import('./workspace-registry.js');
437
+ registerWorkspace(workingDir);
438
+
439
+ // 不需要 ensureHooks — SDK canUseTool 处理 AskUserQuestion + 权限
440
+ // 不需要 proxy — SDK 直接管理 API 通信
441
+
442
+ // 设置环境标记(必须在 import server.js 之前)
443
+ process.env.CCV_CLI_MODE = '1';
444
+ process.env.CCV_SDK_MODE = '1';
445
+ process.env.CCV_PROJECT_DIR = workingDir;
446
+ process.env.CCV_PROXY_MODE = '1'; // 使 interceptor.js 惰性
447
+
448
+ // 启动 HTTP 服务器
449
+ const serverMod = await import('./server.js');
450
+
451
+ await new Promise(resolve => {
452
+ const check = () => {
453
+ const port = serverMod.getPort();
454
+ if (port) resolve(port);
455
+ else setTimeout(check, 100);
456
+ };
457
+ setTimeout(check, 200);
458
+ });
459
+
460
+ const port = serverMod.getPort();
461
+ const { basename } = await import('node:path');
462
+
463
+ // 解析 permission mode from CLI args
464
+ // --d / --dangerously-skip-permissions → bypassPermissions(跳过所有权限检查)
465
+ // --ad / --allow-dangerously-skip-permissions → default(只是允许用户后续切换,不立即跳过)
466
+ let permissionMode = 'default';
467
+ if (extraClaudeArgs.includes('--dangerously-skip-permissions')) {
468
+ permissionMode = 'bypassPermissions';
469
+ }
470
+
471
+ // 初始化 SDK 会话
472
+ sdkManager.initSdkSession(workingDir, basename(workingDir), {
473
+ onEntry: (entry) => serverMod.pushSdkEntry(entry),
474
+ onStreamingStatus: (data) => serverMod.setSdkStreamingState(data),
475
+ broadcastWs: (msg) => serverMod.broadcastWsMessage(msg),
476
+ permissionMode,
477
+ });
478
+
479
+ // 注册 SDK 回调到 server.js(WS 消息路由用)
480
+ serverMod.setSdkResolveApproval(sdkManager.resolveApproval);
481
+ serverMod.setSdkSendUserMessage(sdkManager.sendUserMessage);
482
+
483
+ // 自动打开浏览器
484
+ const protocol = serverMod.getProtocol();
485
+ const url = `${protocol}://127.0.0.1:${port}`;
486
+ try {
487
+ const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
488
+ const { execSync } = await import('node:child_process');
489
+ execSync(`${cmd} ${url}`, { stdio: 'ignore', timeout: 5000 });
490
+ } catch {}
491
+
492
+ console.log(`CC Viewer (SDK mode):`);
493
+ console.log(` ➜ Local: ${url}`);
494
+ const _lanIps = serverMod.getAllLocalIps();
495
+ const _token = serverMod.getAccessToken();
496
+ for (const _ip of _lanIps) {
497
+ console.log(` ➜ Network: ${protocol}://${_ip}:${port}?token=${_token}`);
498
+ }
499
+
500
+ // 注册退出处理
501
+ const cleanup = () => {
502
+ sdkManager.stopSession();
503
+ serverMod.stopViewer().finally(() => process.exit());
504
+ };
505
+ process.on('SIGINT', cleanup);
506
+ process.on('SIGTERM', cleanup);
507
+ }
508
+
382
509
  async function runCliModeWorkspaceSelector(extraClaudeArgs = []) {
383
510
  // 首先尝试 npm 版本(包括 nvm 安装),找不到再尝试 native 版本
384
511
  let claudePath = resolveNpmClaudePath();
@@ -617,9 +744,16 @@ if (isLogger) {
617
744
 
618
745
  if (args[0] === 'run') {
619
746
  runProxyCommand(args);
747
+ } else if (args.includes('-SDK') || args.includes('--sdk')) {
748
+ // SDK 模式(显式 -SDK 切换)
749
+ const claudeArgs = args.filter(a => a !== '-SDK' && a !== '--sdk')
750
+ .map(a => a === '--d' ? '--dangerously-skip-permissions' : a === '--ad' ? '--allow-dangerously-skip-permissions' : a);
751
+ runSdkMode(claudeArgs, process.cwd()).catch(err => {
752
+ console.error('SDK mode error:', err);
753
+ process.exit(1);
754
+ });
620
755
  } else {
621
- // 默认行为:所有参数透传给 claude(通过 PTY + Web Viewer)
622
- // 展开快捷方式:--d → --dangerously-skip-permissions, --ad → --allow-dangerously-skip-permissions
756
+ // PTY 模式(默认)
623
757
  const claudeArgs = args.map(a => a === '--d' ? '--dangerously-skip-permissions' : a === '--ad' ? '--allow-dangerously-skip-permissions' : a);
624
758
  runCliMode(claudeArgs, process.cwd()).catch(err => {
625
759
  console.error('CLI mode error:', err);