仓库结构¶
工作区地图¶
apps/
auth-api/ Public web and /app browser entry, accounts, memberships, connection tickets, and billing
discord-app/ Developer Portal settings of the OpenBot Discord app (no code)
mobile/ Expo React Native client for remote team hosts
site-router/ Cloudflare Worker that serves published sites from private R2 storage
slack-app/ Slack CLI projects with the OpenBot Slack app manifests (production, development)
status/ Public status page on GitHub Pages, and the check and webhook scripts of its workflow
telegram-app/ BotFather settings of the OpenBot Telegram bot (no code)
packages/
ui/ Shared SolidJS controls and primitive styles for desktop, web, and Storybook
brand/ Shared logos, avatars, and design tokens
contracts/ Process and network boundary types, limits, and pure validation
i18n/ Message catalogs, translate and format functions for desktop, shared UI and mobile
logging/ ts-log Logger interface plus the redacting console/file implementation
telemetry/ Safe error reports, bounded retry queue, and local storage/HTTP adapters
team-client/ Shared team connection, recovery, WebRTC framing, Dynamic Island state, and routine schedules
user-errors/ Shared user-facing error messages for desktop and mobile
remote/
api/ Bun Signal service for SDP, ICE, ticket checks, TURN credentials, and the Slack, Discord, Telegram and webhook relays
scripts/ Bun checks and update commands for Signal and coturn
src/
backend/ Agent runtime, provider adapters, event storage, queues, and browser host
main/ Electron lifecycle, trusted IPC, host server, and operating-system adapters
preload/ Narrow typed bridge from Electron main to the renderer
renderer/ SolidJS user interface
scripts/ Development, smoke, release, and package verification entry points
tools/ Biome GritQL rules, the UI foundation check, the vitest sequencer and setup, and the type baseline
.agents/skills/ Task instructions for coding agents, such as release and smoke checks
桌面应用程序位于仓库根目录。其包元数据同时也是 Electron Builder 和 GitHub 发布所使用的发布元数据。将其移入 apps/desktop 会创建第二个版本源,并增加包签名风险,而不会增加有用的运行时边界。
依赖方向¶
依赖指向稳定的边界:
packages/contracts不依赖 Electron、Node.js、SolidJS、provider 或 Cloudflare。- 渲染器不能导入
src/main或src/backend。 - preload 桥接层不包含业务规则。它将类型化调用映射到 IPC 通道。
- Electron 主进程在调用服务之前会验证不受信任的 IPC 输入。
- Provider 代码不能写入 UI 状态。它将事件发送到
AgentService,后者在主进程将更改发送到渲染器之前写入 SQLite 投影。 - auth API 服务器不能导入桌面实现文件。仅浏览器的路由组合可以通过显式的 preview 和 web 别名导入渲染器 UI。这些入口点不会加载 Electron、preload、setup 或 updater 提供程序。
biome.json 中的 noRestrictedImports 覆盖规则强制执行上述导入规则:渲染器和共享 UI 不能导入 main、backend 和 preload;main、backend 和 preload 不能导入渲染器;contracts 不能导入 Electron、SolidJS、provider、Cloudflare 和应用代码;账户服务器不能导入桌面代码。noNodejsModules 使 Node.js 不进入 contracts 和 team client。
状态所有权¶
openbot.db是 OpenBot 代理、会话、队列、反应、附件和 provider 会话绑定的事实来源。RoutineStore在一个事务中保存例程及其 webhook 触发器。WebhookRouteStore拥有路由 ID、加密密钥、回执和路由撤销。RoutineRecords为主进程提供这些数据的中立所有者视图。Webhook 运行使用现有的代理和通道队列。主进程拥有签名检查、密钥加密器和 Signal 入口(HostEventsService、WebhookRelay)。D1 只存储路由元数据。参见 Webhook 例程。MailboxStore拥有附件记录、暂存的生成附件、邮箱提交和文件删除发件箱。AttachmentFiles拥有草稿和传输文件:复制、大小限制、哈希、清单、受管路径检查和清理。它不读写数据库。生成的响应附件仅在会话和邮箱提交成功后才可见。代理删除和队列编辑会在邮箱事务中记录文件移除;删除发件箱会重试失败的移除。src/backend/provider-history.ts定义内部片段读取器。Provider 适配器拥有分页和解码。provider-history-import.ts提交规范化消息页,而不会删除页面中不存在的消息。SQLite 存储不完整的轮次和导入进度。没有稳定 OpenBot 消息 ID 的 ACP 重放记录仍作为 provider 记录用于交接和恢复。它们不会为实时轮次已保存的消息创建第二份副本。ConversationRuntime保留进行中的工作和有界近期缓存。已发布的完整历史 API 为每个请求从 SQLite 构建响应。它们不会设置工作缓存。~/.codex、~/.claude、~/.grok、~/.gemini、~/.cursor、~/.cline、~/.pi以及 OpenCode 和 Muse 的 XDG 文件夹是 provider 拥有的登录和恢复状态。它们不是 OpenBot 会话存储。- D1 是中央账户、远程成员资格、邀请和逻辑会话的事实来源。
- Stripe 是付费计划的事实来源。D1
billing_subscriptions是由 Stripe webhook 保持最新的副本;参见计费。 - 本地团队主机拥有会话、文件、代理以及 Team API 使用的本地成员投影。
openbot-approval-automation-v3.json保存哪些代理拥有完全访问权限:每个代理权限级别(仅工作区、先询问、完全访问)中的autoApprove部分。当不存在 v3 文件时,OpenBot 会读取较旧的-v2或-v1文件,并将其保留以供降级使用;这类文件中开启 Turbo 模式会让每个代理都获得完全访问权限。该文件属于运行代理的计算机,绝不会跨 Team API 传递;Team API 已发布的适配器会将审批响应限定为accept或decline:开启自动化的远程主机自行应答自己的审批,因此这些审批永远不会到达客户端,客户端也无法代表远程主机授予批准。AttentionRegistry在每次审批时都会读取该文件,包括托管站点发布、替换和删除。站点验证、所有权检查和活动标记仍然适用。授权更改(AgentService.notifyAgentsChanged)或访问更改也会应答那些正在等待某个现已拥有完全访问权限的代理的审批(AttentionRegistry.answerGrantedRequests)。该注册表还会一次性接受 Codex 对运行 MCP 工具的同意(_meta.codex_approval_kind为mcp_tool_call,包括设置为每次都询问的工具),并且不保存任何内容:“始终允许”仍是用户的选择,由 Codex 按服务器和工具保存。仅工作区代理保留其卡片;Computer Use 工具则不保留。OpenBot 将 Codex 的approvalPolicy保持在on-request,因为never会拒绝 MCP 工具调用并拒绝引导请求。其他问题、MCP 表单和登录请求以及浏览器接管仍然保持交互式。- 仅工作区代理可以更改其工作区、共享文件夹以及用户添加的文件夹中的文件(
AgentSummary.additionalFolders,位于agent_json中,真实路径,最多 32 个)。一个函数workspaceWritableRoots将这些根目录提供给每个 provider 沙箱,并且代理的开发人员指令会指明这些根目录。只有本地的agentFoldersIPC 端点可以更改该列表;代理不能自行添加文件夹。主进程拒绝磁盘根目录、主文件夹以及包含 OpenBot 数据的文件夹。不在磁盘上的文件夹会保留在列表中,但不会作为根目录。该列表是本地的,就像access一样:Team API 不会携带它。 browser-tabs.json是嵌入式浏览器自身的持久状态,位于openbot.db之外,也不在迁移运行器的管理范围内。它在文件中进行版本管理(v1早于每个标签页的BrowserEnvironment,v2携带该环境),并且始终以当前版本重写,因此降级时会读取一个它无法识别的文件。没有任何东西会先复制它,所以src/backend/browser-state.ts会重新验证它读取的每一个绑定,而不是直接信任该文件:环境验证失败的标签页仍然会被返回,但不包含该环境,因为丢失用户打开的标签页比丢失模拟视口更糟糕。~/OpenBot/Shared/Data/agent-data.db是一个 SQLite 文件,保存代理为自身创建的每一个表,位于openbot.db之外,也不在迁移运行器的管理范围内。一个文件为代理提供了一个命名空间,并让它们能够跨彼此的表进行连接。每个代理都可以读写每个表;openbot_metadata表记录创建每个表的代理,并且只有该所有者代理被允许删除或修改该表。SQLite 自身的授权器会拒绝其他情况,因此该规则不依赖于读取模型的 SQL。代理拥有这些模式,所以发布前不会有任何东西复制或迁移它们,并且当创建该表的代理被删除时,该表仍然保留。用户可以从代理设置中删除表,这是移除所有者已消失的表的唯一方法。代理读取的指南作为受管技能resources/managed-skills/openbot-data发布,与站点托管和技能创建器并列,因此常驻提示只列出工具名称。- 渲染器信号和存储只是当前屏幕的投影。它们不是持久状态,并且一个关注点对应一条记录——其字段上的一排并行信号会让屏幕持有产品并不存在的状态。
- 桌面会话上下文在带键的服务器作用域内为每个代理保存一条记录。分页、已读、运行时消息和移除命令会使其字段保持一致。其他域不能写入其存储。自动已读重试标记保持在该作用域之上;编辑器草稿和进行中的附件保持其现有的控制器生命周期。会话视图作用域组合行为存储。搜索请求、高亮、计时器和清理属于搜索存储。
共享 UI 软件包¶
@openbot/ui 拥有现有的 SolidJS 原语及其原语样式表。桌面端、Web 和 Storybook 直接导入此工作区。它不依赖渲染器、Electron、账户会话或主机连接。在品牌令牌之后导入 @openbot/ui/styles.css,并将包源码包含在 Tailwind 扫描中。应用特定样式仍保留在应用程序中。桌面 TypeScript 项目包含用于 CI 检查的包源码。
该包还拥有由 props 驱动的功能 UI:完整的侧边栏及其作用域交互存储、账户登录、服务器轨道和邀请对话框、消息渲染、composer 编辑器、附件卡片、预览渲染器、代理设置和可复用的设置面板。功能导出使用显式子路径,例如 @openbot/ui/features/sidebar/Sidebar。共享显示模型位于 @openbot/ui/data。源文件是被移动的,而非从渲染器复制或重新导出。测试仍保留在渲染器测试框架中,并直接导入该包。
浏览器面板和实时画布也位于此包中。其类型化的 BrowserViewRuntime 是必需的;渲染器提供桌面预加载适配器或 Web 主机适配器。共享的侧边栏活动和头像情绪功能使用调用方提供的状态。会话样式表作为 @openbot/ui/features/conversation/conversation.css 导出;应用程序在与先前渲染器样式表相同的级联位置导入它。此文件是 features/conversation/styles/ 中组件样式的有序清单。保持导入顺序:后面的表面规则和响应式规则覆盖前面的组件规则。
@openbot/ui/features/marketplace/* 渲染 Marketplace 窗口:Agents、Apps 和 Skills 标签页,以及每个列表项的页面。它读取类型化的 MarketplaceModel,并且不持有任何自身数据。渲染器的 marketplace-controller.ts 在注入的 MarketplaceCalls 上构建模型,MarketplaceModal 添加连接和卸载对话框。ConnectorsProvider 只创建一次连接器控制器;连接器的应用页面显示来自它们的 ConnectorDetailPanel。服务器设置没有连接器部分。
AgentSettingsPanel 拥有表单草稿、有序保存队列、头像编辑器和模型控件。其渲染器适配器拥有持久化宽度和原生记忆、例程、技能和表格,并将它们作为内容槽提供。ConversationHeader 拥有头部控件;其渲染器适配器拥有上下文读取、能力、翻译和操作错误处理。两个共享组件都接收类型化的 props 和回调。共享包的 Biome 覆盖规则拒绝应用导入和直接的桌面预加载访问。边界夹具通过聚焦的 scripts/ui-foundation-check.test.ts 测试运行。
桌面侧边栏持久化保留在 sidebar-pins-storage.ts 和 sidebar-sections-storage.ts 中。主会话控制器、应用上下文和平台适配器保留在渲染器中。进一步提取需要为这些依赖提供显式的运行时输入。React Native 使用品牌令牌和契约,而不是这些 DOM 组件。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 openbo/openbot