Repository navigation
R.2: remove model-level retry_config; decisions use core maxRetries (A6, stacked on #19) - #20
Open
cunninghamcard-bit wants to merge 11 commits into
Open
cunninghamcard-bit wants to merge 11 commits into
cunninghamcard-bit wants to merge 11 commits into
Conversation
Drop ProviderOptions.body_overrides and both arcships#226 rejections in provider_handle.rs; ProviderOptions now denies unknown fields. Node ProviderConfig loses bodyOverrides and reports any unknown key as InvalidArgumentError 'unknown field `x`'. Python docs updated; Python already rejects unknown keys via serde. Tests in Rust/Python/Node. Adds docs/amendments/A6-remove-226-per-rfc.md verbatim.
…keys) Replace the hand-written key allowlist: the JS object is read as a raw JSON map (undefined values skipped), maxRetries is rejected first with the call-level message, then the map deserializes into ProviderConfig with #[serde(deny_unknown_fields, rename_all = "camelCase")]. The max_retries struct field is gone (index.d.ts loses maxRetries?). Tests: maxRetries gets the call-level message, undefined keys are absent.
…ies only (A6 item 2) Drop RetryConfig and prepare_retries_with_config from aimux-core, DecisionModel::retry_config, the retry fields/overrides in jev, openai/decision (with_retry_config), runtime_decision and decision_support (snapshot no longer records max_retries), and the handle-level ProviderOptions.max_retries default in provider_handle. decide() uses retry::prepare_retries(options.max_retries, ...). New mock test: max_retries = 0/1/3/None makes exactly 1/2/4/3 requests.
…n jev_test Retry counting moves into aimux-core decision_model::retry_tests, using a crate-internal #[cfg(test)] PreparedRetries::with_initial_delay(ZERO); asserts attempts = max_retries + 1 and RetryErrorReason::MaxRetriesExceeded with the last 503/429/529 error. jev_test keeps status classification at max_retries = 0 plus one max_retries = 1 run on 503 asserting 2 requests and retry exhaustion. No public API, feature or binding change.
This was referenced Oct 11, 2026
… the struct Drop #[napi(skip)] invalid: Option<String>; from_napi_value now returns the InvalidArgumentError directly. The constructors' 3rd arg becomes ConfigArg (dispatch on JS type) because napi's Either swallowed the member error.
Constructors accept the config argument as serde_json::Value (d.ts unchanged), so conversion never throws synchronously; maxRetries, unknown keys and wrong types are refused inside the async body as InvalidArgumentError. ConfigArg and the custom ProviderConfig FromNapiValue are gone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1R unit R.2 (A6 item 2; D5/D6). Stacked on #19 (
exp/u1R.1-remove-body-overrides@6f0aa367). Both units editProviderOptionsandProviderHandle::decision_modelinprovider_handle.rs, so until #19 merges this diff includes #19. The R.2-only change is commit 5ac114d.Removed (line numbers at 8455db9)
aimux-core/src/decision_model.rs:562-566DecisionModel::retry_config(). At:651-655,decide()now callsretry::prepare_retries(options.max_retries, abort). That is the same core pathgenerate/moause: call-levelmaxRetries, default 2, fixed delay and backoff.aimux-core/src/retry.rs:18-41RetryConfig(including the:19doc reference) and:73-89prepare_retries_with_config.aimux-providers/src/jev.rs:26-27,38,116-118(JevConfig.retry_configand its impl).aimux-providers/src/openai/decision.rs:17,35,39-44,410-412,417(field,with_retry_config, impl, snapshot argument).aimux-providers/src/runtime_decision.rs:32,55,637-639,644.aimux-providers/src/decision_support.rs:54,78: the snapshot no longer takes a retry config or recordsmax_retriesinprovider_options.aimux-providers/src/provider_handle.rs:15,39-40(the handle-levelProviderOptions.max_retriesdefault; docs: full-chain AI SDK alignment design and impact map arcships/aimux#200:1025 says not to reintroduce provider defaultmax_retries),:195-201, and theHandleDecisionModelretry field,retry_config()and themax_retriessnapshot insert.HandleDecisionModelstays only forapi_key_source(R.3/R.4).scripts/check_provider_boundaries.sh(R.5) and the bindings. Node/Python/FFI already rejectmax_retriesin the provider config and passmaxRetriesper call. Node keeps its "call-level option" message (R.1: remove body_overrides; reject as unknown field (A6) #19).Tests
runtime_decision_test::call_level_max_retries_sets_the_exact_retry_count: a wiremock always returns 503 withretry-after: 0.max_retries= 0/1/3/None makes exactly 1/2/4/3 requests (N retries; the default is 2). The error isApiCallfor 0 andRetryotherwise.decision_handle_test::handle_options_reach_decisionswas replaced byhandle_has_no_max_retries_option:{"max_retries":0}→unknown field `max_retries`.jev_test/openai_decision_test: removed theinitial_delay = 0/with_retry_configsetup. The retrying tests useretry-after: 0. jev_test now takes about 10s because its other retrying cases wait the default 2s backoff.Acceptance
git grep -n "retry_config\|RetryConfig" -- aimux-providers aimux-core/src/decision_model.rs: no hits. The remaining repo hits are only inscripts/check_provider_boundaries.sh(rules plus the D16 allowance, R.5).Results vs R.0 baseline (8455db9, local linux x64; test binaries rebuilt, new test names appear in the log)
Go/Java/Kotlin/Swift/Flutter were not run locally.
Update (8cfdf46): tests without real backoff
decision_model::retry_tests. The first retry delay is set to zero through the crate-internal#[cfg(test)] PreparedRetries::with_initial_delay; there is no public API, feature or binding change. These tests checkmax_retries1/3/None → 2/4/3 attempts for 429/503/529, withRetryErrorReason::MaxRetriesExceededand the last error's status.max_retries=0and non-retryable errors make one attempt.jev_test: status classification runs withmax_retries=0, so there's no wait. Onemax_retries=1run on 503 asserts 2 requests, retries exhausted, and a 503unavailablelast error. jev_test went from 10.14s to 0.95s.runtime_decision_test::call_level_max_retries_sets_the_exact_retry_countnow also asserts retries-exhausted with a 503 cause.Review follow-up