Reference | 关键 import 关系图¶
目的:理解"谁依赖谁"—— 知道改一处会影响哪些地方。 方法:从 import 列表反推依赖。
1. 顶层 import 链¶
[src/main.tsx]
├─ ./utils/startupProfiler.js (startupProfiler)
├─ ./utils/settings/mdm/rawRead.js (startMdmRawRead)
├─ ./utils/secureStorage/keychainPrefetch.js (keychainPrefetch)
├─ ./context.js (getOauthConfig, getRemoteSessionUrl)
├─ ./constants/oauth.js, ./constants/product.js
├─ ./entrypoints/init.js (init, initializeTelemetryAfterTrust)
├─ ./replLauncher.js (launchRepl)
├─ ./services/analytics/growthbook.js
├─ ./services/api/bootstrap.js, filesApi.js
├─ ./services/api/referral.js
├─ ./services/mcp/officialRegistry.js
├─ ./services/mcp/types.js (类型)
├─ ./services/policyLimits/index.js
├─ ./services/remoteManagedSettings/index.js
├─ ./Tool.js (类型)
├─ ./tools/SyntheticOutputTool/SyntheticOutputTool.js
├─ ./tools.js (getTools)
└─ ... ~50 个工具/服务
2. src/entrypoints/cli.tsx 依赖¶
[cli.tsx]
├─ (动态) ../utils/startupProfiler.js
├─ (动态) ../utils/config.js
├─ (动态) ../utils/model/model.js
├─ (动态) ../constants/prompts.js
├─ (动态) ../utils/claudeInChrome/mcpServer.js
└─ (动态) ../utils/chrome/nativeHost.js
关键:全用动态 import(await import(...))—— fast-path 设计。
3. src/screens/REPL.tsx 依赖(按层)¶
3.1 Ink 渲染层¶
REPL → ../../ink.js
├─ Box, Text, useStdin, useTheme, useTerminalFocus, useTerminalTitle, useTabStatus
└─ useInput
3.2 输入层¶
REPL → ../components/PromptInput/PromptInput.js (default)
→ ../components/PromptInput/PromptInputQueuedCommands.js
→ ../components/PromptInput/inputModes.js
3.3 状态层¶
3.4 副作用层(hooks)¶
REPL → ../hooks/useLogMessages.js
→ ../hooks/useReplBridge.js
→ ../hooks/useRemoteSession.js
→ ../hooks/useDirectConnect.js
→ ../hooks/useSSHSession.js
→ ../hooks/useAssistantHistory.js
→ ../hooks/useIdeLogging.js
→ ../hooks/useApiKeyVerification.js
→ ../hooks/useSkillImprovementSurvey.js
→ ../hooks/useAfterFirstRender.js
→ ../hooks/useDeferredHookMessages.js
→ ../hooks/useBackgroundTaskNavigation.js
→ ../hooks/useSwarmInitialization.js
→ ../hooks/useTeammateViewAutoExit.js
3.5 键位层¶
REPL → ../hooks/useGlobalKeybindings.js (GlobalKeybindingHandlers)
→ ../hooks/useCommandKeybindings.js (CommandKeybindingHandlers)
→ ../keybindings/KeybindingProviderSetup.js (KeybindingSetup)
→ ../keybindings/useShortcutDisplay.js
→ ../keybindings/shortcutFormat.js
→ ../hooks/useCancelRequest.js (CancelRequestHandler)
3.6 工具/权限层¶
REPL → ../components/permissions/PermissionRequest.js
→ ../components/permissions/WorkerPendingPermission.js
→ ../components/mcp/ElicitationDialog.js
→ ../components/hooks/PromptDialog.js
3.7 上下文/通知层¶
REPL → ../context/notifications.js
→ ../services/notifier.js
→ ../context/fpsMetrics.js
→ ../ink/useTerminalNotification.js
3.8 业务功能层(30+)¶
REPL → ../commands.js
→ ../types/textInputTypes.js
→ ../components/MessageSelector.js
→ ../services/Spinner.js
→ ../constants/prompts.js
→ ../utils/systemPrompt.js
→ ../utils/claudemd.js
→ ../utils/backgroundHousekeeping.js
→ ../history.ts
→ ../ssh/createSSHSession.js
→ ../server/directConnectManager.js
→ ../moreright/useMoreRight.js
→ ../tasks/InProcessTeammateTask/InProcessTeammateTask.js
→ ../tasks/LocalAgentTask/LocalAgentTask.js
→ ... (~30+ 业务模块)
4. src/state/ 内部依赖¶
[store.ts] ← 无外部依赖(自给自足 60 行)
[AppStateStore.ts]
├─ ../../services/mcp/types.js
├─ ../../tools/AgentTool/agentColorManager.js
├─ ../../tools/AgentTool/loadAgentsDir.js
├─ ../../tools/ExitPlanModeTool/ExitPlanModeV2Tool.js
├─ ../../types/ids.js
├─ ../../types/message.js
├─ ../../types/plugin.js
├─ ../../types/utils.js
├─ ../../utils/...
└─ ./store.js (Store<T>)
[AppState.tsx]
└─ ./AppStateStore.js (AppState 类型)
[selectors.ts]
├─ ../tasks/InProcessTeammateTask/types.js
├─ ../tasks/LocalAgentTask/LocalAgentTask.js
└─ ./AppStateStore.js (类型)
5. src/services/mcp/ 内部依赖¶
[MCPConnectionManager.tsx] ← 核心
├─ ./types.js (MCPServerConnection, ...)
├─ ./InProcessTransport.js
├─ ./SdkControlTransport.js
├─ ./client.ts (stdio / HTTP / SSE client)
├─ ./auth.js (OAuth)
└─ ./useManageMCPConnections.ts (React hook)
[client.ts] (3348 行)
├─ ./types.js
├─ ./normalization.js
└─ ./auth.js
6. src/Tool.ts 依赖¶
[Tool.ts] (792 行)
├─ @anthropic-ai/sdk/resources/index.mjs (类型)
├─ @modelcontextprotocol/sdk/types.js (类型)
├─ zod/v4 (类型)
├─ ./commands.js (Command 类型)
├─ ./hooks/useCanUseTool.js (CanUseToolFn 类型)
├─ ./utils/thinking.js (ThinkingConfig 类型)
├─ ./context/notifications.js (Notification 类型)
├─ ./services/mcp/types.js (MCPServerConnection)
├─ ./tools/AgentTool/loadAgentsDir.js (AgentDefinition)
├─ ./types/message.js (Message, AssistantMessage, ...)
├─ ./types/permissions.js (PermissionMode, PermissionResult)
├─ ./types/tools.js (各种 ToolProgressData)
├─ ./utils/fileStateCache.js
└─ ./utils/permissions/denialTracking.js
7. src/services/compact/ 内部依赖¶
[autoCompact.ts]
├─ ./autoCompact.js
└─ ../../utils/tokenBudget.js
[microCompact.ts]
├─ ./microCompact.js
└─ ../../utils/toolResult.js
[compact.ts]
├─ ./grouping.js
└─ ../../utils/messages.js
[grouping.ts]
└─ ../../types/message.js
[sessionMemoryCompact.ts]
└─ ../../memdir/...
8. src/bridge/ 内部依赖¶
[bridgeMain.ts] (2999 行) ← 核心
├─ ./bridgeApi.js
├─ ./bridgeConfig.js
├─ ./bridgeMessaging.js
├─ ./bridgePermissionCallbacks.js
└─ ./replBridge.ts
[replBridge.ts] (2406 行)
├─ ./bridgeMessaging.js
├─ ./bridgeStatusUtil.js
└─ ./inboundMessages.ts
9. 循环依赖的处理¶
9.1 注释里反复出现的"打破循环依赖"¶
// src/state/teammateViewHelpers.ts
// Inlined from framework.ts — importing creates a cycle through
// BackgroundTasksDialog. Keep in sync with PANEL_GRACE_MS there.
// src/services/mcp/elicitationHandler.ts (推测)
// Import from centralized location to break import cycles
9.2 解决方案¶
| 方案 | 出现位置 |
|---|---|
| 类型提到独立文件 | types/permissions.js / types/tools.js / types/ids.js |
| 重复代码 + 注释 "keep in sync" | teammateViewHelpers.ts 里的 PANEL_GRACE_MS |
| 运行时检查 | isInProcessTeammateTask(task) 用 type guard 替代 import |
10. 关键洞察¶
10.1 REPL.tsx 是"依赖中心"¶
5005 行 REPL.tsx 引入了 ~80 个其他模块。
改 REPL = 改整个项目。
10.2 state/ 是"低耦合岛"¶
store.ts0 依赖AppStateStore.ts30+ import(但都是 type-only)state/是整个项目"被引用最多"的地方,但主动依赖最少
10.3 services/ 是"高度互联"¶
mcp/内部 7-8 个 import 循环风险点compact/内部有 grouping、microCompact 互相依赖services/改一处要考虑多个(用 type-only 缓解)
10.4 utils/ 是"被引用最多"¶
utils/format.ts被 100+ 文件 importutils/messages.ts自身 5512 行 + 被广泛 importutils/是基础设施,不能轻易改签名
10.5 ink/ 是"独立"¶
- 几乎不依赖项目其他代码
- 唯一外部依赖是 React
- 可以单独研究
11. 阅读清单¶
- ✅ 任意 5 个文件的顶部 import
- ✅
src/state/AppStateStore.ts:1-30(看类型导入) - ✅
src/services/mcp/MCPConnectionManager.tsx:1-30(看 MCP 内部依赖) - 📌
src/screens/REPL.tsx:1-120(完整 import 列表) - 📌
src/bridge/bridgeMain.ts:1-30(bridge 内部依赖)
12. 练习任务¶
- 画 5 个文件的 import 关系图 —— 用 graphviz / mermaid
- 找循环依赖 —— 跑
madge --circular src/(如果有 madge 工具) - 数每个文件的 import 数 ——
grep -c "^import" file,画分布 - 思考:REPL.tsx 引入了 ~80 个模块,怎么让"组件级隔离"更容易?React.lazy?Code split?