ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

holaOS 桌面端计费额度可见性实现指南:基于 Electron IPC 的只读 Billing 桥接与 UI 落地

holaOS 桌面端计费额度可见性实现指南:基于 Electron IPC 的只读 Billing 桥接与 UI 落地 人工智能AI AgentAI 应用前端后端即时通讯交互助手工具调用【免费下载链接】holaOSOpen-source agentic workspace enterprises can make their own. Connect the systems you already run — 100 integrations, MCP, chat tools, apps, browser, local files — with shared memory. Any agent (Claude Code, Codex), any model, or BYOK. Set up in clicks, not months. Local-first: your data never leaves your machines.项目地址https://gitcode.com/GitHub_Trending/ho/holaOS点击查看免费下载导读本文基于holaOS仓库中的《Desktop Billing Credits Implementation Plan》docs/plans/2026-04-02-desktop-billing-credits-implementation-plan.md系统讲解如何在桌面应用中为托管计费hosted billing增加只读可见性顶栏额度胶囊CreditsPill、账户级套餐与额度摘要卡片BillingSummaryCard、聊天中的低余额提醒与额度耗尽拦截以及仅网页端可执行的计费操作策略。读完本文你将掌握一套Electron 主进程持有凭证、渲染进程通过 IPC 读取归一化数据、UI 组件只读展示、恢复动作一律跳转浏览器的完整实现范式并了解其在apps/desktop中的实际落地形态。一、方案背景与总体架构1.1 目标该计划的目标非常聚焦为 holaOS 桌面端增加只读的托管计费可见性具体包括顶栏Top Bar的额度余额徽标credits badge账户级别的套餐与额度汇总plan and credits summary聊天Chat中的低余额警告low-balance warnings仅限网页端执行的计费操作web-only billing actions。1.2 核心架构决策信任边界放在 Electron 主进程计划文档明确了架构原则Keep all hosted billing and quota reads inside Electron main so Better Auth cookies and environment-specific URLs stay in the trusted process. Expose a small desktop-focused billing IPC surface to the renderer, then build a single renderer hook and two UI components (CreditsPill,BillingSummaryCard) that consume that normalized shape. Billing mutations and management remain web-only: desktop may open billing URLs in the browser, but never performs Stripe or subscription management locally.翻译成可执行的工程原则凭证不出主进程Better Auth 的会话 Cookie、环境相关的托管 URL 全部保留在 Electron 主进程这个可信进程内渲染进程不直接接触渲染进程只拿归一化形状主进程把托管数据规整成 renderer-safe 的载荷如DesktopBillingOverviewPayload通过一个小而专的 billing IPC 面暴露给渲染进程渲染侧单 Hook 双组件一个useDesktopBilling()Hook 承载数据获取与派生状态两个 UI 组件CreditsPill与BillingSummaryCard只做消费计费变更永远走网页桌面端可以把计费链接交给浏览器打开但绝不在本地执行 Stripe 或订阅管理操作。该决策与仓库中渲染进程无 Cookie、主进程统一代理认证请求的既有模式一脉相承例如 apps/desktop/electron/appSdkClient.ts 第 11 行的注释就明确写道Mirrors the billingFetch pattern already used for the Better-Auth RPC——可见billingFetch是仓库中 Better-Auth RPC 认证模式的复用样板。1.3 技术栈Electron IPC主进程 ↔ 预加载脚本 ↔ 渲染进程React 19TypeScriptBetter Auth 会话 Cookie既有托管 control-plane APINode 测试运行器node:testtsc类型检查二、Task 1在主进程添加 Billing IPC 桥这是整个方案的基石让主进程具备带认证的托管计费读取能力并把能力通过 preload 暴露给渲染进程。2.1 涉及文件修改apps/desktop/electron/main.ts修改apps/desktop/electron/preload.ts修改apps/desktop/src/types/electron.d.ts测试apps/desktop/electron/billing-ipc.test.mjs关联测试apps/desktop/electron/settings-pane-routing.test.mjs2.2 先写失败测试TDD 第一步计划要求先新增billing-ipc.test.mjs通过读取main.ts源码断言注册了billing:getOverview、billing:getUsage、billing:getLinks三个处理器存在一个使用 Better Auth Cookie 头执行认证托管请求的辅助函数对 add-credits、billing portal、usage 路由存在仅网页端的链接策略。示例断言如下原文直接可用import assert from node:assert/strict; import { readFile } from node:fs/promises; import { test } from node:test; const MAIN_PATH new URL(./main.ts, import.meta.url); test(desktop billing IPC handlers are registered, async () { const source await readFile(MAIN_PATH, utf8); assert.match(source, /handleTrustedIpc\(billing:getOverview/); assert.match(source, /handleTrustedIpc\(billing:getUsage/); assert.match(source, /handleTrustedIpc\(billing:getLinks/); });运行方式node --test desktop/electron/billing-ipc.test.mjs此时预期FAIL处理器与辅助函数尚不存在这正是 TDD 的红灯阶段。2.3 最小实现要点在main.ts中新增billingFetchT()辅助函数模式对齐仓库既有的composioFetchT()同为主进程带认证代理托管请求的封装使用authCookieHeader()为托管请求注入 Better Auth Cookie 头完成认证将托管返回的原始载荷归一化为面向桌面端的 overview 形状网页链接从托管 base URL 推导而不是在渲染进程里硬编码保证环境本地开发 / preview / 生产切换时链接天然正确注册三个受信任 IPC 处理器billing:getOverview、billing:getUsage、billing:getLinks。在preload.ts中暴露window.electronAPI.billing.getOverview(); window.electronAPI.billing.getUsage(); window.electronAPI.billing.getLinks();在 apps/desktop/src/types/electron.d.ts 中为 overview、usage、links 增加载荷类型扩展ElectronAPI接口加入新的billing命名空间该文件 2252 行处定义有interface ElectronAPI内含platform、versions、fs等既有能力billing 命名空间与之并列。2.4 主进程输出归一化形状主进程必须把托管数据规整为 renderer-safe 的形状计划给出了完整类型定义interface DesktopBillingOverviewPayload { isManagedBillingUser: boolean; planName: string | null; planStatus: active | trialing | past_due | canceled | inactive; renewsAt: string | null; expiresAt: string | null; creditsBalance: number; monthlyCreditsIncluded: number; monthlyCreditsUsed: number; dailyRefreshCredits: number | null; dailyRefreshTarget: number | null; lowBalanceThreshold: number; isLowBalance: boolean; }可以看到该形状同时承载了是否托管计费用户、套餐状态机、续费/到期时间、余额、月度配额、每日刷新额度与低余额阈值等全部渲染所需字段。2.5 验证与提交node --test desktop/electron/billing-ipc.test.mjs预期PASS。随后提交git -C holaOS add desktop/electron/main.ts desktop/electron/preload.ts desktop/src/types/electron.d.ts desktop/electron/billing-ipc.test.mjs git -C holaOS commit -m feat: add desktop billing ipc bridge仓库现状印证在 apps/desktop/electron/main.ts 中已能看到billingFetch的引用8544 行注释would destroy a valid session shared with billingFetch说明该辅助函数已成为主进程中共享认证会话的核心设施同时在 1172-1193 行UiSettingsPaneSection联合类型与UI_SETTINGS_PANE_SECTIONS常量中已包含billing段normalizeUiSettingsPaneSection()会把未知段回退到settings确保点击额度徽标跳到计费设置页的路由行为有据可依。三、Task 2渲染进程共享 Billing Hook3.1 涉及文件新建desktop/src/lib/billing/useDesktopBilling.ts测试desktop/src/lib/billing/useDesktopBilling.test.mjs3.2 测试断言先红useDesktopBilling.test.mjs需要断言 Hook 源码调用了window.electronAPI.billing.getOverview调用了window.electronAPI.billing.getUsage由creditsBalance 0派生isOutOfCredits暴露了refresh方法。node --test desktop/src/lib/billing/useDesktopBilling.test.mjs预期FAILHook 文件尚不存在。3.3 Hook 实现契约新建useDesktopBilling.ts挂载mount时并行拉取 overview 与 usage暴露isLoading、error、overview、usage、links、refresh派生状态isManagedBillingUser、isLowBalance、isOutOfCreditsHook 保持只读不包含任何 Stripe 或计费变更逻辑。建议返回形状原文return { isLoading, error, overview, usage, links, isManagedBillingUser, isLowBalance, isOutOfCredits, refresh, };3.4 仓库中的实际落地在 apps/desktop/src/lib/billing/useDesktopBilling.tsx 中该 Hook 以 React Context 形式提供DesktopBillingContextValue包含isAvailable、hasHostedBillingAccount等额外字段并实现了真实的额度换算与派生逻辑可视为对计划的直接落地Token → 额度换算DESKTOP_BILLING_TOKENS_PER_CREDIT 2000即 2000 tokens 兑换 1 credit通过desktopBillingTokensToCredits()向下取整低余额阈值DESKTOP_BILLING_LOW_BALANCE_THRESHOLD 10余额低于 10 credits 即触发低余额状态套餐元数据DESKTOP_BILLING_PLAN_META定义了basicholaOS月额度 200、proholaOS Pro月额度 2000、customizeholaOS Custom月额度为 null 即不限三档数据源通过billingRpcFetch并行请求/rpc/quota/myQuota余额与配额与/rpc/billing/myBillingInfo订阅信息、Stripe 客户 ID续费/到期推导renewsAt取未取消订阅的currentPeriodEndexpiresAt取cancelAtPeriodEnd为 true 时的currentPeriodEnd。链路清晰主进程billingFetch→ 渲染进程billingRpcFetch→ Hook 归一化 → UI 消费。3.5 验证与提交node --test desktop/src/lib/billing/useDesktopBilling.test.mjs预期PASS。提交git -C holaOS add desktop/src/lib/billing/useDesktopBilling.ts desktop/src/lib/billing/useDesktopBilling.test.mjs git -C holaOS commit -m feat: add desktop billing renderer hook四、Task 3顶栏 Credits Pill额度胶囊4.1 涉及文件新建desktop/src/components/billing/CreditsPill.tsx修改desktop/src/components/layout/TopTabsBar.tsx修改desktop/src/components/layout/AppShell.tsx测试desktop/src/components/layout/TopTabsBar.test.mjs4.2 测试断言TopTabsBar.test.mjs断言TopTabsBar.tsx在账户触发器account trigger左侧渲染额度胶囊非托管计费模式下胶囊隐藏点击胶囊跳转到账户设置。node --test desktop/src/components/layout/TopTabsBar.test.mjs预期FAIL。4.3 实现要点新建CreditsPill.tsx渲染圆角胶囊rounded capsule带 sparkles 风格图标与余额数字支持状态loading、normal、low、empty接受onClick回调。修改TopTabsBar.tsx消费useDesktopBilling()在用户下拉触发器左侧渲染CreditsPill仅当isManagedBillingUser为 true 时显示。修改AppShell.tsx允许TopTabsBar打开账户设置并预聚焦到计费摘要保持既有账户/设置行为不变。4.4 仓库现状印证apps/desktop/src/components/billing/CreditsPill.tsx 已存在且配套有 apps/desktop/src/components/billing/BillingSettingsPanel.tsx 与对应的BillingSettingsPanel.test.mjs。同时 apps/desktop/electron/main.ts 的UiSettingsPaneSection已把billing纳入合法设置段配合normalizeUiSettingsPaneSection的回退逻辑点击胶囊 → 打开 billing 设置段的路由在类型层面得到保障。4.5 验证与提交node --test desktop/src/components/layout/TopTabsBar.test.mjs预期PASS。提交git -C holaOS add desktop/src/components/billing/CreditsPill.tsx desktop/src/components/layout/TopTabsBar.tsx desktop/src/components/layout/AppShell.tsx desktop/src/components/layout/TopTabsBar.test.mjs git -C holaOS commit -m feat: add desktop credits pill to top bar五、Task 4只读账户计费摘要卡片5.1 涉及文件新建desktop/src/components/billing/BillingSummaryCard.tsx修改desktop/src/components/auth/AuthPanel.tsx修改desktop/src/components/layout/SettingsDialog.tsx测试desktop/src/components/layout/SettingsDialog.test.mjs5.2 测试断言扩展SettingsDialog.test.mjs断言账户段仍渲染AuthPanelAuthPanel包含计费摘要卡片摘要卡片包含仅网页端操作Add credits、Manage on web、View usage。node --test desktop/src/components/layout/SettingsDialog.test.mjs预期FAIL。5.3 实现要点新建BillingSummaryCard.tsx展示套餐名称与续费/到期行展示主额度数字展示月度额度已用/总量当存在时展示每日刷新额度若存在 usage 数据则展示最近使用记录行提供三个按钮Add credits、Manage on web、View usage每个按钮必须通过window.electronAPI.ui.openExternalUrl(...)打开外部浏览器绝不在应用内呈现支付 UI。修改AuthPanel.tsx消费useDesktopBilling()在账户状态区域下方渲染BillingSummaryCard卡片保持只读当计费不适用本地 provider 模式时渲染本地 provider 提示文案。修改SettingsDialog.tsx仅在有间距或分段聚焦需求时调整。5.4 仓库现状印证apps/desktop/src/components/billing/BillingSummaryCard.tsx 与 apps/desktop/src/components/auth/AuthPanel.tsx 均已存在并有测试覆盖。链接的构造集中在 apps/desktop/src/lib/billing/billing-links.ts其buildDesktopBillingLinks()把四个计费动作统一映射到环境自适应的网页 URLbillingPageUrl→${base}/app/settings?tabbillingaddCreditsUrl→${base}/app/settings?tabbillingintentadd-creditsupgradeUrl→${base}/app/settings?tabbillingintentupgradeusageUrl→${base}/app/settings?tabbillingintentusagederiveAppBaseUrl()负责从 API base URL 推导 Web App base URL内置了多套环境规则可视为计划从托管 base URL 推导链接而非硬编码的具体实现localhost:4000→localhost:4321本地 API 与本地 Web 端口映射api-preview.*→preview.*预览环境api.holaos.ai→www.holaos.aiholaos.ai 的 Web 应用托管在www.而非app.注释说明了该例外原因其他api.*主机 →app.*按各部署布局配对解析失败或空值回退到HOLAOS_HOME_URLhttps://www.holaos.ai。5.5 验证与提交node --test desktop/src/components/layout/SettingsDialog.test.mjs预期PASS。提交git -C holaOS add desktop/src/components/billing/BillingSummaryCard.tsx desktop/src/components/auth/AuthPanel.tsx desktop/src/components/layout/SettingsDialog.tsx desktop/src/components/layout/SettingsDialog.test.mjs git -C holaOS commit -m feat: add read-only desktop billing summary六、Task 5聊天中的低余额警告与额度耗尽守卫6.1 涉及文件修改desktop/src/components/panes/ChatPane.tsx测试desktop/src/components/panes/ChatPane.test.mjs6.2 测试断言扩展ChatPane.test.mjs断言源码包含托管用量场景下的低余额警告文案额度耗尽守卫文案仅网页端 CTA 标签如Add credits、Manage on web。node --test desktop/src/components/panes/ChatPane.test.mjs预期FAIL。6.3 实现要点修改ChatPane.tsx消费useDesktopBilling()在排队queue托管会话输入前调用refresh()刷新余额若isOutOfCredits阻止发送显示内联 CTA 状态若isLowBalance显示警告横幅但允许发送本地 provider 会话不套用该逻辑。必需行为清单原文local providers remain unaffected本地 provider 不受影响managed mode warns when low托管模式余额低时警告managed mode blocks only when balance is exhausted托管模式仅在额度耗尽时拦截all recovery actions open web URLs所有恢复动作打开网页 URL。6.4 仓库现状印证apps/desktop/src/components/panes/ChatPane/index.tsx 中已落地该守卫3531-3532 行消费isLowBalance与isOutOfCredits7253 行处理isOutOfCredits的发送拦截分支9901-9902 行分别推导showLowBalanceWarningusesHostedManagedCredits isLowBalance !isOutOfCredits与showOutOfCreditsWarningusesHostedManagedCredits isOutOfCredits10332 与 10347 行附近渲染Add credits与Manage on web两个网页 CTA。usesHostedManagedCredits这一前提变量保证了本地 provider 完全不受托管计费门禁影响。6.5 验证与提交node --test desktop/src/components/panes/ChatPane.test.mjs预期PASS。提交git -C holaOS add desktop/src/components/panes/ChatPane.tsx desktop/src/components/panes/ChatPane.test.mjs git -C holaOS commit -m feat: add desktop low-credit chat guardrails七、Task 6端到端验证7.1 源码测试全量回归node --test desktop/electron/billing-ipc.test.mjs desktop/electron/settings-pane-routing.test.mjs desktop/src/lib/billing/useDesktopBilling.test.mjs desktop/src/components/layout/TopTabsBar.test.mjs desktop/src/components/layout/SettingsDialog.test.mjs desktop/src/components/panes/ChatPane.test.mjs预期全部PASS。7.2 类型检查npm run typecheck工作目录holaOS/desktop即仓库中的apps/desktop。预期PASS。7.3 桌面构建冒烟npm run build工作目录holaOS/desktop。预期PASS。7.4 人工验证清单计划给出了明确的手工验收项可直接作为 QA 用例顶栏仅在托管托管模式下显示额度胶囊点击额度胶囊可打开账户设置账户卡片以只读方式展示套餐与额度Add / Manage / View 按钮打开浏览器而非应用内支付 UI低余额在聊天中产生警告余额为零时拦截托管发送并提供网页 CTA本地 provider 模式不展示托管计费门禁。7.5 收尾提交git -C holaOS add desktop/src/components/billing desktop/src/components/layout desktop/src/components/auth desktop/src/components/panes desktop/src/lib/billing desktop/electron desktop/src/types/electron.d.ts docs/plans/2026-04-02-desktop-billing-credits-implementation-plan.md git -C holaOS commit -m feat: add read-only desktop billing visibility八、实现模式总结与可复用要点从计划到 apps/desktop 的落地代码可以提炼出四条可复用的工程模式凭证隔离的 IPC 桥Better Auth Cookie 只存在于主进程渲染进程永远拿不到原始凭证billingFetch/billingRpcFetch的分层既是认证代理也是数据归一化边界。这一模式在仓库中同样服务于 app SDK见 apps/desktop/electron/appSdkClient.ts 的注释Mirrors the billingFetch pattern。环境自适应的网页链接所有仅网页端操作 URL 由deriveAppBaseUrl()buildDesktopBillingLinks()从 API base URL 推导覆盖 localhost / preview / 生产多套环境映射杜绝硬编码导致的跨环境失效见 apps/desktop/src/lib/billing/billing-links.ts。只读 UI 契约渲染侧只有 Hook 展示组件无任何 Stripe/订阅变更逻辑所有恢复动作Add credits / Manage on web / View usage统一走openExternalUrl在类型层面UiSettingsPaneSection含billing保证跳转路由可解析。按模式区分的门禁语义本地 provider 完全不受托管计费约束托管模式低余额警告但不拦截、零余额才拦截且每次排队发送前先refresh()拉取最新余额保证门禁判断基于实时数据。如果需要为其他桌面功能如额度明细、发票下载、套餐变更入口扩展可见性沿用主进程代理认证读取 → preload 暴露 → Hook 归一化 → 组件只读展示 → 变更动作走网页这条链路即可无需改变信任边界与安全模型。赞分享人工智能AI AgentAI 应用前端后端即时通讯交互助手工具调用【免费下载链接】holaOSOpen-source agentic workspace enterprises can make their own. Connect the systems you already run — 100 integrations, MCP, chat tools, apps, browser, local files — with shared memory. Any agent (Claude Code, Codex), any model, or BYOK. Set up in clicks, not months. Local-first: your data never leaves your machines.项目地址https://gitcode.com/GitHub_Trending/ho/holaOS点击查看免费下载相关推荐MediaGo 桌面端 preload 桥接层解析基于 contextBridge 的安全 IPC 通信设计MediaGo 桌面端 preload 桥接层解析基于 contextBridge 的安全 IPC 通信设计 导读 本文围绕 MediaGo 开源仓库中的 p音视频桌面应用后端Calypso 桌面端 IPC 桥接深入解析 desktop-listeners 模块的 Electron 事件机制Calypso 桌面端 IPC 桥接深入解析 desktop listeners 模块的 Electron 事件机制 导读 client/lib/deskto前端CMSM3E Canvas AI 草图Beta让 Claude Code、Codex 读 agent.md 替你画出 UI 设计M3E Canvas AI 草图Beta让 Claude Code、Codex 读 agent.md 替你画出 UI 设计 M3E Canvas 是一款免前端Vibe Coding上一篇librealsense 的 rs-depth 示例源码解析用 C API 在终端实时可视化深度图下一篇告别提交失误Ungit可视化变更预览完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表