Beacon Solution / 项目目录¶
配套 RFC-001。本文以当前仓库实际结构为准(2026-10-09 同步)。 Beacon 代码只能在 Windows 上构建运行(WinUI 3,CI
windows-latest);Linux 工作环境可构建并运行 4 个测试项目作为本地门禁。
1. Solution 总览¶
Beacon/
├── Beacon.sln
├── Directory.Build.props # 公共编译设置(nullable、langversion、invariants)
├── Directory.Packages.props # Central Package Management(统一版本)
├── global.json # 钉 SDK 10.0.100(rollForward latestFeature)
├── .editorconfig
├── .github/workflows/ # ci.yml(构建+测试+Codecov)/ daily-build.yml(nightly)/ docs.yml(Pages)
├── docs/ # 任务书 / RFC / Issue 列表 / 定位 / 审计 / 验收记录
├── packaging/ # beacon.iss:Inno Setup 安装包定义(daily-build 产出 setup.exe)
├── src/
│ ├── Beacon.App/ # WinUI 3 壳(唯一 exe,代码建 UI 为主)
│ ├── Beacon.Core/ # 领域模型 + 抽象 + 服务(无 UI 依赖)
│ ├── Beacon.Connections/ # 连接与 Widget Provider(17 类:GitHub / Jenkins / 本机 / Herald / HTTP / 智谱 / 方舟 / Claude / Kimi / Moonshot / DeepSeek / MiMo / Codex / Copilot / OpenCode / 百炼 / 商汤)
│ ├── Beacon.Actions/ # Action 执行器
│ └── Beacon.Storage/ # JSON 配置 / 缓存 / DPAPI Secrets / 导入导出
└── tests/
├── Beacon.Core.Tests/
├── Beacon.Connections.Tests/
├── Beacon.Storage.Tests/
└── Beacon.Actions.Tests/
2. 项目依赖规则¶
Beacon.App ──────► Beacon.Core ◄────── Beacon.Connections
│ ▲ Beacon.Actions
│ │ Beacon.Storage
└──────────────────┴──────────────────┘(实现 Core 抽象,被 App 组合)
tests/* ──► 对应被测项目(+ Beacon.Core 接口)
硬规则:
Beacon.Core不引用任何项目(仅引用 BCL +Microsoft.Extensions.Logging.Abstractions)——保证 UI 与 Provider 可替换。- Connections / Actions / Storage 只依赖 Core(实现其接口),互相不依赖。
Beacon.App是唯一可执行项目,负责 DI 组装:把 Provider/Executor/Store 注册进Microsoft.Extensions.DependencyInjection(App.BuildServices+BeaconRuntime)。- 二期 Plugin 化时,把 Connections 内的 Provider 拆为独立程序集,接口不变。
3. 各项目内容¶
3.1 src/Beacon.Core(类库)¶
Beacon.Core/
├── Models/ # 13 文件
│ ├── Severity.cs # Info/Success/Warning/Error/Critical(+ Offline 展示态)
│ ├── LifecycleState.cs # Queued/Running/…/Unknown
│ ├── ConnectionConfig.cs ConnectionHealthState.cs WidgetConfig.cs WidgetTypeDescriptor.cs
│ ├── WidgetDisplayPolicy.cs # 数值类悬浮总闸(FloatingOptIn × NumericFloatingEnabled,两 L0 形态共用)
│ ├── WidgetState.cs # widgetId/widgetType/connectionId/severity/summary/payload/…
│ ├── ActionModels.cs # ActionConfig / ActionResult(合并文件)
│ ├── NotificationModels.cs # NotificationRule / NotificationRecord / Delivery(合并文件)
│ ├── RefreshTiers.cs # 7 级刷新策略(pr/ci/machine/agent/workflow/static/default)
│ ├── AppConfig.cs # 全局设置 + PinTile/PinsConfig
│ └── PinLayout.cs # monitor/anchor/offsetDips/collapsed + floatingX/Y(悬浮框位置)
├── Abstractions/ # 8 文件
│ ├── IConnectionProvider.cs # IConnectionProvider + IWidgetProvider + IWidgetProviderResolver(合并文件)
│ ├── IActionExecutor.cs ISecretStore.cs IConfigurationStore.cs ICacheStore.cs
│ ├── IClock.cs # 注入时钟,供退避/冷却单测
│ ├── IEventBus.cs
│ └── INotificationSink.cs # 通知出口(App 侧 Toast/声音/托盘着色实现)+ 记录落盘抽象 INotificationRecordStore
├── Services/ # 20 文件
│ ├── EventBus.cs # 线程安全的进程内发布/订阅
│ ├── RefreshScheduler.cs # (connection,tier,间隔覆盖) 合并轮询 + 抖动 + 退避
│ ├── StatusAggregator.cs # WidgetState* → 总体 Severity + 计数
│ ├── NotificationEngine.cs # 规则求值 + 冷却去重 + 默认规则
│ ├── ActionRunner.cs # 确认策略 + 超时 + 取消 + 可选重试(DSL retry 参数,默认 1 次)
│ ├── ActionVisibility.cs # 动作显隐纯函数(widgetType 逗号多值 + connection_id 限定)
│ ├── WidgetHost.cs TemplateRenderer.cs PaletteResolver.cs PinLayoutMath.cs
│ ├── SvgPathParser.cs # SVG path d → 中性几何(品牌图标渲染前置层,纯函数供单测)
│ ├── BrandIcons.cs # Simple Icons CC0 品牌 path 字典 + 连接类型别名归一(纯字符串零依赖,供单测;未收录由 App 字形兜底)
│ ├── WidgetValueHint.cs # 悬浮 tile 数值位短文本(各家额度源 payload 键 → 主数值映射 + 多窗口额度「NN%/窗」拼接,纯函数供单测)
│ ├── DebugInjection.cs # debug 注入面(BEACON_DEBUG_SEVERITY=critical → 刷新成功态改判 Critical/Failed;环境变量门控、缺省零行为,仅 CI 场景 V 与装机演练用,不进用户文档)
│ ├── WidgetTypeNames.cs # 组件类型 → 短显示名(tile 标签/L2 分组 chip 共用,纯函数供单测)
│ ├── QuickPanelSections.cs # L2 面板三分区判定(Warning+/过期/断连 → NEEDS ATTENTION,纯函数供单测)
│ ├── DpiLayoutMath.cs # DIP↔物理像素唯一换算口径(AppWindow 只认物理像素)
│ ├── ContrastMath.cs # WCAG 2.x 对比度数学(纯函数,Linux 门禁可测)
│ ├── HighContrastPalette.cs # 高对比调色板(WCAG AA 4.5:1,配对经 Core.Tests 断言)
│ └── UpdateCheck.cs # 版本解析/比较/判定 + GitHub tag_name 提取(纯函数,Linux 门禁可测;App 侧只做网络与 UI)
├── Events/
│ └── Events.cs # WidgetStateChanged / AggregateStatusChanged 等事件
└── Json/
└── BeaconJson.cs # JsonSerializerOptions(camelCase + 枚举字符串)
3.2 src/Beacon.Connections(类库,文件平铺无子目录)¶
Beacon.Connections/ # 35 文件
├── TileSizing.cs # 全类型 tile 宽度字宽预算(逐列最坏文本:标签/数值/读数 + 固定件 + 间距,下限 168;纯函数供单测,2026-10-12 二修)
├── GitHub 6 文件
│ ├── GitHubConnectionProvider.cs # PAT 认证、连接测试、rate-limit 感知
│ ├── GitHubApiClient.cs # 手写 REST 客户端(不引 Octokit)+ ETag 条件请求 + 限额感知
│ ├── GitHubWidgetDescriptors.cs # Widget 类型元数据注册表(type: github.pull_requests / github.actions.runs)
│ ├── GitHubPullRequestsProvider.cs # type: github.pull_requests
│ ├── GitHubActionsProvider.cs # type: github.actions.runs
│ └── GitHubWorkflowExecutors.cs # gh.workflow_dispatch/rerun/cancel 执行器
├── Jenkins 1 文件
│ └── JenkinsBuildProvider.cs # type: jenkins.build(开源标准 JSON API,color 判级)+ JenkinsConnectionProvider(同文件)
├── Machine 4 文件(本机数据,零凭据零网络)
│ ├── MachineNetProvider.cs # type: machine.net(IP/↑↓速率/累计流量,差分算速率)+ MachineWidgetDescriptors + MachineConnectionProvider(同文件)
│ ├── MachineLocalProvider.cs # type: machine.local(CPU/内存/磁盘,CPU 差分同速率口径;Linux /proc + Windows API 注入抽象)
│ ├── MachineShowOptions.cs # config["show"] 可选展示项解析(缺省全选/未知键 fail-loud;宽度推算在 TileSizing)
│ └── GitWorkspaceProvider.cs # type: machine.git(本地 Git 工作区 ↑↓·改·stash,git CLI 只读)
├── Herald 1 文件(用户自有项目 cuihairu/herald:统一订阅与投递中枢)
│ └── HeraldProvider.cs # type: herald.incidents(事件台账 open 亮黄/critical 亮红)+ herald.feed(RSS 未读基线,token 走 DPAPI)+ herald.deliveries(投递失败 failed 即黄)+ HeraldConnectionProvider(同文件)
├── HTTP 7 文件(Generic HTTP 接入)
│ ├── HttpConnectionProvider.cs # 连接测试(支持 auth_header/auth_prefix 覆盖)
│ ├── HttpEndpoint.cs # 端点请求与凭据装配
│ ├── HttpJsonPath.cs # $.a.b[0] 点路径提取
│ ├── HttpQuotaProvider.cs # type: http.quota(任意配额 JSON 字段映射 → 数值卡 + 进度条)
│ ├── HttpStatusProvider.cs # type: http.status(点路径 + 状态词表 → Severity)
│ └── ProviderDsl.cs # YAML provider DSL(批3-补42):dsl_path 声明层(mapping 数据提取缺省 + actions 带 retry)+ YamlLite 极小解析器
├── BigModel 2 文件
│ ├── BigModelConnectionProvider.cs # 裸 Key 认证(Authorization 不带 Bearer)
│ └── BigModelUsageProvider.cs # type: bigmodel.usage(quota/limit 三窗口归一化)
├── Ark 2 文件
│ ├── ArkConnectionProvider.cs # V4 签名连接测试(失败按 4xx/5xx 分级 Degraded/Offline)
│ └── ArkUsageProvider.cs # type: ark.usage(GetCodingPlanUsage 三窗口百分比;AK/SK 只进 DPAPI)
├── Claude 2 文件
│ ├── ClaudeConnectionProvider.cs # 零网络连接测试(会话目录存在即 Healthy)
│ └── ClaudeUsageProvider.cs # type: claude.usage(本机 JSONL 聚合,零凭据)
├── Kimi 1 文件
│ └── KimiCodingUsageProvider.cs # type: kimi.coding(5h/周套餐余量)+ KimiConnectionProvider(同文件)
├── DeepSeek 1 文件
│ └── DeepSeekBalanceProvider.cs # type: deepseek.balance(开放平台余额)+ DeepSeekConnectionProvider(同文件)
├── MiMo 1 文件
│ └── MiMoUsageProvider.cs # type: mimo.usage(官方未开放用量口→模型目录真数据)+ MiMoConnectionProvider(同文件)
├── Codex 1 文件
│ └── CodexUsageProvider.cs # type: codex.usage(本机 rollout 会话统计,source=local 如实标注)+ CodexConnectionProvider(同文件)
├── Copilot 1 文件
│ └── CopilotUsageProvider.cs # type: copilot.usage(官方扩展同款配额端点直连,quota_snapshots 三槽)+ CopilotConnectionProvider(同文件)
├── OpenCode 1 文件
│ └── OpenCodeUsageProvider.cs # type: opencode.usage(官方 Console Budgets API 直连,micro-cents 金额)+ OpenCodeConnectionProvider(同文件)
├── Qwen 1 文件
│ └── QwenUsageProvider.cs # type: qwen.usage(百炼 Token Plan 四档探测:官方口→自定义→配额探针→模型目录兜底)+ QwenConnectionProvider(同文件)
├── Moonshot 1 文件
│ └── MoonshotBalanceProvider.cs # type: moonshot.balance(开放平台余额,区别于 Kimi For Coding 套餐)+ MoonshotConnectionProvider(同文件)
└── SenseNova 1 文件
└── SenseNovaUsageProvider.cs # type: sensenova.usage(控制台 Token Plan 积分池:多池 × 5h/7d 双窗,最差窗判级)+ SenseNovaWidgetDescriptors + SenseNovaConnectionProvider(同文件)
3.3 src/Beacon.Actions(类库)¶
Beacon.Actions/ # 5 文件
├── ActionVars.cs # 参数模板占位符替换({repo} 等)
├── OpenUrlExecutor.cs # open.url(系统默认浏览器)
├── HttpExecutor.cs # http(GET/POST + 头/体模板)
├── WebhookExecutor.cs # webhook(POST + HMAC-SHA256 签名头,密钥 credentialRef 只进 DPAPI、取不到即 fail closed)
└── LocalCommandExecutor.cs # local.command(powershell/cmd/exe,工作目录/Env/超时/捕获输出)
gh.workflow_dispatch / gh.workflow_rerun / gh.workflow_cancel三个执行器在Beacon.Connections/GitHubWorkflowExecutors.cs。
3.4 src/Beacon.Storage(类库)¶
Beacon.Storage/ # 6 文件
├── JsonConfigurationStore.cs # config/connections/widgets/pins.json 原子写 + 备份
├── AppConfigFile.cs # config.json 快速读写(App 启动主题等早期读取)
├── JsonNotificationRecordStore.cs # notifications.json 通知记录 + 已读态(滚动保留跨重启)
├── JsonCacheStore.cs # cache\{connId}\states.json last-known-state
├── DpapiSecretStore.cs # DPAPI CurrentUser → secrets.bin(唯一默认实现)
└── ImportExport.cs # 打包导出(不含 secrets)/导入
备选(未实现):Windows Credential Manager 密钥存储——同一 ISecretStore 接口,代码未落地。
3.5 src/Beacon.App(WinUI 3,打包=None)¶
Beacon.App/
├── App.xaml / App.xaml.cs # 入口:单实例、全局异常兜底、DI 组装、窗口装配、退出清理
├── app.manifest / Assets/ # PerMonitorV2 DPI;图标与托盘 logo 掩膜(嵌入资源)
├── Infrastructure/
│ ├── MonitorService.cs # 显示器枚举/工作区/按像素定位(多屏)
│ ├── NativeMethods.cs # P/Invoke(NOTIFYICONDATA、窗口扩展样式、DPI、热键)
│ └── Win32MessageWindow.cs # 自驻留消息窗(托盘/热键/单实例事件回调)
├── Services/ # 15 文件
│ ├── BeaconRuntime.cs # 运行时装配:Provider 解析器、调度、聚合、启停联动
│ ├── UpdateCheckService.cs # 检查更新(B-806):GitHub releases/latest,10s 超时 + 进程内缓存 + 失败降级不抛异常
│ ├── TrayIconService.cs # Win32 Shell_NotifyIcon 自实现:菜单、按配置色着色、气泡
│ ├── ToastNotificationService.cs # Microsoft.Toolkit.Uwp.Notifications(Compat 激活路由、深链 L3)
│ ├── TopmostGuard.cs # 置顶哨兵(Watch 单窗 / WatchAll 动态窗集)
│ ├── HotkeyService.cs # RegisterHotKey,可配置(默认 Ctrl+Alt+B)
│ ├── StartupService.cs # HKCU Run 键开关
│ ├── SingleInstanceGuard.cs # Mutex + 命名事件(二次启动通知既有实例弹气泡)
│ ├── FileLoggerProvider.cs CrashLog.cs # beacon-YYYYMMDD.log / crash-*.log
│ ├── UiPalette.cs MotionEngine.cs ShellStateStore.cs UiDispatcher.cs
│ └── AppIcon.cs # 应用图标唯一来源(逐窗 AppWindow.SetIcon——unpackaged 任务栏图标坑)
└── Windows/ # 10 文件(8 .cs + 2 .xaml,UI 多为代码构建)
├── CapsuleWindow.xaml|cs # L1 聚合胶囊(独立置顶常驻窗,位置记忆;右键直达设置)
├── QuickPanelWindow.xaml|cs # L2 快捷面板(可激活,ESC 关;通知中心/组件列表)
├── PinnedHostWindow.cs # ★ L0 宿主面板形态(默认):每显示器一窗,代码建 UI,
│ # Topmost+NoActivate+空白点击穿透;含 PinTile 控件
├── FloatingTileWindow.cs # ★ L0 独立悬浮框形态(pinDisplayMode=floating):
│ # 每钉选组件一窗,拖放位置按组件持久化(FloatingX/Y)
├── BrandIconFactory.cs # 品牌 path → Path(Stretch=Uniform)(设置目录/悬浮 tile 共用,
│ # 空几何/渲染失败退 null 让调用方字形兜底)
├── DetailWindow.cs # L3 详情 + 全部 Action(代码建 UI)
├── ThemeColors.cs # 主题色桥:Core 高对比调色板 → WinUI 画刷(配对断言见 ContrastMathTests)
└── SettingsWindow.cs # B-801/802/805:PowerToys 形态配置中心(模块目录+启停+连接/组件 CRUD,
# 悬浮形态二选一、导入导出、通知规则;代码建 UI)
注:无 Controls/、ViewModels/、Themes/、Notifications/ 目录——状态灯/PinTile 等以代码类组合(PinTile 在 PinnedHostWindow.cs 内),无 XAML 资源字典;Toast 在 Services/。
3.6 tests/¶
xUnit;Beacon.Core.Tests(聚合/调度/退避/规则/通知引擎/ActionRunner,时钟注入;SvgPathParser、BrandIcons 字典全量可解析与别名、WidgetValueHint 数值映射)、Beacon.Connections.Tests(Fake HttpMessageHandler + API 夹具 + ETag 分支,程序集串行化避免共享客户端缓存竞态)、Beacon.Storage.Tests(往返/原子写/DPAPI,需 Windows 环境)、Beacon.Actions.Tests(open.url/local.command/http/webhook 执行器,Windows 专属用例 OS 门控)。全部接入 coverlet.collector(CI 上报 Codecov)。当前 4 个项目共 1057 个测试(Connections 652 / Core 347 / Actions 27 / Storage 31),即本地门禁。Core 侧另覆盖 QuickPanelSections 三分区判定、ContrastMath/HighContrastPalette 对比度配对、WidgetTypeNames 短名映射、PinLayoutMath/DpiLayoutMath 换算与钳位、UpdateCheck 版本解析与 SemVer 比较(v 前缀/构建元数据/预发布规则/限流降级体)。
4. 关键 NuGet 包(Directory.Packages.props 统一版本)¶
| 包 | 用于 |
|---|---|
Microsoft.WindowsAppSDK |
WinUI 3 运行时 |
Microsoft.Windows.SDK.BuildTools |
Win32 interop(NoActivate/热键等) |
CommunityToolkit.Mvvm |
App 工程已引用,当前代码未使用(UI 为 code-behind 代码建,见 §6) |
| 托盘 | 不引第三方库,Win32 Shell_NotifyIcon 自实现(TrayIconService) |
Microsoft.Toolkit.Uwp.Notifications |
Toast(unpackaged AUMID 自愈与激活路由) |
System.Drawing.Common |
托盘图标按配置色运行时绘制(GDI+ 位图 → HICON,B-706) |
| GitHub API | 手写 REST 客户端(ETag/限额可控,B-301 决策,不引 Octokit) |
System.Security.Cryptography.ProtectedData |
DPAPI 密钥存储 |
Microsoft.Extensions.Hosting / .DependencyInjection / .Logging |
DI/日志 |
xunit / NSubstitute / coverlet.collector |
测试与覆盖率 |
(版本集中在 Directory.Packages.props;表中不含未引用的包。)
5. Windows 机器上的脚手架命令(历史存档,工程已建成)¶
下列为初始建仓时实际使用的命令,保留备查;当前结构与文件以 §1/§3 为准。
dotnet new sln -n Beacon
dotnet new classlib -o src/Beacon.Core -f net10.0
dotnet new classlib -o src/Beacon.Connections -f net10.0
dotnet new classlib -o src/Beacon.Actions -f net10.0
dotnet new classlib -o src/Beacon.Storage -f net10.0
dotnet new winui -o src/Beacon.App # 模板可用缺失时:手建 csproj(WindowsAppSDKSelfContained,打包=None)
dotnet new xunit -o tests/Beacon.Core.Tests
dotnet new xunit -o tests/Beacon.Connections.Tests
dotnet new xunit -o tests/Beacon.Storage.Tests
dotnet new xunit -o tests/Beacon.Actions.Tests
dotnet sln add (git ls-files "**/*.csproj")
注意(.NET 10 LTS,RFC §16 决策 8):四个类库目标框架 net10.0(DPAPI 走 System.Security.Cryptography.ProtectedData 包,无 Windows 专属 TFM);Beacon.App 目标 net10.0-windows10.0.19041.0,TargetPlatformMinVersion=10.0.17763.0(WinUI 3 / Windows App SDK)。SDK 版本由根 global.json 钉 10.0.100(rollForward latestFeature)。
6. 编码约定¶
nullable enable、file-scoped namespace、C# 12。- UI 以代码构建 + code-behind 为主(WinUI
Window子类直接组装控件),状态来自事件总线订阅(BeaconRuntime/窗口内Subscribe);CommunityToolkit.Mvvm包已引用但当前未使用(无 ViewModel 层)。 - 所有时间相关逻辑经
IClock注入。 - 配置 JSON 用
System.Text.Json:BeaconJson统一JsonSerializerOptions(camelCase 属性 + 枚举字符串),非 source-gen。 - 日志经
ILogger,Secrets 一律不进日志(RFC-001 §13)。