cc-viewer 1.6.271 → 1.6.273

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 (186) hide show
  1. package/cli.js +44 -43
  2. package/concepts/ar/GlobalSettings.md +2 -2
  3. package/concepts/ar/MainAgent.md +1 -1
  4. package/concepts/ar/ProxySwitch.md +1 -1
  5. package/concepts/da/GlobalSettings.md +2 -2
  6. package/concepts/da/MainAgent.md +1 -1
  7. package/concepts/da/ProxySwitch.md +1 -1
  8. package/concepts/de/GlobalSettings.md +2 -2
  9. package/concepts/de/MainAgent.md +1 -1
  10. package/concepts/de/ProxySwitch.md +1 -1
  11. package/concepts/en/GlobalSettings.md +2 -2
  12. package/concepts/en/MainAgent.md +1 -1
  13. package/concepts/en/ProxySwitch.md +1 -1
  14. package/concepts/es/GlobalSettings.md +2 -2
  15. package/concepts/es/MainAgent.md +1 -1
  16. package/concepts/es/ProxySwitch.md +1 -1
  17. package/concepts/fr/GlobalSettings.md +2 -2
  18. package/concepts/fr/MainAgent.md +1 -1
  19. package/concepts/fr/ProxySwitch.md +1 -1
  20. package/concepts/it/GlobalSettings.md +2 -2
  21. package/concepts/it/MainAgent.md +1 -1
  22. package/concepts/it/ProxySwitch.md +1 -1
  23. package/concepts/ja/GlobalSettings.md +2 -2
  24. package/concepts/ja/MainAgent.md +1 -1
  25. package/concepts/ja/ProxySwitch.md +1 -1
  26. package/concepts/ko/GlobalSettings.md +2 -2
  27. package/concepts/ko/MainAgent.md +1 -1
  28. package/concepts/ko/ProxySwitch.md +1 -1
  29. package/concepts/no/GlobalSettings.md +2 -2
  30. package/concepts/no/MainAgent.md +1 -1
  31. package/concepts/no/ProxySwitch.md +1 -1
  32. package/concepts/pl/GlobalSettings.md +2 -2
  33. package/concepts/pl/MainAgent.md +1 -1
  34. package/concepts/pl/ProxySwitch.md +1 -1
  35. package/concepts/pt-BR/GlobalSettings.md +2 -2
  36. package/concepts/pt-BR/MainAgent.md +1 -1
  37. package/concepts/pt-BR/ProxySwitch.md +1 -1
  38. package/concepts/ru/GlobalSettings.md +2 -2
  39. package/concepts/ru/MainAgent.md +1 -1
  40. package/concepts/ru/ProxySwitch.md +1 -1
  41. package/concepts/th/GlobalSettings.md +2 -2
  42. package/concepts/th/MainAgent.md +1 -1
  43. package/concepts/th/ProxySwitch.md +1 -1
  44. package/concepts/tr/GlobalSettings.md +2 -2
  45. package/concepts/tr/MainAgent.md +1 -1
  46. package/concepts/tr/ProxySwitch.md +1 -1
  47. package/concepts/uk/GlobalSettings.md +2 -2
  48. package/concepts/uk/MainAgent.md +1 -1
  49. package/concepts/uk/ProxySwitch.md +1 -1
  50. package/concepts/zh/GlobalSettings.md +2 -2
  51. package/concepts/zh/MainAgent.md +1 -1
  52. package/concepts/zh/ProxySwitch.md +1 -1
  53. package/concepts/zh-TW/GlobalSettings.md +2 -2
  54. package/concepts/zh-TW/MainAgent.md +1 -1
  55. package/concepts/zh-TW/ProxySwitch.md +1 -1
  56. package/dist/assets/App-DLdA05Yx.js +1 -0
  57. package/dist/assets/App-TGGslOeT.css +1 -0
  58. package/dist/assets/{MdxEditorPanel-B7oOvR3k.js → MdxEditorPanel-D2Wt6kg-.js} +1 -1
  59. package/dist/assets/Mobile-Dhkz2rBB.js +1 -0
  60. package/dist/assets/{_baseUniq-Dgkw4IXM.js → _baseUniq-CPJrFyUF.js} +1 -1
  61. package/dist/assets/{arc-AiHQLijx.js → arc-BLBrFElt.js} +1 -1
  62. package/dist/assets/{architectureDiagram-Q4EWVU46-CPRvAIHK.js → architectureDiagram-Q4EWVU46-CbnBsMiQ.js} +1 -1
  63. package/dist/assets/{blockDiagram-DXYQGD6D-CK2cwrfX.js → blockDiagram-DXYQGD6D-0mYr6-Fl.js} +1 -1
  64. package/dist/assets/{c4Diagram-AHTNJAMY-BP-UBbgv.js → c4Diagram-AHTNJAMY-CS7vcr0z.js} +1 -1
  65. package/dist/assets/{channel-Ny3Nm_-t.js → channel-CF3zZzSR.js} +1 -1
  66. package/dist/assets/{chunk-4BX2VUAB-DdsULqPZ.js → chunk-4BX2VUAB-1FZYtnJ7.js} +1 -1
  67. package/dist/assets/{chunk-4TB4RGXK-BDSjQHh0.js → chunk-4TB4RGXK-COs1qui5.js} +1 -1
  68. package/dist/assets/{chunk-55IACEB6-DrKr3wBa.js → chunk-55IACEB6-p77Qw3wN.js} +1 -1
  69. package/dist/assets/{chunk-EDXVE4YY-o_0SUbAB.js → chunk-EDXVE4YY-5qaIrQKg.js} +1 -1
  70. package/dist/assets/{chunk-FMBD7UC4-Ca_AgqWi.js → chunk-FMBD7UC4-DmCR8mDZ.js} +1 -1
  71. package/dist/assets/{chunk-OYMX7WX6-CyWWbq5o.js → chunk-OYMX7WX6-D6xDfgW3.js} +1 -1
  72. package/dist/assets/{chunk-QZHKN3VN-5rXHErSL.js → chunk-QZHKN3VN-B6cmUU0N.js} +1 -1
  73. package/dist/assets/{chunk-YZCP3GAM-DznXBadU.js → chunk-YZCP3GAM-l-OyOqnn.js} +1 -1
  74. package/dist/assets/classDiagram-6PBFFD2Q-BiCYgTHO.js +1 -0
  75. package/dist/assets/classDiagram-v2-HSJHXN6E-BiCYgTHO.js +1 -0
  76. package/dist/assets/clone-ChTCnPsO.js +1 -0
  77. package/dist/assets/{cose-bilkent-S5V4N54A-BhGyix0v.js → cose-bilkent-S5V4N54A-CEzaS8XS.js} +1 -1
  78. package/dist/assets/{dagre-KV5264BT-CzzHxIvc.js → dagre-KV5264BT-B3U2njWW.js} +1 -1
  79. package/dist/assets/{diagram-5BDNPKRD-tu3BXl0c.js → diagram-5BDNPKRD-BRSDbyBr.js} +1 -1
  80. package/dist/assets/{diagram-G4DWMVQ6-C6WkK7sj.js → diagram-G4DWMVQ6-BZfOi9B7.js} +1 -1
  81. package/dist/assets/{diagram-MMDJMWI5-DBeD_WW-.js → diagram-MMDJMWI5-CWpb3Cg0.js} +1 -1
  82. package/dist/assets/{diagram-TYMM5635-BXUyHHJ4.js → diagram-TYMM5635-CTJyBSVj.js} +1 -1
  83. package/dist/assets/{erDiagram-SMLLAGMA-Bye5tnW2.js → erDiagram-SMLLAGMA-CHtTRd5S.js} +1 -1
  84. package/dist/assets/{flowDiagram-DWJPFMVM-C3pYOs38.js → flowDiagram-DWJPFMVM-Bda8X-WJ.js} +1 -1
  85. package/dist/assets/{ganttDiagram-T4ZO3ILL-DxXkI_FW.js → ganttDiagram-T4ZO3ILL-CPfnGu5V.js} +1 -1
  86. package/dist/assets/{gitGraphDiagram-UUTBAWPF-nsxsXsGX.js → gitGraphDiagram-UUTBAWPF-B5QxesQg.js} +1 -1
  87. package/dist/assets/{graph-Da-Z9hB7.js → graph-ChltdhTU.js} +1 -1
  88. package/dist/assets/{index-4gmR7Eun.js → index-B7lK5fJz.js} +1 -1
  89. package/dist/assets/{index-C8w5Sxw3.js → index-BK4sui_O.js} +1 -1
  90. package/dist/assets/{index-CA8JGh5J.js → index-C2fhupP6.js} +1 -1
  91. package/dist/assets/{index-CLfbZzwF.js → index-C3dxIBgt.js} +2 -2
  92. package/dist/assets/{index-D7XF7UJ8.js → index-C5PA4OJg.js} +1 -1
  93. package/dist/assets/{index-C0PhJcXG.js → index-CfEkC3bc.js} +1 -1
  94. package/dist/assets/{index-Brh2V8V0.js → index-DyGa-jNv.js} +1 -1
  95. package/dist/assets/{index-CsuhosSl.js → index-yClPXlMf.js} +1 -1
  96. package/dist/assets/{infoDiagram-42DDH7IO-Ca9j90t5.js → infoDiagram-42DDH7IO-CD4TS4O2.js} +1 -1
  97. package/dist/assets/{ishikawaDiagram-UXIWVN3A-DhjV0XPD.js → ishikawaDiagram-UXIWVN3A-jhiYabQ7.js} +1 -1
  98. package/dist/assets/{journeyDiagram-VCZTEJTY-CRSHLZPV.js → journeyDiagram-VCZTEJTY-BDzIXxxt.js} +1 -1
  99. package/dist/assets/{jszip.min-CcCCdMNW.js → jszip.min-CuGGBMI4.js} +1 -1
  100. package/dist/assets/{kanban-definition-6JOO6SKY-Bg0CUwgc.js → kanban-definition-6JOO6SKY-D34MYATQ.js} +1 -1
  101. package/dist/assets/{layout-CWNu13XT.js → layout-D6sLAapX.js} +1 -1
  102. package/dist/assets/{linear-Dcmw1639.js → linear-CFV4P-wn.js} +1 -1
  103. package/dist/assets/{mermaid.core-1heNIJ5f.js → mermaid.core-YmJi7T-s.js} +2 -2
  104. package/dist/assets/{min-CC9CkAxn.js → min-akJQqRMn.js} +1 -1
  105. package/dist/assets/{mindmap-definition-QFDTVHPH-Gr0ex_Ny.js → mindmap-definition-QFDTVHPH-w5zaJyrN.js} +1 -1
  106. package/dist/assets/{pieDiagram-DEJITSTG-D7P3sUJY.js → pieDiagram-DEJITSTG-B6EM4Ow6.js} +1 -1
  107. package/dist/assets/{quadrantDiagram-34T5L4WZ-Bov3lcpV.js → quadrantDiagram-34T5L4WZ-2TmBxFy-.js} +1 -1
  108. package/dist/assets/{requirementDiagram-MS252O5E-BcLptaOU.js → requirementDiagram-MS252O5E-EOjvbxUy.js} +1 -1
  109. package/dist/assets/{sankeyDiagram-XADWPNL6-B2qAUsON.js → sankeyDiagram-XADWPNL6-BmTQD5eT.js} +1 -1
  110. package/dist/assets/seqResourceLoaders-Dov_BuQp.js +2 -0
  111. package/dist/assets/{seqResourceLoaders-N07Gfom9.css → seqResourceLoaders-DwpfKCub.css} +2 -2
  112. package/dist/assets/{sequenceDiagram-FGHM5R23-Do62Uz-a.js → sequenceDiagram-FGHM5R23-CLjtqA1D.js} +1 -1
  113. package/dist/assets/{stateDiagram-FHFEXIEX-Wu8aqa8C.js → stateDiagram-FHFEXIEX-Cbq90iZ8.js} +1 -1
  114. package/dist/assets/{stateDiagram-v2-QKLJ7IA2-BfYq7Jgo.js → stateDiagram-v2-QKLJ7IA2-BKDg-3t_.js} +1 -1
  115. package/dist/assets/{timeline-definition-GMOUNBTQ-DYfz5xD6.js → timeline-definition-GMOUNBTQ-f3kEDay0.js} +1 -1
  116. package/dist/assets/{vendor-antd-BG1SvzuN.js → vendor-antd-5xE7sz6B.js} +1 -1
  117. package/dist/assets/{vendor-codemirror-8NDhydlF.js → vendor-codemirror-ib-jPbXC.js} +1 -1
  118. package/dist/assets/{vendor-mdxeditor-BB4hhpxM.js → vendor-mdxeditor-BdKMdw6O.js} +2 -2
  119. package/dist/assets/{vendor-qrcode-DMsNGQ10.js → vendor-qrcode-vKlE-WYu.js} +1 -1
  120. package/dist/assets/{vendor-virtuoso-BUT96ALa.js → vendor-virtuoso-DOIfjLfU.js} +1 -1
  121. package/dist/assets/{vennDiagram-DHZGUBPP-CGr-cc7e.js → vennDiagram-DHZGUBPP-0GDSFVnH.js} +1 -1
  122. package/dist/assets/{wardley-RL74JXVD-BN899vMf.js → wardley-RL74JXVD-B2rj5j7G.js} +1 -1
  123. package/dist/assets/{wardleyDiagram-NUSXRM2D-xUsI1E7h.js → wardleyDiagram-NUSXRM2D-COVTciJP.js} +1 -1
  124. package/dist/assets/{xychartDiagram-5P7HB3ND-woQrslzB.js → xychartDiagram-5P7HB3ND-DXoLnGxX.js} +1 -1
  125. package/dist/index.html +4 -4
  126. package/findcc.js +26 -7
  127. package/interceptor.js +11 -1061
  128. package/package.json +6 -12
  129. package/plugins/.gitkeep +0 -0
  130. package/server/_paths.js +35 -0
  131. package/server/interceptor.js +1057 -0
  132. package/{lib → server/lib}/approval-modal-prefs.js +2 -1
  133. package/{lib → server/lib}/ask-store.js +51 -10
  134. package/server/lib/cli-inject.js +81 -0
  135. package/{lib → server/lib}/context-watcher.js +41 -1
  136. package/{lib → server/lib}/delta-reconstructor.js +1 -0
  137. package/{lib → server/lib}/enrich-plan-input.js +2 -2
  138. package/{lib → server/lib}/ensure-hooks.js +76 -12
  139. package/{lib → server/lib}/extract-plugin-name.mjs +1 -1
  140. package/{lib → server/lib}/file-access-policy.js +2 -2
  141. package/{lib → server/lib}/jsonl-archive.js +1 -1
  142. package/{lib → server/lib}/plugin-loader.js +5 -4
  143. package/{lib → server/lib}/plugin-manager.js +1 -1
  144. package/{lib → server/lib}/sdk-manager.js +1 -1
  145. package/{lib → server/lib}/session-transcript-reader.js +1 -1
  146. package/{lib → server/lib}/terminal-env.js +1 -1
  147. package/{lib → server/lib}/tools-xml-formatter.js +2 -1
  148. package/{lib → server/lib}/updater.js +3 -2
  149. package/{lib → server/lib}/voice-pack-events.js +4 -3
  150. package/{lib → server/lib}/voice-pack-manager.js +4 -8
  151. package/{proxy.js → server/proxy.js} +1 -1
  152. package/{pty-manager.js → server/pty-manager.js} +19 -5
  153. package/{scratch-pty-manager.js → server/scratch-pty-manager.js} +16 -4
  154. package/server/server.js +5467 -0
  155. package/{workspace-registry.js → server/workspace-registry.js} +2 -2
  156. package/server.js +5 -5459
  157. package/dist/assets/App-DOYmReD4.css +0 -1
  158. package/dist/assets/App-LEYaH-CM.js +0 -1
  159. package/dist/assets/Mobile-Cwf21Pmq.js +0 -1
  160. package/dist/assets/classDiagram-6PBFFD2Q-CLYcbnwx.js +0 -1
  161. package/dist/assets/classDiagram-v2-HSJHXN6E-CLYcbnwx.js +0 -1
  162. package/dist/assets/clone-5GFhU8Pv.js +0 -1
  163. package/dist/assets/seqResourceLoaders-CmFg0jyW.js +0 -2
  164. /package/{i18n.js → server/i18n.js} +0 -0
  165. /package/{lib → server/lib}/ask-bridge.js +0 -0
  166. /package/{lib → server/lib}/ask-constants.js +0 -0
  167. /package/{lib → server/lib}/ccv-editor.js +0 -0
  168. /package/{lib → server/lib}/claude-md-discovery.js +0 -0
  169. /package/{lib → server/lib}/file-api.js +0 -0
  170. /package/{lib → server/lib}/git-diff.js +0 -0
  171. /package/{lib → server/lib}/interceptor-core.js +0 -0
  172. /package/{lib → server/lib}/kv-cache-analyzer.js +0 -0
  173. /package/{lib → server/lib}/log-management.js +0 -0
  174. /package/{lib → server/lib}/log-stream.js +0 -0
  175. /package/{lib → server/lib}/log-watcher.js +0 -0
  176. /package/{lib → server/lib}/perm-bridge.js +0 -0
  177. /package/{lib → server/lib}/proxy-env.js +0 -0
  178. /package/{lib → server/lib}/proxy-errors.js +0 -0
  179. /package/{lib → server/lib}/sdk-adapter.js +0 -0
  180. /package/{lib → server/lib}/skills-api.js +0 -0
  181. /package/{lib → server/lib}/sse-backpressure.js +0 -0
  182. /package/{lib → server/lib}/stats-worker.js +0 -0
  183. /package/{lib → server/lib}/team-runtime.js +0 -0
  184. /package/{lib → server/lib}/turn-end-bridge.js +0 -0
  185. /package/{lib → server/lib}/user-profile.js +0 -0
  186. /package/{lib → server/lib}/zip-safety.js +0 -0
package/cli.js CHANGED
@@ -5,15 +5,18 @@ import { resolve, isAbsolute } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { homedir } from 'node:os';
7
7
  import { spawn } from 'node:child_process';
8
- import { t } from './i18n.js';
9
- import { INJECT_IMPORT, resolveCliPath, resolveNativePath, resolveNpmClaudePath, buildShellCandidates, setLogDir, LOG_DIR, hasClaude2xWrapper, getGlobalNodeModulesDir, PACKAGES, getClaudeConfigDir } from './findcc.js';
10
- import { ensureHooks } from './lib/ensure-hooks.js';
8
+ import { t } from './server/i18n.js';
9
+ import { INJECT_IMPORT, LEGACY_INJECT_IMPORTS, resolveCliPath, resolveNativePath, resolveNpmClaudePath, buildShellCandidates, setLogDir, LOG_DIR, hasClaude2xWrapper, getGlobalNodeModulesDir, PACKAGES, getClaudeConfigDir } from './findcc.js';
10
+ import { ensureHooks, removeAllManagedHooks } from './server/lib/ensure-hooks.js';
11
+ import { injectCliJsAt, removeCliJsInjectionAt, INJECT_START as _INJECT_START, INJECT_END as _INJECT_END, buildInjectBlock as _buildInjectBlock } from './server/lib/cli-inject.js';
11
12
 
12
13
  const __dirname = fileURLToPath(new URL('.', import.meta.url));
13
14
 
14
- const INJECT_START = '// >>> Start CC Viewer Web Service >>>';
15
- const INJECT_END = '// <<< Start CC Viewer Web Service <<<';
16
- const INJECT_BLOCK = `${INJECT_START}\n${INJECT_IMPORT}\n${INJECT_END}`;
15
+ // 注入 marker 常量定义在 server/lib/cli-inject.js(便于单元测试);
16
+ // 本文件仅 re-export helper hook 使用,保持现有行为。
17
+ const INJECT_START = _INJECT_START;
18
+ const INJECT_END = _INJECT_END;
19
+ const INJECT_BLOCK = _buildInjectBlock(INJECT_IMPORT);
17
20
 
18
21
 
19
22
  const SHELL_HOOK_START = '# >>> CC-Viewer Auto-Inject >>>';
@@ -198,36 +201,17 @@ function removeShellHook() {
198
201
  }
199
202
 
200
203
  function injectCliJs() {
201
- const content = readFileSync(cliPath, 'utf-8');
202
- if (content.includes(INJECT_START)) {
203
- return 'exists';
204
- }
205
- // 保留主导 EOL:若原文件 CRLF,注入完仍 CRLF(否则 split('\n')+join('\n') 会把 Win 文件
206
- // 一次性转 LF,git/编辑器抱怨混合行尾且对哈希签名敏感的脚本可能失效)。
207
- const eol = content.includes('\r\n') ? '\r\n' : '\n';
208
- const lines = content.split(/\r?\n/);
209
- lines.splice(2, 0, INJECT_BLOCK);
210
- writeFileSync(cliPath, lines.join(eol));
211
- return 'injected';
204
+ return injectCliJsAt(cliPath, INJECT_IMPORT, LEGACY_INJECT_IMPORTS);
212
205
  }
213
206
 
214
207
  function removeCliJsInjection() {
215
- try {
216
- if (!existsSync(cliPath)) return 'not_found';
217
- const content = readFileSync(cliPath, 'utf-8');
218
- if (!content.includes(INJECT_START)) return 'clean';
219
- const regex = new RegExp(`${INJECT_START}\\n${INJECT_IMPORT}\\n${INJECT_END}\\n?`, 'g');
220
- writeFileSync(cliPath, content.replace(regex, ''));
221
- return 'removed';
222
- } catch {
223
- return 'error';
224
- }
208
+ return removeCliJsInjectionAt(cliPath, INJECT_IMPORT, LEGACY_INJECT_IMPORTS);
225
209
  }
226
210
 
227
211
  async function runProxyCommand(args) {
228
212
  try {
229
213
  // Dynamic import to avoid side effects when just installing
230
- const { startProxy } = await import('./proxy.js');
214
+ const { startProxy } = await import('./server/proxy.js');
231
215
  const proxyPort = await startProxy();
232
216
 
233
217
  // args = ['run', '--', 'command', 'claude', ...] or ['run', 'claude', ...]
@@ -285,7 +269,7 @@ async function runProxyCommand(args) {
285
269
  // 可通过环境变量 CCV_SKIP_THINKING_DISPLAY=1 强制跳过。
286
270
  const isClaudeCmd = cmd === 'claude' || /[\\/]claude(\.exe)?$/.test(cmd);
287
271
  if (isClaudeCmd && process.env.CCV_SKIP_THINKING_DISPLAY !== '1') {
288
- const { withDefaultThinkingDisplay } = await import('./pty-manager.js');
272
+ const { withDefaultThinkingDisplay } = await import('./server/pty-manager.js');
289
273
  cmdArgs = withDefaultThinkingDisplay(cmdArgs);
290
274
  }
291
275
 
@@ -308,7 +292,7 @@ async function runProxyCommand(args) {
308
292
  }
309
293
  }
310
294
 
311
- // ensureHooks() extracted to lib/ensure-hooks.js (shared with electron/tab-worker.js)
295
+ // ensureHooks() extracted to server/lib/ensure-hooks.js (shared with electron/tab-worker.js)
312
296
 
313
297
  async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
314
298
  // 首先尝试 npm 版本(包括 nvm 安装),找不到再尝试 native 版本
@@ -329,7 +313,7 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
329
313
  const workingDir = cwd || process.cwd();
330
314
 
331
315
  // 注册工作区
332
- const { registerWorkspace } = await import('./workspace-registry.js');
316
+ const { registerWorkspace } = await import('./server/workspace-registry.js');
333
317
  registerWorkspace(workingDir);
334
318
 
335
319
  // 确保 AskUserQuestion hook 已注册到 ~/.claude/settings.json
@@ -347,12 +331,12 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
347
331
  }
348
332
 
349
333
  // 1. 启动代理
350
- const { startProxy } = await import('./proxy.js');
334
+ const { startProxy } = await import('./server/proxy.js');
351
335
  const proxyPort = await startProxy();
352
336
  process.env.CCV_PROXY_PORT = String(proxyPort);
353
337
 
354
338
  // 3. 启动 HTTP 服务器
355
- const serverMod = await import('./server.js');
339
+ const serverMod = await import('./server/server.js');
356
340
 
357
341
  // 等待服务器启动完成
358
342
  await new Promise(resolve => {
@@ -368,7 +352,7 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
368
352
  const serverProtocol = serverMod.getProtocol();
369
353
 
370
354
  // 3. 启动 PTY 中的 claude
371
- const { spawnClaude, killPty } = await import('./pty-manager.js');
355
+ const { spawnClaude, killPty } = await import('./server/pty-manager.js');
372
356
  try {
373
357
  await spawnClaude(proxyPort, workingDir, extraClaudeArgs, claudePath, isNpmVersion, port, serverProtocol, serverMod.getInternalToken());
374
358
  } catch (err) {
@@ -416,7 +400,7 @@ async function runSdkMode(extraClaudeArgs = [], cwd, noOpen = false) {
416
400
  // 检查 SDK 是否可用
417
401
  let sdkManager;
418
402
  try {
419
- sdkManager = await import('./lib/sdk-manager.js');
403
+ sdkManager = await import('./server/lib/sdk-manager.js');
420
404
  if (!sdkManager.isSdkAvailable()) throw new Error('query not available');
421
405
  } catch {
422
406
  console.warn('[CC Viewer] Agent SDK not available, falling back to PTY mode (-C)');
@@ -426,7 +410,7 @@ async function runSdkMode(extraClaudeArgs = [], cwd, noOpen = false) {
426
410
  const workingDir = cwd || process.cwd();
427
411
 
428
412
  // 注册工作区
429
- const { registerWorkspace } = await import('./workspace-registry.js');
413
+ const { registerWorkspace } = await import('./server/workspace-registry.js');
430
414
  registerWorkspace(workingDir);
431
415
 
432
416
  // 不需要 ensureHooks — SDK canUseTool 处理 AskUserQuestion + 权限
@@ -439,7 +423,7 @@ async function runSdkMode(extraClaudeArgs = [], cwd, noOpen = false) {
439
423
  process.env.CCV_PROXY_MODE = '1'; // 使 interceptor.js 惰性
440
424
 
441
425
  // 启动 HTTP 服务器
442
- const serverMod = await import('./server.js');
426
+ const serverMod = await import('./server/server.js');
443
427
 
444
428
  await new Promise(resolve => {
445
429
  const check = () => {
@@ -467,7 +451,7 @@ async function runSdkMode(extraClaudeArgs = [], cwd, noOpen = false) {
467
451
  onStreamingStatus: (data) => serverMod.setSdkStreamingState(data),
468
452
  broadcastWs: (msg) => serverMod.broadcastWsMessage(msg),
469
453
  permissionMode,
470
- runWaterfallHook: (await import('./lib/plugin-loader.js')).runWaterfallHook,
454
+ runWaterfallHook: (await import('./server/lib/plugin-loader.js')).runWaterfallHook,
471
455
  // Round-3 P0: SDK mode has no Stop hook (ensureHooks() skipped above), so
472
456
  // the only place we learn a turn ended is the SDK 'result' message. Forward
473
457
  // it to the same SSE channel the Stop hook bridge uses in PTY mode.
@@ -545,12 +529,12 @@ async function runCliModeWorkspaceSelector(extraClaudeArgs = [], noOpen = false)
545
529
  process.env.CCV_WORKSPACE_MODE = '1';
546
530
 
547
531
  // 启动代理
548
- const { startProxy } = await import('./proxy.js');
532
+ const { startProxy } = await import('./server/proxy.js');
549
533
  const proxyPort = await startProxy();
550
534
  process.env.CCV_PROXY_PORT = String(proxyPort);
551
535
 
552
536
  // 启动 HTTP 服务器(工作区模式,不初始化 interceptor 日志)
553
- const serverMod = await import('./server.js');
537
+ const serverMod = await import('./server/server.js');
554
538
 
555
539
  // 工作区模式下 server.js 跳过了自动启动,需要手动调用
556
540
  await serverMod.startViewer();
@@ -588,7 +572,7 @@ async function runCliModeWorkspaceSelector(extraClaudeArgs = [], noOpen = false)
588
572
  }
589
573
 
590
574
  // 注册退出处理
591
- const { killPty } = await import('./pty-manager.js');
575
+ const { killPty } = await import('./server/pty-manager.js');
592
576
  const cleanup = () => {
593
577
  killPty();
594
578
  serverMod.stopViewer().finally(() => process.exit());
@@ -702,16 +686,33 @@ if (isUninstall) {
702
686
  console.log(t('cli.uninstall.hookFail', { error: shellResult.error }));
703
687
  }
704
688
 
705
- // 清理 statusLine 配置和脚本(兼容历史版本遗留)
689
+ // 清理 settings.json 里的 cc-viewer-managed hooks + 历史 statusLine 残留
690
+ // 一次性 read-modify-write,避免对 settings.json 做两轮 IO。
706
691
  try {
707
692
  const settingsPath = resolve(getClaudeConfigDir(), 'settings.json');
708
693
  if (existsSync(settingsPath)) {
709
694
  const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
695
+ let mutated = false;
696
+
697
+ // 1) 移除所有带 cc-viewer-managed marker 的 hook entry(PreToolUse + Stop)
698
+ // 无此清理 → npm uninstall 后用户 settings.json 仍含 dead path → claude 启动
699
+ // 时每个工具调用都 ENOENT 报错。
700
+ const removed = removeAllManagedHooks(settings);
701
+ if (removed > 0) {
702
+ mutated = true;
703
+ console.log(`Removed ${removed} cc-viewer-managed hook entr${removed === 1 ? 'y' : 'ies'} from settings.json`);
704
+ }
705
+
706
+ // 2) 历史 statusLine 残留
710
707
  if (settings.statusLine?.command?.includes('ccv-statusline')) {
711
708
  delete settings.statusLine;
712
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
709
+ mutated = true;
713
710
  console.log('Cleaned statusLine config from settings.json');
714
711
  }
712
+
713
+ if (mutated) {
714
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
715
+ }
715
716
  }
716
717
  const ccvScript = resolve(getClaudeConfigDir(), 'ccv-statusline.sh');
717
718
  if (existsSync(ccvScript)) {
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent هو سلسلة الطلبات الرئيسية في Claude Code عن
6
6
 
7
7
  ## طريقة التعرف
8
8
 
9
- في cc-viewer، يُعرَّف MainAgent من خلال `req.mainAgent === true`، ويتم تعيينه تلقائياً بواسطة `interceptor.js` عند التقاط الطلب.
9
+ في cc-viewer، يُعرَّف MainAgent من خلال `req.mainAgent === true`، ويتم تعيينه تلقائياً بواسطة `server/interceptor.js` عند التقاط الطلب.
10
10
 
11
11
  شروط التحديد (يجب استيفاؤها جميعاً):
12
12
  - جسم الطلب يحتوي على حقل `system` (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent er den primære requestkæde i Claude Code, når det ikke er i agent t
6
6
 
7
7
  ## Identifikationsmetode
8
8
 
9
- I cc-viewer identificeres MainAgent via `req.mainAgent === true`, automatisk markeret af `interceptor.js` ved request-opfangning.
9
+ I cc-viewer identificeres MainAgent via `req.mainAgent === true`, automatisk markeret af `server/interceptor.js` ved request-opfangning.
10
10
 
11
11
  Betingelser for bestemmelse (alle skal være opfyldt):
12
12
  - Request body indeholder feltet `system` (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent ist die Hauptanfragekette von Claude Code im Nicht-Agent-Team-Modus. J
6
6
 
7
7
  ## Erkennung
8
8
 
9
- In cc-viewer wird MainAgent durch `req.mainAgent === true` identifiziert und von `interceptor.js` beim Abfangen der Anfrage automatisch markiert.
9
+ In cc-viewer wird MainAgent durch `req.mainAgent === true` identifiziert und von `server/interceptor.js` beim Abfangen der Anfrage automatisch markiert.
10
10
 
11
11
  Erkennungsbedingungen (alle müssen erfüllt sein):
12
12
  - Der Request-Body enthält das `system`-Feld (System-Prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer auto-registers hooks in `~/.claude/settings.json` under `hooks.PreTool
122
122
 
123
123
  ### 1. AskUserQuestion Bridge
124
124
  - **Matcher**: `"AskUserQuestion"`
125
- - **Command**: `node <install_dir>/lib/ask-bridge.js`
125
+ - **Command**: `node <install_dir>/server/lib/ask-bridge.js`
126
126
  - **Purpose**: Forward Claude's questions to Web UI, wait for user answers
127
127
 
128
128
  ### 2. Permission Approval Bridge
129
129
  - **Matcher**: `""` (empty = match all tools)
130
- - **Command**: `node <install_dir>/lib/perm-bridge.js`
130
+ - **Command**: `node <install_dir>/server/lib/perm-bridge.js`
131
131
  - **Purpose**: Only `Bash`/`Edit`/`Write`/`NotebookEdit` require Web UI approval; others pass through
132
132
 
133
133
  ## 7. Shell Integration
@@ -6,7 +6,7 @@ MainAgent is the primary request chain in Claude Code when not in agent team mod
6
6
 
7
7
  ## Identification
8
8
 
9
- In cc-viewer, MainAgent is identified by `req.mainAgent === true`, automatically tagged by `interceptor.js` during request capture.
9
+ In cc-viewer, MainAgent is identified by `req.mainAgent === true`, automatically tagged by `server/interceptor.js` during request capture.
10
10
 
11
11
  Criteria (all must be met):
12
12
  - The request body contains a `system` field (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent es la cadena de solicitudes principal de Claude Code en estado no agen
6
6
 
7
7
  ## Método de identificación
8
8
 
9
- En cc-viewer, MainAgent se identifica mediante `req.mainAgent === true`, marcado automáticamente por `interceptor.js` durante la captura de la solicitud.
9
+ En cc-viewer, MainAgent se identifica mediante `req.mainAgent === true`, marcado automáticamente por `server/interceptor.js` durante la captura de la solicitud.
10
10
 
11
11
  Condiciones de determinación (deben cumplirse todas):
12
12
  - El cuerpo de la solicitud contiene el campo `system` (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent est la chaîne de requêtes principale de Claude Code en état non age
6
6
 
7
7
  ## Méthode d'identification
8
8
 
9
- Dans cc-viewer, MainAgent est identifié par `req.mainAgent === true`, marqué automatiquement par `interceptor.js` lors de la capture de la requête.
9
+ Dans cc-viewer, MainAgent est identifié par `req.mainAgent === true`, marqué automatiquement par `server/interceptor.js` lors de la capture de la requête.
10
10
 
11
11
  Conditions de détermination (toutes doivent être remplies) :
12
12
  - Le corps de la requête contient le champ `system` (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent è la catena di richieste principale di Claude Code quando non è in m
6
6
 
7
7
  ## Metodo di identificazione
8
8
 
9
- In cc-viewer, MainAgent è identificato tramite `req.mainAgent === true`, contrassegnato automaticamente da `interceptor.js` al momento della cattura della richiesta.
9
+ In cc-viewer, MainAgent è identificato tramite `req.mainAgent === true`, contrassegnato automaticamente da `server/interceptor.js` al momento della cattura della richiesta.
10
10
 
11
11
  Condizioni di determinazione (tutte devono essere soddisfatte):
12
12
  - Il corpo della richiesta contiene il campo `system` (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent は、Claude Code が非 agent team 状態における主幹リクエ
6
6
 
7
7
  ## 識別方法
8
8
 
9
- cc-viewer では、MainAgent は `req.mainAgent === true` で識別され、`interceptor.js` がリクエストキャプチャ時に自動的にマーキングします。
9
+ cc-viewer では、MainAgent は `req.mainAgent === true` で識別され、`server/interceptor.js` がリクエストキャプチャ時に自動的にマーキングします。
10
10
 
11
11
  判定条件(すべて満たす):
12
12
  - リクエストボディに `system` フィールド(system prompt)が含まれる
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent는 Claude Code가 비 agent team 상태에서의 주간 요청 체인
6
6
 
7
7
  ## 식별 방법
8
8
 
9
- cc-viewer에서 MainAgent는 `req.mainAgent === true`로 식별되며, `interceptor.js`가 요청 캡처 시 자동으로 마킹합니다.
9
+ cc-viewer에서 MainAgent는 `req.mainAgent === true`로 식별되며, `server/interceptor.js`가 요청 캡처 시 자동으로 마킹합니다.
10
10
 
11
11
  판정 조건 (모두 충족):
12
12
  - 요청 본문에 `system` 필드 (system prompt) 포함
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent er hovedforespørselskjeden i Claude Code når den ikke er i agent tea
6
6
 
7
7
  ## Identifisering
8
8
 
9
- I cc-viewer identifiseres MainAgent gjennom `req.mainAgent === true`, som automatisk settes av `interceptor.js` ved forespørselsfangst.
9
+ I cc-viewer identifiseres MainAgent gjennom `req.mainAgent === true`, som automatisk settes av `server/interceptor.js` ved forespørselsfangst.
10
10
 
11
11
  Bestemmelsesvilkår (alle må oppfylles):
12
12
  - Forespørselskroppen inneholder `system`-felt (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成
@@ -6,7 +6,7 @@ MainAgent to główny łańcuch żądań Claude Code w trybie bez agent team. Ka
6
6
 
7
7
  ## Sposób identyfikacji
8
8
 
9
- W cc-viewer MainAgent jest identyfikowany przez `req.mainAgent === true`, automatycznie oznaczany przez `interceptor.js` podczas przechwytywania żądania.
9
+ W cc-viewer MainAgent jest identyfikowany przez `req.mainAgent === true`, automatycznie oznaczany przez `server/interceptor.js` podczas przechwytywania żądania.
10
10
 
11
11
  Warunki kwalifikacji (wszystkie muszą być spełnione):
12
12
  - Treść żądania zawiera pole `system` (system prompt)
@@ -18,7 +18,7 @@ Hot-Switch Proxy lets you dynamically redirect API requests to a different endpo
18
18
 
19
19
  ## How It Works
20
20
 
21
- When a proxy is active, `interceptor.js` performs the following before each API request:
21
+ When a proxy is active, `server/interceptor.js` performs the following before each API request:
22
22
 
23
23
  1. **URL Rewrite** — Replaces the request origin with the proxy's Base URL
24
24
  2. **Auth Replace** — Replaces `x-api-key` or `Authorization` header with the proxy's API Key
@@ -122,12 +122,12 @@ CC-Viewer 自动注册到 `~/.claude/settings.json` 的 `hooks.PreToolUse` 中
122
122
 
123
123
  ### 1. AskUserQuestion 桥接
124
124
  - **匹配器**: `"AskUserQuestion"`
125
- - **命令**: `node <安装目录>/lib/ask-bridge.js`
125
+ - **命令**: `node <安装目录>/server/lib/ask-bridge.js`
126
126
  - **作用**: 将 Claude 的问题转发到 Web UI,等待用户回答
127
127
 
128
128
  ### 2. 权限审批桥接
129
129
  - **匹配器**: `""` (空 = 匹配所有工具)
130
- - **命令**: `node <安装目录>/lib/perm-bridge.js`
130
+ - **命令**: `node <安装目录>/server/lib/perm-bridge.js`
131
131
  - **作用**: 仅 `Bash`/`Edit`/`Write`/`NotebookEdit` 需要 Web UI 审批,其余自动放行
132
132
 
133
133
  ## 七、Shell 集成