Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
178 commits
Select commit Hold shift + click to select a range
62cff37
feat(session): versioned schema migrations, busy_timeout, missing ind…
senamakel Aug 8, 2026
db37294
fix(retry): additive jitter, backoff-on-by-default, Retry-After, retr…
senamakel Aug 8, 2026
70f0c80
feat(events): failure-path variants and a panic-safe dispatch guard
senamakel Aug 8, 2026
90fc612
feat(limits): fail-closed cap reconciliation and stop-with-partial ex…
senamakel Aug 8, 2026
cc3a177
fix(harness): pairing-safe trimming, tool-aware token estimates, tool…
senamakel Aug 8, 2026
b5b6c3c
fix(steering): validate batches atomically and latch pauses across ch…
senamakel Aug 8, 2026
69339e4
fix(session): guard the task-claim CAS on status, keep upsert read-ba…
senamakel Aug 8, 2026
f1231a0
feat(session): atomic FTS indexing, retention/pruning entry points, F…
senamakel Aug 8, 2026
47762fa
feat(checkpoint): put_writes/get_writes protocol, durable file writes…
senamakel Aug 8, 2026
7ec1b94
feat(harness/tool): unique synthetic call ids, callable schema projec…
senamakel Aug 8, 2026
f071be0
feat(stream,no-progress): event projection and a drivable no-progress…
senamakel Aug 8, 2026
8328c9d
chore: files changed src/harness/embeddings/cloud.rs,src/harness/embe…
senamakel Aug 8, 2026
b7c0118
test(context): add tests for context and schema tool surface
senamakel Aug 8, 2026
63457f1
test(runtime): add resilience tests for runtime primitives
senamakel Aug 8, 2026
4bfb2c6
test(persistence): add conformance test for persistence module
senamakel Aug 8, 2026
48b3ef4
test(persistence): update import path for conformance test helpers
senamakel Aug 8, 2026
01a3bd8
fix(checkpoint): disable cycle detection and skip thread existence check
senamakel Aug 8, 2026
3a5ec45
test: public-API regression suite for the runtime primitives
senamakel Aug 8, 2026
f3fb9ce
test(context_and_schema_tool_surface): reformat artifact assertion
senamakel Aug 8, 2026
63a75a5
fix(steering): clamp steering angle to valid range
senamakel Aug 8, 2026
7f9ba12
fix(steering): pass current checkpoint to pause commands
senamakel Aug 8, 2026
d2c8776
test(persistence): add session persistence tests
senamakel Aug 8, 2026
6fef42d
test(persistence): extract test helpers for team and task creation
senamakel Aug 8, 2026
6442424
test(feature_infra_resilience): add tests for infrastructure resilience
senamakel Aug 8, 2026
84558b1
test(e2e): add public API contract tests
senamakel Aug 8, 2026
b65e891
test(persistence_store): add tests for persistence store
senamakel Aug 8, 2026
d4f859b
chore(store): add namespaced types module
senamakel Aug 8, 2026
7c62890
chore(tests): reformat long lines to comply with style guide
senamakel Aug 8, 2026
f87dcc8
fix(checkpoint): correct cycle detection and thread copy logic
senamakel Aug 8, 2026
809bb47
fix(store): handle missing namespace in namespaced store
senamakel Aug 8, 2026
7284cb2
docs(store): document the new namespaced store module
senamakel Aug 8, 2026
ff537b6
fix(openai): add CacheTokenAccounting to stream accumulator and parse…
senamakel Aug 8, 2026
c1f5ff4
fix(openai): handle empty response body in provider
senamakel Aug 8, 2026
3d06bf4
refactor(openai): remove unused usage conversion and probe result alias
senamakel Aug 8, 2026
ef72af1
chore: files changed src/harness/providers/openai/test.rs
senamakel Aug 8, 2026
e4a3e1c
fix(openai): handle empty tool call arguments
senamakel Aug 8, 2026
27d0fa6
refactor(openai): unify schema preparation for response format and tools
senamakel Aug 8, 2026
aa06395
fix(openai): handle empty assistant message content
senamakel Aug 8, 2026
523339e
chore(tests): update doc references to renamed RunPolicy field
senamakel Aug 8, 2026
e68d323
fix(tests): update provider local wire test assertions
senamakel Aug 8, 2026
60037db
chore: format test files with rustfmt
senamakel Aug 8, 2026
3837b55
fix(harness): replace manual index with enumerate and use const asser…
senamakel Aug 8, 2026
d6a15ee
feat(openai): add responses provider harness
senamakel Aug 8, 2026
537d1b6
fix(test): record request before writing reply in mock server
senamakel Aug 8, 2026
0ec000d
refactor(session): remove unnecessary Ok wrapping in prune functions
senamakel Aug 8, 2026
548d130
docs(checkpoint): document performance characteristics of scoped look…
senamakel Aug 8, 2026
32e039e
chore(session): make busy-timeout guarantee explicit
senamakel Aug 8, 2026
99d7f18
docs(session): correct the busy-timeout test rationale to match the v…
senamakel Aug 8, 2026
ae5c01d
chore(cache): add types module for harness cache
senamakel Aug 8, 2026
cabab11
chore(cache): use stable hash for cache keys
senamakel Aug 8, 2026
0012f71
chore(harness): add context type definitions
senamakel Aug 8, 2026
4d31c13
chore(harness): add context types module
senamakel Aug 8, 2026
c1fb635
chore(harness): remove unused context module
senamakel Aug 8, 2026
ffb8eba
chore(harness): remove unused context module
senamakel Aug 8, 2026
a0a9c8b
chore(cache): derive Hash for cache key struct
senamakel Aug 8, 2026
488a0ba
chore(harness): remove unused context module
senamakel Aug 8, 2026
fd4f8b2
test(harness): update run config tests for optional call caps
senamakel Aug 8, 2026
440e03e
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
665eda9
fix(harness): correct agent loop cache layout handling
senamakel Aug 8, 2026
fa33922
perf(cache): reduce memory cache lock contention
senamakel Aug 8, 2026
8c5929b
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
23ee1a7
fix(runtime): make runtime types Send and Sync
senamakel Aug 8, 2026
970afa6
fix(runtime): make runtime types Send and Sync
senamakel Aug 8, 2026
b6cdf79
fix(harness): use sqlite cache for test results
senamakel Aug 8, 2026
14da7e7
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
3850612
chore(cache): add singleflight deduplication for cache loads
senamakel Aug 8, 2026
7c79e60
chore(cache): add cache module
senamakel Aug 8, 2026
5a2ec88
chore(model): derive common traits for harness types
senamakel Aug 8, 2026
6e2269a
fix(agent_loop): preserve partial transcript on run failure
senamakel Aug 8, 2026
d521b5b
fix(agent_loop): handle empty run loop gracefully
senamakel Aug 8, 2026
28ff4de
fix(harness): use agent loop for model execution
senamakel Aug 8, 2026
81e39f9
chore(model): derive common traits for model types
senamakel Aug 8, 2026
efcaf45
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
3dc608d
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
7b563bd
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
6b0f384
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
9eef9d2
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
874cd43
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
003a5c6
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
48b6938
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
d3596f8
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
79b3f9c
fix(agent_loop): handle empty model responses
senamakel Aug 8, 2026
8580233
feat(agent_loop): add LoopExit enum for deliberate loop stops
senamakel Aug 8, 2026
4c67a2a
refactor(agent_loop): simplify middleware type handling
senamakel Aug 8, 2026
8c90fda
fix(agent_loop): handle empty model response
senamakel Aug 8, 2026
e88cb9b
fix(agent_loop): handle empty entry list gracefully
senamakel Aug 8, 2026
e4aea6c
fix(agent_loop): handle empty model response
senamakel Aug 8, 2026
1b79fbc
fix(agent_loop): handle empty entry list gracefully
senamakel Aug 8, 2026
986a94a
refactor(agent_loop): simplify model call and tool handling
senamakel Aug 8, 2026
a074996
chore(agent_loop): rename types module for clarity
senamakel Aug 8, 2026
163a01a
fix(agent_loop): handle tool call errors gracefully
senamakel Aug 8, 2026
630fc42
fix(agent_loop): handle empty model response
senamakel Aug 8, 2026
f81a397
fix(agent_loop): handle empty model responses
senamakel Aug 8, 2026
e8f3fe2
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
e6a809b
fix(agent_loop): track emitted deltas across streaming retries
senamakel Aug 8, 2026
1b62e82
fix(agent_loop): handle empty model responses
senamakel Aug 8, 2026
826779d
fix(agent_loop): handle empty model responses
senamakel Aug 8, 2026
41c8a4d
chore(context): remove unused context middleware
senamakel Aug 8, 2026
269c472
fix(agent_loop): handle empty model response
senamakel Aug 8, 2026
a33af39
test(wave2): add execution tests for wave2 tools
senamakel Aug 8, 2026
9a02bf5
fix(harness): enforce budget limits in middleware library
senamakel Aug 8, 2026
596c7c1
test(wave2_tools_execution): use push_middleware and trim unused imports
senamakel Aug 8, 2026
1b9b466
fix(openai): handle empty tool call arguments
senamakel Aug 8, 2026
9deb1af
chore(harness): remove unused context middleware
senamakel Aug 8, 2026
130e311
fix(openai): handle empty tool call arguments
senamakel Aug 8, 2026
5f19989
fix(openai): handle empty tool call arguments
senamakel Aug 8, 2026
47c44b2
test(wave2): update tool execution tests for new context API
senamakel Aug 8, 2026
d71a43a
fix(harness): retry transient failures with backoff
senamakel Aug 8, 2026
3c48e8d
test(wave2_loop_limits): add tests for loop limit edge cases
senamakel Aug 8, 2026
bef0ca3
fix(tests): use default run limits in concurrent admission test
senamakel Aug 8, 2026
11f6bc9
feat(harness): add cache metadata to model responses
senamakel Aug 8, 2026
7c13985
test(wave2_loop_structured): add structured loop test
senamakel Aug 8, 2026
0db70a4
fix(error): include source error in display output
senamakel Aug 8, 2026
c53f8a2
test: update test fixtures for new model response fields
senamakel Aug 8, 2026
8c0f164
test(agent_loop): complete cache policy in test request
senamakel Aug 8, 2026
03e3062
test(wave2): add loop recovery test
senamakel Aug 8, 2026
464154a
test(e2e_observability): add served_from_cache field to test responses
senamakel Aug 8, 2026
7b756d3
refactor(harness): rename agent loop tests and update provider types
senamakel Aug 8, 2026
937a21b
fix(model): remove stray field from ModelResponse
senamakel Aug 8, 2026
c7c1462
fix(repair): handle missing parent nodes during repair
senamakel Aug 8, 2026
3fe9a7c
fix(harness): remove stray retry_after_ms fields
senamakel Aug 8, 2026
f428a36
fix(test): remove invalid field from test model
senamakel Aug 8, 2026
25b0f84
fix(validate): allow empty structured values
senamakel Aug 8, 2026
47f89d0
test: rework wave2 loop estimator tests around shared token counting
senamakel Aug 8, 2026
92fbc38
chore(types): add structured type definitions
senamakel Aug 8, 2026
e7a5975
test: remove unused retry_after_ms field from test fixtures
senamakel Aug 8, 2026
8f4d6ba
chore(types): add missing Debug derive to structured types
senamakel Aug 8, 2026
a6d30bb
chore(types): add structured type definitions
senamakel Aug 8, 2026
df35356
chore(harness): remove unused structured module
senamakel Aug 8, 2026
a6c3031
chore(harness): remove unused structured module
senamakel Aug 8, 2026
6e36bc5
fix(harness): correct loop control and limit test expectations
senamakel Aug 8, 2026
97c9a81
chore(harness): remove unused structured module
senamakel Aug 8, 2026
a3d7c94
test(wave2): add loop control tests
senamakel Aug 8, 2026
25fe0ea
feat(harness): repair invalid tool-call arguments during extraction
senamakel Aug 8, 2026
5681b8e
test(wave2): add cache key scope tests
senamakel Aug 8, 2026
7336f44
test(wave2_tools_structured): add structured output tests
senamakel Aug 8, 2026
8aaced4
test(wave2_tools_structured): update provider error construction in t…
senamakel Aug 8, 2026
8c881bd
test(wave2_cache_loop): add test for cache loop behavior
senamakel Aug 8, 2026
b27e773
fix(error): include source error in display output
senamakel Aug 8, 2026
893f92e
test: update cache loop tests for new RunPolicy API
senamakel Aug 8, 2026
573093c
test(wave2_loop_structured): enable tool calling in test model profile
senamakel Aug 8, 2026
eaab3a5
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
9f7d720
test(wave2_cache_store): add tests for cache store behavior
senamakel Aug 8, 2026
e00c834
test(wave2_loop_structured): clarify default profile comment
senamakel Aug 8, 2026
fb69ab5
test(wave2_cache_layout): add cache layout tests
senamakel Aug 8, 2026
ef458d2
test(wave2): add structured feature harness and cache retry-after tests
senamakel Aug 8, 2026
247f538
test(agent_loop): pin fail-closed behavior in tool error tests
senamakel Aug 8, 2026
0c873c0
test(openai): add retry-after header parsing tests
senamakel Aug 8, 2026
515e016
test: derive expected token counts from shared estimator
senamakel Aug 8, 2026
257017d
chore(cache): add singleflight deduplication for cache misses
senamakel Aug 8, 2026
1b8d65f
chore(cache): add singleflight deduplication for cache misses
senamakel Aug 8, 2026
f16cf75
fix(harness): correct tool-call identity, started/terminal pairing, e…
senamakel Aug 8, 2026
d3c6468
style: apply rustfmt formatting to structured harness code
senamakel Aug 8, 2026
d66b75f
test(wave2): clarify retry-after fallback test messages
senamakel Aug 8, 2026
e6bdfd9
chore: apply rustfmt formatting across cache and loop modules
senamakel Aug 8, 2026
1938bbc
test(feature_infra_resilience): add retry_after_ms field to test fixt…
senamakel Aug 8, 2026
3501af9
test(e2e): opt into fail-closed policies in middleware and unknown-to…
senamakel Aug 8, 2026
88a3d34
test(e2e_middleware): import InvalidArgsPolicy in test
senamakel Aug 8, 2026
cc42044
chore(harness): update cache docs and context middleware
senamakel Aug 8, 2026
057dd4f
docs(harness): document cache module
senamakel Aug 8, 2026
2cfe7af
fix(agent_loop): handle empty agent response gracefully
senamakel Aug 8, 2026
81b30d9
fix(harness): enforce budget limits in middleware library
senamakel Aug 8, 2026
5c138e2
fix(agent_loop): handle empty agent output gracefully
senamakel Aug 8, 2026
2b65e28
test(wave2): add loop cache accounting tests
senamakel Aug 8, 2026
d870ed1
fix(tests): update snapshot usage field access
senamakel Aug 8, 2026
03ee52e
test(wave2_loop_cache_accounting): reformat model registration
senamakel Aug 8, 2026
594a295
test(wave2_cache_layout): add cache layout tests
senamakel Aug 8, 2026
a86a27e
chore(harness): add middleware types module
senamakel Aug 8, 2026
fc26013
chore(context): remove unused context middleware
senamakel Aug 8, 2026
4332785
chore(context): remove unused context middleware
senamakel Aug 8, 2026
95d3447
chore(harness): add middleware types module
senamakel Aug 8, 2026
0ebf35f
test(live_local_models): add tests for local model loading
senamakel Aug 8, 2026
d3acf7f
test(live_local_models): add tests for local model loading
senamakel Aug 8, 2026
b7d5c76
test(cache): pin run-scoped prompt-cache guard baseline
senamakel Aug 8, 2026
283af0e
test(wave2_cache_store): add tests for cache store behavior
senamakel Aug 8, 2026
c9e2330
test(wave2_cache_store): add tests for cache store edge cases
senamakel Aug 8, 2026
b1582f5
Merge remote-tracking branch 'refs/remotes/upstream/main' into pr/95
senamakel Aug 8, 2026
5877372
Fix PR review findings
senamakel Aug 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 73 additions & 13 deletions docs/modules/harness/cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,25 +107,65 @@ stable prefix fingerprint even if the full request changes.

## Cache Policy

As implemented today (`harness::cache::CachePolicy`):

```rust
pub struct CachePolicy {
pub enabled: bool,
pub ttl: Option<Duration>,
pub scope: CacheScope,
pub include_tools: bool,
pub include_model_responses: bool,
pub preserve_provider_prefix: bool,
pub stable_prefix_min_tokens: Option<usize>,
pub response_cache_enabled: bool,
pub protect_prompt_prefix: bool,
pub ttl_ms: Option<u64>,
pub namespace: Option<String>,
}
```

Cache keys must include every behavior-affecting input: model, messages, tools,
tool schemas, response format, provider options, and relevant metadata. Unsafe
or side-effecting tool calls should not be cached by default.
`ttl_ms` and `namespace` cover the `ttl` / `scope` this spec asks for. The
remaining aspirational fields (`include_tools`, `include_model_responses`,
`stable_prefix_min_tokens`) are **not implemented**; tools are always part of
the key and there is no minimum-prefix threshold.

Unsafe or side-effecting tool calls should not be cached by default.

### Key composition

The key is a two-part composition, never the prompt alone:

The local response cache key is a SHA-256 digest of canonical request JSON.
Prompt text is not embedded directly in the key, but every serialized
behavior-affecting request field participates in the digest.
```text
scoped_cache_key(cache_key(request), model.cache_identity(), streaming, namespace)
```

- `cache_key(request)` is a SHA-256 digest over per-message and per-tool frames
plus an **explicit allowlist projection** of the behaviour-affecting
parameters. The projection destructures `ModelRequest` exhaustively, so adding
a request field is a compile error until someone decides whether it belongs in
the key. Fields that cannot change the answer — `tags`, `timeout_ms`,
`metadata`, `cache_policy`, `prompt_fingerprint`, `cache_segments` — are
deliberately excluded; folding them in gave a caller who put a run id in
`metadata` a permanent 0% hit rate.
- `cache_identity()` names the provider family, model id, API base URL, optional
scope, and a **fingerprint** of the credential. It is computed *after* model
resolution, because the real model is chosen by `ModelRegistry::resolve_request`
and the endpoint and credential live inside the `Arc<dyn ChatModel>`, never in
the request. Without it one shared cache serves a hosted harness's answer to a
local one.
- `streaming` is a parameter of the call rather than a request field, so it is
folded explicitly; a warm streaming run is not served an entry written by a
unary run.

Raw credentials never reach a key: `credential_fingerprint` hashes them first.

### Write rules

- Only the **primary** model's answer is written under its own key. When the
fallback chain answers, the write is skipped — otherwise the primary's key is
poisoned (permanently, absent a TTL) with a different model's response.
- A cache read or write failure is logged and ignored. The provider call has
already succeeded and been paid for; discarding its answer because the cache
was unavailable is strictly worse than not caching.
- A cache hit is stamped `ModelResponse::served_from_cache` so token/cost
accounting can tell a replay from a real call and not re-bill it.
- A cache hit on a **streaming** run is replayed as synthetic `ModelDelta`
events (text, then one per tool call) so warm and cold runs are
observationally identical.

## Cache Key Inputs

Expand Down Expand Up @@ -167,5 +207,25 @@ Every lookup should produce a decision:
- write skipped
- write completed

Implemented today: `AgentEvent::CacheHit` / `AgentEvent::CacheMiss` are emitted
as events, and the "no lookup happened at all" half is reported as a
`CacheSkipReason` (`no_cache_attached`, `policy_disabled`,
`multi_turn_transcript`) on a `[cache]`-prefixed debug log. A cache also exposes
`ResponseCache::stats() -> CacheStats` (hits, misses, writes, evictions,
expirations, entries, bytes). The remaining decisions are not yet distinct
events.

The usage feature should record provider prompt-cache hits separately from local
response-cache hits.

## Backends

- `InMemoryResponseCache` — bounded on **both** an entry count and an
approximate byte budget (an entry count alone does not bound memory when
responses are long-context). Recency is an ordered map, not a linear scan.
- `SqliteResponseCache` (feature `sqlite`) — durable, WAL, `(ns, key)` primary
key with an `expiry` column and a lazy purge on read. Namespaces do not
cross-serve and clear independently.
- `SingleFlight` — collapses concurrent identical misses into one provider call
so N simultaneous callers do not all pay for the same answer. Errors are not
shared: a follower whose leader failed runs its own call.
2 changes: 2 additions & 0 deletions examples/agent_loop_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ fn tool_call_response(id: &str, name: &str, arguments: serde_json::Value) -> Mod
raw: None,
resolved_model: None,
continue_turn: None,
served_from_cache: false,
}
}

Expand All @@ -98,6 +99,7 @@ fn text_response(text: &str) -> ModelResponse {
raw: None,
resolved_model: None,
continue_turn: None,
served_from_cache: false,
}
}

Expand Down
79 changes: 79 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,35 @@ pub enum TinyAgentsError {
#[error("model error: {0}")]
Provider(Box<crate::harness::model::ProviderError>),

/// The request did not fit in the model's context window.
///
/// Distinguished from the generic [`TinyAgentsError::Provider`] because the
/// remedy is specific and mechanical — compact or drop transcript history
/// and retry — where a generic provider failure has none. A caller that can
/// summarise its own transcript (see
/// [`crate::harness::summarization`]) can match on this variant instead of
/// string-matching a provider message that differs per vendor and changes
/// without notice. Port of LangChain's `ContextOverflowError`.
///
/// # Detection is best-effort, and asymmetric
///
/// Hosted providers raise an explicit 400 for this, which
/// [`crate::harness::providers::openai::CONTEXT_OVERFLOW_CODE`] classifies.
/// **Local servers usually truncate the front of the prompt silently
/// instead**, so the absence of this error is not evidence that the prompt
/// fitted — pair it with a probed real context window
/// ([`crate::harness::providers::openai::LocalProbe`]) rather than relying
/// on it alone.
#[error("context overflow: {message}")]
ContextOverflow {
/// Provider family identifier, for example `openai` or `ollama`.
provider: String,
/// Provider model id, when known.
model: Option<String>,
/// The provider's own message, preserved verbatim.
message: String,
},

/// A tool invocation returned an error. The payload describes the failure.
#[error("tool error: {0}")]
Tool(String),
Expand Down Expand Up @@ -235,6 +264,56 @@ pub enum TinyAgentsError {
Storage(String),
}

impl TinyAgentsError {
/// Builds the right error for a structured provider failure, promoting a
/// recognised context overflow to [`TinyAgentsError::ContextOverflow`].
///
/// Provider adapters classify the overflow and stamp
/// [`CONTEXT_OVERFLOW_CODE`][code] on
/// [`ProviderError::code`][pc]; this is where that code becomes a type. Use
/// it in place of `TinyAgentsError::Provider(Box::new(error))` at every
/// site that has a `ProviderError` in hand — the generic variant is still
/// correct for everything else, and is what this returns when the code is
/// absent or unrecognised.
///
/// [code]: crate::harness::providers::openai::CONTEXT_OVERFLOW_CODE
/// [pc]: crate::harness::model::ProviderError::code
pub fn from_provider_error(error: crate::harness::model::ProviderError) -> Self {
if error.code.as_deref() == Some(crate::harness::providers::openai::CONTEXT_OVERFLOW_CODE) {
Comment thread
senamakel marked this conversation as resolved.
tracing::debug!(
"[error] promoting provider `{}` context-overflow code to a typed error",
error.provider
);
return Self::ContextOverflow {
provider: error.provider,
model: error.model,
message: error.message,
};
}
Self::Provider(Box::new(error))
}

/// Whether this error means the request did not fit the model's context
/// window.
///
/// Recognises **both** the typed [`TinyAgentsError::ContextOverflow`] and a
/// [`TinyAgentsError::Provider`] still carrying the classification code, so
/// a caller's compact-and-retry logic behaves identically no matter which
/// construction site produced the error. Call sites are migrating to
/// [`Self::from_provider_error`]; until every one has, the two shapes must
/// classify the same or the same failure would be handled two ways.
pub fn is_context_overflow(&self) -> bool {
match self {
Self::ContextOverflow { .. } => true,
Self::Provider(error) => {
error.code.as_deref()
== Some(crate::harness::providers::openai::CONTEXT_OVERFLOW_CODE)
}
_ => false,
}
}
}

/// Converts a raw `rusqlite` failure into [`TinyAgentsError::Storage`] so the
/// session store and run ledger can use `?` on driver calls directly. Call
/// sites that have useful context to add should still map explicitly rather
Expand Down
Loading