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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
| A host service (`mail`, `calendar`, `news`, `llm`, `model`) | `apps/mail/host-service/`, `apps/calendar/host-service/`, `apps/news/host-service/`, `apps/ai-providers/` (`llm` and `model.complete`) | `cargo test --locked -p octosense-mail-service -p octosense-calendar-service -p octosense-news-service -p octosense-llm-service` |
| Connected accounts: OAuth and the `auth`, `github`, `gmail`, `gcalendar` host services; installed apps' Gmail events and the native review of their saves and sends | `crates/oauth-service/` (its README); `crates/shell/src/connected_events.rs`, `crates/shell/src/connected_review.rs` | `cargo test --locked -p octosense-oauth-service` and `cargo test --locked -p octosense-oauth-service --features host`; the two shell files build and test with the shell (from `phone/`: `cargo test --locked --features mobile-apps -p octosense-shell`); `apps.yml`, `phone.yml` |
| AppCard (opt-in) | `apps/appcard/` | [apps/appcard/AGENTS.md](apps/appcard/AGENTS.md), `apps.yml` |
| A native app (App Hub, Rinx, Terminal, Sheets, Reference, AppCard, and the Makepad apps made native: Calculator, Clock, Notes, Reminders, Weather, and Task, which runs only as its own process): its crate, pin, features, hosting per target, sandbox, storage, its tools, which of them the system agent may call (`agent.system_tools`) and which its own agent may (`agent.own_tools`) | `native-apps.json` only; `python3 tools/native_apps.py` writes the marked blocks in the `Cargo.toml`s, `crates/shell/src/native_apps.rs` and `Cargo.lock` | `python3 tools/native_apps.py --check`, `python3 -m unittest discover -s tools -p 'test_*.py'` |
| A native app (App Hub, Rinx, Terminal, Sheets, Reference, AppCard, and the Makepad apps made native: Calculator, Clock, Notes, Reminders, Weather, and Task, which runs only as its own process; and OctosCode, whose `kernel` port the coding scope holds, `crates/shell/src/coding_scope.rs`): its crate, pin, features, hosting per target, sandbox, storage, its tools, which of them the system agent may call (`agent.system_tools`) and which its own agent may (`agent.own_tools`) | `native-apps.json` only; `python3 tools/native_apps.py` writes the marked blocks in the `Cargo.toml`s, `crates/shell/src/native_apps.rs` and `Cargo.lock` | `python3 tools/native_apps.py --check`, `python3 -m unittest discover -s tools -p 'test_*.py'` |
| An external pin (Makepad, OctoScript, App Hub, octos, Rinx) | root `Cargo.toml` `[workspace.dependencies]` (a native app's in `native-apps.json`), `native-runtime.lock.json`, `runtime-patches.lock.json` | `python3 tools/setup.py --update`, then `--check --cargo` and `python3 tools/native_apps.py --check` |
| A decision | `docs/adr/` (next free number) | — |

Expand Down
105 changes: 89 additions & 16 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ makepad-clock = { git = "https://github.com/OctoSense-org/makepad.git", rev = "3
makepad-notes = { git = "https://github.com/OctoSense-org/makepad.git", rev = "32d6415fb7476345ad36ee4f98d6f844d1f07fd2", default-features = false }
makepad-reminders = { git = "https://github.com/OctoSense-org/makepad.git", rev = "32d6415fb7476345ad36ee4f98d6f844d1f07fd2", default-features = false }
makepad-weather = { git = "https://github.com/OctoSense-org/makepad.git", rev = "32d6415fb7476345ad36ee4f98d6f844d1f07fd2", default-features = false }
octoscode-module = { git = "https://github.com/octos-org/octoscode-app.git", rev = "5d0c2a0962218aa94497201ce1a39b7429f09e36", default-features = false, features = ["octosense-module"] }
makepad-task = { git = "https://github.com/OctoSense-org/makepad.git", rev = "32d6415fb7476345ad36ee4f98d6f844d1f07fd2" }
# END native-apps: pins
# --- Makepad (OctoSense-org/makepad), the revision Octoscript-Makepad's
Expand Down Expand Up @@ -296,6 +297,8 @@ octoscript-schema = { path = ".sources/octoscript/crates/octoscript-schema" }
octoscript-makepad = { path = ".sources/octoscript-makepad/crates/octoscript-makepad" }
octoscript-widgets = { path = ".sources/octoscript-makepad/crates/octoscript-widgets" }
octoscript-node = { path = ".sources/octoscript-makepad/crates/octoscript-node" }
# OctosCode's cards register their globals through it (octos-org/octoscode-app).
octoscript-render = { path = ".sources/octoscript-makepad/crates/octoscript-render" }

# Rinx takes the app-peers contract from this repository by git. Redirect
# it to the same local workspace crates, so the host and module share one
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ Pinned exactly once, in the root `Cargo.toml` and the runtime locks:
| [OctoSense-App-Hub](https://github.com/OctoSense-org/OctoSense-App-Hub) | The signed catalog, the store, and the Card runner that contains every script app. |
| [octos](https://github.com/octos-org/octos) | The agent kernel. Android bundles it in the APK as `liboctos.so`; the desktop runs the packaged `octos-kernel` beside the shell, checked against this revision (`tools/kernel-artifact.py --host --stage` builds it). |
| [Rinx](https://github.com/hagency-org/Rinx) | Matrix chats and mini apps, hosted as a native module. |
| [OctosCode](https://github.com/octos-org/octoscode-app) | The coding client of the person's assistant, hosted as a native module that reaches the kernel through its port in the coding scope (ADR 0003, item 9). |

Related, not build inputs: [OctoScript-App-Design-Flow](https://github.com/OctoSense-org/OctoScript-App-Design-Flow) (how apps are built and published), [OctoScript-Android](https://github.com/OctoSense-org/OctoScript-Android) and [OctoScript-OH](https://github.com/OctoSense-org/OctoScript-OH) (other renderers), the [OctoSense website](https://github.com/OctoSense-org/octosense-org.github.io).

Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ Shell 只有一份,位于 `crates/shell`([ADR 0001(英文)](docs/adr/000
| [OctoSense-App-Hub](https://github.com/OctoSense-org/OctoSense-App-Hub) | 签名目录、商店,以及隔离运行每个脚本应用的 Card runner。 |
| [octos](https://github.com/octos-org/octos) | Agent 内核。Android 上 APK 以 `liboctos.so` 形式内置它;桌面端运行 Shell 旁随附的 `octos-kernel`,并核对其版本与此处固定的一致(由 `tools/kernel-artifact.py --host --stage` 构建)。 |
| [Rinx](https://github.com/hagency-org/Rinx) | Matrix 聊天与小程序,作为原生模块托管。 |
| [OctosCode](https://github.com/octos-org/octoscode-app) | 用户助手的编码客户端,作为原生模块托管,经由编码范围内的内核端口访问内核(ADR 0003 第 9 条)。 |

相关但不参与构建:[OctoScript-App-Design-Flow](https://github.com/OctoSense-org/OctoScript-App-Design-Flow)(如何构建和发布应用)、[OctoScript-Android](https://github.com/OctoSense-org/OctoScript-Android) 和 [OctoScript-OH](https://github.com/OctoSense-org/OctoScript-OH)(其他渲染后端)、[OctoSense 网站](https://github.com/OctoSense-org/octosense-org.github.io)。

Expand Down
47 changes: 37 additions & 10 deletions crates/kernel/src/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader
use tokio::sync::{mpsc, watch};

use crate::launch::Launch;
use crate::router::{ConnId, Router};
use crate::router::{ConnId, Routed, Router, Scope};
use crate::network::Network;
use crate::{ClientAccess, CloseReason, LogSink};
use std::path::PathBuf;
Expand All @@ -25,7 +25,8 @@ pub(crate) enum Inbound {

/// Messages to a generation's supervisor.
pub(crate) enum Ctl {
Attach(ConnId, mpsc::UnboundedSender<Inbound>),
/// A consumer, held to its scope when it has one (an app's kernel port).
Attach(ConnId, mpsc::UnboundedSender<Inbound>, Option<Arc<dyn Scope>>),
Frame(ConnId, String),
Detach(ConnId),
/// Set the system agent's exact kernel tool list again (a grant changed).
Expand Down Expand Up @@ -338,7 +339,7 @@ pub(crate) async fn supervise(
tokio::select! {
biased;
msg = ctl.recv() => match msg {
Some(Ctl::Attach(id, tx)) => { router.attach(id); consumers.insert(id, tx); }
Some(Ctl::Attach(id, tx, scope)) => { attach(&mut router, id, scope); consumers.insert(id, tx); }
Some(Ctl::Detach(id)) => { router.detach(id); consumers.remove(&id); }
Some(Ctl::Stop(reason)) => break Err(reason),
Some(frame) => queued.push_back(frame),
Expand Down Expand Up @@ -366,17 +367,24 @@ pub(crate) async fn supervise(
tokio::select! {
biased;
msg = async { if queued.is_empty() { ctl.recv().await } else { queued.pop_front() } } => match msg {
Some(Ctl::Attach(id, tx)) => {
router.attach(id);
Some(Ctl::Attach(id, tx, scope)) => {
attach(&mut router, id, scope);
consumers.insert(id, tx);
}
Some(Ctl::Frame(id, text)) => {
if let Some(frame) = router.consumer_frame(id, &text) {
Some(Ctl::Frame(id, text)) => match router.consumer_frame(id, &text) {
Routed::Kernel(frame) => {
if let Err(e) = write_line(&mut io, &frame).await {
break CloseReason::Exited(format!("writing to the kernel failed: {e}"));
}
}
}
Routed::Answer(frame) => {
(log)(&format!("octos-core: kernel {generation}: consumer {id}: {}", crate::router::refusal_note(&frame)));
if let Some(tx) = consumers.get(&id) {
let _ = tx.send(Inbound::Frame(frame));
}
}
Routed::Drop | Routed::Held => {}
},
Some(Ctl::SystemToolList) => {
let frame = set_tool_list(&mut tool_lists);
if let Err(e) = write_line(&mut io, &frame).await {
Expand All @@ -399,11 +407,23 @@ pub(crate) async fn supervise(
(log)(&format!("octos-core: kernel {generation}: the system agent's tool list {outcome}"));
continue;
}
for (id, frame) in router.kernel_frame(&text) {
let delivery = router.kernel_frame(&text);
for (id, frame) in delivery.consumers {
if let Some(tx) = consumers.get(&id) {
let _ = tx.send(Inbound::Frame(frame));
}
}
// Frames a session's preparation held, now released.
let mut failed = None;
for frame in delivery.kernel {
if let Err(e) = write_line(&mut io, &frame).await {
failed = Some(CloseReason::Exited(format!("writing to the kernel failed: {e}")));
break;
}
}
if let Some(reason) = failed {
break reason;
}
}
Ok(None) => break CloseReason::Exited("the kernel closed its output".into()),
Err(e) => break CloseReason::Exited(format!("reading from the kernel failed: {e}")),
Expand Down Expand Up @@ -436,7 +456,7 @@ pub(crate) async fn supervise(
// whose Attach is still queued.
ctl.close();
while let Ok(msg) = ctl.try_recv() {
if let Ctl::Attach(id, tx) = msg {
if let Ctl::Attach(id, tx, _) = msg {
consumers.insert(id, tx);
}
}
Expand All @@ -447,6 +467,13 @@ pub(crate) async fn supervise(
let _ = done.send(true);
}

fn attach(router: &mut Router, id: ConnId, scope: Option<Arc<dyn Scope>>) {
match scope {
Some(scope) => router.attach_scoped(id, scope),
None => router.attach(id),
}
}

async fn write_line(io: &mut Io, frame: &str) -> std::io::Result<()> {
io.writer.write_all(frame.as_bytes()).await?;
io.writer.write_all(b"\n").await?;
Expand Down
Loading
Loading