Add CLI providers runtime — Rust mirror of npcpy#2
Open
svax974 wants to merge 1 commit into
Open
Conversation
Mirrors npcpy/llm_funcs.py CLI provider support so the Rust REPL and
serve binaries route CLI agent tools (claude_code, opencode, codex,
kimi_code, kilo, gemini, amp, aider) identically to the Python core.
Cross-language parity is required by the project rule (see project
memory: Rust/Python CLI provider sync).
src/llm_funcs.rs:
- run_cli_provider: tokio::process::Command + BufReader::lines() live
streaming, Arc<AtomicBool>/Mutex spinner coordination, \x1b7/\x1b8\x1b[J
post-stream cursor restore. Same API parity with the litellm path as
the Python implementation
- ClaudeStreamParser, OpencodeStreamParser, CodexStreamParser,
KimiStreamParser: structs implementing the same feed/finalize pattern
as the Python parser hierarchy. Wrapped in
`enum CliStreamParser { Claude, Opencode, Codex, Kimi }` with zero-cost
dispatch (no Box<dyn Trait>); for_provider() constructs the right
variant from the provider string
- ParserResult { text, usage, cost, parsed_session_id }: uniform output
type across all parsers
- resolve_session_id(): single match consolidating the two parallel
per-provider chains that previously existed
- parse_claude_output, parse_opencode_output, parse_codex_output:
one-shot wrappers around the parsers (backward compatible)
- build_cli_cmd, wrap_with_system, fetch_*_session_id helpers
- md5_hex shells out to python3 to avoid pulling in an MD5 crate
- LlmResponseResult.session_id: Option<String>
src/npc_compiler.rs, src/serve/mod.rs:
- Forward two new None args to get_llm_response_ext call sites
(session_id + a CLI streaming flag) — internal-only signature update
cargo build clean: 0 errors, 0 warnings. File length 2553 -> 2732 lines.
7 tasks
2 tasks
cagostino
added a commit
to NPC-Worldwide/npcsh
that referenced
this pull request
May 11, 2026
- Remove unused _is_cli_provider import (F401) - Fix f-string without placeholders in ui.py (F541) - Update test_jinxes.py to look in lib/search/ for search jinxes - Comment out Rust CLI provider intercept block until npcrs publishes CLI_PROVIDERS + run_cli_provider (depends on NPC-Worldwide/npcrs#2)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rust mirror of
NPC-Worldwide/npcpy#235. Routes CLI agent tools (claude_code,opencode,codex,kimi_code,kilo,gemini,amp,aider) through the Rust REPL and serve binaries identically to the Python core. Cross-language parity is required so the Rust shell behaves the same as the Python one when an NPC is bound to a CLI provider.Depends on: npcpy#235 — same set of providers, same JSONL formats, same session-id semantics. Should land after npcpy#235.
What's in this PR
run_cli_providerinsrc/llm_funcs.rs—tokio::process::Command+BufReader::lines()live streaming,Arc<AtomicBool>/Mutexspinner coordination,\x1b7/\x1b8\x1b[Jpost-stream cursor restore. Same API parity with the litellm path as the Python implementation.ClaudeStreamParser,OpencodeStreamParser,CodexStreamParser,KimiStreamParser) implementing the samefeed/finalizepattern as the Python parser hierarchy. Wrapped inenum CliStreamParser { Claude, Opencode, Codex, Kimi }with zero-cost dispatch (noBox<dyn Trait>);for_provider()constructs the right variant from the provider string.ParserResult { text, usage, cost, parsed_session_id }— uniform output type across all parsers.resolve_session_id()— single match consolidating the two parallel per-provider chains that previously existed.build_cli_cmd,wrap_with_system,fetch_*_session_idhelpers mirroring the Python signatures.parse_claude_output,parse_opencode_output,parse_codex_output— one-shot wrappers around the parsers (backward compatible).md5_hexshells out topython3 -c hashlib...to avoid pulling in an MD5 crate.Verification
cargo buildclean: 0 errors, 0 warnings.src/npc_compiler.rsandsrc/serve/mod.rsonly forward two newNoneargs toget_llm_response_extcall sites (internal-only signature update, no behaviour change for non-CLI providers).Test plan
provider: opencode, send a prompt — response streams live, session ID is captured and reused on the next turnprovider: claude_codewith pre-assigned UUID — multi-turn continuitycargo build && cargo clippyremain clean🤖 Generated with Claude Code