KeiSeiKit-1.0/_primitives/_rust/kei-router/INTEGRATION.md
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

111 lines
3.8 KiB
Markdown

# kei-router LLM provider — INTEGRATION.md
> v0.40 Wave 32. Multi-provider LLM abstraction. This file is the orchestrator
> wiring guide for `kei-cortex/src/handlers/chat.rs`. The kei-router crate
> ships standalone — wiring it into kei-cortex is a separate commit owned by
> the orchestrator (RULE 0.13: agent writes files only; orchestrator commits).
## Three-step orchestrator wire-in (kei-cortex)
### 1. CLI flag on the daemon (`kei-cortex/src/main.rs`)
Add a `--provider <name>` flag to the existing clap config. Default = `anthropic`.
```rust
#[arg(long, default_value = "anthropic")]
provider: String,
```
Pass it into `AppState` at startup.
### 2. Replace direct `anthropic::open_stream` with `LlmRouter::pick`
In `kei-cortex/src/handlers/chat.rs`, find the call site:
```rust
let stream = anthropic::open_stream(system, &messages).await?;
```
Replace with:
```rust
let provider = state.router.pick(&provider_name)?;
let stream = provider.stream_message(system, &messages, None).await?;
```
The stream type changes from `Stream<Item = Result<String, Error>>` to
`BoxStream<'static, Result<StreamEvent, LlmError>>`. Update the handler's
SSE forwarding loop to match on `StreamEvent::Token(t)` for tokens and
`StreamEvent::Done` for clean stream end.
### 3. Wire `LlmRouter` into `AppState`
In `kei-cortex/src/state.rs`:
```rust
use std::sync::Arc;
use kei_router::LlmRouter;
pub struct AppState {
// ... existing fields ...
pub router: Arc<LlmRouter>,
}
```
At startup (`kei-cortex/src/main.rs::run` or wherever `AppState` is
constructed):
```rust
let router = Arc::new(LlmRouter::from_env());
let state = AppState { /* ..., */ router };
```
`LlmRouter::from_env()` registers any provider whose API key is present:
`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `KIMI_API_KEY` (or
`MOONSHOT_API_KEY` as fallback for kimi).
## Errors to surface to clients
`kei_router::LlmError` enum maps to:
| LlmError variant | HTTP status | Notes |
|------------------------|--------------|-----------------------------------|
| `MissingKey(_)` | 500 (config) | Daemon misconfig — log + alert |
| `RateLimit(_)` | 429 | Pass through to client |
| `ServiceUnavailable(_)`| 503 | Pass through |
| `Timeout(_)` | 504 | Per-provider 60s handshake budget |
| `Upstream { ... }` | 502 | With truncated body in log only |
| `UnknownProvider(_)` | 400 | Bad `--provider` value |
| `Http(_)` | 502 | Connection-level |
## Cost-based dispatch (optional, v0.40+)
When the caller provides a token estimate, `LlmRouter::cheapest_for_estimated_tokens`
returns the cheapest registered provider. Useful for batch / non-interactive
flows. NOT used for interactive chat by default — interactive flows pin the
provider via `--provider`.
## Testing the integration
After the three steps above, run the existing kei-cortex tests AND:
```bash
ANTHROPIC_API_KEY=sk-ant-... \
cargo test -p kei-cortex chat_smoke_test
```
A new smoke test should hit `/chat` with `?provider=anthropic` and assert
stream of `data: { "type": "token", "text": "..." }` events.
## Constructor Pattern compliance
| File | LOC | Cubes |
|---------------------------------------|-----|----------------------|
| `src/provider.rs` | ~80 | trait + 4 types |
| `src/llm_router.rs` | ~100| `LlmRouter` only |
| `src/providers/anthropic.rs` | ~140| 1 provider |
| `src/providers/openai.rs` | ~140| 1 provider |
| `src/providers/kimi.rs` | ~140| 1 provider |
| `src/providers/sse.rs` | ~70 | shared parser |
All under the 200 LOC/file, 30 LOC/fn budgets.