跳转到内容

架构概览

Dline 目前以一个 VS Code 扩展发布,内嵌 React Webview。本页按运行时的层次说明主要模块及其源码位置,便于修改前找到真正的入口。

目录内容
src/扩展主体:入口、核心逻辑、宿主适配、共享代码和测试
webview-ui/独立的 React + Vite Webview 项目
proto/Protobuf 合同,见 Protobuf 与 ProtoBus
scripts/代码生成、打包、测试与构建辅助脚本
docs/本文档站(独立的 Astro Starlight 项目)和英文更新日志
standalone/、src/standalone/、src/hosts/external/为未来的独立可执行程序保留的代码,当前发布只包含 VS Code 扩展
testing-platform/、tests/独立集成测试客户端和 Storybook 等附加测试

src/core 是源码分组,不是单独部署的产品。

package.json 的入口是 dist/extension.js,源码为 src/extension.ts 中的 activate()。启动顺序如下:

  1. setupHostProvider() 通过 HostProvider.initialize() 注册 VS Code 版本的 Webview、diff、review、终端和宿主桥接实现;
  2. 立即创建并注册侧边栏 Webview 提供者,它的 Controller 稍后才创建;
  3. 清理旧的 VS Code 存储;Dline 不会导入 Cline 数据(手动步骤见从 Cline 迁移);
  4. createStorageContext() 解析存储根目录,exportVSCodeStorageToSharedFiles() 把旧的 ExtensionContext 状态导出到文件存储;
  5. initialize()(src/common.ts)初始化 StateManager 和 ModelRegistry,创建 Controller 并挂到 Webview 提供者上,同时注册为编排器的主 Controller;
  6. 注册编辑器面板的序列化器、测试模式和钩子,最后注册 VS Code 命令。

src/hosts/host-provider.ts 中的 HostProvider 让任务和服务模块不直接依赖编辑器 API。VS Code 实现在 src/hosts/vscode/:

  • 宿主桥接的每个服务方法实现在 src/hosts/vscode/hostbridge/<service>/ 下,例如 window/showMessage.ts;
  • 请求分发在 src/hosts/vscode/hostbridge-grpc-handler.ts,它使用生成的服务配置;
  • 终端、diff 和 review 的 VS Code 实现也在这个目录下。

VS Code API 调用应当留在宿主和集成边界内。

组件源码职责
VscodeWebviewProvidersrc/hosts/vscode/VscodeWebviewProvider.ts绑定 VS Code 侧边栏
WebviewProvidersrc/core/webview/WebviewProvider.ts侧边栏和编辑器面板共用的生命周期
WebviewProviderRegistrysrc/core/webview/WebviewProviderRegistry.ts跟踪侧边栏和额外面板
Controllersrc/core/controller/index.ts协调任务、状态投影、RPC 处理和 Webview 更新
OrchestratorControllersrc/core/orchestrator/OrchestratorController.ts管理主 Controller、面板 Controller、Profile 广播和父子任务关系

每个 Webview 提供者拥有一个 Controller。React 端从 webview-ui/src/main.tsx 启动并渲染 App.tsx;共享的扩展状态通过 webview-ui/src/context/ExtensionStateContext.tsx 提供。

扩展与 Webview 之间的 RPC 是经 VS Code postMessage 传递的 ProtoBus 请求/响应信封,不是网络 gRPC 连接。

任务运行在基于日志(journal)的内核之上。Controller 为每个打开的任务持有一个 session/ActiveTaskSession.ts,所有生命周期变化都经过以下组件:

源码职责
shell/Task.ts、shell/TaskShell.ts任务的对外接口:打开、启动、提交输入、响应、取消和终止
kernel/transition.ts纯转换函数,按任务状态校验每个事件
kernel/hydrate.ts、kernel/recovery.ts任务重新打开时从 state.json 与日志重建状态,并恢复被中断的工作
runtime/TaskRuntime.ts串行处理事件,经提交管线持久化,并从持久化的 outbox 分发命令
stores/每次提交背后的日志、载荷与状态存储
composition/组装会话的运行时、存储与执行器,包括导入旧版本对话的升级流程
session/ActiveTaskSession.ts管理一个打开任务的资源,以及本窗口是否可以写入它
session/TaskInteractionOwner.ts管理审批、重试、恢复、问答、计划和完成等用户交互
MessageChannel.ts、message-state.ts串行投递消息并投影聊天行
activity/TaskActivityStore.ts管理聊天和 Activities 视图中的任务活动

以上路径都相对于 src/core/task/。新的生命周期转换应当表达为事件,经内核转换函数校验,再投影到界面;不要在 TaskRuntime 旁边另建布尔状态机。只有持有任务锁的窗口可以写入任务:在 TaskShell.open() 授予写入所有权之前,运行时以 read_only 拒绝所有事件,Controller 以只读方式显示该任务。

位置内容
src/shared/tools.ts内置工具身份,枚举 DlineDefaultTool
src/core/prompts/tools/tool-specs.ts规范工具描述 STANDARD_TOOL_SPECS
src/core/prompts/tools/tool-ids.ts按顺序列出 Standard 与 Lite 注册的工具 ID
src/core/prompts/tools/provider-projector.ts投影为服务商原生工具 Schema
src/core/prompts/tools/xml-tool-projector.ts投影为 XML 工具说明
src/core/task/tools/handlers/各工具的运行时处理器
src/core/task/ToolExecutor.ts、src/core/task/tools/ToolExecutorCoordinator.ts工具执行协调

原生工具和 XML 工具是同一套规范描述的两种投影。提示词与工具的关系见提示词架构,工具块的执行方式见工具执行域。

  • src/core/api/index.ts 的 buildApiHandler() 取当前模式的 Profile,经 buildApiHandlerFromProfile() 调用 createHandlerForProvider(),按 profile.provider 选择 src/core/api/providers/ 下的处理器;未知的服务商 ID 会抛出错误。
  • src/core/model-registry/ModelRegistry.ts 是运行时模型目录。
  • API 格式 ApiFormat 定义在 proto/dline/models/metadata.proto。服务商元数据和 API 格式决定原生工具、托管工具、图片、推理和传输能力。

扩展侧代码必须通过 src/shared/net.ts 访问网络,不要使用全局 fetch 或默认的 Axios 实例:

导出用途
fetch普通网络请求
providerFetch服务商 API 请求,会计入服务商请求观测
getAxiosSettings()为 Axios 请求提供共享的传输设置
createOpenAIClient()使用 providerFetch 的 OpenAI 兼容 SDK 客户端
mockFetchForTesting()测试时在限定范围内替换共享传输

按 Profile 创建 OpenAI 客户端的 createOpenAIClientForProfile() 位于 src/core/api/providers/openai-client-factory.ts。Webview 运行在浏览器环境中,可以使用浏览器自带的 fetch。

src/services/mcp/McpHub.ts 是多个 Controller 共享、按引用计数管理的实例,支持 stdio、sse 和 streamableHttp 三种传输;OAuth 只用于后两种远程传输。MCP 配置本身不会授予任务审批。