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.
- package/cli.js +150 -16
- package/dist/assets/{App-D4nsyVOs.js → App-CpDREOeV.js} +16 -16
- package/dist/assets/AppHeader-B2WxpwwK.css +41 -0
- package/dist/assets/{AppHeader.module-S7b16Luh.js → AppHeader.module-CmeLfozP.js} +176 -176
- package/dist/assets/Mobile-dzPMTNzK.js +10 -0
- package/dist/assets/{_basePickBy-uFgBWU_1.js → _basePickBy-DtCw5KGL.js} +1 -1
- package/dist/assets/{_baseUniq-D9OrCsW-.js → _baseUniq-ImoXbuWJ.js} +1 -1
- package/dist/assets/{arc-B5paIHbL.js → arc-DPeHTMnU.js} +1 -1
- package/dist/assets/{architectureDiagram-2XIMDMQ5-CVR0S5_A.js → architectureDiagram-2XIMDMQ5-CBXj01rK.js} +1 -1
- package/dist/assets/{blockDiagram-WCTKOSBZ-DbExq97J.js → blockDiagram-WCTKOSBZ-D7wcf1pW.js} +1 -1
- package/dist/assets/{c4Diagram-IC4MRINW-CyyZQH7U.js → c4Diagram-IC4MRINW-BRPLIdn4.js} +1 -1
- package/dist/assets/channel-CIlWz43T.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-D-TxZu2j.js → chunk-4BX2VUAB-BXdgQxSh.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-BpiK1KHs.js → chunk-55IACEB6-CGjaWrfY.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-BsVETng4.js → chunk-FMBD7UC4-mMdkjRFC.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-ByEZLFF3.js → chunk-JSJVCQXG-C6OK5M-I.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-DGedEdfQ.js → chunk-KX2RTZJC-AEEd0Ryd.js} +1 -1
- package/dist/assets/{chunk-NQ4KR5QH-CVuE5E20.js → chunk-NQ4KR5QH-B-8p6H36.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BDDf3H2l.js → chunk-QZHKN3VN-B-CVp8R8.js} +1 -1
- package/dist/assets/{chunk-WL4C6EOR-D57kZtSM.js → chunk-WL4C6EOR-A-wxrsg9.js} +1 -1
- package/dist/assets/classDiagram-VBA2DB6C-CFFsxNG8.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-CFFsxNG8.js +1 -0
- package/dist/assets/clone-CKeKraNB.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-CF2LKXX0.js → cose-bilkent-S5V4N54A-8lbzR16F.js} +1 -1
- package/dist/assets/{dagre-KLK3FWXG-AKm2eMFa.js → dagre-KLK3FWXG-DMayMOCq.js} +1 -1
- package/dist/assets/{diagram-E7M64L7V-Dy0ZpqYE.js → diagram-E7M64L7V-ChHSZyAh.js} +1 -1
- package/dist/assets/{diagram-IFDJBPK2-BwulOlMM.js → diagram-IFDJBPK2-BwUoLoNA.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-BlGWqbdU.js → diagram-P4PSJMXO-W3hHvhQv.js} +1 -1
- package/dist/assets/{erDiagram-INFDFZHY-DlKoWq8q.js → erDiagram-INFDFZHY-ToaX7NX1.js} +1 -1
- package/dist/assets/{flowDiagram-PKNHOUZH-fbS7K31R.js → flowDiagram-PKNHOUZH-D2ZMeP7M.js} +1 -1
- package/dist/assets/{ganttDiagram-A5KZAMGK-CrXC6aZY.js → ganttDiagram-A5KZAMGK-B3G9qGij.js} +1 -1
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-DgL6ifkO.js → gitGraphDiagram-K3NZZRJ6-DVPNEMEl.js} +1 -1
- package/dist/assets/{graph-D8OSNuBb.js → graph-7WxqTkFG.js} +1 -1
- package/dist/assets/{index-vXPJvGyq.js → index-BJPMV8pJ.js} +2 -2
- package/dist/assets/{infoDiagram-LFFYTUFH-D-yXUDBn.js → infoDiagram-LFFYTUFH-BpGp_HF2.js} +1 -1
- package/dist/assets/{ishikawaDiagram-PHBUUO56-BSLzUZNI.js → ishikawaDiagram-PHBUUO56-B5VsmnNJ.js} +1 -1
- package/dist/assets/{journeyDiagram-4ABVD52K-BsZGTLTS.js → journeyDiagram-4ABVD52K-C2z-HVVr.js} +1 -1
- package/dist/assets/{kanban-definition-K7BYSVSG-qHcQ8IDf.js → kanban-definition-K7BYSVSG-BD5yr9Bu.js} +1 -1
- package/dist/assets/{layout-BT82KtcO.js → layout-CE4RECIN.js} +1 -1
- package/dist/assets/{linear-C-NY3Tys.js → linear-D1KJlzdf.js} +1 -1
- package/dist/assets/{mermaid.core-Iu-Haj2d.js → mermaid.core-CUfJ0HRg.js} +4 -4
- package/dist/assets/{mindmap-definition-YRQLILUH-bYKflbjM.js → mindmap-definition-YRQLILUH-DxHuRKwL.js} +1 -1
- package/dist/assets/{pieDiagram-SKSYHLDU-EBV2nFfI.js → pieDiagram-SKSYHLDU-D9WiCCJ-.js} +1 -1
- package/dist/assets/{quadrantDiagram-337W2JSQ-CDbCpLQ6.js → quadrantDiagram-337W2JSQ-CZ8WY2Jp.js} +1 -1
- package/dist/assets/{requirementDiagram-Z7DCOOCP-DTepHdzH.js → requirementDiagram-Z7DCOOCP-D0DF0apq.js} +1 -1
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-BDGKah3z.js → sankeyDiagram-WA2Y5GQK--FyELbOO.js} +1 -1
- package/dist/assets/{sequenceDiagram-2WXFIKYE-DOTt340N.js → sequenceDiagram-2WXFIKYE-BCuHKjuI.js} +1 -1
- package/dist/assets/{stateDiagram-RAJIS63D-C-dx3ZVl.js → stateDiagram-RAJIS63D-Luke3XUg.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-BKK8D7Gx.js +1 -0
- package/dist/assets/{timeline-definition-YZTLITO2-CQuH8MMr.js → timeline-definition-YZTLITO2-5YJwGq5n.js} +1 -1
- package/dist/assets/{treemap-KZPCXAKY-Bh6K3rqD.js → treemap-KZPCXAKY-sJliY-5m.js} +1 -1
- package/dist/assets/{vennDiagram-LZ73GAT5-B4Avwovu.js → vennDiagram-LZ73GAT5-BU34zfK3.js} +1 -1
- package/dist/assets/{xychartDiagram-JWTSCODW-CNDvIAFk.js → xychartDiagram-JWTSCODW-ALa7ypHt.js} +1 -1
- package/dist/index.html +2 -2
- package/i18n.js +3 -3
- package/lib/perm-bridge.js +128 -0
- package/lib/sdk-adapter.js +77 -0
- package/lib/sdk-manager.js +458 -0
- package/package.json +5 -2
- package/server.js +216 -4
- package/dist/assets/AppHeader-q5FApoep.css +0 -41
- package/dist/assets/Mobile-ZoUy632Q.js +0 -10
- package/dist/assets/channel-Bk-jFRd9.js +0 -1
- package/dist/assets/classDiagram-VBA2DB6C-BIEQkv07.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-BIEQkv07.js +0 -1
- package/dist/assets/clone-CDtWj5DG.js +0 -1
- 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
|
|
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
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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:
|
|
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
|
-
|
|
288
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
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);
|