Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,31 @@
本文件记录可发布版本中用户可感知的变化。最新版本必须位于最前,并与 `package.json`、
`app.config.ts` 和发布 tag 保持一致;自动发布流水线只提取首个版本段作为 GitHub Release 正文。

## [0.0.13] - 2026-08-29

> Preview:让设备本地信箱可经 Tool Bridge durable mailbox 投递;不是 production、
> App Store 或 Google Play 正式版本。

### 新增与变更

- 将 `@tool-bridge/sdk` 精确升级到 0.20.1,消费正式 `createDeviceMailboxProcessor`、
`DeviceOperationJournal` 和 command `delivery` metadata,不复制上游协议源码。
- `phone/inbox.deliver` 对 Gateway 宣告 `delivery: both`,保留 realtime 直调并允许 caller 显式
选择 mailbox/fallback;`phone/productivity.notify` 仍是 realtime-only。
- 新增 SQLite v5 installation-local operation journal。`discovered/executing/terminal` barrier 先持久化
再进入副作用;崩溃恢复时不重放已进入 executing 的命令,而是保守提交
`result_unknown`。journal 不保存命令 arguments、消息正文或凭证。
- App 在初始化、Gateway 配置完成和回到前台时执行一次有界 mailbox drain;
切到后台、Disabled、换配置或凭证被拒绝会中止拉取并联动 realtime transport。

### 安全与验证边界

- mailbox 不自启 timer、不注册 APNs/FCM token,也不提供 push 或后台必达;用户未重新打开
App 时,设备不会因此发起新的拉取。本版本没有新增系统权限或远程通知入口。
- consumer contract 覆盖 delivery 投影、claim/complete、journal barrier、正文脱敏、崩溃后
`result_unknown`、前后台中止与 401 凭证联动;它们不替代真实 Gateway、真机、弱网、
锁屏或系统终止进程证据。

## [0.0.12] - 2026-08-28

> Preview:修复 Android 15+ 后台 `dataSync` 前台服务超时后的崩溃与重启循环;不是 production、
Expand Down Expand Up @@ -137,6 +162,7 @@

- 首个内部 Preview,包含移动端脚手架、前台 device transport、本地安全执行链和基础能力。

[0.0.13]: https://github.com/TokenRollAI/tool-bridge-mobile/releases/tag/v0.0.13
[0.0.12]: https://github.com/TokenRollAI/tool-bridge-mobile/releases/tag/v0.0.12
[0.0.11]: https://github.com/TokenRollAI/tool-bridge-mobile/releases/tag/v0.0.11
[0.0.10]: https://github.com/TokenRollAI/tool-bridge-mobile/releases/tag/v0.0.10
Expand Down
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
> 25 MiB 流式下载与 2 小时播放时长上限约束且支持 seek 的 App 自有媒体会话,
> 受控 HTTPS App handoff、只接受结构化目标的地图 handoff、逐次确认的一次性前台位置、由用户在
> App 内主动授权的即时本地通知、以 SQLite 为真源的单次 App 内计时器、可解释且可由用户单独清除的
> 本机活动审计,以及由 Agent 通过在线 direct call 投递、在 SQLite 中保留最近 1,000 条并可选发出
> 本机活动审计,以及由 Agent 通过在线 direct call,或由 Gateway durable mailbox 入队并在
> App 启动/回到前台后显式拉取投递、在 SQLite 中保留最近 1,000 条并可选发出
> 固定隐私提醒的设备本地信箱;单条正文支持最多 64,000 字符的 Markdown、用户主动安全加载的 HTTPS
> 图片、紧急程度、可选 Agent 发送时间、全文搜索、六种排序、单条/全部已读。App 现有六个本地页面的
> 无障碍语义自动化基线
Expand All @@ -29,14 +30,17 @@
> 当前还实现了仅前台的 `phone/camera.capture_photo`:Ask every time / Trusted session 会在可见预览中
> 由用户按快门并复核,用户主动选择的 Direct call 会在可见预览就绪后自动拍摄;照片重编码为有界 JPEG,
> 通过本次 call 的窄 Store capability 上传,协议结果只含受保护的 `store://default/...` 引用与元数据。
> 当前已精确锁定并接入 `@tool-bridge/sdk/device@0.17.0`:Android/iOS transport 使用官方
> 当前已精确锁定并接入 `@tool-bridge/sdk/device@0.20.1`:Android/iOS realtime transport 使用官方
> hello/ready/call/result、心跳、重连与 cancel,支持命令叶子并入 path 的新 device wire 与网关签发
> invocation context,并使用官方 call-scoped Store upload;调用继续经过本地安全执行链,只有收到 gateway ready
> invocation context,并使用官方 call-scoped Store upload。`phone/inbox.deliver` 另声明
> `delivery: both`,并通过官方 mailbox processor 执行 claim/lease/complete;调用继续经过本地安全
> 执行链,只有收到 gateway ready
> 才显示 online。Android Preview 0.0.6 已通过当前 Railway Gateway 的单次真机
> `status/get` 直连读调用;该证据不外推到其他能力、iOS、后台、弱网或完整 pairing。
> 当前内测入口允许用户在本机填写 Gateway HTTPS URL 与 API key,secret 只进入
> SecureStore;这不等于 pairing、最小权限设备凭证或短期 ticket。设备本地信箱不是网关 command
> mailbox;离线队列、远程 push 和通用 object 读取/生命周期契约仍等待
> SecureStore;这不等于 pairing、最小权限设备凭证或短期 ticket。设备本地信箱是正文存储域,
> Gateway command mailbox 是 durable operation 投递域;当前只在 App 启动/回到前台时有界拉取,
> 没有远程 push、隐式后台轮询或后台必达。通用 object 读取/生命周期契约仍等待
> [上游交付](llmdoc/integration/upstream-and-platform-gaps.mdx)。

## 它解决什么问题
Expand Down Expand Up @@ -120,7 +124,7 @@ SDK `deviceId` 默认由设备硬件标识(Android ID / iOS IDFV)经单向
不变;也可在同一表单中自定义(字母、数字、`.`、`_`、`-`,最长 64 字符)。设备声明挂载到
`device/phone/<deviceId>`。该 deviceId 不是网关签发身份,手工入口只是 pairing 交付前的内测通道。

相机上传要求目标 Gateway 支持 SDK 0.17 Store,并为本次 device call 注入有界、短期 upload capability。
相机上传要求目标 Gateway 支持 SDK 0.20.1 兼容的 call-scoped Store,并为本次 device call 注入有界、短期 upload capability。
App 不接收 capability token、signed upload URL,也不会把照片字节放进 HTBP JSON result;缺少该 capability
时会在本地确认和打开相机前拒绝。

Expand All @@ -140,7 +144,7 @@ APK。GitHub Actions 的 `android-preview-apk` job 会上传 APK 与 SHA-256,a

## 版本与 GitHub 预发布

当前 App/package 版本为 `0.0.11`。版本变更合并到 `main` 后,[`verify`](.github/workflows/verify.yml)
当前 App/package 版本为 `0.0.13`。版本变更合并到 `main` 后,[`verify`](.github/workflows/verify.yml)
全绿会触发 [`auto-release-preview`](.github/workflows/auto-release.yml):当 `package.json` 对应 tag 尚不存在时,
它复用该次已通过双端门禁的 Android artifact,核对 package、Expo App 版本与 `CHANGELOG.md` 最新版本段,
再创建版本 tag 和 GitHub Pre-release,并附带版本化 APK 与 SHA-256。版本已发布时幂等跳过;新的 main
Expand Down
8 changes: 4 additions & 4 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ type VariantConfig = Readonly<{
export const EXPO_OWNER = 'tokenroll'
export const EAS_PROJECT_ID = '378c7a3e-437a-49a6-ae20-fef5af6f6188'
export const EXPO_PROJECT_SLUG = 'tool-bridge'
export const APP_VERSION = '0.0.12'
export const ANDROID_VERSION_CODE = 12
export const IOS_BUILD_NUMBER = '12'
export const APP_VERSION = '0.0.13'
export const ANDROID_VERSION_CODE = 13
export const IOS_BUILD_NUMBER = '13'

export const APP_VARIANTS: Readonly<Record<AppVariant, VariantConfig>> = {
development: {
Expand Down Expand Up @@ -212,7 +212,7 @@ export default ({ config }: ConfigContext): ExpoConfig => {
gatewayOrigin: parseGatewayOrigin(process.env.EXPO_PUBLIC_GATEWAY_ORIGIN),
linkHosts: parseLinkHosts(process.env.EXPO_PUBLIC_LINK_HOSTS),
mediaHosts: parseMediaHosts(process.env.EXPO_PUBLIC_MEDIA_HOSTS),
productionTransport: '@tool-bridge/sdk/device@0.17.0',
productionTransport: '@tool-bridge/sdk/device@0.20.1',
},
}
}
38 changes: 22 additions & 16 deletions llmdoc/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,17 @@ development build 面向 Android 和 iOS。它让 Agent 在用户明确授权、
- `src/capabilities/`、`modules/`:类型化设备能力及必要的 Expo 原生模块;
- `test/contract/`:本地执行边界的注入式契约测试,不是 Gateway wire 或真机端到端测试。

本仓库不拥有 HTBP 通用协议、Tool Bridge Gateway、跨运行时公共 SDK、异步 command mailbox、push
registration/dispatch、动态 capability profile、对象存储或浏览器扩展。缺失的通用能力必须在上游交付,
不能复制 `@tool-bridge/core` 私有源码建立长期分叉。
本仓库不拥有 HTBP 通用协议、Tool Bridge Gateway、跨运行时公共 SDK、服务端异步 command mailbox、push
registration/dispatch、动态 capability profile、对象存储或浏览器扩展;只拥有正式 SDK mailbox API 的
移动 consumer wiring 与 installation-local operation journal。缺失的通用能力必须在上游交付,不能复制
`@tool-bridge/core` 私有源码建立长期分叉。

## 整体数据流

```text
官方 SDK device call / 本地测试 dispatcher
官方 SDK realtime device call / durable mailbox claim / 本地测试 dispatcher
-> transport adapter 归一化 command
-> mailbox 路径先持久化 operation execution barrier
-> LocalCommandExecutor
-> schema / deadline / cancellation / admission / live probe / policy / confirmation
-> SQLite claim 与防重放
Expand All @@ -70,20 +72,23 @@ deadline/cancel、逐次确认和 emergency disable 始终高于远程命令或

## 现状

- P0 本地安全运行时、官方 `@tool-bridge/sdk/device@0.17.0` 前台 consumer wiring、手工 Gateway
HTTPS origin/API key 内测入口和若干能力纵向切片已经实现。
- P0 本地安全运行时、官方 `@tool-bridge/sdk/device@0.20.1` realtime 与 durable mailbox consumer wiring、
手工 Gateway HTTPS origin/API key 内测入口和若干能力纵向切片已经实现。
- `phone/camera.capture_photo` 已形成仅前台的本地纵向切片:非 Direct 模式由用户拍摄并复核,Direct call
仍展示可见预览但在相机就绪后自动拍摄;处理后的 JPEG 通过 SDK 0.17 每次调用下发的 Store capability
上传,成功结果只返回稳定 `store://default/...` URI 与脱敏元数据。缺少该 capability 时会在确认和相机
probe 前 fail closed。
仍展示可见预览但在相机就绪后自动拍摄;处理后的 JPEG 通过 0.17 首次交付、当前 0.20.1 继续提供的
每次调用 Store capability 上传,成功结果只返回稳定 `store://default/...` URI 与脱敏元数据。缺少该
capability 时会在确认和相机 probe 前 fail closed。
- 只有 SDK `ready` 可投影为 online;手工长期 API key 不等于 pairing credential,也不证明真实 Gateway
的完整兼容矩阵。
- 设备本地信箱只保存已经在线到达 executor 的 direct call;它不是上游 U-5 command mailbox,也没有
离线 enqueue、push 唤醒或最终送达语义。
- `phone/inbox.deliver` 声明 `delivery: both`:既可 realtime 直调,也可由官方 processor 在 App 初始化/
配置完成且 active 或回到 active 时显式有界 drain。SQLite v5 operation journal 让 executing crash
保守恢复为 `result_unknown`;它没有 timer 驱动的新 drain、后台轮询或 push 唤醒,不提供后台必达或
最终送达语义。
- Android 已有一次 SDK 0.17 Preview 后置相机 Direct call 完成拍摄、Store 上传、stat 和受保护回读校验;
该日期化证据不能外推到 iOS、其他镜头/权限状态、后台/弱网、长期稳定性或 pairing。
- 当前仍未达到 MVP;pairing、credential 生命周期 binding、动态 profile、mailbox/push、通用受保护对象
读取与完整 U-7、真实 Gateway/storage 兼容矩阵、完整双端构建/真机矩阵与 production 发布证据仍未完成。
- 当前仍未达到 MVP;pairing、credential 生命周期 binding、动态 profile、U-5 真实 Gateway/双端联合验收、
U-6 push、通用受保护对象读取与完整 U-7、真实 Gateway/storage 兼容矩阵、完整双端构建/真机矩阵与
production 发布证据仍未完成。

## 已决定

Expand All @@ -97,9 +102,10 @@ deadline/cancel、逐次确认和 emergency disable 始终高于远程命令或

## 未实现与未验证

上游 U-2 至 U-7、真实 Gateway 能力矩阵、iOS 原生/真机、双端权限/后台/锁屏、production signing、
商店合规、rollout 与 rollback 都必须保持明确的“未实现”或“未验证”标签。历史日期化快照不作为 V3
持续事实;证据应按 `delivery/verification-evidence.mdx` 回到对应 commit/artifact 和当前命令结果。
上游 U-2/U-3/U-4/U-6、U-5 剩余联合验收、完整 U-7、真实 Gateway 能力矩阵、iOS 原生/真机、双端权限/
后台/锁屏、production signing、商店合规、rollout 与 rollback 都必须保持明确的“未实现”或“未验证”
标签。历史日期化快照不作为 V3 持续事实;证据应按 `delivery/verification-evidence.mdx` 回到对应
commit/artifact 和当前命令结果。

## 主题路由

Expand Down
32 changes: 23 additions & 9 deletions llmdoc/capabilities/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ code:
paths:
- src/capabilities/**
- src/inbox/**
- src/gateway/sdkDeviceMailboxTransport.ts
- src/storage/deviceMailboxJournalRepository.ts
- src/storage/migrations/0005_device_mailbox_journal.ts
- modules/**
- app.config.ts
---
Expand Down Expand Up @@ -82,9 +85,9 @@ adapter。registry 在展示与执行前读取真实 probe,并在返回 SDK
command hash 文件名和 idempotency key,并严格核对 SDK 返回的稳定 `store://default/...` descriptor。
inline result 只含 URI、MIME、大小、尺寸与 SHA-256,不含照片、Store capability、relay URL、私有文件 URI
或虚构的对象过期时间。
- 离开 `active` 会取消本地相机/处理和结果提交;SDK 0.17 的 call-scoped upload 不能接收 controller 的本地
AbortSignal,因此上传已开始后不能保证终止 Store HTTP 副作用。当前 Gateway 的约 60 秒权威期限会收紧
相机 120 秒本地 ceiling。
- 离开 `active` 会取消本地相机/处理和结果提交;当前 SDK 0.20.1 的 call-scoped upload 仍不能接收
controller 的本地 AbortSignal,因此上传已开始后不能保证终止 Store HTTP 副作用。当前 Gateway 的约
60 秒权威期限会收紧相机 120 秒本地 ceiling。
- 本地自动化覆盖相机 schema、状态机、处理和 SDK upload consumer;2026-08-26 的 Android Preview
后置 Direct call 已完成真实拍摄、Store 上传/stat/受保护回读。iOS、其余权限/镜头/生命周期矩阵、系统
指示/快门声和 crash 后孤儿清理仍必须按各自证据层单独判断。
Expand Down Expand Up @@ -141,8 +144,14 @@ adapter。registry 在展示与执行前读取真实 probe,并在返回 SDK

### `phone/inbox.deliver`

- 设备本地内容信箱只处理已通过在线 SDK direct-call session 到达 executor 的消息;`queuePolicy` 是
`reject_offline`,它不是 U-5 gateway command mailbox,也没有离线 enqueue 或 push 唤醒。
- 设备本地内容信箱的 `queuePolicy` 是 `enqueue`,registry 只为它投影 `delivery: both`:既支持 realtime
direct call,也允许 Gateway durable mailbox operation 在 App 显式前台 drain 时到达 executor。
- Gateway operation mailbox 与本地 `inbox_messages` 内容信箱是不同层。前者由官方 SDK processor 和
SQLite v5 `device_operation_journal` 管理 claim/lease/complete 恢复,后者保存用户可见正文与已读状态;
journal 不保存 arguments、正文或 credential,恢复 `executing` 时提交 `result_unknown` 而不重放。
- drain 只在初始化/配置完成且 App active 或回到 active 时显式触发,单次最多 20 项;后台/inactive、
Disabled、换配置和 credential 失效会中止。没有 timer 驱动的新 drain、push、后台轮询或进程终止后的
自启动。
- strict schema 接受 `title/Markdown body/category/format/urgency/sentAt/sourceLabel/notify`;format 固定
`markdown`,urgency 是四值枚举,可选 sentAt 必须为 canonical UTC。sourceLabel/urgency/sentAt 只是 Agent
内容元数据,不能冒充 invocation caller 或本机 receivedAt。
Expand Down Expand Up @@ -186,9 +195,11 @@ adapter。registry 在展示与执行前读取真实 probe,并在返回 SDK
channel importance 为 NONE 则映射 channel disabled/settings。
- 成功 result 只报告确定性 notification id、`status: scheduled`、`presentation: system_determined` 与本地
scheduledAt。它不声称通知已呈现、送达或点击,普通 audit/command outcome 不保存 purpose/message。
- SDK expose 中 `phone/productivity.notify` 没有 `delivery` metadata,保持 realtime-only;信箱的
`notify: true` 只是 `inbox.deliver` commit 后的固定本地提醒,不会把 notify capability 变成 mailbox。
- final Expo config 移除 APNs `aps-environment`;Android blocked permissions 移除 boot/exact、C2DM 与厂商
badge,custom plugin 移除 FCM/Firebase service/receiver/provider 和 transport scheduler,只保留不可导出
的本地 event receiver 与 forwarder。该切片不满足 U-5 mailbox U-6 push。
的本地 event receiver 与 forwarder。该切片不支持 mailbox,也不满足 U-6 push。

详细权限映射、native 内容与最终配置边界见 `llmdoc/capabilities/local-notifications.mdx`。

Expand Down Expand Up @@ -230,6 +241,9 @@ adapter。registry 在展示与执行前读取真实 probe,并在返回 SDK
- local device inbox:`src/inbox/` + `src/storage/migrations/0003_inbox.ts` +
`src/storage/migrations/0004_inbox_metadata.ts` +
`src/storage/inboxRepository.ts`
- durable mailbox consumer:`src/gateway/sdkDeviceMailboxTransport.ts` +
`src/storage/migrations/0005_device_mailbox_journal.ts` +
`src/storage/deviceMailboxJournalRepository.ts`
- inbox image hostname:没有配置入口;media 与 App handoff 仍分别使用 `EXPO_PUBLIC_MEDIA_HOSTS` 和
`EXPO_PUBLIC_LINK_HOSTS`,其 allowlist 语义没有因信箱图片 policy 放宽而改变
- local timer persistence:`src/storage/migrations/0002_timers.ts` + `src/storage/timerRepository.ts`
Expand All @@ -241,13 +255,13 @@ adapter。registry 在展示与执行前读取真实 probe,并在返回 SDK
unit/component/local contract 证明的是本地边界。registry 将单项 probe 异常隔离为
`unavailable: probe_failed`。任何 clean build 只证明对应 commit/artifact 的原生依赖与配置能编译;prebuild
或 Metro 不可写成 Android/iOS 原生 build,它们也不证明 production gateway、storage 或真机前台/后台/
锁屏行为。信箱还必须把本地自动化、真实
Gateway `inbox/deliver`、双端真机与 U-5/U-6 离线 mailbox/push 分为四层,不得互相替代
锁屏行为。信箱还必须把本地内容自动化、SDK 0.20.1 mailbox consumer contract、真实 Gateway operation
path、双端真机与 U-6 push/后台唤醒分层,不得互相替代;当前只能称 U-5 consumer 接入,不能称完整验收

## 产品阶段映射

- P0 先提供真实 probe、policy、confirmation、幂等、审计、撤销和可达性地基;没有正式 pairing、动态
profile、mailbox/push 与双端真机前,不把单个本地 handler 称为 MVP。
profile、U-5 真实 Gateway 联合验收、U-6 push 与双端真机前,不把单个本地 handler 称为 MVP。
- P1-A 以 attention 为首个物理设备 golden slice;P1-B 覆盖媒体和受控 handoff;P1-C 覆盖仅前台相机
与受保护对象;P1-D 覆盖位置、inbox、notification、timer、accessibility 和发布准备。
- P2/P3 候选能力进入 registry 前必须先补用户用例、平台/权限/商店矩阵、abuse case 和独立 DOD;能力
Expand Down
Loading