Skip to content
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
8640f1a
chore(deps): add tinyruntime submodule
senamakel Aug 21, 2026
01b8323
chore(deps): add tinyruntime-bus dependency
senamakel Aug 21, 2026
aebac0d
feat(registry): add tinyruntime module records
senamakel Aug 21, 2026
44a81f0
fix(registry): give each runtime provider its own object path
senamakel Aug 21, 2026
060366e
fix(modules): handle missing runtime module gracefully
senamakel Aug 21, 2026
8ea7862
feat(modules): add runtime module to the public API
senamakel Aug 21, 2026
fe7fa5d
chore(deps): add tinyruntime-bus dependency to Cargo.lock
senamakel Aug 21, 2026
327be1d
fix(test): simplify imports in runtime tests
senamakel Aug 21, 2026
b1d8e34
test(registry): split host-coverage test into two focused assertions
senamakel Aug 21, 2026
67b5010
chore(runtime): reformat imports and match arms
senamakel Aug 21, 2026
6df774f
Serve each provider at its own derived object path
enamakel Aug 21, 2026
f47a532
refactor(runtime): delegate Node.js toolchain resolution to tinyrunti…
senamakel Aug 21, 2026
3663c55
refactor(node): move Node toolchain resolution into the bootstrap module
senamakel Aug 21, 2026
0fa2081
refactor(runtime): delegate Python interpreter resolution to the tiny…
senamakel Aug 21, 2026
91883a1
refactor(runtime/pool): delegate pool implementation to tinyruntime m…
senamakel Aug 21, 2026
4837094
refactor(pool): delegate node and python pool backends to a shared di…
senamakel Aug 21, 2026
4064461
refactor(ops): simplify bootstrap construction by passing root config
senamakel Aug 21, 2026
ca1fa1e
refactor(config): share a single Arc-wrapped Config across runtime bo…
senamakel Aug 21, 2026
5aa13f2
fix(tools): remove unused parameter from try_pool_inline
senamakel Aug 21, 2026
0a843cf
fix(tools): remove unused resolved parameter from pool inline calls
senamakel Aug 21, 2026
2fd130d
chore(python_exec): remove unused parameter from try_pool_inline
senamakel Aug 21, 2026
6e5de96
chore(runtime): clarify module docs after toolchain extraction
senamakel Aug 21, 2026
046e7d4
refactor(runtime): switch bootstrap constructors to accept `Arc<Config>`
senamakel Aug 21, 2026
a6e38a3
fix(runtime): simplify NodeBootstrap construction
senamakel Aug 21, 2026
3119074
docs(runtime): update module-level doc comment and narrow re-exports
senamakel Aug 21, 2026
e56ed8b
refactor(tools): simplify test bootstrap construction
senamakel Aug 21, 2026
0281584
chore(exec): remove unused NodeConfig import from test modules
senamakel Aug 21, 2026
a6ebc7f
chore(deps): remove xz2 dependency from runtime-node feature
senamakel Aug 21, 2026
2693c6f
chore(deps): remove unused xz2 and lzma-sys dependencies
senamakel Aug 21, 2026
b7c705e
docs(runtime): document extraction of toolchain install logic into ti…
senamakel Aug 21, 2026
b178896
chore: reorder imports and reformat long assertions
senamakel Aug 21, 2026
e63bf4a
docs(library-minimal-recipe, specs): update xz2 removal and runtime b…
senamakel Aug 21, 2026
f70d41e
docs(library-benchmarking): document worker relocation to tinyruntime…
senamakel Aug 21, 2026
7e93ca7
docs(AGENTS.md): update runtime-node and skills dep notes to reflect …
senamakel Aug 21, 2026
d001028
docs(config): clarify NodeConfig field semantics
senamakel Aug 21, 2026
391419c
docs(library-benchmarking): clarify that the pool relocation does not…
senamakel Aug 21, 2026
c621a27
docs(runtime): add README for pool module
senamakel Aug 21, 2026
9628975
chore(deps): update Cargo.lock
senamakel Aug 21, 2026
71c2e0c
refactor(runtime): route runtime lookups through a local client facade
senamakel Aug 21, 2026
9fa8eff
chore: files changed src/openhuman/runtime/client/disabled.rs,src/ope…
senamakel Aug 21, 2026
ec8ff0f
chore(runtime): remove unused languages function from disabled client
senamakel Aug 21, 2026
33eba71
chore(client): drop unused `languages` re-export from the modules facade
senamakel Aug 21, 2026
7edcb94
chore(scripts): update kernel-floor limits for tinyruntime-bus addition
senamakel Aug 21, 2026
d7ce619
chore(ci): update expected name count in dep-sim guard
senamakel Aug 21, 2026
232d274
chore(deps): update tinyagents subproject commit
senamakel Aug 21, 2026
75e22fe
fix(AGENTS.md): correct native build count in contributor feature set
senamakel Aug 21, 2026
db2d844
fix(runtime): implement custom Debug for NodeBootstrap stub
senamakel Aug 21, 2026
f1b9ef0
test(raw_coverage): simplify NodeBootstrap construction in e2e test
senamakel Aug 21, 2026
c2c418b
test(Feedback): add mock for validateFeedback in test setup
senamakel Aug 21, 2026
09afdac
fix(tools): share config Arc instead of cloning root_config
senamakel Aug 21, 2026
36097af
Merge remote-tracking branch 'refs/remotes/upstream/main' into pr/5664
senamakel Aug 22, 2026
afa1a55
test(raw_coverage): add missing tool_specs field to test fixture
senamakel Aug 22, 2026
7cc661e
test(raw_coverage): add missing tool_specs field to expected prompt d…
senamakel Aug 22, 2026
9cc8817
test(raw_coverage): update assertion for delegate-tool description
senamakel Aug 22, 2026
77a81c0
fix(tests): update research description assertion in e2e coverage test
senamakel Aug 22, 2026
168e087
Merge remote-tracking branch 'upstream/main' into pr/5664
senamakel Aug 22, 2026
4359399
fix(tests): remove duplicate tool_specs fields in raw coverage test s…
senamakel Aug 22, 2026
dc2c17d
Merge remote-tracking branch 'upstream/main' into pr/5664
senamakel Aug 22, 2026
d0d03ad
Merge remote-tracking branch 'upstream/main' into pr/5664
senamakel Aug 22, 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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@
path = vendor/tinyhosts
url = https://github.com/tinyhumansai/tinyhosts.git
branch = main
[submodule "vendor/tinyruntime"]
path = vendor/tinyruntime
url = https://github.com/tinyhumansai/tinyruntime.git
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ two paths' equivalence — keep that as call sites migrate.

A move never changes the wire surface — RPC namespaces are string literals in `ControllerSchema`, not derived from module paths — so **do not rename namespace strings to match new paths**.

**Skills runtime**: the QuickJS per-skill VM engine is gone. `src/openhuman/skills/` holds skill metadata/tool descriptors; execution of installed `SKILL.md` workflows lives in `src/openhuman/skills/runtime/` (starts/cancels runs, hosts the `skill_executor` agent, reuses `runtime_node`/`runtime_python`).
**Skills runtime**: the QuickJS per-skill VM engine is gone. `src/openhuman/skills/` holds skill metadata/tool descriptors; execution of installed `SKILL.md` workflows lives in `src/openhuman/skills/runtime/` (starts/cancels runs, hosts the `skill_executor` agent, reuses `runtime::node`/`runtime::python`, which are clients for the `tinyruntime` module).

**Rules:**

Expand Down Expand Up @@ -515,7 +515,7 @@ Two columns because there are two sets (see above): **Contrib** is `[features] d
| `channels` | ON | ON | `openhuman::channels` (external-messaging providers — Telegram/Discord/Slack/Signal/WhatsApp/iMessage/IRC/… — plus the channel runtime, controllers, host, proactive messaging + inbound dispatch) and the `channels::webview_accounts` / `webview_apis` / `webview_notifications` / `channels::whatsapp_data` webview-bridge domains (incl. the 3 `whatsapp_data_*` agent tools). **Carve-outs `channels::{traits, cli}` stay ungated.** | **28** via `tinychannels/{email,lark}` — the crate itself stays (load-bearing), its two heavy providers do not |
| `memory-git` | OFF | ON | `openhuman::memory::diff` (git-backed snapshots/checkpoints/read markers, the `memory_diff` RPC namespace + agent tool) and the git wiki mirror in `memory::store::content::wiki_git`. **Type carve-out**: `memory::diff::types` compiles in BOTH builds — the always-on subconscious memory profile renders `CrossSourceDiff`/`ChangeKind` into prompts, and tinycortex makes the matching split (its `memory::diff::{types,source}` are ungated, only the `Ledger`/`DiffEngine` half sits behind `git-diff`). Off ⇒ `memory_diff` is unknown-method, the tool is absent, the embedded driver drops `Capability::Diff` **and** `as_diff()` returns `None` in lockstep (`audit_provider` fails on either half alone), and summary nodes are still written to disk but not mirrored into git. **This crate declares no `git2`** — tinycortex owns every libgit2 call in the stack (the diff ledger, the wiki mirror, the persona git-history reader), and the gate reaches the cohort by forwarding `tinycortex/git-diff` + `tinycortex/wiki-git`; `tinymemory-core/memory-git` forwards the same pair. Do not re-add a direct `git2` dependency to this crate or to `tinymemory-core`: it would buy no crates and invite a second major pin, which `links = "git2"` makes a hard cargo error. Test code that must read a ledger back goes through the `tinycortex::git2` re-export (`tests/memory_artifacts_e2e.rs`). | **3**: `git2`, `libgit2-sys`, `libz-sys` — two of the five native C builds in the kernel profile, the largest native shed in the program |
| `contacts` | OFF | ON | `memory::people::address_book`'s macOS CNContactStore reader — the address-book seeding path for the people domain. Leaf gate over a **pre-existing** off-state: the module already shipped a non-macOS `imp` stub returning an empty contact list, so the gate only widens that stub's cfg. `read`/`read_with`/`AddressBookError`/`SystemContactsSource` and the whole `people` RPC surface stay compiled in every build; off ⇒ a refresh seeds nothing instead of failing. | **6** on macOS (`objc2`, `objc2-foundation`, `objc2-contacts`, `block2` + 2 transitive). **No-op on Linux/Windows** — never in those graphs, so the kernel-floor ratchet does not move. Verify cross-target: `cargo tree --target aarch64-apple-darwin -e normal -i objc2-contacts --no-default-features` (294 → 288 packages). |
| `runtime-node` | OFF | ON | `runtime::node` (download / verify / extract / install a pinned Node.js toolchain), the `runtime::javascript` language slot, `runtime::pool::node`, the `node_exec` / `npm_exec` agent tools, and the `node_runtime` harness-init step. **Facade + stub** — `ShellTool` holds `Option<Arc<NodeBootstrap>>` and `shell.rs` is kernel, so the module cannot simply vanish; `runtime/node/stub.rs` carries the `NodeBootstrap` type surface while registration sites are leaf-gated. **The generic native-tool dispatcher (`runtime::node::ops` / `runtime::node::types`) is NOT gated** — it backs both the gated `javascript.*` controllers and the ungated `flows` `oh:` `NativeToolBackend`, so native flow tools (`memory_search`, file, shell, …) keep working when the managed Node runtime is off. Off ⇒ `try_cached`/`probe_installed` return `None` and the shell never prepends a managed bin dir, identical to today's `node.enabled = false` path. | **`xz2` + its static liblzma C build.** First gate to remove a NATIVE toolchain build: `lzma-sys` leaves the list, 6 → 5. `tar`/`zip` are NOT shed — shared with `inference` (install_piper), `runtime::python`, and the document tools. |
| `runtime-node` | OFF | ON | `runtime::node` (the client that asks the `tinyruntime` module for a Node.js toolchain), the `runtime::javascript` language slot, `runtime::pool::node`, the `node_exec` / `npm_exec` agent tools, and the `node_runtime` harness-init step. **Facade + stub** — `ShellTool` holds `Option<Arc<NodeBootstrap>>` and `shell.rs` is kernel, so the module cannot simply vanish; `runtime/node/stub.rs` carries the `NodeBootstrap` type surface while registration sites are leaf-gated. **The generic native-tool dispatcher (`runtime::node::ops` / `runtime::node::types`) is NOT gated** — it backs both the gated `javascript.*` controllers and the ungated `flows` `oh:` `NativeToolBackend`, so native flow tools (`memory_search`, file, shell, …) keep working when the managed Node runtime is off. Off ⇒ `try_cached`/`probe_installed` return `None` and the shell never prepends a managed bin dir, identical to today's `node.enabled = false` path. | **Nothing any more.** This gate used to shed `xz2` and its static liblzma C build; download and extraction moved into the `tinyruntime` module, so that native build left the manifest for **every** configuration rather than only for slim ones. The gate still buys the absence of the tools and controllers. |
Comment thread
coderabbitai[bot] marked this conversation as resolved.

**Facade pattern (pathfinder for the other gates).** `pub mod voice;` is **always compiled** as a facade: the real submodules are `#[cfg(feature = "voice")]`, and a `#[cfg(not(feature = "voice"))] mod stub;` (`src/openhuman/voice/stub.rs`) re-exposes the same public surface that always-on / other-gated callers use (`server`, `dictation_listener`, `streaming`, `reply_speech`, `cloud_transcribe`, `cli`, `create_stt_provider`, `effective_stt_provider`, `publish_ptt_transcript_committed`) with no-op / `None` / disabled-error bodies. Callers therefore do **not** need per-call `#[cfg]`. When voice is off: the voice/audio controllers are unregistered (unknown-method over `/rpc`, absent from `/schema`), the `audio_generate_podcast` agent tools are absent, and `openhuman voice` returns a "voice disabled" error. Stub signatures must match the real ones exactly — the disabled build (`--no-default-features`) is the **only** thing that catches drift, so run it before pushing any change to the voice surface.

Expand Down Expand Up @@ -560,7 +560,7 @@ Two places the carve-out doesn't reach, and why they are `#[cfg]` at the call si
- `agent/registry/agents/loader.rs` — the `skill_setup` / `skill_executor` `BuiltinAgent` entries. `include_str!` embeds the agent TOML from disk regardless of module gating, so the entry itself must disappear.
- `agent/task_dispatcher/executor.rs` — the workflow-resolution branch. `registry::get_workflow` returns `Option<WorkflowDefinition>`, which flattens in `AgentDefinition` and is destructured at the call site; stubbing it would mean re-declaring that struct (exactly what the carve-out avoids). With the domain compiled out no handle can resolve to a skill, so falling through to the builtin-agent branch is correct, not degraded.

**Dep note:** `skills = []` — the empty list is **intentional, do not "fix" it**. Unlike `voice` (`hound`/`lettre`), these domains have no exclusive dependencies: every crate they touch is shared with always-on domains, and `runtime_node` / `runtime_python` are used by Agent / Flows / Memory too. This gate's value is tool-surface + prompt-bloat + startup cost, **not** binary size.
**Dep note:** `skills = []` — the empty list is **intentional, do not "fix" it**. Unlike `voice` (`hound`/`lettre`), these domains have no exclusive dependencies: every crate they touch is shared with always-on domains, and `runtime::node` / `runtime::python` are used by Agent / Flows / Memory too. This gate's value is tool-surface + prompt-bloat + startup cost, **not** binary size.

When skills are off: the `skills` / `skill_runtime` / `skill_registry` controllers are unregistered (unknown-method over `/rpc`, absent from `/schema`), the 16 skill agent tools (incl. `run_workflow` / `await_workflow`) are **absent** from the tool list rather than degraded to an error, the `skill_setup` / `skill_executor` builtin agents are gone, and the boot-time remote catalog refresh is skipped. Composes with the runtime `DomainSet::skills` flag (#4796) — that axis needed no change here; #4798 is compile-time only.

Expand Down
30 changes: 9 additions & 21 deletions Cargo.lock

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

49 changes: 32 additions & 17 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,19 @@ tinycortex-api = { path = "vendor/tinycortex/api" }
# rather than the one pinned inside the tinymemory submodule.
#
# After cloning: `git submodule update --init --recursive vendor/tinymemory`.
# tinyruntime — the runtime router
# (https://github.com/tinyhumansai/tinyruntime). Only the *contract* crate is
# taken here, never the router itself: the router ships as a loadable TinyBus
# module, and a host that also compiled it would carry the download pipeline, the
# worker pool, and their dependency trees for nothing.
#
# `tinyruntime-bus` is deliberately dependency-light — `serde` and `serde_json`
# and nothing else — which is what makes naming the payload types cost this
# manifest almost nothing. The module's own CI asserts it stays that way.
#
# After cloning: `git submodule update --init --recursive vendor/tinyruntime`.
tinyruntime-bus = { path = "vendor/tinyruntime/crates/tinyruntime-bus" }

tinymemory = { path = "vendor/tinymemory/crates/tinymemory" }
tinymemory-api = { path = "vendor/tinymemory/crates/tinymemory-api" }
tinymemory-tinycortex = { path = "vendor/tinymemory/crates/tinymemory-tinycortex" }
Expand Down Expand Up @@ -341,18 +354,18 @@ sha2 = "0.10"
# graph is a hard cargo error, not a warning. Test code that must inspect a
# ledger goes through `tinycortex::git2`.
hmac = "0.12"
# Archive extraction for the Node.js runtime bootstrap. Unix Node
# distributions ship as .tar.xz, Windows as .zip. `xz2` with `static`
# bundles liblzma so we don't need it as a system dependency.
# Archive handling for the Piper voice installer and the document tools. The
# Node.js and Python toolchain archives are no longer unpacked here — the
# `tinyruntime` module owns that — which is what let `xz2` and its static
# liblzma C build leave this manifest entirely.
tar = "0.4"
xz2 = { version = "0.1", features = ["static"], optional = true }
zip = { version = "2", default-features = false, features = ["deflate"] }
# gzip decoder for the Piper tar.gz binary releases on macOS / Linux. Already
# pulled in transitively by zip's `deflate` feature; declared directly so
# the installer module can `use flate2::read::GzDecoder`.
flate2 = "1"
# Real timeout for `node --version` probes in the runtime resolver. Guards
# against a broken shim on PATH hanging the bootstrap forever.
# Real timeout around a blocking child wait, for the Claude Code auth probe.
# Guards against a broken binary on PATH hanging the caller forever.
wait-timeout = "0.2"
uuid = { version = "1", features = ["v4"] }
anyhow = "1.0"
Expand Down Expand Up @@ -632,7 +645,7 @@ proptest = "1"
# web3's ethers/secp256k1 cohort, `documents`' zstd/bzip2 native builds,
# `voice`+`inference`'s cpal/lettre/arboard/enigo/rdev stack, `contacts`'
# macOS objc2 cohort, `crash-reporting`'s sentry tree, and `tui`'s
# ratatui/crossterm, and `runtime-node`'s xz2/liblzma. Turning them off takes a
# ratatui/crossterm. Turning them off takes a
# bare `cargo check` from 540 packages / 7 native builds down to ~350 / 2, which
# is the inner loop every contributor pays on every edit.
#
Expand Down Expand Up @@ -834,13 +847,17 @@ web3 = [
"modules",
]

# Managed Node.js runtime: `runtime::node` (download / verify / extract / install
# a pinned toolchain), the `runtime::javascript` language slot over it,
# `runtime::pool::node`, the `node_exec` / `npm_exec` agent tools, and the
# `node_runtime` harness-init step. Default-ON. Slim builds opt out via
# `--no-default-features --features "<list without runtime-node>"`, which drops
# the exclusive `xz2` AND its static liblzma C build — the FIRST native
# toolchain build this gating program removes (6 native -> 5).
# Managed Node.js runtime: `runtime::node` (the client that asks the
# `tinyruntime` module for a toolchain), the `runtime::javascript` language slot
# over it, `runtime::pool::node`, the `node_exec` / `npm_exec` agent tools, and
# the `node_runtime` harness-init step. Default-ON. Slim builds opt out via
# `--no-default-features --features "<list without runtime-node>"`.
#
# This gate no longer sheds a dependency. It used to carry the exclusive `xz2`
# and its static liblzma C build; downloading and unpacking a toolchain moved to
# the `tinyruntime` module, so that native build left this manifest for every
# configuration rather than only for slim ones. What the gate still buys is the
# absence of the tools and controllers themselves.
#
# FACADE + STUB, not a leaf gate. `ShellTool` holds `Option<Arc<NodeBootstrap>>`
# for managed-Node PATH injection and `tools/impl/system/shell.rs` is kernel, so
Expand All @@ -856,9 +873,7 @@ web3 = [
#
# Off-state: `try_cached`/`probe_installed` return `None`, so the shell never
# prepends a managed bin dir — identical to today's `node.enabled = false` path.
# `tar` and `zip` are NOT shed: `tar` is shared with `inference` (install_piper)
# and `runtime::python`, `zip` with `inference` and the document tools.
runtime-node = ["dep:xz2"]
runtime-node = []

# macOS Contacts seeding for the people domain: `memory::people::address_book`
# reads CNContactStore to seed handles. Default-ON. Slim / headless builds opt
Expand Down
30 changes: 9 additions & 21 deletions app/src-tauri/Cargo.lock

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

7 changes: 7 additions & 0 deletions docs/library-benchmarking.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,13 @@ The pool is configured in `[runtime_pool]` (master switch + per-language
`max_queue_depth`); `enabled = false` reverts every caller to the legacy
per-call spawn.

The pool itself now lives in the `tinyruntime` module. That does **not** change
what this scenario measures: a TinyBus module is a `cdylib` loaded into this
process, so a worker it spawns is still a child of the host and still shows up in
the process-tree sample the gate asserts on. What changed is which code spawns
it. The configuration keys, the backpressure behaviour, and the
`enabled = false` escape hatch are unchanged.

Watch-items from the sweep: thread count grows ~0.35/agent (needs
attribution + cap before real 1000-agent runs), and p95 latency at N=500 on
2 workers shows CPU saturation is the load constraint, not memory.
Expand Down
10 changes: 6 additions & 4 deletions docs/library-minimal-recipe.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,12 @@ prioritization.
**and** `native-tls` — two full TLS stacks linked simultaneously. A headless
host on a known target could pick one, shedding the other.

5. **Node/Python runtime bootstrap deps** (`tar`, `xz2`+liblzma, `zip`, `flate2`).
Only needed if `skills`/`flows` actually execute node/python workloads; kept
here because `skills` is on. If a deployment runs only pure-LLM skills, these
archive/decompression deps become sheddable.
5. ~~**Node/Python runtime bootstrap deps**~~ — **no longer applicable.**
Downloading and unpacking language toolchains moved into the `tinyruntime`
module, so `xz2` and its liblzma build left this manifest entirely. `tar`,
`zip`, and `flate2` remain, but for the Piper voice installer and the document
tools rather than for any runtime bootstrap; they are sheddable with those
features, not with `skills`.

## See also

Expand Down
Loading
Loading