Skip to content

feat(inference): TinyAgents model-interface inversion — Motion A complete + managed-backend crate cutover (Motion B)#4769

Merged
senamakel merged 40 commits into
tinyhumansai:mainfrom
senamakel:feat/inference-crate-provider-cutover
Jul 11, 2026
Merged

feat(inference): TinyAgents model-interface inversion — Motion A complete + managed-backend crate cutover (Motion B)#4769
senamakel merged 40 commits into
tinyhumansai:mainfrom
senamakel:feat/inference-crate-provider-cutover

Conversation

@senamakel

@senamakel senamakel commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Motion A (complete): inverts the agent-harness model interface so no harness struct (Agent, AgentBuilder, ParentExecutionContext, ChatTurnGraph, both AgentTurnRequests) holds Arc<dyn Provider> — they hold the seam-owned TurnModelSource. All Provider-trait handling is confined to the seam + factory, making the Phase-3 router→ModelRegistry swap seam-local. Zero behavior change.
  • Motion B (managed backend cut over): the managed OpenHuman backend — the common inference path (memory/learning/meeting summaries, chat turns) — now routes through a crate-native ChatModel (OpenHumanBackendModel bridging the dynamic session JWT + thread_id + billing envelope onto the vendored tinyagents OpenAiModel) instead of a ProviderModel-wrapped host provider.
  • Motion B (local-runtime builder ready): adds make_crate_local_runtime_chat_model + crate OpenAiModel capability toggles (tinyagents#49: with_native_tool_calling/with_vision/with_default_provider_options) so local runtimes (Ollama et al.) can move crate-native without a capability regression. The live dispatch flip is deferred (see Impact).
  • Records the migration state in the TinyAgents drift ledger (docs/tinyagents-drift-ledger.md) with a full Motion B cutover table; pins vendor/tinyagents to 1057acf.

Problem

The TinyAgents inference migration (#4249) needs the OpenHuman host to stop naming Box<dyn Provider> end-to-end and target the crate's ChatModel, so the provider stack can be dismantled and the router replaced by the crate ModelRegistry in Phase 3. Doing that in one atomic change across the live turn paths (~30 files) is too risky to review or land safely.

Solution

Two structural motions, each zero-behavior-change and landed incrementally:

  • Motion A re-homes the Provider behind a seam newtype (TurnModelSource); turn paths read capabilities off the built crate models rather than Provider methods, with a provider() escape hatch only at seam-boundary resolution sites.
  • Motion B cuts each provider construction site to crate-native. The managed backend is flipped (gated by resolves_to_managed_backend so a test-provider override still wins). The generic OpenAI-compat and local-runtime builders are in place; the local-runtime dispatch flip is held for a follow-up because it must re-run the cfg(not(test)) verify_session_active gate (see Impact).

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) — crate: 55 openai unit tests incl. the new toggles + merge_provider_options (non-object override passthrough is the failure case). Host: managed-vs-local routing tests (create_chat_model managed → profile() None, local → ProviderModel Some) + local-runtime builder profile test + existing OpenHumanBackendModel tests.
  • Diff coverage ≥ 80% — verified by this PR's rust-core-coverage job on the changed inference/provider/* lines; changed lines are exercised by the tests above.
  • Coverage matrix updated — N/A: structural/refactor change, no new user-facing feature rows.
  • All affected feature IDs from the matrix are listed under ## Related — N/A: no matrix feature rows affected.
  • No new external network dependencies introduced — none; the crate wire client speaks the same OpenAI endpoints the host provider did (mock-covered).
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: no release-cut surface touched.
  • Linked issue — see ## Related (Improve agent harness with LangGraph-style state machine or Polaris-like architecture #4249 tracker; Complete tinyagents inference migration (Motion B): crate-native provider clients, delete duplicated provider stack #4727 Motion B).

Impact

  • Runtime: desktop/CLI Rust core only. The managed-backend path changes wire client (host OpenAiCompatibleProvider → crate OpenAiModel) while preserving JWT resolution, thread_id injection, and the openhuman.usage billing/charged-USD + cached-token envelope. BYOK/local providers are unchanged (still on the host Provider path) until the deferred dispatch flip.
  • Deferred (security-gated): flipping local runtimes to the crate path in create_chat_model would jump ahead of the verify_session_active gate (custom/local providers require an active OpenHuman session). That gate is #[cfg(not(test))], so no unit test or CI compile-check covers a regression — the flip lands as its own tightly-scoped, verified change. Documented in the drift ledger's Motion B table.
  • Migration/compatibility: zero intended behavior change; structural groundwork for Phase 3 (provider consolidation) and the eventual Provider trait deletion.

Related


AI Authored PR Metadata

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/inference-crate-provider-cutover
  • Commit SHA: 034fac338 (merge current with upstream/main)

Validation Run

  • pnpm --filter openhuman-app format:check — N/A: no app/ changes.
  • pnpm typecheck — N/A: no app/ changes.
  • Focused tests: cargo test --lib managed/local routing + crate_openai + openhuman_backend_model; crate cargo test --lib openai:: (55 pass).
  • Rust fmt/check — cargo fmt clean; host lib cargo check --lib green on the merged tree (0 errors); CI Rust Quality (fmt, clippy) passed.
  • Tauri fmt/check — N/A: no app/src-tauri changes.

Validation Blocked

  • command: full cargo test --lib / cargo llvm-cov locally
  • error: dev box is shared/contended (concurrent sibling builds, cold target, OOM history) — full local suites unreliable; targeted tests + merged-tree cargo check --lib run clean
  • impact: full-suite + coverage verification delegated to this PR's CI

Behavior Changes

  • Intended behavior change: none (structural inversion + managed-path wire-client swap)
  • User-visible effect: none intended

Parity Contract

  • Legacy behavior preserved: managed JWT resolution, thread_id body field, billing envelope recovery, temperature semantics, test-provider override precedence
  • Guard/fallback/dispatch parity checks: resolves_to_managed_backend mirrors the empty/cloud/openhuman dispatch; test override short-circuits before the crate path; the deferred local flip must preserve verify_session_active

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this
  • Resolution: N/A

https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB

Summary by CodeRabbit

  • New Features
    • Improved AI model routing across managed, cloud-compatible, and local runtimes using crate-native chat model construction.
    • Added unified per-turn model sourcing with richer metadata (context window, vision support, native tool capability).
  • Bug Fixes
    • Improved agent run error reporting by preserving full error cause chains.
    • Improved non-retryable classification for locally unreachable providers.
  • Documentation
    • Updated Phase 0 anchors; expanded Phase 1 drift tracking; added Phase 3 router/registry design guidance.
  • Tests
    • Expanded unit/e2e coverage for managed-vs-local routing and vision/native capability paths, plus async Tokio and contract updates.

senamakel and others added 26 commits July 7, 2026 13:56
Record the model-layer inversion baseline (create_chat_model exists as a
zero-behavior-change shim; ~7 runtime create_chat_provider call sites + 25
non-test files outside inference/provider/ still name dyn Provider) ahead of
completing inference-migration-plan Phase 1.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Move the cron model-id resolver and the accessibility vision-locate fallback
off Box<dyn Provider>/create_chat_provider onto the crate ChatModel factory
(create_chat_model / create_chat_model_with_model_id), part of inference
migration Phase 1 (tinyhumansai#4249). Zero behavior change: the factory wraps the same
provider stack via ProviderModel; the [IMAGE:] marker survives the crate
Message -> host ChatMessage round-trip verbatim; cron only needs the resolved
model id (built model discarded).

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
P1-8: one-shot caller migration done (cron, vision); caps.rs + inference_probe
deferred. P1-9: investigation finding that plan Buckets 2-4 (routing/channels,
harness, subagent) are one coupled refactor gated on a ChatModel-accepting
build_turn_models (async context-window + telemetry id must be re-homed), not
independently landable — must be its own reviewed PR with behavior-parity tests.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
The plan's 'harness holds Arc<dyn ChatModel>' is architecturally blocked in
Phase 1: build_turn_models needs the raw Provider for route projection
(per-tier ProviderModel re-aliasing) + separate-error-slot summarizer, and the
crate ChatModel has no downcast to recover it. True inversion is gated on
Phase 3 (RouterProvider -> crate ModelRegistry, upstream). Documents the
host-only alternative (seam newtype boundary).

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Ground-truth finding: RouterProvider -> crate ModelRegistry is ALREADY done at
the seam (assemble_turn_harness registers routes + wires RunPolicy.fallback +
RequiredCapabilitiesMiddleware). The crate's missing capability-selection /
capability-aware-fallback are NOT needed (caller picks the tier; fallback chains
are hand-safe). So Phase 3 needs no upstream crate change. Real remaining work is
host-only Motion A: move build_turn_models to the producer/factory boundary so
the harness holds crate ChatModels (TurnModels), not Arc<dyn Provider>. Motion B
(crate-native clients, deletes compatible*.rs) is the later LOC win.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
- Introduced a comprehensive document outlining the referral system, including an overview, main rules, data model, migration instructions, core services, API endpoints, and payment integration details.
- The document specifies the structure of referral codes, transactions, and the rewards system, ensuring clarity for developers and users.
- Added migration commands for setting up the referral system in the application, enhancing the onboarding process for new users.
…vider

Phase 3 / Motion A (tinyhumansai#4249): introduce the seam-owned TurnModelSource — a
model-agnostic handle that builds a turn's tiered crate ChatModel set
(build_turn_models) — and thread it through the native-bus channel/triage turn
path instead of Arc<dyn Provider>. TurnModels now carries the provider telemetry
id + native-tool/vision/context-window metadata, so run_channel_turn_via_graph
reads capabilities off the built crate models and no longer names the Provider
trait. AgentTurnRequest.provider -> turn_model_source; channels/triage producers
wrap their resolved provider at the bus boundary; the Provider stays confined to
the inference factory + seam.

Zero behavior change: same ProviderModels, same registry/fallback wiring. Both
Cargo worlds' lib compile green; the 3 bus integration tests compile green.
(Pre-existing full --tests breakage in unrelated modules — config load, web,
ollama, sandbox — is untouched.)

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
TurnModelSource landed; channel/bus turn path fully off Arc<dyn Provider>
(commit 30c7dfd). Records remaining subagent + session slices and their
tentacles (SubagentCheckpoint summary provider; Agent lifecycle + model_vision).

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Phase 3 / Motion A (tinyhumansai#4249): thread TurnModelSource through the sub-agent turn
path instead of Arc<dyn Provider>. agent_graph::AgentTurnRequest.provider ->
turn_model_source; run_subagent_via_graph takes the source, reads vision/
native-tool caps + telemetry id off the built crate models, and resolves the
context window via the source. The cap-hit SubagentCheckpoint now summarizes on
a crate ChatModel (built via TurnModelSource::build_summarizer) instead of
provider.chat, so it no longer names the Provider trait. Runner wraps its
resolved subagent_provider at both dispatch sites.

Zero behavior change: same ProviderModels, same registry/fallback; checkpoint
maps ChatRequest->ModelRequest faithfully (max_tokens preserved, temperature
baked). Core lib green; changed files clean under --lib --tests. (extract_tool +
subagent provider.rs resolution remain as documented exit-sweep stragglers.)

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Subagent turn path off Arc<dyn Provider> (commit 8db8887); records remaining
Agent session path + extract_tool/provider.rs stragglers + exit sweep.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…Provider

Phase 3 / Motion A (tinyhumansai#4249): ExtractFromResultTool now holds a TurnModelSource —
queries the model context window through it (source.effective_context_window)
and builds a summarizer crate ChatModel per call (source.build_summarizer) that
it invokes, replacing provider.chat_with_system. Runner wraps the resolved
extract_provider at the tool boundary. Adds TurnModelSource::is_local_provider
passthrough (needed by the upcoming ParentExecutionContext migration). Core lib
green; extract_tool test module clean under --lib --tests; zero behavior change.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Phase 3 / Motion A (tinyhumansai#4249): the final major turn path. Agent + AgentBuilder,
ParentExecutionContext, and ChatTurnGraph now hold a seam TurnModelSource /
built TurnModels instead of Arc<dyn Provider>:

- Agent.turn_model_source builds the tiered crate ChatModel set per turn; core
  resolves the context window + builds up front, reads vision off the built
  models, and hands TurnModels to ChatTurnGraph (which no longer builds/holds a
  provider).
- ParentExecutionContext carries the source; sub-agent inheritance / extract
  summarization-route / rhai model build / is_local_provider read through it.
  TurnModelSource gains is_local_provider() + a provider() escape hatch for the
  few seam-boundary sites that still resolve a raw provider inline (sub-agent
  provider resolution + its 9 unit tests, rhai, payload summarizer) — no
  agent-harness struct holds a Provider.
- The session_io cap-hit checkpoint keeps its streaming provider.chat via
  source.provider() (crate ChatModel::invoke doesn't expose the delta sink).
- Builder .provider()/.provider_arc() setters wrap into a source; Agent
  provider_arc() accessor -> turn_model_source().

Zero behavior change: same ProviderModels, same registry/fallback wiring. Core
lib green; all touched test files (inline + 10 integration tests) compile clean;
remaining --tests errors are pre-existing unrelated modules (config load, web,
ollama, sandbox, reliable_tests, memory) untouched by this change.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…ated)

Session path migrated (9112330); no agent-harness struct holds Arc<dyn Provider>.
Records the remaining provider-resolution boundaries (factory, resolve, delegate,
triage, builder setters) as Motion B (crate-native client) territory.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Formatting-only (line wrapping) applied by cargo fmt over the Motion A changes.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
Restore two e2e specs (cron-jobs-flow, telegram-channel-flow) to upstream/main;
they rode into this branch via an upstream-sync merge and are not part of the
TurnModelSource migration.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…nyagents#44)

Re-pin vendor/tinyagents to the merged crate main (333f9a5), which adds the
configurable AuthStyle (None/Bearer/XApiKey/Anthropic/Custom) + static headers
to OpenAiModel needed to cut the host provider stack over to crate-native
clients (Motion B, tinyhumansai#4727). Both Cargo worlds build green against it (the other
10 crate commits since our pin are additive — no seam adaptation needed);
Cargo.lock picks up sha2 0.11 transitively.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…+temp+merge)

Cutover-branch-only pin to the integration of tinyagents#44 (merged) + tinyhumansai#47 +
tinyhumansai#48, so the host can build the crate-native OpenAiModel provider path against
with_auth_style / with_temperature_* / with_merge_system_into_user. Replaced by
a released-crate bump once tinyhumansai#47/tinyhumansai#48 merge.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…tion B)

First host-side step of the provider cutover (tinyhumansai#4727): a new provider::crate_openai
module that builds a crate-native tinyagents OpenAiModel (ChatModel) from resolved
OpenAI-compatible provider config — mapping the host AuthStyle 1:1 to the crate's,
and applying temperature suppression/override, merge-system-into-user, and static
headers (the tinyagents tinyhumansai#44/tinyhumansai#47/tinyhumansai#48 config). This is the single boundary where
host provider config becomes a crate-native ChatModel; bespoke providers (managed
backend, claude-code/agent-sdk, codex) stay host ChatModel impls and don't route
through here.

Additive + unit-tested (auth mapping 1:1, profile carries provider/model, local
None-auth shape). Not yet wired as the factory default — that + per-provider wire
parity validation (before deleting compatible*.rs) is the follow-up. Core lib
green; module clean under --lib --tests.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…rged)

tinyhumansai#47/tinyhumansai#48 merged; crate main (95fa263) now carries all three OpenAiModel
host-parity features (auth styles tinyhumansai#44, temperature suppression/override tinyhumansai#47,
merge_system_into_user tinyhumansai#48). Re-pin the cutover branch from the local
integration branch to released main so the vendor pin references published
API. Core lib green.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…tover)

Add make_crate_openai_chat_model — the drop-in parallel to the host
make_openai_compatible_provider_with_config, taking the same resolved inputs
(slug, endpoint, credential, host auth style, model, temperature suppression +
override, merge-system) and returning a crate ChatModel instead of a
Box<dyn Provider>. This is the ready swap point for each generic OpenAI-compat
construction site in the factory. Unit-tested; core lib green.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
The bespoke-provider rewrite that gates deleting compatible*.rs: a host
ChatModel (OpenHumanBackendModel) that bridges the managed backend's three
non-generic needs onto the crate wire client — resolves the dynamic session JWT
per call and builds a fresh crate OpenAiModel (Bearer); injects the ambient
thread_id into ModelRequest.provider_options so the crate emits it as a body
field (parity with with_openhuman_thread_id); and relies on the crate preserving
the full response on ModelResponse.raw so the seam still recovers the
openhuman.usage/billing charged-USD + cached-token envelope. resolve_bearer /
base_url exposed pub(super) for reuse. Additive + unit-tested; core lib green.

Not yet wired (make_openhuman_backend still returns the Provider) — that swap is
the create_chat_model flip.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
…end (Motion B)

Wire the cutover: extract resolve_managed_backend (shared model/options
resolution) and add make_openhuman_backend_model (crate-native
OpenHumanBackendModel). create_chat_model_with_model_id now routes the managed
OpenHuman backend through the crate ChatModel instead of a ProviderModel-wrapped
provider — so every one-shot ChatModel caller (memory summarize, learning,
meeting summaries, etc.) uses the crate wire client for the managed backend (the
common case). Test-provider override still wins; temperature rides the per-call
ModelRequest on the crate path. resolves_to_managed_backend mirrors the
empty/cloud/openhuman dispatch. Core lib green.

Claude-Session: https://claude.ai/code/session_018MnMVgnzxchtcs1DDUxTfF
@senamakel senamakel requested a review from a team July 10, 2026 01:20
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces TurnModelSource and richer TurnModels metadata, adds crate-native managed and OpenAI-compatible ChatModel builders, and migrates agent turns, sub-agents, accessibility flows, orchestration paths, and tests away from direct provider payloads.

Changes

Crate-native model migration

Layer / File(s) Summary
Model seam and provider metadata
src/openhuman/tinyagents/mod.rs
Adds TurnModelSource, extends TurnModels with context, capability, and provider metadata, and exposes model-building helpers.
Crate-native provider builders
src/openhuman/inference/provider/*
Adds OpenAI-compatible and managed-backend ChatModel construction, authentication, provider options, capability flags, and thread ID propagation.
Turn and session routing
src/openhuman/agent/...
Replaces direct provider fields with TurnModelSource and passes prebuilt TurnModels through turn execution.
Sub-agent and summarizer paths
src/openhuman/agent/harness/subagent_runner/*
Uses source-built chat models for extraction and checkpoint summaries, and derives vision, provider ID, and context metadata from turn models.
Integration and validation updates
src/openhuman/accessibility/*, src/openhuman/channels/*, src/openhuman/agent_orchestration/*, tests/*, docs/*, vendor/tinyagents
Updates call sites, test fixtures, migration documentation, the TinyAgents revision, retry classification, and asynchronous orchestration tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant TurnModelSource
  participant ChatModel
  participant TurnRunner
  Caller->>TurnModelSource: provide provider source
  TurnModelSource->>ChatModel: build crate-native model
  TurnModelSource->>TurnRunner: provide TurnModels metadata
  TurnRunner->>ChatModel: invoke or stream model request
Loading

Possibly related issues

Possibly related PRs

Suggested labels: feature, rust-core, agent

Suggested reviewers: CodeGhost21, M3gA-Mind

Poem

A rabbit builds models, hop-hop in the flow,
Providers become sources wherever they go.
Tiny tools and visions follow the stream,
Summaries bloom softly from each native dream.
Crates and tests hop onward, aligned as a team.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change set: Motion A completion plus the managed-backend TinyAgents cutover in Motion B.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e98c1b390

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +956 to +957
if !test_override_active && resolves_to_managed_backend(role, config) {
return make_openhuman_backend_model(role, config);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the LocalOnly gate for managed ChatModels

When a role resolves to the managed OpenHuman backend, this early return bypasses the existing create_chat_provider_from_string path that calls enforce_local_only_inference; in LocalOnly privacy mode, callers using create_chat_model/create_chat_model_with_model_id for default chat, summarization, or subconscious roles can still construct and invoke the OpenHuman cloud model. Route the managed shortcut through the same privacy check (including the resolved cloud/empty sentinel) before returning the crate-native model.

Useful? React with 👍 / 👎.

Comment on lines +43 to +47
pub fn new(backend: OpenHumanBackendProvider, default_model: impl Into<String>) -> Self {
Self {
backend,
default_model: default_model.into(),
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply the construction temperature on managed models

For managed-backend roles, the factory still accepts a temperature, but this model stores only the backend and default model, so callers that pass temperature at construction and do not also set ModelRequest::with_temperature lose their requested setting on cloud calls. For example automation uses create_chat_model("summarization", ..., 0.0) and meeting summaries use 0.3; those remain honored for BYOK/local through ProviderModel, but the managed shortcut falls back to the wire client's default unless the default temperature is carried here and applied when the request lacks one.

Useful? React with 👍 / 👎.

Comment on lines +101 to +102
let model = self.build_wire_model()?;
model.invoke(state, with_thread_id(request)).await

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve OpenHuman billing metadata in managed responses

Managed backend responses include openhuman.billing.charged_amount_usd, but this path returns the crate OpenAiModel response unchanged; downstream usage_info_from_response only recovers charged USD from the adapter-specific raw.openhuman_usage_meta shape produced by ProviderModel. For one-shot managed callers such as memory summarization audits, token usage may still exist but charged_amount_usd is recorded as zero, so this wrapper should translate the backend raw metadata into the seam's expected usage meta (or teach the recovery helper to parse the managed raw shape).

Useful? React with 👍 / 👎.

…gents pin (Motion B)

Bump vendor/tinyagents to 1057acf (tinyagents#49: OpenAiModel native-tool/vision
profile toggles + baked provider options) and add the crate-native local-runtime
builder that consumes them:

- crate_openai.rs: CrateOpenAiConfig gains native_tool_calling / vision /
  default_provider_options; build_crate_openai_model applies them after
  provider/model are set (which re-derive the profile the toggles mutate).
- make_crate_local_runtime_chat_model: the crate-native counterpart of the host
  make_*_provider local builders — native tools + vision forced off, Ollama
  num_ctx baked as {"options":{"num_ctx":N}}, matching the host wire shape.
  Unit-tested (profile flags off, provider/model carried).

Builder is ready but NOT yet the live dispatch: create_chat_provider_from_string's
local branches run the verify_session_active gate (custom/local providers require
an active OpenHuman session), and that gate is #[cfg(not(test))] so a crate-native
short-circuit that skipped it would be a security regression no test/CI catches.
The dispatch flip is deferred to a verified-build follow-up (see drift ledger's
Motion B cutover table). Also folds in fmt drift from prior Motion B commits.

Host lib compiles clean with the pin bump (inference/provider changes error-free;
the only local --lib breakage is pre-existing voice/dictation_listener hotkey
imports fixed on upstream/main, resolved by the upstream merge that follows).

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jul 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 034fac3385

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

.chat_with_system(Some(locate_system_prompt()), &user, model, 0.0)
let request = ModelRequest::new(vec![
Message::system(locate_system_prompt().to_string()),
Message::user(user),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve image content for managed vision calls

When the chat role resolves to the managed OpenHuman backend, create_chat_model now returns OpenHumanBackendModel, which forwards this ModelRequest directly to the crate OpenAiModel instead of going through the host compatible provider's MessageContent::from_chat_text marker parser. In that path this Message::user(user) is only a text block containing [IMAGE:data:...], so the screenshot is not sent as an image and locate_via_vision cannot actually inspect the UI. Build a crate message with an actual image content block here, or keep managed vision calls on the host provider path that expands [IMAGE:] markers.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/inference/provider/factory.rs`:
- Around line 940-961: The managed backend path in
create_chat_model_with_model_id drops the constructor temperature, causing
requests without ModelRequest.temperature to differ from provider-backed
behavior. Update make_openhuman_backend_model and OpenHumanBackendModel
construction to accept and retain temperature, or consistently apply it to
managed requests, while preserving the test-provider override behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e37dc8e0-f351-4af4-a642-8195d4693e88

📥 Commits

Reviewing files that changed from the base of the PR and between f5b77ed and 034fac3.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • app/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (48)
  • docs/tinyagents-drift-ledger.md
  • docs/tinyagents-phase3-router-registry-design.md
  • src/openhuman/accessibility/automate.rs
  • src/openhuman/accessibility/vision_click.rs
  • src/openhuman/agent/bus.rs
  • src/openhuman/agent/harness/agent_graph.rs
  • src/openhuman/agent/harness/fork_context.rs
  • src/openhuman/agent/harness/graph.rs
  • src/openhuman/agent/harness/session/builder/setters.rs
  • src/openhuman/agent/harness/session/runtime.rs
  • src/openhuman/agent/harness/session/runtime_tests.rs
  • src/openhuman/agent/harness/session/turn/core.rs
  • src/openhuman/agent/harness/session/turn/graph.rs
  • src/openhuman/agent/harness/session/turn/session_io.rs
  • src/openhuman/agent/harness/session/turn/tools.rs
  • src/openhuman/agent/harness/session/types.rs
  • src/openhuman/agent/harness/subagent_runner/extract_tool.rs
  • src/openhuman/agent/harness/subagent_runner/ops/checkpoint.rs
  • src/openhuman/agent/harness/subagent_runner/ops/graph.rs
  • src/openhuman/agent/harness/subagent_runner/ops/runner.rs
  • src/openhuman/agent/triage/evaluator.rs
  • src/openhuman/agent_orchestration/parent_context/builder.rs
  • src/openhuman/channels/runtime/dispatch/processor.rs
  • src/openhuman/cron/scheduler.rs
  • src/openhuman/inference/provider/crate_openai.rs
  • src/openhuman/inference/provider/factory.rs
  • src/openhuman/inference/provider/mod.rs
  • src/openhuman/inference/provider/openhuman_backend.rs
  • src/openhuman/inference/provider/openhuman_backend_model.rs
  • src/openhuman/rhai_workflows/bridge.rs
  • src/openhuman/skills/e2e_plumbing_tests.rs
  • src/openhuman/skills/e2e_run_tests.rs
  • src/openhuman/tinyagents/mod.rs
  • src/openhuman/tinyagents/payload_summarizer.rs
  • tests/agent_archivist_debug_round21_raw_coverage_e2e.rs
  • tests/agent_harness_leftovers_raw_coverage_e2e.rs
  • tests/agent_harness_public.rs
  • tests/agent_harness_raw_coverage_e2e.rs
  • tests/agent_large_round25_raw_coverage_e2e.rs
  • tests/agent_prompts_subagent_raw_coverage_e2e.rs
  • tests/agent_session_turn_raw_coverage_e2e.rs
  • tests/agent_tool_loop_raw_coverage_e2e.rs
  • tests/agent_turn_toolloop_round22_raw_coverage_e2e.rs
  • tests/calendar_grounding_e2e.rs
  • tests/composio_list_tools_stack_overflow_regression.rs
  • tests/inference_agent_raw_coverage_e2e.rs
  • tests/tools_agent_credentials_state_raw_coverage_e2e.rs
  • vendor/tinyagents

Comment on lines +940 to 961
// Managed OpenHuman backend → crate-native host `ChatModel`
// ([`OpenHumanBackendModel`], issue #4727 Motion B) instead of a
// `ProviderModel`-wrapped provider. A test-provider override (below, inside
// `create_chat_provider`) must still win, so only take this path when no
// override is installed. Temperature rides the per-call `ModelRequest` on the
// crate path (the managed model is reused across prompts of differing temp).
let test_override_active = {
#[cfg(any(test, feature = "e2e-test-support"))]
{
test_provider_override::current().is_some()
}
#[cfg(not(any(test, feature = "e2e-test-support")))]
{
false
}
};
if !test_override_active && resolves_to_managed_backend(role, config) {
return make_openhuman_backend_model(role, config);
}
let (provider, model) = create_chat_provider(role, config)?;
let chat = chat_model_from_provider(provider, model.clone(), temperature);
Ok((chat, model))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find callers of create_chat_model* to see whether they later set request.temperature.
rg -nP --type=rust -C3 '\bcreate_chat_model(_with_model_id)?\s*\(' src
# Inspect whether OpenHumanBackendModel or its wire model ever pins a temperature.
rg -nP --type=rust -C3 'with_temperature_override|temperature' src/openhuman/inference/provider/openhuman_backend_model.rs
# Confirm ProviderModel's temperature fallback for comparison.
rg -nP --type=rust -C2 'request\.temperature' src/openhuman/tinyagents/model.rs

Repository: tinyhumansai/openhuman

Length of output: 7524


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the managed-backend constructor and the chat model temperature fallback.
sed -n '880,1040p' src/openhuman/inference/provider/factory.rs
printf '\n---\n'
sed -n '430,590p' src/openhuman/tinyagents/model.rs
printf '\n---\n'
# Find any managed-backend-specific temperature wiring.
rg -n --type=rust 'with_temperature_override|temperature.*OpenHumanBackendModel|OpenHumanBackendModel' src/openhuman/inference/provider src/openhuman/tinyagents

Repository: tinyhumansai/openhuman

Length of output: 17812


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect OpenHumanBackendModel temperature handling and the managed-backend constructor.
sed -n '1,220p' src/openhuman/inference/provider/openhuman_backend_model.rs
printf '\n---\n'
sed -n '1280,1365p' src/openhuman/inference/provider/factory.rs
printf '\n---\n'
# Check whether the managed backend is constructed with any temperature override elsewhere.
rg -n --type=rust 'make_openhuman_backend_model\(|OpenHumanBackendModel::new\(' src/openhuman/inference/provider/factory.rs src/openhuman/inference/provider/openhuman_backend_model.rs

Repository: tinyhumansai/openhuman

Length of output: 10548


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the upstream OpenAiModel temperature semantics and whether it defaults anywhere.
rg -n --type=rust -C3 'compatible_provider\(|struct OpenAiModel|temperature' src/tinyagents src/openhuman | sed -n '1,260p'

Repository: tinyhumansai/openhuman

Length of output: 20408


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the tinyagents/OpenAiModel implementation and inspect temperature handling.
git ls-files | rg '(^|/)(tinyagents|openai)(/|\.rs$)'
printf '\n---\n'
fd -a 'model.rs|openai.rs|compatible.rs' src . 2>/dev/null | sed -n '1,120p'
printf '\n---\n'
rg -n --type=rust -C4 'struct OpenAiModel|compatible_provider\(|temperature' . | sed -n '1,260p'

Repository: tinyhumansai/openhuman

Length of output: 21817


Managed backend drops the constructor temperature
create_chat_model_with_model_id returns make_openhuman_backend_model(role, config) on the managed route, so the temperature argument never reaches OpenHumanBackendModel. Calls that leave ModelRequest.temperature unset will sample differently on the managed path than on the provider-backed path; thread the temp into the managed model, or set it on every managed request, to keep parity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/inference/provider/factory.rs` around lines 940 - 961, The
managed backend path in create_chat_model_with_model_id drops the constructor
temperature, causing requests without ModelRequest.temperature to differ from
provider-backed behavior. Update make_openhuman_backend_model and
OpenHumanBackendModel construction to accept and retain temperature, or
consistently apply it to managed requests, while preserving the test-provider
override behavior.

Add routing tests proving create_chat_model's Motion B dispatch:
- resolves_to_managed_backend: true for default/cloud-tier roles, false once a
  role points at a local runtime (ollama:).
- managed role → crate-native OpenHumanBackendModel (profile() None, serves every
  tier via request.model).
- local role → ProviderModel wrapper (profile() Some, neutral "local" origin,
  native tools + vision off — the same knobs make_crate_local_runtime_chat_model
  will carry post-flip).

profile() presence is the cheapest observable distinguishing the two
construction paths without a network round-trip. cargo fmt clean; the four
targeted tests pass on a warm target.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
…nyhumansai#49 merged)

The lib-test target (cargo test --lib) did not compile: Motion A renamed
ParentExecutionContext.provider -> turn_model_source (and the AgentBuilder
field), but ~8 agent_orchestration/harness test modules still built the struct
with the old field. No PR existed before tinyhumansai#4769, so this was never CI-tested;
CI rust-core-coverage compiles the full lib-test target and would fail here.

Wrap each stale site in TurnModelSource::new(provider) and fix the AgentBuilder
default-test field access. Sites: subagent_runner/ops_tests, agent_orchestration
{ops_tests, agent_teams/runtime_tests, workflow_runs/engine_tests, tools/
(close_subagent, spawn_parallel_agents_tests, spawn_worker_thread, tools_e2e_tests)}.

Also bump vendor/tinyagents to 7c6e81a (tinyagents#49 merged onto v1.8.0 main:
OpenAiModel native-tool/vision toggles + baked provider options; carries v1.8.0's
tinyhumansai#45 tool-call-arg recovery + tinyhumansai#46 microcompact gate). Cargo.lock 1.7.1 -> 1.8.0;
the `version = "1.7"` requirement admits 1.8.

Verified: lib-test target type-checks with 0 errors (reaches codegen); full
compile/run delegated to CI (contended dev box can't link the full test binary
in-budget). Crate: 61 openai unit tests pass on 7c6e81a.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
@coderabbitai coderabbitai Bot added the feature Net-new user-facing capability or product behavior. label Jul 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/tinyagents-drift-ledger.md`:
- Around line 30-31: The drift ledger entries for the current host pin and
verification PR reference stale commit 7c6e81a; update them to match
vendor/tinyagents commit 85f7c4e796167f6b06a5baaf88896949952c2a63, or clearly
label the existing entries as historical context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f095c8ff-7252-428c-8e87-f09845bf4776

📥 Commits

Reviewing files that changed from the base of the PR and between 034fac3 and 85f7c4e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • docs/tinyagents-drift-ledger.md
  • src/openhuman/agent/harness/session/types.rs
  • src/openhuman/agent/harness/subagent_runner/ops_tests.rs
  • src/openhuman/agent_orchestration/agent_teams/runtime_tests.rs
  • src/openhuman/agent_orchestration/ops_tests.rs
  • src/openhuman/agent_orchestration/tools/close_subagent.rs
  • src/openhuman/agent_orchestration/tools/spawn_parallel_agents_tests.rs
  • src/openhuman/agent_orchestration/tools/spawn_worker_thread.rs
  • src/openhuman/agent_orchestration/tools/tools_e2e_tests.rs
  • src/openhuman/agent_orchestration/workflow_runs/engine_tests.rs
  • src/openhuman/inference/provider/factory_tests.rs
  • vendor/tinyagents
✅ Files skipped from review due to trivial changes (1)
  • src/openhuman/agent_orchestration/tools/spawn_worker_thread.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/openhuman/agent/harness/session/types.rs

Comment thread docs/tinyagents-drift-ledger.md Outdated
Comment on lines +30 to +31
| Current host pin | `v1.8.0-1-g7c6e81a` ([tinyagents#49](https://github.com/tinyhumansai/tinyagents/pull/49) **merged** onto v1.8.0 main) |
| Verification PR | [openhuman#4769](https://github.com/tinyhumansai/openhuman/pull/4769) — Motion A + Motion B checkpoint |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the actual pinned commit for vendor/tinyagents submodule
git -C vendor/tinyagents rev-parse HEAD 2>/dev/null
cat .gitmodules 2>/dev/null | grep -A2 tinyagents
rg -n 'tinyagents' Cargo.toml Cargo.lock 2>/dev/null | head -20

Repository: tinyhumansai/openhuman

Length of output: 1148


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== docs/tinyagents-drift-ledger.md (relevant lines) =="
sed -n '20,40p;85,100p' docs/tinyagents-drift-ledger.md | cat -n

echo
echo "== submodule status =="
git submodule status -- vendor/tinyagents vendor/tinyflows || true

echo
echo "== search for SHAs mentioned in review =="
rg -n '1057acf|7c6e81a|85f7c4e' -S . || true

echo
echo "== vendor/tinyagents HEAD and commit details =="
git -C vendor/tinyagents rev-parse HEAD
git -C vendor/tinyagents show -s --format='%H %s' HEAD

Repository: tinyhumansai/openhuman

Length of output: 3405


Update the ledger pin to match vendor/tinyagents. vendor/tinyagents currently points at 85f7c4e796167f6b06a5baaf88896949952c2a63, so the 7c6e81a entries here are stale; either refresh these lines or mark them as historical context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/tinyagents-drift-ledger.md` around lines 30 - 31, The drift ledger
entries for the current host pin and verification PR reference stale commit
7c6e81a; update them to match vendor/tinyagents commit
85f7c4e796167f6b06a5baaf88896949952c2a63, or clearly label the existing entries
as historical context.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85f7c4e796

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


async fn invoke(&self, state: &(), request: ModelRequest) -> TaResult<ModelResponse> {
let model = self.build_wire_model()?;
model.invoke(state, with_thread_id(request)).await

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Publish SessionExpired for backend auth failures

When a managed OpenHuman call returns HTTP 401/403 from this direct crate path, the error now bubbles out of OpenAiModel without running the legacy backend-auth branch (publish_backend_session_expired in the provider HTTP layer). In non-RPC/background callers that use create_chat_model (for example memory or meeting summarization), that means an expired app-session JWT no longer flips the scheduler gate or clears the session, so the same background work can keep retrying against a permanently invalid token until some separate RPC path happens to classify it. Please translate managed-backend auth failures here into the same SessionExpired publish before returning the error.

Useful? React with 👍 / 👎.

…ck CI)

tests/orchestration_effect_executor_e2e.rs (added by tinyhumansai#4738) still called
dispatch_device_tool/handle_tool_call with the old sync 2-arg signatures after
tinyhumansai#4753 made them async/3-arg — broken identically on upstream/main. It only
surfaced in this PR because the Motion A test-debt fix touched agent_orchestration
files, pulling the orchestration domain into CI rust-core-coverage's scope.

Convert the two affected tests to #[tokio::test] + .await, and pass the cycle_id
arg (the exec gate is bypassed for non-local-exec tools like device_status).

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
… error chain

The full test suite compiles now (Motion A compile debt fixed), which surfaced 5
runtime failures. Deep root-cause: 4 are stale tests written against pre-migration
internals (never CI-run), 1 is a real minor error-surfacing gap. No Motion A/B
runtime-behavior regression — the error/retry/model-resolution contracts hold.

Stale tests (fixed):
- agent_tool_loop / agent_prompts_subagent *surfaces_provider_error*: the crate-owned
  retry (RunPolicy.retry, max 3, mirroring the old ReliableProvider) rides a
  single-shot failing mock through to its empty-queue default Ok. Add an
   field so the mock fails persistently (all attempts) — a genuinely
  unreachable provider still surfaces its error.
- agent_large_round25: extract_from_result now runs per-chunk extraction through the
  crate ChatModel (build_summarizer().invoke() → chat), not the legacy
  chat_with_system; 6 chunk calls drained the agent-turn queue. Route extraction
  calls (detected by the extraction system prompt) to the fixed result in the mock.
- inference_agent…user_state_edges: expected an unknown model to collapse to
  reasoning-v1; the managed backend forwards it verbatim (tinyhumansai#4598). Update the assertion.

Code fix:
- cron run_agent_job surfaced  as e.to_string() (outermost message only),
  dropping the  cause the halt-guard classifier
  needs to detect an offline local provider. Surface the full anyhow chain (),
  matching the comment's stated intent that raw carry provider-URL/stack detail.

Locally verified (RUST_MIN_STACK=128M): the 4 integration-test fixes pass; the cron
lib test is delegated to CI (the full lib-test target won't link in-budget on the
contended dev box).

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/openhuman/cron/scheduler.rs (1)

958-976: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Scrub the Sentry-facing error string src/core/observability.rs:1830-1838 forwards the message directly to sentry::capture_message(...), so the new full {e:#} chain will reach Sentry unchanged. Use a scrubbed capture string, or split the classifier input from the reported message.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/cron/scheduler.rs` around lines 958 - 976, The full anyhow
chain stored in `last_agent_error` is forwarded by `report_error` to Sentry via
`sentry::capture_message`, exposing provider URLs and other sensitive details.
Update `report_error` in `src/core/observability.rs` to scrub the message before
Sentry capture, while preserving the raw error string for local-provider
classification and other non-user-facing observability needs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/openhuman/cron/scheduler.rs`:
- Around line 958-976: The full anyhow chain stored in `last_agent_error` is
forwarded by `report_error` to Sentry via `sentry::capture_message`, exposing
provider URLs and other sensitive details. Update `report_error` in
`src/core/observability.rs` to scrub the message before Sentry capture, while
preserving the raw error string for local-provider classification and other
non-user-facing observability needs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e288d933-7dd5-40e4-b09f-3fcafed9773f

📥 Commits

Reviewing files that changed from the base of the PR and between 85f7c4e and 82ccb3f.

📒 Files selected for processing (7)
  • docs/tinyagents-drift-ledger.md
  • src/openhuman/cron/scheduler.rs
  • tests/agent_large_round25_raw_coverage_e2e.rs
  • tests/agent_prompts_subagent_raw_coverage_e2e.rs
  • tests/agent_tool_loop_raw_coverage_e2e.rs
  • tests/inference_agent_raw_coverage_e2e.rs
  • tests/orchestration_effect_executor_e2e.rs
✅ Files skipped from review due to trivial changes (1)
  • docs/tinyagents-drift-ledger.md

…on fast-fail)

The full suite now runs (14,433 pass); these were the last 4 failures. 3 are
pre-existing branch/merge debt (zero migration commits), surfaced only because
the inference-migration changes broadened the coverage job's scope; 1 is a
migration-adjacent fast-fail fix.

- subconscious tinyplace: tinyhumansai#4738 (hosted-brain migration) retired the tinyplace
  local-world subconscious (SubconsciousKind::ALL = [Memory]), but the trigger
  RPC error message still listed it and json_rpc_e2e still triggered it. Point the
  test at "memory" and correct the error message to "expected memory|all".
- memory_threads schema count: the threads controller surface exposes 19 schemas,
  not 17; the schema/controller parity assert (the real invariant) already held at
  19. Update the tracked count.
- approval decide message: an approve_always_for_flow decision now sits between
  approve_always_for_tool and deny, so the test's stale substring no longer
  matched. Update it to the full current option list.
- cron loopback fast-fail: is_non_retryable now classifies a refused loopback
  connection (offline local LLM server) as non-retryable, so the crate-owned
  retry does not burn ~1.5s of pointless backoff before the identical
  connect-refused. This lets execute_job_with_retry halt within its 5s bound once
  the classification (fixed via the {e:#} cause-chain) trips on the first attempt.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e3f748cda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/src-tauri/Cargo.lock
"serde",
"serde_json",
"sha2 0.10.9",
"sha2 0.11.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Regenerate the Tauri lockfile for tinyagents 1.8

The root lockfile in this same change resolves the patched vendor/tinyagents package as 1.8.0, but the Tauri lockfile's tinyagents stanza is still 1.7.1 while only its dependency list changed here. Because app/src-tauri/Cargo.toml patches the same ../../vendor/tinyagents path and embeds openhuman_core, a locked Tauri build/metadata run will require the lockfile to be updated before compiling the new 1.8 APIs added in this commit. Please regenerate app/src-tauri/Cargo.lock so the tinyagents package version matches the vendored crate.

Useful? React with 👍 / 👎.

… override

create_chat_provider returns the sentinel model mock-model whenever a
process-global test_provider_override is installed (factory.rs). The
create_chat_model seam test installs one while holding inference_test_guard,
but nine create_chat_provider/create_chat_model routing tests read the global
without the guard, so cargo's parallel runner could run them during the
override window and observe mock-model instead of the resolved id. Adding the
new create_chat_model routing tests shifted scheduling enough to surface the
latent race (create_chat_provider_subconscious_honours_byok_route flaked).

Hold inference_test_guard in every create_chat_provider/model routing test so
they serialize with the override-installing tests. Isolation-only; no behavior
change.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
create_chat_model_with_model_id now routes local OpenAI-compatible runtimes
(Ollama / LM Studio / MLX / OMLX / local-openai) through a crate-native
tinyagents OpenAiModel instead of a ProviderModel-wrapped host provider, via the
new try_create_local_runtime_chat_model. Cloud / BYOK / bespoke providers return
None there and fall through to the existing Provider path.

Safety:
- The flip re-runs the SAME access gate the Provider path applies to
  custom/local providers: enforce_local_only_inference (privacy mode) +
  verify_session_active (session requirement, cfg(not(test))). Routing here
  cannot bypass either.
- Endpoint / auth / num_ctx resolution mirrors each make_*_provider exactly
  (same ollama_base_url_from_config / lm_studio_base_url / profile helpers);
  native tools + vision forced off; Ollama num_ctx baked as
  {"options":{"num_ctx":N}}. Temperature rides the per-call ModelRequest
  (managed-path parity; the @<temp> suffix still bakes a fixed override).
- Bumps vendor/tinyagents to b580f1a (tinyagents#50): the crate wire client now
  surfaces the full transport error source chain, so the crate-native local path
  still exposes the connection-refused errno the cron loopback halt guard needs.
  Without it, flipping lmstudio to crate-native would re-break
  cron_agent_job_local_provider_offline_trips_halt_guard.

Tests: the ollama routing test now asserts crate-native (profile provider
"ollama", tools/vision off) instead of the ProviderModel adapter's neutral
"local"; add a None-path test (managed + cloud fall through); guard the memory
build_chat_runtime local tests against the global override. Lib compiles clean;
full verification on CI.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e226aba875

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +964 to +965
if let Some(result) = try_create_local_runtime_chat_model(role, config) {
return result;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve construction temperature for local runtimes

When chat_provider/memory_provider resolves to a local runtime without an @temperature suffix, this new shortcut returns a crate OpenAiModel before the fallback chat_model_from_provider(..., temperature) path can bake in the caller-supplied temperature; try_create_local_runtime_chat_model only forwards the parsed provider-string suffix (temp) and has no access to this temperature argument. One-shot callers such as meeting summaries (create_chat_model("summarization", ..., 0.3)) and automation decisions (..., 0.0) do not set ModelRequest::with_temperature, so local Ollama/LM Studio/etc. calls now fall back to the wire client's default sampling instead of the requested deterministic/low-temperature behavior.

Useful? React with 👍 / 👎.

…e-provider-cutover

# Conflicts:
#	src/openhuman/subconscious/schemas.rs
#	tests/orchestration_effect_executor_e2e.rs
#	tests/raw_coverage/agent_prompts_subagent_raw_coverage_e2e.rs
#	tests/raw_coverage/agent_tool_loop_raw_coverage_e2e.rs
#	tests/raw_coverage/memory_threads_raw_coverage_e2e.rs
…avior

The upstream merge replaced the old cron_agent_job_local_provider_offline_trips_
halt_guard test with cron_agent_job_short_loopback_send_error_stays_retryable —
i.e. upstream decided an offline local provider STAYS RETRYABLE (it may be
transiently starting up), rather than tripping the halt guard.

My earlier cron loopback work went the opposite way (surface the connection-
refused errno so the offline signal trips the halt guard). With the local-runtime
flip routing lmstudio crate-native and tinyagents#50 (error_source_chain) surfacing
the errno, run_agent_job's raw now carried "connection refused (os error N)", so
is_local_provider_unreachable_failure returned true and the new upstream test
failed.

Defer to upstream:
- run_agent_job raw back to e.to_string() (drop the {e:#} cause-chain surfacing).
- Remove the is_non_retryable loopback fast-fail branch.
- Re-pin vendor/tinyagents to 7c6e81a (before tinyhumansai#50), so the crate-native local
  error does not surface the errno the classifier trips on. tinyhumansai#50 stays a good crate
  improvement but is deliberately not consumed here.

The local-runtime crate cutover itself (which needs tinyhumansai#49's toggles, not tinyhumansai#50) is
unchanged. Resolves the sole failure after the upstream merge.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36c1dca43b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +66 to +70
Ok(OpenAiModel::compatible_provider(
PROVIDER_LABEL,
token,
base_url,
&self.default_model,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve configured proxy for managed backend calls

When users configure OpenHuman's runtime proxy with the default openhuman scope or a provider.*/provider.compatible service scope, the legacy managed backend path built its reqwest client through compatible_request.rs, which applies apply_runtime_proxy_to_builder. This direct OpenAiModel::compatible_provider construction has no hook for that host client/proxy config, so managed one-shot calls now cut over here (memory/meeting summaries, automation) will try a direct connection and fail in proxied environments unless the proxy was exported as process env. Please keep the managed backend on the host client path or thread the configured client/proxy into the crate model before dispatch.

Useful? React with 👍 / 👎.

…tream

The upstream merge moved the raw_coverage tests to tests/raw_coverage/ and, for
agent_tool_loop + agent_prompts_subagent, I took upstream's version (which had
the same always_fail fix). But upstream/main does not carry Motion A's
AgentTurnRequest.provider -> turn_model_source / ParentExecutionContext.provider
-> turn_model_source rename, so those two upstream files construct the old field
and don't compile against this branch. (Latent until the submodule-pin change
triggered CI's full-suite fallback, which compiles raw_coverage_all.)

Re-wrap both sites in TurnModelSource::new(provider). A full tests/ scan confirms
no other old-provider construction sites remain.

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
@senamakel senamakel merged commit d5ce6aa into tinyhumansai:main Jul 11, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant