Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
555dfc2
ADR 0014 phase 4: an app's pinned shared components in the wasm service
ymote Oct 10, 2026
06fce6f
docs: shared components in the wasm service (ADR 0014 phase 4)
ymote Oct 10, 2026
740e1f6
ADR 0014: phase 4's parts, and iOS not planned for now
ymote Oct 10, 2026
0f8461d
fix: make host capability declarations descriptive while preserving c…
ymote Oct 10, 2026
de2bb82
Merge commit '740e1f6dd2e2fbc93b0dad0bd944989c07a281bd' into fix/decl…
ymote Oct 10, 2026
4da4d95
test(wasm): exercise shared components through installed Store admission
ymote Oct 10, 2026
71d5744
docs: align component boundaries and release status with declaration …
ymote Oct 10, 2026
480194a
fix: align acceptance host adapter and document device consent migration
ymote Oct 10, 2026
da233a6
test(wasm): accept real GitHub shared components through native app t…
ymote Oct 10, 2026
4f04d10
test(wasm): assert the concrete runtime descriptor response shape
ymote Oct 10, 2026
c44d093
test: retain camera consent coverage and isolate missing-service fixture
ymote Oct 10, 2026
2f68a0b
fix: derive script toolbox sharing from exact agent tool requests
ymote Oct 10, 2026
7e0241d
docs: separate API disclosure from agent authorization boundaries
ymote Oct 10, 2026
711a8b7
fix: unwrap optional shared component script before execution
ymote Oct 10, 2026
ed4e1e0
test: validate native device consent independently of declarations
ymote Oct 10, 2026
c3e8922
test: create isolated catalog cache directory before admission
ymote Oct 10, 2026
deafd41
docs: align component policy and location fixture boundaries
ymote Oct 10, 2026
c5f0c5c
test: verify the final shared component app is presented
ymote Oct 10, 2026
3d6fa63
docs: record authenticated shared component device acceptance
ymote Oct 10, 2026
4ed694a
fix: preserve device consent when seating Glance cards
ymote Oct 10, 2026
4c492ce
test: prepare packaged desktop shared component acceptance
ymote Oct 10, 2026
2547dae
test(glance): observe device consent through public host requests
ymote Oct 10, 2026
337fed6
Merge current main after component integration
ymote Oct 10, 2026
d3babef
test: assert the broker's background device refusal
ymote Oct 10, 2026
2c157c4
test: record agent refusal and own-process teardown in release rehearsal
ymote Oct 10, 2026
8ee0dad
fix: advertise card tool dispatch before catalog admission
ymote Oct 10, 2026
9e9c5a0
docs: keep component platform scope consistent
ymote Oct 10, 2026
3824ae2
fix: show App Hub compatibility errors in app details
ymote Oct 10, 2026
3311d1a
fix: expose device consent ABI before cold card launches
ymote Oct 10, 2026
dedd14a
test: provide complete cold-host manifest fixture
ymote Oct 10, 2026
6344414
test: wait for each installed app to become openable
ymote Oct 10, 2026
6b57253
test: give Glance policy fixtures isolated admitted profiles
ymote Oct 10, 2026
00f3806
fix: bound Wasm compiled-cache reads and fall back to source
ymote Oct 10, 2026
015d96f
test: distinguish ready Wasm cache hits from cold UI loads
ymote Oct 10, 2026
0c018f8
docs: explain bounded cache fallback and first-call limits
ymote Oct 10, 2026
3e27d8d
test: verify live native storage is bound to its admitted app
ymote Oct 10, 2026
8b09e05
fix: bind admitted app identity in the shared card loader
ymote Oct 10, 2026
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ On a machine that already has clones of Makepad, OctoScript or Octoscript-Makepa
9. **Keep docs honest and bilingual.** Every command in a doc was run; anything not run is marked **unverified**. User-facing docs are `README.md` plus `README.zh-CN.md`, linked by the single switcher line under the title (`English | [简体中文](README.zh-CN.md)`), and change together. `AGENTS.md` files are English only.
10. **Keep signing keys, keystores, tokens and personal paths out of the repository.** `rom/tests/test_no_local_paths.py` checks for local paths.
11. **App icon shapes belong to the shell style.** Use `octosense::style::AppIconDraw` on shell app-icon surfaces; never draw a bundle PNG/SVG directly. Keep new identities in the shared platform frame policy (`crates/shell/src/octosense/icon_frame.rs`), including App Hub and Assistant. Supply square artwork with its important content in the central safe area, without baked platform corners or shadows. Verify Android, macOS and iOS styles, including PNG/SVG and transparent artwork. Native Android package icons already have the system's mask and badges; do not mask them again. See [app icon guidelines](apps/README.md#launcher-icon-artwork).
12. **Capability declarations describe usage.** `capabilities` and `network.hosts` do not grant or deny execution of public APIs. Apply this consistently to Splash, app-agent tools and components. Keep verified bundle and profile identity, device consent, OS permissions, account scope, trusted write review, storage jail/quota and inter-app tool sharing. `requires` and `host_api.required` remain compatibility checks. Capture intent is explicit (`audio`/`library` options), never inferred from API availability. See [capabilities and execution boundaries](docs/capabilities.md).

## Architecture documentation and code walkthroughs

Expand Down
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ octosense-reference = { path = "apps/reference" }
makepad-sheets = { git = "https://github.com/OctoSense-org/makepad.git", rev = "d653bc4493619ab979ccff165cf48c0c63b77d19", default-features = false }
makepad-terminal = { git = "https://github.com/OctoSense-org/makepad.git", rev = "d653bc4493619ab979ccff165cf48c0c63b77d19" }
octosense-appcard = { path = "apps/appcard/module" }
octosense-app-hub-app = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "40abb23b50d5c3e546c50d1d91ab27258a203eaf" }
octosense-app-hub-app = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "8347a489141c0e24cab564883db7c4592935a8b2" }
makepad-calculator = { git = "https://github.com/OctoSense-org/makepad.git", rev = "d653bc4493619ab979ccff165cf48c0c63b77d19", default-features = false }
makepad-clock = { git = "https://github.com/OctoSense-org/makepad.git", rev = "d653bc4493619ab979ccff165cf48c0c63b77d19", default-features = false }
makepad-notes = { git = "https://github.com/OctoSense-org/makepad.git", rev = "d653bc4493619ab979ccff165cf48c0c63b77d19", default-features = false }
Expand Down Expand Up @@ -130,17 +130,17 @@ octoscript-makepad = { git = "https://github.com/OctoSense-org/Octoscript-Makepa
octoscript-node = { git = "https://github.com/OctoSense-org/Octoscript-Makepad.git", rev = "6cf2d90aa33ff4ae603f49c7557f3ecf986207f0" }
# --- App Hub's host service registry the Mail and llm services register
# into; the same revision as App Hub's app crate (a native app, above).
octosense-appstore = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "40abb23b50d5c3e546c50d1d91ab27258a203eaf" }
octosense-appstore = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "8347a489141c0e24cab564883db7c4592935a8b2" }
# The app policy (resolution, isolate settings, the Splash adapter) and the
# Hub client the Card runner resolves an app's policy with; the shell's
# glance tiles run cards under it (crates/shell/src/glance_card.rs).
octosense-app-policy = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "40abb23b50d5c3e546c50d1d91ab27258a203eaf" }
octosense-app-hub = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "40abb23b50d5c3e546c50d1d91ab27258a203eaf" }
octosense-app-policy = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "8347a489141c0e24cab564883db7c4592935a8b2" }
octosense-app-hub = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "8347a489141c0e24cab564883db7c4592935a8b2" }
# The app contract (ADR 0005), from crates.io by version: App Hub, the shell
# and Rinx all depend on `octosense-app-contract = "1"`, so Cargo links ONE
# 1.x for the whole build (Cargo.lock pins the exact version OctoSense ships)
# and App Hub and Rinx no longer need the same App Hub commit.
octosense-app-contract = "1.10"
octosense-app-contract = "1.11"
# --- octos: ONE source for every octos crate (reviewed octos#2715 at
# b0759a57: bounded ledger session-directory names, serialized peer purge
# against session writes, and provider transport diagnostics that omit
Expand Down Expand Up @@ -437,7 +437,7 @@ ruma = { git = "https://github.com/project-robius/ruma.git", branch = "tsp" }
# -i octos-core` still sees one octos source.
[patch.crates-io]
# Keep the contract identical to the pinned SDK for this release candidate.
octosense-app-contract = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "40abb23b50d5c3e546c50d1d91ab27258a203eaf" }
octosense-app-contract = { git = "https://github.com/OctoSense-org/OctoSense-App-Hub", rev = "8347a489141c0e24cab564883db7c4592935a8b2" }
nix = { git = "https://github.com/octos-org/octos.git", rev = "18fcd3f16e527d2b601d7ae244f056fb711bb6b8" }

# pdfcraft's bootstrap PDF stack: its workspace patches these five
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ English | [简体中文](README.zh-CN.md)

[Host OS API status](docs/host-os-api-status.md) tracks file, location and external-link support, existing services, remaining gaps and validation limits.

[Capabilities and execution boundaries](docs/capabilities.md) explains declaration-only APIs, consent, accounts and app isolation.

**Desktop download:** [OctoSense 0.1.0-rc.2](https://github.com/OctoSense-org/OctoSense/releases/tag/desktop-v0.1.0-rc.2) supports the current App Hub catalog, GitHub-attested app releases and the public host APIs declared by SDK 1.10.0. Choose the asset for your operating system and architecture; the release notes record prerequisites, signing status and platform validation. This desktop release does not update Android Home.

Run the [live Mail → card → Calendar demo](docs/demos/mail-calendar/README.md) with your own mailbox: pinned source, selective policy, fictional test inputs, human draft edits and Calendar navigation.
Expand Down
2 changes: 2 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

[宿主 OS API 状态](docs/host-os-api-status.zh-CN.md)记录文件、定位和外部链接支持,以及已有服务、剩余缺口和验证范围。

[能力声明与执行边界](docs/capabilities.zh-CN.md)说明声明式 API、用户同意、账户和应用隔离。

**桌面版下载**:[OctoSense 0.1.0-rc.2](https://github.com/OctoSense-org/OctoSense/releases/tag/desktop-v0.1.0-rc.2) 支持当前的 App Hub 签名目录、带 GitHub 证明的应用 Release 及 SDK 1.10.0 声明的公开宿主 API。请选择与操作系统和架构对应的文件;运行前置条件、签名状态和各平台验收范围见发行说明。此桌面版本不会更新 Android Home。

用自己的邮箱[复现真实邮件 → 卡片 → Calendar 演示](docs/demos/mail-calendar/README.zh-CN.md):固定源码版本、重要邮件策略、虚构测试输入、人工修改草稿和日历跳转。
Expand Down
38 changes: 23 additions & 15 deletions apps/ai-providers/host-service/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# octosense-llm-service: the `llm` host service

English | [简体中文](README.zh-CN.md)

The AI providers app (`os.ai-providers`, [../bundle](../bundle)) edits the
LLM providers the AppCard assistant runs on, through this service. The app
never sees a key, a PIN or a QR: keys are typed on a host-owned sheet, the
Expand Down Expand Up @@ -219,24 +221,22 @@ unreadable to the kernel. A key the keychain refuses also stays in the profile.

## Tests

From `apps/ai-providers`:
From the repository root, after `python3 tools/setup.py`:

```sh
cargo test --workspace
cargo test --locked -p octosense-llm-config -p octosense-llm-service
cargo test --locked -p octosense-llm-service --features octos-core
```

The workspace resolves Makepad, Octoscript-Makepad and Octoscript from
checkouts beside this repository (`../makepad` and so on, as the shells do),
and the makepad one must carry the contained-app runtime the shells build with
(splash host requests and sheets). To use another checkout without editing
the manifest, pass a `--config` file with `[patch."https://github.com/OctoSense-org/makepad.git"]`
entries pointing at it. The macOS keychain test runs only when asked:
`cargo test -p octosense-llm-service -- --ignored keychain`.
The root workspace pins Makepad, Octoscript-Makepad and Octoscript once;
setup prepares their `.sources/` worktrees. Do not add local source patches.
The macOS keychain test runs only when explicitly requested:
`cargo test --locked -p octosense-llm-service -- --ignored keychain`.

## The `model` service (`model.complete`)

The same crate offers a second family, `model` ([src/complete](src/complete)):
contained apps granted the `model` capability make a direct, one-shot,
admitted contained apps make a direct, one-shot,
schema-checked call to the person's providers (OctoSense ADR 0002, "Direct
one-shot model calls"). The app names a model class (`fast` or `strong`), a
task, an input and a JSON Schema; the host picks the provider in the
Expand All @@ -247,11 +247,19 @@ charges a per-app daily budget (defaults: 6 calls a minute, 100 calls and
never sees the provider, the model id or the key. The method table and the
error codes are in [src/complete/mod.rs](src/complete/mod.rs).

`crates/ai-host` registers it with the `llm` service:

```rust
octosense_llm_service::register_model(&options, octosense_llm_service::complete::Options::default());
```
The shell registers it through [`crates/ai-host`](../../../crates/ai-host).
Capability declarations describe usage: an app can call `model.complete`
without listing `model`. The host must supply `complete::Options::grants`
with a verified app-identity and exact host-directory check. Missing admission
fails closed; reading an app-provided manifest is not sufficient. The shell
also supplies an active account lookup. An account app that is signed out
gets no device-scope fallback; changing accounts invalidates pending results.

Direct `model` calls do not create a persistent app agent. An agent needs
separate opt-in and user consent. Model workers retain request/schema limits,
per-app budgets, concurrency bounds and cancellation checks, and recheck
admission and account state before delivery. The stable `capability` error
code now reports denied caller admission, not a missing declaration.

Tests use a fake transport: `cargo test --locked -p octosense-llm-service --test complete`.
A live check against DeepSeek (costs a fraction of a cent):
Expand Down
85 changes: 85 additions & 0 deletions apps/ai-providers/host-service/README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# octosense-llm-service:`llm` 和 `model` 宿主服务

[English](README.md) | 简体中文

AI providers 系统应用 `os.ai-providers` 通过 `llm` 服务配置 Shell 共用的模型供应商。普通应用通过 `model` 进行一次性的结构化模型调用;持久应用 Agent 则通过 `ai-host` 和 `app-peers` 使用同一个内核。这三个接口承担不同职责。

密钥、PIN 和供应商二维码由宿主界面处理,脚本应用不会得到这些秘密。方法定义见 [src/lib.rs](src/lib.rs) 和 [src/complete/mod.rs](src/complete/mod.rs)。

## 供应商配置

模型目录来自 `octosense_llm_config::catalog`。`llm.families` 和 `llm.models` 为选择器提供模型名称、上下文窗口和价格。宿主设置向导依次选择模型家族、模型、服务地址和协议、API 密钥,然后测试并保存。测试失败时可以明确选择不测试直接保存。

官方路线不保存单独的 route 对象;自定义路线保存 octos 识别的 `route_id`、`label`、`base_url` 和 `api_key_env`。模型调用按照用户设置的主供应商和备用顺序执行。

Shell 先配置唯一的 `octosense-kernel`,再注册服务。启用 `octos-core` 时,服务写入同一个内核目录的 `profiles/_main.json`,供应商变更后重启内核,消费者随后重新连接。没有该 feature 时服务只更新配置。

Shell 通常通过 [`crates/ai-host`](../../../crates/ai-host) 完成注册。`Options` 可设置:

| 配置 | 作用 |
| --- | --- |
| `core_dir` | 内核使用的配置目录 |
| `vault` | 平台秘密存储;测试可使用隔离实现 |
| `scanner` | 手机摄像头扫描,桌面可不提供 |
| `image_picker` | 从系统文件或照片选择器导入二维码图片 |
| `image_drops` | 桌面将拖放的图片交给服务 |
| `on_changed` | 保存、排序、删除、导入后的回调;内核重启后触发,可能在工作线程运行 |

`llm` 属于宿主的供应商管理接口,仍仅服务系统应用。删除普通应用的能力声明检查,不会让商店应用读取或配置用户的供应商密钥。

## 扫码、图片与导入

`QrScanner`、`QrImagePicker` 是 Shell 提供的适配器。服务本身不链接 Makepad。Shell 在 UI 线程打开扫描器或系统选择器,完成回调必须恰好调用一次;取消保留原界面,失败显示原因。

图片以原始 PNG/JPEG 字节传给服务,在工作线程中解码和查找二维码。解码前拒绝超过 20 MB 或 4000 万像素的图片。识别尝试原图、二值化和缩放副本;成功后在宿主界面输入 PIN。桌面拖放同样进入此流程,不将文件直接交给脚本 isolate。

导出界面展示 `OCTOS1E:` 代码及 PIN,最长五分钟;关闭或到期后清除。测试可以缩短有效期,不能延长。界面使用单次定时器,避免切换 Splash 内容后旧的重复定时器继续运行。

导入只增加或更新,不删除已有供应商,也不改变已有顺序:

- 没有现有配置时,代码中的第一项成为主供应商。
- 已有相同模型和路线时,保留位置并更新密钥。
- 新路线追加为备用;不同密钥使用独立 `api_key_env` 槽,避免覆盖另一条路线。
- 重复导入相同代码不产生变化;删除供应商时,仅在没有其他路线引用其槽时才删除该槽。

界面显示已添加、已更新或已存在的结果,不将密钥展示给应用。

## 密钥存储

| 平台 | 保存位置 | profile 中的值 |
| --- | --- | --- |
| macOS | 登录钥匙串,服务 `octos`,账号为环境变量名 | `keychain:` |
| Linux | `<core_dir>/secrets/<ENV>`,权限 0600 | `keychain:` |
| Android、iOS 等 | 应用私有 profile,权限 0600 | 密钥本身 |
| 开发覆盖 `OCTOSENSE_LLM_VAULT=file` | profile | 密钥本身 |

Android 内核从 profile 的 `env_vars` 读取密钥,因此不能直接使用它无法解密的 Android Keystore 密文。平台钥匙串拒绝写入时,密钥仍保存在私有 profile。这是当前实现边界;不能把脚本应用不能读取密钥误写为所有平台都使用硬件加密存储。

## 一次性 `model` 调用

`model.complete` 接受任务、输入、JSON Schema,以及可选的 `fast`/`strong` 模型类别和 URL 输出选项。宿主选择供应商,校验返回 JSON,不合格时重试一次。应用不指定供应商或密钥,不建立工具调用、浏览、记忆或持久对话。

主要限制包括:任务 4 KiB、应用输入 32 KiB、结构化输出 16 KiB;默认每个应用每分钟 6 次、每天 100 次和 100,000 tokens。账本保存在 `<host dir>/model/ledger.json`。`model.budget` 返回调用应用的预算。工具箱的模型调用也共用这条预算路径。

`capabilities` 是使用说明,省略 `model` 不阻止调用。授权仍由宿主完成:

- Shell 必须通过 `complete::Options::grants` 验证已准入应用、bundle 身份和精确宿主目录。没有回调时拒绝;直接读取应用写入的 manifest 不能授权。
- Shell 提供当前账号范围。有账号功能的应用未登录时,不会回退到设备范围;账号切换使旧结果失效。
- 工作线程保持并发、大小、速率和预算限制,并在回复前再次检查准入、账号与取消状态。
- 错误码 `capability` 为兼容保持不变,但现在表示宿主未准入该调用方,而不是缺少能力声明。

直接调用 `model` 不会自动启用持久 Agent。应用 Agent 另有启用意图和用户同意,跨应用工具仍需要共享授权和审批。

## 验证

在仓库根目录运行 `python3 tools/setup.py`,然后:

```sh
cargo test --locked -p octosense-llm-config -p octosense-llm-service
cargo test --locked -p octosense-llm-service --features octos-core
cargo test --locked -p octosense-llm-service --test complete
```

模型测试使用假传输,覆盖省略能力声明后的调用、缺少宿主准入时拒绝、输出校验、预算和取消。媒体测试还检查账号切换、准入撤销、并发限制及迟到回复。这些测试不验证真实模型供应商或手机。

真实供应商示例 `model_complete_live` 会产生真实请求和费用,只有明确进行该项验收时才运行。macOS 钥匙串测试也默认忽略,需显式选择 `-- --ignored keychain`。仓库只使用根目录统一固定的依赖及 `.sources/`,不增加个人机器路径或本地 patch。
Loading
Loading