Commit graph

4560 commits

Author SHA1 Message Date
Bryan Helmkamp
a4978812e7 Implement spec gaps: StepFinish stream event, OpenAI org/project headers, default_headers
Add StepFinish stream event variant emitted between tool execution steps
during streaming, matching spec section 5.9. Add OPENAI_ORG_ID and
OPENAI_PROJECT_ID env var support with corresponding HTTP headers. Add
default_headers builder method to all four provider adapters for custom
header injection in programmatic setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:41:16 -04:00
Bryan Helmkamp
2f89a440c0 Implement spec gaps: Anthropic structured output, metadata, Gemini rate limits
- Anthropic: Add response_format support via tool-based extraction (JsonSchema
  injects synthetic tool, JsonObject appends system prompt instruction)
- Anthropic: Pass Request.metadata through to Messages API
- Anthropic: Refactor complete()/stream() to share build_api_request()
- Gemini: Parse rate limit headers from HTTP responses in complete() and stream()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:31:26 -04:00
Bryan Helmkamp
5f2385b87b Implement spec gaps: abort signal, StreamResult, provider_options, max_tool_rounds fix
- Add abort signal support using CancellationToken for cooperative cancellation
  of generate() and stream() calls
- Fix max_tool_rounds=0 to skip tool execution entirely (was executing first round)
- Add StreamResult wrapper with response(), text_stream(), partial_response()
  and multi-step tool loop support in high-level stream()
- Add OpenAI metadata and provider_options.openai pass-through to Responses API
- Add Gemini provider_options.gemini pass-through (safety settings, cached content)
- Add OpenAI-compatible provider_options.<name> pass-through using adapter name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:23:22 -04:00
Bryan Helmkamp
ed07d43335 Implement spec gaps: rate limit headers, error classification, total timeout, metadata, stream_object
- Parse x-ratelimit-* headers into RateLimitInfo for Anthropic, OpenAI, and
  OpenAI-compatible providers (previously hardcoded to None)
- Add "not found"/"does not exist" and "unauthorized"/"invalid key" error
  message classification patterns for ambiguous HTTP status codes
- Apply TimeoutConfig.total to wrap the entire multi-step generate() loop
  (previously only per_step was used)
- Add metadata field to GenerateParams with builder method, pass through to
  Request instead of hardcoding None
- Implement stream_object() for streaming structured output with incremental
  JSON parsing via new ObjectStreamEvent type (Partial/Delta/Complete variants)
- Add OpenAI-compatible Chat Completions adapter for third-party endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:05:10 -04:00
Bryan Helmkamp
cfd1d5ccea Simplify codebase: deduplicate providers, remove redundancy, clean up types
Extract shared provider helpers (parse_error_body, send_and_read_body,
extract_system_prompt, ApiMessage) into providers/common.rs, eliminating
duplicated logic across all three providers. Simplify StepResult and
GenerateResult to derive fields from the embedded Response rather than
storing redundant copies. Remove stringly-typed ToolCall.r#type and
ResponseFormat.r#type in favor of proper enums. Remove unused dependencies
(hyper, clap, rayon, base64, etc.), use LazyLock for the model catalog,
and fix miscellaneous idiom issues (unnecessary Vec collects, inconsistent
error Display, module_name_repetitions).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:38:02 -04:00
Bryan Helmkamp
be7f78ba9f Replace stringly-typed structs with proper Rust enums and deduplicate types
- ContentPart: struct with kind discriminant + 7 Option fields → enum with 8 variants
- StreamEvent: struct with type discriminant + 8 Option fields → enum with 13 variants
- FinishReason: struct wrapping String → enum (Stop, Length, ToolCalls, etc.)
- ToolChoice: struct with mode String → enum (Auto, None, Required, Named)
- SdkError: 9 provider variants with identical fields → Provider { kind, detail }
- Merge ToolCallData into ToolCall, remove ToolResultData in favor of ToolResult
- Add provider implementations (anthropic, openai, gemini) and integration tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:20:45 -04:00
Bryan Helmkamp
9e0d40cd00 Add .env to gitignore and add .env.example
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:42:31 -04:00
Bryan Helmkamp
38a2cb0a0a Enable all clippy lints and fix all warnings
Enable clippy::all, pedantic, nursery, and cargo lint groups at the
workspace level. Fix all resulting warnings: merge identical match arms,
add #[must_use] and doc sections, derive Eq, use clone_from, add type
alias for complex types, extract helpers to reduce function length, and
add crate metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:41:43 -04:00
Bryan Helmkamp
4cbd66c670 Empty commit 2026-02-19 13:42:09 -04:00
Bryan Helmkamp
40be740949 specs 2026-02-19 13:41:55 -04:00