- OpenAI-compatible provider: a streamed response now keeps the vendor fields
of
usage(OpenRouter'scost,cost_details,is_byok) onraw, underusage, where the non-streaming response already has them in its wire body. A caller that reads a reported charge from/usage/costsaw it only when it did not stream. The token counts the normalized usage reads stay offraw, so a plain OpenAI stream still hasraw: None. - Depend on
tinystoragedrivers-core/-secretsv0.7.0 (was v0.5.0), so a host that vendors the v0.7.0 storage crates holds oneSecretStoreand oneBlobStoretrait instead of two (tinyhumansai/openhuman#7641).
- Storage goes through tinystoragedrivers ports:
OAuthFlow::newtakes anArc<dyn SecretStore>,start/clear_pendingare async,pending_filenameis nowpending_secret;GeneratedMedia::persistwrites to aBlobStoreand returnsBlobMeta(newError::Storage).
- OpenAI-compatible provider: an Anthropic-family request that asks for
prompt-cache breakpoints now also marks its newest text-bearing message. In a
tool loop the last user message stops moving, so the assistant tool calls and
tool results behind it were re-sent uncached on every call. Measured on
anthropic/claude-haiku-5.5through OpenRouter over an 8-round tool loop: 31% of prompt tokens read from cache before, 82% after. Other models keep the system and last-user breakpoints (Gemini honours only the last breakpoint).
- Removed the stale copy of the harness response cache from
tinyinference_llm::cache:cache_key, theResponseCachetrait,InMemoryResponseCache,PromptCacheLayoutandCacheLayoutEvent. Nothing used them; the maintained versions (scoped keys, SQLite store, singleflight, prompt-layout guard) live intinyagents-harness'scachemodule.CachePolicystays attinyinference_llm::cache::CachePolicy, unchanged.canonical_valueis now public there. The crate no longer depends onsha2.
- OpenAI-compatible provider:
OpenAiConfigaccepts a host-configuredreqwest::Client, used for every transport path, so a custom provider can trust private CA certificates (openhuman#6905). - Model discovery reads an Ollama server's context window from the native
POST /api/showwhen its/v1/modelslisting carries none (LimitSource::NativeApi,DiscoveryRequest::with_ollama_native,ModelListingFetcher::post_json). The smaller ofnum_ctxand the architecturecontext_lengthis used (openhuman#7099). tinyinference-image: theImageGeneratortrait,OpenRouterImageGenerator(POST /images),MockImageGenerator, media-reference standards (URL,data:URL, bytes, local path → OpenRouter content parts), aspect-ratio, resolution and size normalization, per-model capability pre-flight checks, and a billing-aware OpenRouter media transport usable directly or through a proxying backend.tinyinference-video: theVideoGeneratortrait,OpenRouterVideoGenerator(POST /videos,GET /videos/{id},GET /videos/{id}/content),wait_for_job(resume by job id), andMockVideoGenerator. Acompletedjob with no outputs keeps polling instead of failing.- OpenAI-compatible chat: a
ReasoningConfig::budget_tokenssent to an OpenRouter endpoint is now emitted asreasoning: {"max_tokens": N}(andreasoning_effortis omitted, since OpenRouter takes one or the other). Other OpenAI-compatible endpoints still drop the budget, and an explicitreasoningprovider option still wins. - OpenAI-compatible chat: adaptive parameter omission. A 400 whose message
names an optional field the request sent (
temperature,top_p,seed,max_tokens,max_completion_tokens,reasoning_effort) drops that field, retries once, and remembers the omission for that endpoint and model. The evidence rule and the process-wide store are public asproviders::omission::{parameter_blamed_by, remember_omit, is_omitted}. providers::BearerSourceandOpenAiModel::with_bearer_source: a credential read per request (honouringAuthStyle, invalidated on 401) so a rotating token no longer forces rebuilding the model.- Anthropic: a request carrying both a reasoning
effortandbudget_tokensnow keeps adaptive thinking with that effort, byte-identical to the effort-only request. Fixed-budget thinking is used only when no effort is set. (Previously the budget won.)
scrub_credentialsno longer redacts ordinary source code. Keys must be whole identifiers ending in a sensitive word, key/operator/value never span a newline,==comparisons are ignored, and the value must look like a secret: known provider prefixes (sk-,ghp_,github_pat_,xox?-,AKIA, JWTeyJ) always redact, while placeholders ("<eos>"), whitespace, signed or fractional numbers, digit-less identifiers (None,self.vocab) and values followed by(,[or member access pass through.
ModelStreamis a metadata-owning stream struct. This source-breaking change means customChatModelimplementations must replace directOk(Box::pin(stream))returns withOk(ModelStream::new(Box::pin(stream))).ModelRequestnow distinguishesmodelfromrequested_route. Hosts must usewith_requested_routewhen fallback observability needs a route name.ModelResponseincludescorrelationandresolved_route; custom response literals must initialize both fields.
- Typed model-call correlation, route metadata, fixed-point charged usage, and context-window usage fields.
- Abort-on-drop streams, generic model decorators and terminal observers.
- Cancellable, validated embedding requests and responses.
See docs/migrations/0.3.md for migration details.