diff --git a/README.md b/README.md index e1e5364a..d180c55e 100644 --- a/README.md +++ b/README.md @@ -330,7 +330,7 @@ A phone runs the shell, the kernel, up to a dozen app agents and their apps at t - **Threads per service, not per turn.** Turns are Tokio tasks. In the shell, the kernel service runs on one two-worker Tokio runtime, each live agent's broker on a one-thread runtime of its own (so a slow agent cannot stall another agent or the UI), and the system chat on one thread that wakes the UI through Makepad's `SignalToUI` only when something changed. The octos child process (desktop and Android) uses Tokio's default runtime, one worker per CPU core. - **Started on demand, stopped when idle.** The kernel starts on its first connection: at startup if the person has already allowed a script app's agent, otherwise when an agent or the system chat first needs it. The system chat connects only while its pane is open or a turn is running. With Talk to Octos off, the kernel stops when its last connection closes. An app with no granted agent gets no broker and no peer. - **Apps share the shell process.** Script apps are isolates in one Card runner and native apps are modules, so most apps cost no process of their own. A script error stays inside its isolate, and a native module's panic is caught at the module boundary. Only an app declared as its own process (the Terminal, for its OS sandbox, and Task, which has no module) runs as one, where its binary is available. -- **Zero-copy frames for process apps.** The Terminal's frames reach the shell as shared GPU surfaces: IOSurface on macOS, D3D11 shared handles on Windows, DMA_BUF on Linux with Vulkan. Where only a CPU copy would work (Linux with OpenGL), every app runs inside the shell instead. +- **Zero-copy frames for process apps.** The Terminal's frames reach the shell as shared GPU surfaces: IOSurface on macOS, D3D11 shared handles on Windows, DMA_BUF on Linux. On Linux the shell starts the Terminal as a process only in a Vulkan build in a Wayland session, and runs it inside the shell otherwise. Task has no module, so it runs as a process on Linux either way; where the GL driver cannot export a DMA_BUF, its frames are copied. ## Layout diff --git a/README.zh-CN.md b/README.zh-CN.md index 621bbea3..53c2ebf7 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -330,7 +330,7 @@ Agent 的 `ask_user_question` 出现在这一轮的来处:用户和应用自 - **线程按服务分配,而不是按回合。** 回合是 Tokio 任务。在 Shell 中,内核服务运行在一个有两个工作线程的 Tokio 运行时上,每个活跃应用 Agent 的代理有自己的单线程运行时(所以一个慢吞吞的 Agent 拖不住别的 Agent,也拖不住界面),系统对话则用一个线程,只在有变化时才通过 Makepad 的 `SignalToUI` 唤醒界面。octos 子进程(桌面端和 Android)使用 Tokio 的默认运行时,每个 CPU 核心一个工作线程。 - **按需启动,空闲即停。** 内核在第一个连接到来时启动:如果用户已经允许过某个脚本应用的 Agent,就在 Shell 启动时;否则在某个 Agent 或系统对话第一次需要它时。系统对话只在面板打开或有回合运行时才保持连接。Talk to Octos 关闭时,最后一个连接断开,内核就停止。没有获准 Agent 的应用既没有代理,也没有 peer。 - **应用共享 Shell 进程。** 脚本应用是同一个 Card runner 中的隔离环境,原生应用是模块,所以大多数应用不单独占用进程。脚本出错只影响它自己的隔离环境,原生模块的 panic 在模块边界被捕获。只有声明为独立进程的应用(为了系统沙箱的 Terminal,以及没有模块的 Task)才作为进程运行,前提是有它的二进制。 -- **进程应用的画面零拷贝。** Terminal 的画面以共享 GPU 表面的形式到达 Shell:macOS 上是 IOSurface,Windows 上是 D3D11 共享句柄,Linux 配 Vulkan 时是 DMA_BUF。在只能靠 CPU 拷贝的环境(Linux 配 OpenGL)中,所有应用都改在 Shell 内运行。 +- **进程应用的画面零拷贝。** Terminal 的画面以共享 GPU 表面的形式到达 Shell:macOS 上是 IOSurface,Windows 上是 D3D11 共享句柄,Linux 上是 DMA_BUF。在 Linux 上,Shell 只在 Vulkan 构建且处于 Wayland 会话时把 Terminal 作为进程启动,否则在 Shell 内运行它。Task 没有模块,所以在 Linux 上总是作为进程运行;GL 驱动无法导出 DMA_BUF 时,它的画面经 CPU 拷贝送到 Shell。 ## 目录结构 diff --git a/desktop/README.md b/desktop/README.md index 9d2be9a2..0ced740c 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -94,7 +94,7 @@ The native apps' features (`app-hub`, `app-rinx`, `app-reference`, `app-sheets`, | `app-rinx` | on | Links [Rinx](https://github.com/hagency-org/Rinx), the Matrix client, as a module; implies `octos-core` (its assistant is the shell's). | | `app-reference` | off | Links Reference (`../apps/reference`) as a module. | | `app-sheets` | off | Links Makepad's Sheets as a module. | -| `app-terminal` | on | Links Makepad's Terminal as a system app: a login shell in a tile. On macOS and Windows it runs as its own process (`terminal`, built from the pinned Makepad checkout with `cargo run`, else the binary beside `octosense`), so a crash in it leaves the shell running; on Linux only with a Vulkan build in a Wayland session. Where it cannot start a process (no checkout and no binary: release packages do not ship it yet, [#94](https://github.com/OctoSense-org/OctoSense/pull/94)) it opens in-process, as it does on phones; a `terminal: Module` or `terminal: Process` line in `wm/apps.splash` under the state directory overrides that. In either hosting the assistant gets the same tools (ADR 0004 §10): it reads (`read_screen`, `read_scrollback`) and may type a command (`run`), and every command waits for the person's live confirmation on the assistant's confirm card (`confirm: host`, `auto_approvable: false` in `native-apps.json`); a command too long for the card to show in full is refused. In-process on macOS, the shell's PTY helper is `octosense` itself. | +| `app-terminal` | on | Links Makepad's Terminal as a system app: a login shell in a tile. On macOS and Windows it runs as its own process (`terminal`, which the shell builds from the OctoSense checkout with `cargo build` and starts itself, else the binary beside `octosense`), so a crash in it leaves the shell running; on Linux only with a Vulkan build in a Wayland session. Where it cannot start a process (no checkout and no binary: release packages ship only `octosense` and the kernel) it opens in-process; a `terminal: Module` or `terminal: Process` line in `wm/apps.splash` under the state directory overrides that. The AI pane can read it in either hosting (`read_screen`, `read_scrollback`), but it can type a command (`run`) only when the Terminal runs as its own process; in-process, the Terminal offers its read tools only (ADR 0004 §10). Outside developer mode, each command waits for the person's approval on a host sheet (`confirm: host`, `auto_approvable: false` in `native-apps.json`), and a command over 4 KiB is refused. In-process on macOS, the shell's PTY helper is `octosense` itself. | | `app-appcard` | off | Links the AppCard assistant module (`../apps/appcard/module`); implies `octos-core`. Opt-in on every target, phones included; not shipped for now. | | `app-aichat` | off | Links Makepad's AI chat as a module, without its model engine. | | `mobile-apps` | off | `app-rinx` + `app-reference` + `app-sheets` + `app-hub` + `octos-core`: the set phone builds link, for testing on desktop. Not AppCard. | diff --git a/desktop/README.zh-CN.md b/desktop/README.zh-CN.md index a29ef3fb..21f05456 100644 --- a/desktop/README.zh-CN.md +++ b/desktop/README.zh-CN.md @@ -94,7 +94,7 @@ cargo run --release -p octosense | `app-rinx` | 开 | 以模块形式链接 Matrix 客户端 [Rinx](https://github.com/hagency-org/Rinx);隐含 `octos-core`(它的助手就是 Shell 的助手)。 | | `app-reference` | 关 | 以模块形式链接 Reference(`../apps/reference`)。 | | `app-sheets` | 关 | 以模块形式链接 Makepad 的 Sheets。 | -| `app-terminal` | 开 | 以系统应用形式链接 Makepad 的 Terminal:在磁贴中运行的登录 Shell。在 macOS 和 Windows 上它作为独立进程运行(`terminal`,从固定版本的 Makepad 检出中用 `cargo run` 构建,否则使用 `octosense` 旁边的二进制文件),因此它崩溃不会影响 Shell;在 Linux 上只有 Vulkan 构建且处于 Wayland 会话时才如此。无法启动进程时(没有检出也没有二进制文件:发布包目前还不附带它,见 [#94](https://github.com/OctoSense-org/OctoSense/pull/94)),它在进程内打开,与手机上相同;在状态目录下的 `wm/apps.splash` 中写一行 `terminal: Module` 或 `terminal: Process` 可覆盖默认值。无论哪种托管方式,助手获得的工具都相同(ADR 0004 §10):它可以读取(`read_screen`、`read_scrollback`),也可以输入命令(`run`),每条命令都要等待用户在助手的确认卡片上实时确认(`native-apps.json` 中为 `confirm: host`、`auto_approvable: false`);确认卡片无法完整显示的过长命令会被拒绝。在 macOS 上进程内运行时,Shell 的 PTY 辅助程序就是 `octosense` 本身。 | +| `app-terminal` | 开 | 以系统应用形式链接 Makepad 的 Terminal:在磁贴中运行的登录 Shell。在 macOS 和 Windows 上它作为独立进程运行(`terminal`,由 Shell 在 OctoSense 检出中用 `cargo build` 构建后自己启动,否则使用 `octosense` 旁边的二进制文件),因此它崩溃不会影响 Shell;在 Linux 上只有 Vulkan 构建且处于 Wayland 会话时才如此。无法启动进程时(没有检出也没有二进制文件:发布包只附带 `octosense` 和内核),它在进程内打开;在状态目录下的 `wm/apps.splash` 中写一行 `terminal: Module` 或 `terminal: Process` 可覆盖默认值。无论哪种托管方式,AI 面板都能读取它(`read_screen`、`read_scrollback`),但只有 Terminal 作为独立进程运行时才能输入命令(`run`);在进程内,Terminal 只提供读取工具(ADR 0004 §10)。在开发者模式之外,每条命令都要等待用户在宿主面板上批准(`native-apps.json` 中为 `confirm: host`、`auto_approvable: false`),超过 4 KiB 的命令会被拒绝。在 macOS 上进程内运行时,Shell 的 PTY 辅助程序就是 `octosense` 本身。 | | `app-appcard` | 关 | 链接 AppCard 助手模块(`../apps/appcard/module`);隐含 `octos-core`。在所有目标平台(包括手机)上都需显式启用;目前不随产品发布。 | | `app-aichat` | 关 | 以模块形式链接 Makepad 的 AI chat,不含其模型引擎。 | | `mobile-apps` | 关 | `app-rinx` + `app-reference` + `app-sheets` + `app-hub` + `octos-core`:手机构建所链接的集合,用于在桌面上测试。不含 AppCard。 | diff --git a/docs/architecture.md b/docs/architecture.md index 32a4f0ce..1ce993c7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -463,10 +463,10 @@ Each item is an ADR decision that the code at HEAD does not follow. 5. **After the fact.** ADR 0004 §8 promises a send queue with an undo window, and auto-approvals audited with their arguments. There is no queue or undo, and the audit keeps a digest. 6. **Per-client file grants.** ADR 0004 §11 narrows the host read tools by per-client grants; no manifest field declares them yet. 7. **Rinx.** ADR 0004 §9 confirms Rinx's send tool on its own `confirm: app` sheet, §11 moves its data under `apps/rinx/`, and §13 lets developer mode override every app's sheet. At its pinned tag Rinx declares no agent tools, registers no sheet with the router, keeps its own data folder, and its send sheet still asks in developer mode. -8. **The Windows sandbox.** ADR 0004 §3 gives Windows process apps an AppContainer. It is not built, so they run with the person's rights, and `terminal.run` is never offered there. +8. **The Windows sandbox.** ADR 0004 §3 gives Windows process apps an AppContainer. It is not built, so they run with the person's rights. The system agent gets no `terminal.run` there, but other callers can still type into the Terminal (item 11). 9. **Process apps in release packages.** ADR 0004 §2 ships their binaries; release packages ship only `octosense` and the kernel (`desktop/packaging/release.json`). 10. **Mail sending.** ADR 0004 §8 lets a standing rule answer an outward call such as `mail.send`, and §13 lets developer mode override every approval. The code follows ADR 0007 instead: a Mail send needs the host's review and a physical touch whatever the rules or developer mode say, and ADR 0004 does not mention the exception. -11. **The in-process Terminal still offers `run`.** ADR 0004 §10 makes the in-process Terminal read-only. The shell, though, replaces its module's read-only executor with one that also offers `run` (`host_executor` in `crates/shell/src/module_host.rs`, kept by a test). So wherever the desktop runs the Terminal in process (Linux without Vulkan and Wayland, or switched to a module), the desktop's AI pane can still type a command, behind the approval router. The system agent's `terminal.run` follows the ADR: it needs the Terminal as a sandboxed process. +11. **Only the system agent's `terminal.run` checks the sandbox.** ADR 0004 §10 lets the Terminal's AI type commands only while the Terminal runs as its own sandboxed process. The system agent's `terminal.run` checks that (`sandbox::launch_sandboxed`); nothing else does. A process Terminal offers the desktop's AI pane its own `run` either way, and in developer mode the host-tool relay grants `terminal.run` to every covered app agent. So on Windows, which has no sandbox yet, the pane can type into an unsandboxed Terminal behind the approval router, and in developer mode so can those agents. Release packages have no AI pane. The in-process Terminal does follow the ADR, because the shell announces its module's read-only manifest. `host_executor` in `crates/shell/src/module_host.rs` swaps in an executor that would also answer `run`, but nothing sends it `run`: the pane calls only the tools a manifest declares, and the shell's own calls (`AiBus::shell_call`) check the same manifest. ## Source map diff --git a/docs/architecture.zh-CN.md b/docs/architecture.zh-CN.md index 374ceab1..66707047 100644 --- a/docs/architecture.zh-CN.md +++ b/docs/architecture.zh-CN.md @@ -463,10 +463,10 @@ sequenceDiagram 5. **事后控制。**ADR 0004 §8 承诺提供带撤销窗口的发送队列,并在审计中记录自动批准的参数。目前既没有队列也没有撤销,审计只保存参数摘要。 6. **按客户端的文件授权。**ADR 0004 §11 按应用的按客户端授权来收窄宿主读取工具;目前还没有 manifest 字段能声明这类授权。 7. **Rinx。**ADR 0004 §9 让 Rinx 的发送工具在它自己的 `confirm: app` 面板上确认,§11 把它的数据移到 `apps/rinx/` 下,§13 让开发者模式覆盖每个应用的面板。在其锁定的版本中,Rinx 不声明任何 Agent 工具,不向审批路由注册面板,仍使用自己的数据文件夹,而且在开发者模式下它的发送面板仍会询问。 -8. **Windows 沙箱。**ADR 0004 §3 为 Windows 上的进程应用提供 AppContainer。它还没有实现,所以这些应用以用户的权限运行,Windows 上也从不提供 `terminal.run`。 +8. **Windows 沙箱。**ADR 0004 §3 为 Windows 上的进程应用提供 AppContainer。它还没有实现,所以这些应用以用户的权限运行。系统 Agent 在 Windows 上拿不到 `terminal.run`,但其他调用方仍能向 Terminal 输入命令(第 11 条)。 9. **发布包中的进程应用。**ADR 0004 §2 要求附带它们的二进制;发布包只附带 `octosense` 和内核(`desktop/packaging/release.json`)。 10. **发送邮件。**ADR 0004 §8 允许常设规则回答 `mail.send` 这类对外调用,§13 允许开发者模式覆盖所有审批。代码遵循的是 ADR 0007:不论常设规则或开发者模式怎么说,发送邮件都需要宿主的审阅和一次物理触摸;ADR 0004 没有提到这个例外。 -11. **进程内的 Terminal 仍提供 `run`。**ADR 0004 §10 规定进程内的 Terminal 只读。但 Shell 用另一个执行器替换了它模块自带的只读执行器,新执行器也提供 `run`(`crates/shell/src/module_host.rs` 中的 `host_executor`,有测试固定这一行为)。所以只要桌面端在进程内运行 Terminal(没有 Vulkan 和 Wayland 的 Linux,或被切换为模块时),桌面端的 AI 面板仍能经审批路由输入命令。系统 Agent 的 `terminal.run` 则符合 ADR:它要求 Terminal 作为沙箱进程运行。 +11. **只有系统 Agent 的 `terminal.run` 检查沙箱。**ADR 0004 §10 只允许 Terminal 的 AI 在 Terminal 作为独立的沙箱进程运行时输入命令。系统 Agent 的 `terminal.run` 会检查这一点(`sandbox::launch_sandboxed`),其他路径都不检查。进程形式的 Terminal 无论沙箱是否生效,都会把自己的 `run` 提供给桌面端的 AI 面板;在开发者模式下,宿主工具中转还会把 `terminal.run` 授予所覆盖的每个应用 Agent。所以在还没有沙箱的 Windows 上,AI 面板能经审批路由向没有沙箱的 Terminal 输入命令,开发者模式下这些 Agent 也能。发布包里没有 AI 面板。进程内的 Terminal 符合 ADR,因为 Shell 公布的是它模块自带的只读 manifest。`crates/shell/src/module_host.rs` 中的 `host_executor` 换上了一个也能执行 `run` 的执行器,但没有调用会把 `run` 发给它:AI 面板只调用 manifest 声明过的工具,Shell 自己的调用(`AiBus::shell_call`)也按同一份 manifest 检查。 ## 源码位置