Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1e6a5a3
docs: propose composable Mail action cards in ADR 0007
ymote Oct 4, 2026
e2b8742
feat(mail): compose durable reply cards with contextual chat and host…
ymote Oct 4, 2026
a7b313a
fix(mail): refresh composed cards and open bound replies from phone g…
ymote Oct 4, 2026
a4ce10e
fix(phone): activate card notification banners on touch release
ymote Oct 4, 2026
ef3f99a
fix(mail): keep contextual card chat concise and plain text
ymote Oct 4, 2026
3b02a1f
docs: record paired-model Mail card validation and remaining gates
ymote Oct 4, 2026
1369bc1
chore(runtime): synchronize formatting-only Mail capability pins
ymote Oct 4, 2026
d54d347
fix(shell): keep glance cards and focused composers visible
ymote Oct 4, 2026
701443e
fix(phone): scroll Glance cards with vertical touch drags
ymote Oct 4, 2026
d031362
feat(shell): open phone cards in a focused workspace with native chat
ymote Oct 4, 2026
66e5e45
feat(mail): share one saved reply across native chat and editing
ymote Oct 4, 2026
09f3a91
fix(mail): group workspace navigation with bottom actions
ymote Oct 4, 2026
bf788e0
fix(glance): expand compact summaries into inline mail workspaces
ymote Oct 5, 2026
97914db
feat(glance): promote cards into resident full-screen workspaces
ymote Oct 5, 2026
7c50ebd
fix(mail): restore workspace colors after theme refresh
ymote Oct 5, 2026
06cc351
feat(glance): share retained card workspaces and contextual app chat
ymote Oct 5, 2026
8dd8f66
docs: reconcile shared card workspaces with the current architecture …
ymote Oct 5, 2026
8e3112f
docs: correct Calendar availability and legacy card behavior
ymote Oct 5, 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
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ Start with the [architecture walkthrough](docs/architecture-walkthrough.md) and
- For a new tool, update its manifest, `tools.json`, admission offer, caller grant and executable handler. Show which host service or workspace owns its data and how approval reaches the router.
- Read external code at the Cargo/runtime pins. Use current `desktop/`, `phone/`, `rom/` and `apps/` paths when writing product instructions.
- Record test execution in the PR: distinguish unit/scripted connectors from optional real-kernel tests that return early without a binary. Mark unrun launch/device recipes unverified.

For shared Glance workspaces, preserve original publication accounts and model-authored source. Native fallback chat is only for declared app agents and uses `ContextKind::Card`; Mail draft-edit leases require `ContextKind::Mail`. Exercise local state and unsent input across more than three inactive workspaces. Developer `glance-fixtures:<path>` actions must retain normal app grants; `test.*` native prototypes have no app capabilities or agent. Test fixture rendering/local actions separately from actual model calls and external business effects.
16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ makepad-strict-json = { git = "https://github.com/OctoSense-org/makepad.git", re
makepad-app-module = { git = "https://github.com/OctoSense-org/makepad.git", rev = "c155f61d0e1600d2ec474209374444a38a09a470" }
makepad-wm-theme = { git = "https://github.com/OctoSense-org/makepad.git", rev = "c155f61d0e1600d2ec474209374444a38a09a470" }
makepad-aichat = { git = "https://github.com/OctoSense-org/makepad.git", rev = "c155f61d0e1600d2ec474209374444a38a09a470", default-features = false }
# --- OctoScript (Octoscript 5991dfae) and its Makepad runtime
# (Octoscript-Makepad 2cc5ef37, native-runtime.lock.json).
octoscript-ui-l0 = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "5991dfae9344589e732b2605b530f788e8bbcd11" }
# --- OctoScript (Octoscript 2e37d9e6) and its Makepad runtime
# (Octoscript-Makepad 27e9c1bf, native-runtime.lock.json).
octoscript-ui-l0 = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "2e37d9e657a246f16718d9a475e167ccd2d5b5fa" }
# The bounded VM, capability-leased host modules and executable JSON schemas
# (the system toolbox's workflow templates, crates/toolbox).
octoscript-core = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "5991dfae9344589e732b2605b530f788e8bbcd11" }
octoscript-capabilities = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "5991dfae9344589e732b2605b530f788e8bbcd11" }
octoscript-schema = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "5991dfae9344589e732b2605b530f788e8bbcd11" }
octoscript-makepad = { git = "https://github.com/OctoSense-org/Octoscript-Makepad.git", rev = "2cc5ef37d7d6a3d2992673389ce74488f7bb2d87" }
octoscript-node = { git = "https://github.com/OctoSense-org/Octoscript-Makepad.git", rev = "2cc5ef37d7d6a3d2992673389ce74488f7bb2d87" }
octoscript-core = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "2e37d9e657a246f16718d9a475e167ccd2d5b5fa" }
octoscript-capabilities = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "2e37d9e657a246f16718d9a475e167ccd2d5b5fa" }
octoscript-schema = { git = "https://github.com/OctoSense-org/Octoscript.git", rev = "2e37d9e657a246f16718d9a475e167ccd2d5b5fa" }
octoscript-makepad = { git = "https://github.com/OctoSense-org/Octoscript-Makepad.git", rev = "27e9c1bfdbf6021bcad87214ae4ebbe6d683b406" }
octoscript-node = { git = "https://github.com/OctoSense-org/Octoscript-Makepad.git", rev = "27e9c1bfdbf6021bcad87214ae4ebbe6d683b406" }
# --- 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 = "0d5b47a2ae9eb98020feca26b7c895a3cf797dc1" }
Expand Down
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ These apps have an agent:
| Terminal (desktop) | native, its own process | `terminal.read_screen`, `terminal.read_scrollback` | `terminal.run`, behind Setup's switch, approved per command |
| Calculator, Clock, Notes, Reminders, Weather | native, in the shell | each app's read tools | the same read tools |
| Mail | script app | `mail.*` tools scoped to the signed-in account, including `mail.publish_card` | – |
| Calendar (desktop) | script app | `calendar.events`, `calendar.add_event`, `calendar.remove_event` (asks first), `calendar.notify`, `calendar.agenda` | – |
| Calendar | script app | `calendar.events`, `calendar.add_event`, `calendar.remove_event` (asks first), `calendar.notify`, `calendar.agenda` | – |
| News | script app | `news.list`, `news.read`, `news.notify` | – |
| Photos, Maps, YouTube; Camera on phones | script apps | `<app>.notify` | – |

Expand Down Expand Up @@ -160,6 +160,8 @@ The `<app>.notify` tools fill a fixed card template ([`notice.card`](crates/shel

Mail's agent can also start on its own. Once the person has signed in, allowed Mail's agent and asked the system agent to turn on new-mail processing (`agents.provision`), a host worker syncs the inbox and starts the agent for each new message. The agent reads the message with its scoped tools and decides whether to post a card. No other app has events yet; the [Mail event walkthrough](docs/mail-agent-events.md) has the details.

On Android, tapping a card notification opens its exact expanded card. A stale notification falls back to Glance.

### One app agent, two lanes

The system agent and the person talk to the same app agent, each in a lane of their own:
Expand Down Expand Up @@ -204,7 +206,7 @@ The person can talk to any app's agent directly. These turns run in the person's
| Where | How |
| --- | --- |
| **"Ask &lt;app&gt;"** panel | A shell panel for every app with an agent, opened from the bar's "Ask &lt;app&gt;" button or with Shift+F8. On the desktop it opens beside the system chat. The phone draws it full screen but has no touch control for it yet. |
| **In-card chat** | Type in a glance card that declares a chat ([below](#in-card-chat)). |
| **In-card chat** | Open Chat in an agent-enabled card workspace, or type in a card that declares `sys.chat` ([below](#in-card-chat)). |
| **The app's own UI** | An app can open the person's lane itself ([next section](#how-an-app-uses-its-agent)). Rinx draws its own assistant UI; for the other apps, the "Ask &lt;app&gt;" panel is the way in. |

The panel asks for consent first and shows both lanes, each message with its speaker. Its Stop button ends only the person's own turn. [docs/architecture.md §2](docs/architecture.md#2-agents) covers the rest of its behavior.
Expand Down Expand Up @@ -299,7 +301,7 @@ sequenceDiagram
</details>

- **The relay** ([`crates/shell/src/host_tools/`](crates/shell/src/host_tools/)) receives every `peer/tool/call`. It checks that this caller may use this tool, validates the arguments against the tool's schema and charges the caller's budget (by default 32 tool calls a turn and 1000 a day). Only then does it run the tool in the app that owns it: a native app's open window, a script app's host service, or a process app over its peer link. It checks the result against the schema too.
- **The approval router** ([`crates/shell/src/approvals/`](crates/shell/src/approvals/)) decides in a fixed order. Developer mode, which only the person can turn on, approves everything for the apps it covers. A `confirm: app` tool goes to the app's own sheet. Calls that must always ask, such as a Terminal command, go straight to a sheet. Everything else may be decided by the person's standing rules, and otherwise a shell sheet shows the exact arguments. Every decision is written to an audit log. [The walkthrough](docs/architecture-walkthrough.md#approval-order) gives the full order.
- **The approval router** ([`crates/shell/src/approvals/`](crates/shell/src/approvals/)) decides in a fixed order. Developer mode, which only the person can turn on, approves routed calls for the apps it covers. Mail sending still requires its separate host-owned review and physical approval; developer mode and standing rules cannot authorize it. A `confirm: app` tool goes to the app's own sheet. Calls that must always ask, such as a Terminal command, go straight to a sheet. Everything else may be decided by the person's standing rules, and otherwise a shell sheet shows the exact arguments. Every decision is written to an audit log. [The walkthrough](docs/architecture-walkthrough.md#approval-order) gives the full order.
- **Deadlines.** An approval or question nobody answers in 10 minutes is denied, never approved. If the turn is still running 30 seconds later, the shell interrupts it so the next turn can start.

### Cards and questions
Expand All @@ -308,7 +310,11 @@ An app with the `glance` permission publishes cards as itself (`glance.publish`,

#### In-card chat

A card can declare `sys.chat(app, thread, fields)`. The person types in the card, and only the publishing app's own agent answers, in the person's lane. The shell owns the transcript, kept in the app's account folder, and records as the person's only what the person typed. Model-written text is marked as AI-written and never runs as an action. No agent-published card declares a chat yet; the demo card [`mail-request.card`](crates/shell/resources/glance/mail-request.card) shows one with canned replies. See [`crates/l0-chat`](crates/l0-chat/README.md).
On the phone, a compact Glance summary expands into a resident full-screen workspace. An agent-enabled publisher gets **Card / Chat** even without an embedded `sys.chat`; the host binds the conversation to the original publication account and supplies bounded card data and local L0 state. The generated source stays unchanged. Local selections are context, not proof of a completed external action; chat uses only the app's existing tools and consent. Cards without an agent have no Chat tab.

A Mail reply card published with a host-issued `draft_id` uses **Email / Chat**, sharing one saved draft. Requested chat edits save through a revision-bound capability, and final review reads the exact saved recipient, subject and body. Only trusted physical Android touch can approve sending, including in developer mode. Desktop/accessibility send approval remains deferred. See [Composed Mail cards](docs/mail-composable-cards.md) for the DeepSeek/MiniMax phone results, formatting failure/retry and remaining UX limits.

An explicit `sys.chat(app, thread, fields)` keeps its declared thread. The host owns the transcript in the app's account folder; only what the person typed is recorded as theirs. The older [`mail-request.card`](crates/shell/resources/glance/mail-request.card) under `OCTOSENSE_GLANCE_DEMO=mail` still answers with canned text. See [`crates/l0-chat`](crates/l0-chat/README.md) and [`glance_chat.rs`](crates/shell/src/glance_chat.rs).

#### Questions

Expand Down
14 changes: 10 additions & 4 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ flowchart LR
| Terminal(桌面端) | 原生,独立进程 | `terminal.read_screen`、`terminal.read_scrollback` | `terminal.run`,受 Setup 开关控制,每条命令都要批准 |
| Calculator、Clock、Notes、Reminders、Weather | 原生,在 Shell 内 | 各自的只读工具 | 同样的只读工具 |
| 邮件 | 脚本应用 | 绑定当前登录账号的 `mail.*` 工具,包括 `mail.publish_card` | – |
| 日历(桌面端) | 脚本应用 | `calendar.events`、`calendar.add_event`、`calendar.remove_event`(先问用户)、`calendar.notify`、`calendar.agenda` | – |
| 日历 | 脚本应用 | `calendar.events`、`calendar.add_event`、`calendar.remove_event`(先问用户)、`calendar.notify`、`calendar.agenda` | – |
| 新闻 | 脚本应用 | `news.list`、`news.read`、`news.notify` | – |
| 相册、地图、YouTube;手机上的相机 | 脚本应用 | `<app>.notify` | – |

Expand Down Expand Up @@ -160,6 +160,8 @@ sequenceDiagram

邮件的 Agent 也可以自己启动。用户登录、允许邮件的 Agent,并请系统 Agent 打开新邮件处理(`agents.provision`)之后,宿主会在后台同步收件箱,每来一封新邮件就启动一次 Agent。Agent 用绑定账号的工具读取邮件,自己判断要不要发卡片。其他应用还没有事件;详见[邮件事件导读](docs/mail-agent-events.zh-CN.md)。

在 Android 上点击卡片通知会打开准确对应的展开卡片;过期通知回退到 Glance。

### 一个应用 Agent,两条通道

系统 Agent 和用户与同一个应用 Agent 对话,但各走各的通道:
Expand Down Expand Up @@ -204,7 +206,7 @@ flowchart TB
| 入口 | 怎么用 |
| --- | --- |
| **“Ask &lt;app&gt;”** 面板 | Shell 为每个有 Agent 的应用提供的面板,从顶栏的 “Ask &lt;app&gt;” 按钮或按 Shift+F8 打开。桌面端上它出现在系统对话旁边。手机上它全屏显示,但还没有可以打开它的触控入口。 |
| **卡内对话** | 在声明了对话的 glance 卡片里输入([见下文](#卡内对话))。 |
| **卡内对话** | 在有 Agent 的卡片工作区打开 Chat,或在显式声明 `sys.chat` 的卡片里输入([见下文](#卡内对话))。 |
| **应用自己的界面** | 应用可以自己打开用户的通道([见下一节](#应用如何使用自己的-agent))。Rinx 绘制自己的助手界面;其他应用通过 “Ask &lt;app&gt;” 面板进入。 |

面板会先征得同意,然后显示两条通道,每条消息都标明说话者。面板上的“停止”只结束用户自己的回合。面板的其他行为见 [docs/architecture.zh-CN.md 第 2 节](docs/architecture.zh-CN.md#2-agent)。
Expand Down Expand Up @@ -299,7 +301,7 @@ sequenceDiagram
</details>

- **中转**([`crates/shell/src/host_tools/`](crates/shell/src/host_tools/))接收每一个 `peer/tool/call`。它先检查这个调用方能否使用这个工具,按工具的 schema 校验参数,并从调用方的预算中扣除(默认每轮 32 次、每天 1000 次工具调用);之后才在拥有该工具的应用中运行它:原生应用已打开的窗口、脚本应用的宿主服务,或经 peer link 交给进程应用。结果同样要按 schema 检查。
- **审批路由**([`crates/shell/src/approvals/`](crates/shell/src/approvals/))按固定顺序做决定。开发者模式只能由用户打开,它会批准所覆盖应用的一切调用。`confirm: app` 的工具交给应用自己的面板。必须每次都问的调用(例如 Terminal 的命令)直接弹出面板。其余调用可以由用户的常设规则决定,否则由 Shell 面板展示确切参数,请用户确认。每个决定都会写入审计日志。完整顺序见[导读](docs/architecture-walkthrough.zh-CN.md#审批顺序)。
- **审批路由**([`crates/shell/src/approvals/`](crates/shell/src/approvals/))按固定顺序做决定。开发者模式只能由用户打开,它会批准所覆盖应用经路由处理的调用。邮件发送仍要求独立的宿主审核和实体批准;开发者模式和常设规则不能授权发送。`confirm: app` 的工具交给应用自己的面板。必须每次都问的调用(例如 Terminal 的命令)直接弹出面板。其余调用可以由用户的常设规则决定,否则由 Shell 面板展示确切参数,请用户确认。每个决定都会写入审计日志。完整顺序见[导读](docs/architecture-walkthrough.zh-CN.md#审批顺序)。
- **时限。** 10 分钟内无人回答的审批或提问会被拒绝,绝不会被批准。如果 30 秒后这一轮仍在运行,Shell 会中断它,好让下一轮开始。

### 卡片与提问
Expand All @@ -308,7 +310,11 @@ sequenceDiagram

#### 卡内对话

卡片可以声明 `sys.chat(app, thread, fields)`。用户在卡片里输入,只有发布卡片的应用自己的 Agent 回答,回答在用户的通道里进行。对话记录归 Shell 所有,保存在应用的账号文件夹中;只有用户亲手输入的内容才记为用户的话。模型写的文字会标为 AI 撰写,且从不作为操作执行。目前还没有 Agent 发布的卡片声明对话;演示卡片 [`mail-request.card`](crates/shell/resources/glance/mail-request.card) 用固定的回复展示了这一功能。详见 [`crates/l0-chat`](crates/l0-chat/README.md)。
在手机上,紧凑的 Glance 摘要展开为驻留的全屏工作区。有 Agent 的发布者即使没有内嵌 `sys.chat`,也会获得 **Card / Chat**;宿主把会话绑定到发布时的账户,并提供有大小限制的卡片数据和 L0 本地状态。生成源码保持不变。本地选项是上下文,不代表外部操作已经完成;聊天只使用应用已有的工具和同意权限。没有 Agent 的卡片不显示 Chat 页签。

携带宿主签发 `draft_id` 的 Mail 回复卡片使用 **Email / Chat**,共用一份已保存草稿。用户要求的聊天修改通过绑定修订号的凭证保存,最终审核读取确切的已保存收件人、主题和正文。即使在开发者模式,发送仍只能由可信 Android 实体触摸批准;桌面/无障碍发送审批暂缓。DeepSeek/MiniMax 实机结果、格式失败及重试、剩余 UX 限制见[组合 Mail 卡片](docs/mail-composable-cards.zh-CN.md)。

显式 `sys.chat(app, thread, fields)` 保留声明的线程。对话记录由宿主保存在应用账户文件夹中,只有用户亲手输入的内容才记为用户的话。旧的 [`mail-request.card`](crates/shell/resources/glance/mail-request.card) 在 `OCTOSENSE_GLANCE_DEMO=mail` 下仍使用固定回答。详见 [`crates/l0-chat`](crates/l0-chat/README.zh-CN.md) 和 [`glance_chat.rs`](crates/shell/src/glance_chat.rs)。

#### 提问

Expand Down
Loading
Loading