【免费下载链接】aos-ce
AOS Community Edition: the open agent operating system.
AOS Tray 是 AOS Community Edition(下称 AOS CE)的 macOS 菜单栏原生 Shell:一个 accessory 进程、无 Dock 图标、关闭面板只是隐藏窗口、退出 Tray 也绝不触碰 AOS 运行时、挂载、Agent 或 MCP 会话。本文基于 apps/aos-tray/README.md 的完整脉络展开,并结合 AOSTrayCore 与入口源码,覆盖默认启动的二进制绑定规则、全部命令行模式(--snapshot/--demo/--socket/--aos-binary+--aos-home)、本地预览 bundle 组装、Overview/Capsules/卷操作的只读验证边界,以及aos native-setup驱动的 Native Input 配对流程,读完后你可以独立构建、测试并安全地配置这套菜单栏 Shell。
产品定位与生命周期边界
AOS Tray 的核心设计约束是"GUI 是观测与呈现层,不是运行时的一部分"。这一约束在源码中被固化为一份显式的生命周期策略:TrayLifecyclePolicy 的accessoryShell静态值逐条声明了该产品的行为契约:
public static let accessoryShell = TrayLifecyclePolicy( activationPolicy: .accessory, showsDockIcon: false, closeWindowHides: true, terminateAfterLastWindowClosed: false, quitStopsRuntime: false, autoLaunchAtLogin: true, readsLiveHome: false, collectsCredentials: false, performsNetworking: false, installsApps: false, startsDaemons: false )quitStopsRuntime: false:退出 Tray 不启动、不停止任何守护进程;startsDaemons: false、installsApps: false:Tray 自身没有自动守护进程启动或文件系统挂载行为;accessory激活策略 +showsDockIcon: false:对应"Accessory process, no Dock icon",面板关闭只是隐藏(closeWindowHides: true、terminateAfterLastWindowClosed: false);autoLaunchAtLogin: true:macOS 产品安装器把签名好的 App 放到$HOME/Applications,首次打开后由已安装的 App 自行注册登录项。此外,在 macOS 上aos start、aos restart以及面向 Oracle 的aos mcp serve入口点在该稳定 App 存在时也会重新打开它——但可选 GUI 永远不会成为运行时启动的依赖。
面板的分区结构同样在源码中枚举化:PanelSection 定义为overview、requests、capsules三个标签页,后文的验证能力分别对应 Overview 与 Capsules。
构建与运行:默认绑定规则
仓库给出的标准运行方式是 Swift Package Manager,包描述见 Package.swift(最低平台 macOS 13,产品为AOSTrayCore库与aos-tray可执行文件):
swift build --package-path apps/aos-tray swift test --package-path apps/aos-tray swift run --package-path apps/aos-tray aos-tray --snapshot swift run --package-path apps/aos-tray aos-tray --demo --snapshot参数语义:
--snapshot:只打印 presentation JSON 后退出,不打开任何窗口,适合脚本化检查呈现模型;--demo:加载一个带持久 DEMO 横幅的内存 fixture,演示决定只会修改 fixture 本身,不会触碰真实安装;- 省略
--snapshot则进入菜单栏 Shell 运行。
默认无参启动的绑定规则是这套产品的关键不变量:它只绑定当前用户的~/.aos/bin/aos与~/.aos(或一个有效的绝对路径AOS_HOME环境变量),且二进制永远取该 home 下的bin/aos。Tray 不搜索PATH、不使用 App 相邻的可执行文件、不登记设备;找不到二进制时如实报告缺失,而不是"发明"出一份清单。显式的--aos-binary/--aos-home仍然成对选择安装。
这条规则在 LaunchArguments.parse 中可以直接验证:--aos-binary与--aos-home各自要求绝对路径(hasPrefix("/")),解析完成后执行(aosBinary == nil) != (aosHome == nil)的成对校验——只给一个就返回conflictingModes错误。错误消息集合 LaunchParseError 明确了三种失败:未知参数、--socket缺 PATH、以及--socket与--demo/--snapshot互斥。
完整的命令行面(由 helpText 给出):
aos-tray — AOS macOS menu bar shell Usage: aos-tray aos-tray --demo aos-tray --snapshot aos-tray --demo --snapshot aos-tray --socket PATH aos-tray --aos-binary ABSOLUTE_PATH --aos-home ABSOLUTE_PATH aos-tray --overview aos-tray --native-input-config ABSOLUTE_PATH aos-tray --help入口逻辑在 AOSTrayMain:解析失败打印 help 并以退出码 2 结束;--snapshot在TrayPresentation.make(from: store)成功后打印 JSON 即返回;其余情况经InstalledRuntimeLaunch.apply归一化出aosBinary/aosHome/expectedBinary后交给TrayApp.run。DEBUG 构建下还保留了--preview-runtime-input与--preview-input两个内部预览入口,不进入发布文档面。
--socket开发用 presenter 模式
--socket PATH是一个开发用 presenter 监听器,与--demo和--snapshot互斥。约束与行为:
- PATH 必须是一个显式的绝对文件路径,且位于已存在的、用户所有的
0700目录内; - 进程在打开 UI 之前绑定该 socket(
0600权限,同用户 peer 检查); - 每个连接服务一次"换行符分隔的 JSON 请求/响应";
- 载荷中不存在的 principal、capsule、scope 身份一律不发明;
- Cancel、timeout、disconnect、quit 四种结局都不构成批准;
- 这是同用户凭据边界,不是"人类真实发出请求"的证明;Inventory 在该模式下保持不可用。
源码中这一互斥性由 parse 的--socket分支 与结尾的模式冲突检查共同保证。README 还强调:--demo始终是内存 fixture,--socket始终是"无默认 home inventory 的 presenter",而无参启动才会在二进制存在时检查所绑定的安装。
本地预览 bundle 与动作对话框 fixture
不安装、不启动,仅组装一个本地 App bundle:
sh apps/aos-tray/scripts/build-preview.sh该脚本(build-preview.sh)的实际步骤是:swift build→ 取--show-bin-path→ 在.build/AOS Preview.app下复制Info.plist与aos-tray二进制 →plutil -lint校验 plist →codesign --force --sign -ad-hoc 签名 →codesign --verify --strict本地验签,最后打印 bundle 路径。需要明确:它是 ad-hoc 签名、供本地执行的预览,不是Developer ID 签名/公证后的分发包。
预览构建完成后可运行隔离的动作对话框 fixture:
python3 apps/aos-tray/scripts/preview-action.pypreview-action.py 只启动预览 App 和一个临时私有 socket;选择一个选项会打印其响应并关闭预览;它从不接触运行时、不保存任何 grant,且 fixture 五分钟过期。另有 check-capsule-library.py 用于胶囊库一致性检查。
验证一:Overview 的显式只读检查
aos-tray --aos-binary /absolute/path/to/aos --aos-home /absolute/path/to/aos-home两个参数必须一起提供,且不能与 demo/snapshot 混用(对应 parse 结尾的冲突检查)。从菜单栏打开 AOS 或选择 Overview 会触发刷新。行为边界:
- 只执行
aos status --json,不启动守护进程; - 错误显示为unavailable而非stopped;
- "已连接客户端"与"已加载胶囊"来自类型化的 status 响应,不是完整的已装胶囊/agent 会话清单;
- status 输出在内存中限定 64 KiB,并设 15 秒单调时钟截止;超时或超大的 status 子进程会被 kill 并回收——这一信号永远不会发给运行时守护进程本身;
- 任何 status 输出都不落盘。
验证二:Capsules 标签页与 Principal 选择
Capsules 页对同一显式安装调用aos status --json --include-capsules,列出该已认证 principal 可见的名称、版本与描述,并提供本地搜索。principal 的切换规则很严格:
- 视图从
default开始,"Change…" 通过aos principals --json和运行时的 owned-directory API 列出该已认证用户的 principals,禁用的 principal 不可选; - 发现失败时绝不回退到全局名单或自由文本身份;
- 选中的 ID 通过 CLI 的
--principal选项传递,返回的 inventory 必须与请求的 principal 匹配; - 不创建 agent、不枚举全局名单、不变更权限;
- Inventory 复用已认证的 status 连接,并有自己 5 秒的请求超时(Tray 层面给组合操作留 20 秒);
- stopped、denied、unsupported、unreachable 的 inventory 不等于空库——这四种状态都被如实呈现为不可用;
- 不带
--include-capsules的旧 AOS 构建仍可正常使用 Overview,Capsules 页显示 unavailable; - 列表是包元数据,不是有效 grant 或全局清单。
验证三:卷操作(Open files / Eject / Open mounted volume)
卷区块读取runtime/astrid.volume元数据,并可在 Finder 中揭示该容器文件;文件 size 不代表分配量或容量。三个动作的精确语义:
| 动作 | 行为 | 约束 |
|---|---|---|
| Open files | 若所选 owned principal 的固定 App 属文件夹$AOS_HOME/mnt/files尚未挂载为astridfs,先挂载,然后校验aos status --json+ 原生statfs复检,才打开 Finder | 只操作该固定路径 |
| Eject | 卸载上一次捕获的同一挂载路径 | 不自动卸载其他挂载 |
| Open mounted volume… | 让用户选定一个已存在的 macOS 挂载根,通过aos status --json --principal=default --mountpoint=<path>校验其 lease,再复检原生文件系统后打开 Finder | 永不启动、挂载或卸载运行时 |
两者(mount/unmount)都以设置了AOS_HOME的方式派生aos --principal <id> storage mount|unmount;storage是继承的产品级透传,由 AOS 自己选择运行时 home 与 workspace-state 布局。Tray不传--admin、--fleet、--read-write、--workspace,启动时不自动挂载,也不启动守护进程;mount/unmount 失败不算成功。其他平台与更旧的 AOS 版本直接拒绝该操作;README 明确:真实挂载的正向导航仍需实际执行验证,这是开发增量而非打包集成。
测试体系:Swift 套件、Rust/Swift 桥接与原生 Guest 旅程
Swift 测试套件覆盖 choice-index 保持、prompt 取消、socket 隔离与显示元数据,测试位于 Tests/AOSTrayCoreTests,例如 SocketTests、NativeInputCoordinatorTests。
此外还有两层更强的验证:
- Rust/Swift 桥接测试:把
AOS_TRAY_TEST_BINARY指向一个构建好的 AOS 代理二进制即可启用。这些测试使用脚本化的运行时回复,不依赖已安装胶囊; - 可选的 guest 旅程:scripts/test-native-guest.sh 使用构建好的 probe 胶囊(fixture 见 Tests/Fixtures/native-input-probe)、一次性 home 与显式选定的候选二进制,单独演练私有输入与守护进程重启,与脚本化 socket 测试相互独立。
注意其能力边界:guest 旅程本身不证明打包 AOS 安装,也不证明 Windows/Linux 的原生 UI。
Native Input 设置:配对、连接与私有输入通道
在显式提供 AOS 二进制与 home 时,从菜单栏选择Set Up Native Input…,选择一个 owned principal,确认设备登记与 responder 路由。aos native-setup命令会配发一枚专用的 tray key,并在该 AOS home 下创建私有的native-input/connection.json;配对 token 通过标准输入传递,而不是命令行参数(避免出现在进程列表与 shell 历史中)。对应 CLI 实现位于 unicity-aos-bootstrap。
设置的硬性前提与行为:
- 要求一个运行中的兼容运行时;
- 遇到已存在的 enrollment 或 responder 配置时拒绝,而不是替换凭据或策略;
- 设置成功后需要重启运行时以加载 responder 配置,并重启 Tray;Tray 从显式选定的 home 采纳该私有连接文件。
后续维护入口:
- Connect Native Input…:接受一个已存在的私有连接文件(对应
--native-input-config ABSOLUTE_PATH,解析器要求绝对路径且与--demo/--snapshot不兼容); - Reconnect Native Input:重试该连接。
私有文本与 secret 字段走已认证的原生运行时连接,而不是模型侧的 MCP 结果;输入、取消、断连是三种互不合并的结局。运行时决定可用的 approval 选项及其生命周期;在库中选择一个 principal不授予批准权限。相关核心逻辑集中在 NativeInputCoordinator 与 NativeRuntimeInputSession 等模块。
能力边界(Claim Limits)
README 的 "Claim limits" 一节是对该组件最诚实的能力声明,值得逐条保留为工程边界:
- 默认启动不连接任何运行时;显式
--socket模式可以呈现来自 AOS 原生 MCP 适配器的请求,但不读取 principal home; --socket是本地同用户开发传输,不是 grantor,也不是"人类发送了请求"的证明;- 存在 native socket ≠ inventory 可用;
- AOS Tray 不是 consent 强制执行器、不是 updater、不是文件系统 UI;
- bundle 标识是
ai.unicity.aos.tray,不得与org.astrid.runtime.fs混淆; - Host/MCP 动词只在请求列出时才显示,Shell 不会为每个请求发明
always; - 请求身份是 request ID:同一 principal、capsule、scope 也可能是不同的调用;
- 胶囊行身份是 principal + capsule + scope 三元组;
- 运行时 socket 提示按连接(connection)为键,不按 request ID 合并;
- GUI、打包安装与运行时检查必须在发布候选版本上重新执行;VoiceOver 尚未验证。
小结
AOS Tray 的价值在于把"可选 GUI"做成了一个边界清晰、行为可枚举的组件:启动模式互斥由解析器强制(Identity.swift),只读验证用大小/超时/复检三重护栏包裹aos status --json,卷操作只碰固定路径且失败即不可用,Native Input 通过 stdin 传 token、拒绝覆盖既有配置。它提供的是菜单栏上的观测、呈现与受控交互面——而不是第二套运行时控制面。对于要在 AOS CE 上扩展或审计 GUI 行为的开发者,这套"显式绑定 + 互斥模式 + 不可用优于虚构"的设计约定本身也值得参考。
【免费下载链接】aos-ce
AOS Community Edition: the open agent operating system.
相关推荐
如何掌握AOS滚动动画库:轻松实现offset与anchorPlacement的精准控制
如何掌握AOS滚动动画库:轻松实现offset与anchorPlacement的精准控制 AOS(Animate on Scroll)是一款轻量级的滚动动画库,
前端UI组件AOS的单元测试模拟:Jest与Sinon实现的函数调用验证
AOS的单元测试模拟:Jest与Sinon实现的函数调用验证 单元测试在AOS开发中的价值 Animate on Scroll AOS 作为轻量级滚动动画库,其
前端UI组件终极指南:macOS菜单栏VisualEffectView模糊效果深度解析与Ice应用实践
终极指南:macOS菜单栏VisualEffectView模糊效果深度解析与Ice应用实践 想要让你的macOS菜单栏焕然一新吗?通过VisualEffectV
桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考