应文浩wenhao.ying@xiaobao100.com e25ac591a7 init easy-code
2026-04-06 07:24:24 +08:00

8.2 KiB
Raw Blame History

技术栈映射说明

关联文档:总体概述

本文档说明 FreeCode .NET 版在技术选型上的完整映射逻辑,以及每个替代方案的选择依据。


1. 映射原则

在将 TypeScript/Bun 技术栈迁移到 .NET 10 的过程中,我们遵循三条核心原则,优先级由高到低:

成熟库优先 选用社区已经过生产环境验证的库,而不是最新但尚不稳定的方案。工具越成熟,坑越少,维护成本越低。

官方优先 微软官方或 .NET 基金会维护的包拥有更长的生命周期承诺和更一致的 API 风格。第三方包在官方方案缺失或明显不足时才纳入考虑。

AOT 兼容优先 FreeCode 最终需要编译为原生 AOT 二进制,以实现秒级启动和最小依赖。凡是依赖运行时反射、动态代码生成的库都要审慎对待,并在必要时通过 Source Generator 绕过。


2. 技术栈映射总表

层级 原始 (TS/Bun) .NET 10 替代 版本 理由
运行时 Bun 1.x .NET 10 AOT 10.0 原生 AOT 编译,秒级启动,单文件分发,内存占用更低
语言 TypeScript 6 ESM C# 13 13.0 静态类型、模式匹配、records、primary constructors表达力与 TS 相当
终端 UI React 19 + Ink 6 Terminal.Gui v2 2.x 唯一成熟的跨平台 .NET TUI 框架响应式布局AOT 友好
富文本输出 Ink built-in Spectre.Console 0.49.x 表格、进度条、标记语言API 优雅零反射AOT 完全兼容
CLI 解析 Commander.js System.CommandLine v2 2.0.0-beta 微软官方,支持 AOT子命令/选项/参数体系完整
Schema 验证 Zod v4 FluentValidation + JsonSchema.Net 11.x / 7.x FluentValidation 负责业务规则验证JsonSchema.Net 负责 JSON Schema 生成与校验
代码搜索 ripgrep (内置) ripgrep via Process ripgrep 本身是独立二进制,通过 System.Diagnostics.Process 调用,行为完全一致
LSP 客户端 vscode-languageserver-protocol OmniSharp.Extensions.LanguageServer 0.19.x OmniSharp 团队出品,协议覆盖完整,支持双向消息和自定义扩展
MCP 协议 @modelcontextprotocol/sdk 自研 MCP SDK 社区尚无成熟 .NET MCP SDK自研可精确控制传输层和协议版本详见 MCP SDK 自研实现方案
HTTP 客户端 Bun fetch HttpClient + Refit — / 7.x HttpClient 是 .NET 标准组件Refit 提供声明式接口减少样板代码,支持 AOT
OAuth / OIDC 自研 MSAL.NET + IdentityModel.OidcClient 4.x / 5.x MSAL.NET 覆盖 Azure/GitHub/GoogleOidcClient 处理标准 OIDC 设备码流
WebSocket ws System.Net.WebSockets + SignalR — / 8.x 标准库 WebSockets 用于原始帧处理SignalR 用于需要自动重连的场景
子进程 Bun.spawn System.Diagnostics.Process BCL 标准组件,行为跨平台一致,支持异步读写流
JSON 序列化 JSON.parse/stringify System.Text.Json BCL 标准组件Source Generator 模式下零反射AOT 完全兼容
后台任务 自研 TaskQueue BackgroundService + Channel<T> BackgroundService 是 .NET 托管服务标准抽象Channel<T> 提供高性能无锁消息传递
插件系统 dynamic import() AssemblyLoadContext .NET 官方插件隔离机制,支持热加载和独立卸载
依赖注入 Microsoft.Extensions.DependencyInjection 10.0 .NET 官方 DI 容器轻量、AOT 友好,通过 Source Generator 消除反射
日志 console.log Microsoft.Extensions.Logging 10.0 官方日志抽象支持结构化日志后端可插拔Console/File/OTLP

3. NuGet 包完整清单

<!-- FreeCode.csproj 及子项目汇总包引用 -->

<!-- 终端 UI -->
<PackageReference Include="Terminal.Gui" Version="2.*" />
<PackageReference Include="Spectre.Console" Version="0.49.*" />

<!-- CLI 解析 -->
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.*" />

<!-- 验证 -->
<PackageReference Include="FluentValidation" Version="11.*" />
<PackageReference Include="JsonSchema.Net" Version="7.*" />

<!-- HTTP / REST -->
<PackageReference Include="Refit" Version="7.*" />
<PackageReference Include="Refit.HttpClientFactory" Version="7.*" />

<!-- OAuth / OIDC -->
<PackageReference Include="Microsoft.Identity.Client" Version="4.*" />
<PackageReference Include="IdentityModel.OidcClient" Version="5.*" />

<!-- LSP -->
<PackageReference Include="OmniSharp.Extensions.LanguageServer.Client" Version="0.19.*" />
<PackageReference Include="OmniSharp.Extensions.LanguageProtocol" Version="0.19.*" />

<!-- JSON -->
<!-- System.Text.Json 随 .NET 10 SDK 内置,无需额外引用 -->

<!-- DI / 日志 / 托管 -->
<!-- Microsoft.Extensions.* 随 .NET 10 SDK 内置 -->

<!-- 后台任务 -->
<!-- System.Threading.Channels 随 .NET 10 SDK 内置 -->

<!-- AST 搜索ast-grep 绑定) -->
<PackageReference Include="AstGrep.Bindings" Version="0.30.*" />

<!-- 序列化辅助 -->
<PackageReference Include="System.Text.Json.SourceGeneration" Version="10.0.*" />

<!-- 测试 -->
<PackageReference Include="xunit" Version="2.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.*" />
<PackageReference Include="Moq" Version="4.*" />
<PackageReference Include="FluentAssertions" Version="6.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />

4. AOT 兼容性说明

原生 AOT 编译是本项目的核心约束,它要求在编译期完成所有类型分析,运行时不允许动态反射、动态代码生成和未知类型的延迟绑定。

Source Generator 策略

System.Text.Json 的 AOT 支持通过 JsonSerializerContext 实现。每个需要序列化的模型都注册到一个 partial context 类,编译器在构建期生成序列化代码,完全绕开运行时反射:

[JsonSerializable(typeof(ChatRequest))]
[JsonSerializable(typeof(ChatResponse))]
internal partial class FreeCodeJsonContext : JsonSerializerContext { }

System.CommandLine v2 的 AOT 支持已在 beta 阶段引入,通过 Source Generator 生成命令绑定代码,替代早期版本的反射绑定。

Microsoft.Extensions.DependencyInjection 从 .NET 8 起提供 ServiceProviderOptions.ValidateScopes 的 AOT 路径,通过 [ServiceDescriptor] 属性消除反射注册扫描。

裁剪 (Trimming) 配置

<PublishTrimmed>true</PublishTrimmed>
<TrimmerRootDescriptor>TrimmerRoots.xml</TrimmerRootDescriptor>

Terminal.Gui v2 和 Spectre.Console 均已标注 [RequiresUnreferencedCode] 警告可抑制区域,实际裁剪测试证明两者在启用 TrimmerRootDescriptor 白名单后正常工作。

不兼容项处理

AssemblyLoadContext 用于插件加载,插件程序集本身不参与 AOT 编译,以动态加载的 JIT 模式运行。主程序 AOT 编译不受影响,两者通过接口合约隔离。


5. 关键选型设计说明

Terminal.Gui v2 vs. 其他 TUI 方案

Spectre.Console 的 Live 组件可以渲染动态布局但它本质上是顺序输出不支持真正的交互式控件文本框、列表框、焦点切换。FreeCode 的 REPL 界面需要多面板、快捷键绑定和滚动视图Terminal.Gui v2 是目前唯一满足条件的成熟方案。

FluentValidation + JsonSchema.Net vs. 单一方案

Zod 同时承担运行时验证和 Schema 生成两个职责。.NET 生态里没有一个库同时做好两件事因此分开处理FluentValidation 的 Fluent API 在业务规则验证上表达力强JsonSchema.Net 处理 JSON Schema 的生成和校验(主要用于工具参数描述)。

Refit vs. 纯 HttpClient

Refit 将 HTTP 接口声明为 C# interface通过 Source Generatorv7+生成实现代码不依赖运行时代理AOT 兼容。对于结构化的 LLM API 调用来说,减少样板代码的收益明显。

Channel<T> vs. BlockingCollection/Queue

Channel<T> 是 .NET 的高性能异步消息原语,支持有界/无界背压,完全基于 ValueTask 避免内存分配,与 BackgroundService 的异步生命周期天然契合。BlockingCollection 是同步阻塞模型,在异步场景下会占用线程。