Skip to content

ed-acp: on-device inference with Provider::Local - #20

Merged
setoelkahfi merged 2 commits into
developmentfrom
feature/ed-acp-local-provider
Oct 10, 2026
Merged

setoelkahfi merged 2 commits into
developmentfrom
feature/ed-acp-local-provider

Conversation

@setoelkahfi

Copy link
Copy Markdown
Collaborator

Adds a third provider next to Onde Cloud and OpenAI API compatible endpoints. <PREFIX>_PROVIDER=local runs the agent's turns on the device with onde, offline and without a key.

It sits behind an optional local feature, so cloud-only agents don't build mistral.rs. Without the feature the provider can still be chosen, and every turn says how to enable it.

  • Turn loop: LlmClient::complete converts the turn loop's OpenAI message and tool JSON to onde ChatTurns and ToolDefinitions, then runs onde's stateless ChatEngine::complete (Add ChatEngine::complete for caller-owned conversations onde#20). Sessions therefore keep working as they do on the cloud: persisted, loaded and replayed with their tool calls. A turn's reasoning and text arrive when the turn ends, since onde doesn't stream tool-aware turns yet.
  • Engine and models: one engine per process, loaded with the session's model on first use. The first use downloads the model, and a thought says so. Models come from onde's tool-calling catalog, which models() lists. The default is Qwen3 4B Instruct 2507, or Qwen3 1.7B on iOS and Android.
  • No key: AUTH_REQUIRED doesn't apply and check_auth passes. A stored ONDE_API_KEY isn't read as this provider's key.
  • Setup: --setup offers "On-device" when the feature is compiled in.

Blocked on onde 1.4.0. The workspace patches onde to a sibling checkout for now, so CI can't build this PR. Once onde 1.4.0 is on crates.io, the patch goes away and the workspace requires onde = "1.4".

The design is in smbcloudXYZ/splitfire .agents/specs/splitfire-ai-agent/on-device-inference.md.

Tested

  • cargo test -p ed-acp: 35 tests, including the new ones for the message and tool conversion, the default model being in the catalog, and the local config needing no key.
  • clippy is clean with and without local, and on the whole workspace.
  • End to end through LlmClient::complete with Qwen3 4B Instruct 2507: the model called the offered tool (theory_chord {"symbol":"F#m7b5"}), then answered "F#, A, C, and E" from its result. Usage was reported (160 prompt and 26 completion tokens).

A third provider beside Onde Cloud and OpenAI API compatible endpoints:
<PREFIX>_PROVIDER=local runs the agent's turns on the device with onde,
offline and without a key. Behind an optional `local` feature, so
cloud-only agents don't build mistral.rs; without it the provider can
still be chosen and every turn says how to enable it.

- LlmClient::complete converts the turn loop's OpenAI message and tool
  JSON to onde ChatTurns and ToolDefinitions and runs onde's stateless
  ChatEngine::complete, so sessions keep working as they do on the
  cloud: persisted, loaded and replayed with their tool calls. The
  reasoning and text of a turn are reported once the turn ends, since
  onde doesn't stream tool-aware turns yet.
- One engine per process, loaded with the session's model on first use
  (downloaded the first time, with a thought saying so). Models come
  from onde's tool-calling catalogue, which models() lists. Default:
  Qwen3 4B Instruct 2507, or Qwen3 1.7B on iOS and Android.
- No key is needed, so AUTH_REQUIRED doesn't apply and check_auth
  passes. A stored ONDE_API_KEY is not read as this provider's key.
- --setup offers "On-device" when the feature is compiled in.

Needs onde 1.4 (ChatEngine::complete). Until it is published the
workspace patches onde to a sibling checkout.

Checked end to end through LlmClient::complete with Qwen3 4B Instruct
2507: the model called the offered tool, then answered from its result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@sigit-code-review sigit-code-review 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.

This change introduces on-device inference as a new provider (Provider::Local) to ed-acp, allowing agents to run turns locally using onde, without requiring an API key or network access. The feature is optional and gated behind the local feature flag, so cloud-only builds do not include onde dependencies. The CLI setup flow is updated to offer the local provider when available, and the LlmClient logic is extended to route completions and model listings to the local engine when selected. The local.rs module handles conversion between OpenAI-style messages/tools and onde's formats, manages model loading, and provides test coverage for conversion logic and catalog correctness. If the feature is disabled, attempts to use the local provider return a clear error. The change is blocked on onde 1.4.0 being released, as noted in Cargo.toml and the comments. Previous review threads appear addressed, with new tests and feature gating in place.


Automated review by siGit Code Review · commit 15620a5 · see the review dashboard

Comment thread crates/ed-acp/src/local.rs
@paydii
paydii self-requested a review October 9, 2026 18:06
@setoelkahfi setoelkahfi self-assigned this Oct 9, 2026
@setoelkahfi
setoelkahfi requested a review from keypair34 October 9, 2026 19:34
@setoelkahfi
setoelkahfi added this pull request to stack #22 October 9, 2026 19:54

@sigit-code-review sigit-code-review 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.

LGTM, thanks.

Comment thread Cargo.toml Outdated
@setoelkahfi
setoelkahfi removed this pull request from stack #22 October 9, 2026 23:04
1.3.2 ships ChatEngine::complete, so the path override to a sibling onde checkout is no longer needed. It also broke CI, where ../onde does not exist.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

@sigit-code-review sigit-code-review 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.

This change introduces a new on-device inference provider (Provider::Local) to ed-acp, allowing agents to run turns locally using onde's engine when built with the local feature. The provider is integrated into the setup flow, configuration, and model listing. The implementation ensures that only one model is loaded at a time per process, and the provider is selectable even when the feature is disabled, with clear error messaging. The code includes conversion between OpenAI-style messages/tools and onde's internal types, and is covered by targeted tests. The onde dependency is bumped to 1.3.2 to support the required API. Previous findings about engine locking have been addressed as intentional and documented.


Automated review by siGit Code Review · commit 48cb619 · see the review dashboard

@setoelkahfi
setoelkahfi merged commit 7dde490 into development Oct 10, 2026
1 check passed
@setoelkahfi
setoelkahfi deleted the feature/ed-acp-local-provider branch October 10, 2026 05:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants