☰
AOS CE AOS Tray 深度解析:macOS 菜单栏 Shell 的启动模式、只读验证与 Native Input 接入
2026/9/25 3:36:59 网站建设 项目流程

【免费下载链接】aos-ce

AOS Community Edition: the open agent operating system.

项目地址:https://gitcode.com/gh_mirrors/ao/aos-ce
点击查看免费下载

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互斥。约束与行为:

  1. PATH 必须是一个显式的绝对文件路径,且位于已存在的、用户所有的0700目录内;
  2. 进程在打开 UI 之前绑定该 socket(0600权限,同用户 peer 检查);
  3. 每个连接服务一次"换行符分隔的 JSON 请求/响应";
  4. 载荷中不存在的 principal、capsule、scope 身份一律不发明;
  5. Cancel、timeout、disconnect、quit 四种结局都不构成批准;
  6. 这是同用户凭据边界,不是"人类真实发出请求"的证明;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.py

preview-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。

此外还有两层更强的验证:

  1. Rust/Swift 桥接测试:把AOS_TRAY_TEST_BINARY指向一个构建好的 AOS 代理二进制即可启用。这些测试使用脚本化的运行时回复,不依赖已安装胶囊;
  2. 可选的 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.

项目地址:https://gitcode.com/gh_mirrors/ao/aos-ce
点击查看免费下载
上一篇:如何用Video2X实现专业级视频AI增强:4K超分辨率与智能插帧全攻略
下一篇:Kitura Web应用架构:MVC与Clean Architecture实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询