Running the opt-in live suite (CM_LIVE_LLM=1 + ANTHROPIC_API_KEY) against
the real API immediately surfaced a launch blocker: Anthropic (and
OpenAI) restrict tool names to ^[a-zA-Z0-9_-]{1,128}$ — our ENTIRE
registry uses dotted names (clock.now, email.send, shell.exec, ...).
The scripted provider never enforced the pattern, so every real-model
deployment would have 400'd on the first tool call.
- Fix at the provider boundary, where it belongs: wire_tool_name /
internal_tool_name codec (dots <-> __) applied in BOTH HTTP providers
at all three sites (tools list, assistant tool_use echo, inbound
tool_use decode). Internal naming (DB step rows, scenarios, UI traces)
unchanged. Offline unit test round-trips every registry name through
the wire pattern
- New live tests, all passing against api.anthropic.com (Haiku 4.5):
- provider tool ROUND TRIP: real ToolUse arrives, ToolResult ships
back exactly as a checkpoint would reassemble it, model completes,
real usage events on the wire
- full runtime loop: real model calls clock.now, run completes, REAL
token usage metered, credits decremented
- the #1-risk validation: a real model's email.send intercepted ->
suspended -> approved -> checkpoint RESUMED against the live API ->
completed -> outbox exactly 1 (checkpoint/resume fidelity end to end)
- Stray TC_OPENAI_COMPAT_* envs renamed to CM_OPENAI_COMPAT_*
No credentials stored anywhere; the key was passed via env only.
163 Rust tests (+5 live, key-gated).
Co-Authored-By: Claude Fable 5 <[email protected]>
25 lines
895 B
Rust
25 lines
895 B
Rust
//! LLM access for Clawmates. One provider trait, three shipping
|
|
//! implementations selected by configuration:
|
|
//!
|
|
//! - `anthropic` — Anthropic Messages API (cloud target)
|
|
//! - `openai_compat` — any OpenAI-compatible endpoint (air-gapped vLLM /
|
|
//! Ollama / llama.cpp)
|
|
//! - `scripted` — deterministic scenario engine; the test/e2e/smoke-test
|
|
//! provider that exercises the exact production seam
|
|
//!
|
|
//! Everything upstream (runtime, gateway, UI) speaks only the
|
|
//! provider-neutral types in `provider.rs`.
|
|
|
|
mod anthropic;
|
|
mod openai_compat;
|
|
mod provider;
|
|
mod scripted;
|
|
|
|
pub use anthropic::AnthropicProvider;
|
|
pub use openai_compat::OpenAiCompatProvider;
|
|
pub use provider::{
|
|
internal_tool_name, wire_tool_name, ChatMessage, ChatRequest, ChatRole, ContentPart,
|
|
EventStream, LlmError, LlmEvent, LlmProvider, StopReason, ToolDescriptor,
|
|
};
|
|
pub use scripted::ScriptedProvider;
|