Repository navigation
R.4: remove config_snapshot and api_key_source; recordings keep identity only (A6 item 1, D3; stacked on #21) - #22
Open
cunninghamcard-bit wants to merge 21 commits into
Open
cunninghamcard-bit wants to merge 21 commits into
cunninghamcard-bit wants to merge 21 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.
…st time (A6 item 4, D23)
provider_handle no longer reads the generic format!("{}_API_KEY") for local
runtimes (arcships#226). openai with api_key None keeps the package default
OPENAI_API_KEY, now read at request time (arcships#200:538); Some("") is used as
given (RFC-0040:67); a changed base URL without a key sends no credential and
reads no env. Tests inject env as a plain-data map (crate-internal
EnvSource::Vars), never std::env::set_var: generic key not read, env set after
construction is used, Some("") no fallback, replay/auth=none/changed base URL
read nothing. api_key_source field stays for R.4; placeholder key for R.5.
…eep identity only (A6 item 1, D3) decide() records ProviderRecord::from_model(provider, model_id). Removed DecisionModel::config_snapshot and its jev/openai/runtime/handle overrides, DecisionEndpoint::snapshot, ProviderHandle's api_key_source and HandleDecisionModel, and ProviderRecord.api_key_source (ts-rs regenerated). Recording tests now assert no apiKeySource / baseUrl / providerOptions in the provider record; config_snapshot() callers rewritten to the recorded identity.
…only) Nothing writes them since config_snapshot is gone. Also removes the arcships#226-only ProviderRecord::redacted and redact_provider_options. ProviderRecord is not deny_unknown_fields; a new test shows an old record carrying baseUrl / apiKeySource / profile / providerOptions still deserializes (and re-serializes as identity only). ts-rs regenerated.
… 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.
… from env_tests Prod compiles no Handles / fetch / env plumbing. The env is injected, so the tests need no serialization; the replay test keeps only its own recording (unique state) since the recorder is process-global.
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.
…ve-config-snapshot
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.4 (A6 item 1, D3). Stacked on #21 (R.3), #20 and #19, so this diff includes them until they merge. The R.4-only changes are commits 2c57b5f and f5e72b0.
Removed (line numbers at 8455db9; re-located on this stack)
aimux-core/src/decision_model.rs:556: trait defaultDecisionModel::config_snapshot. At:668,decide()now recordsProviderRecord::from_model(model.provider(), model.model_id()), which is provider name + model name only.aimux-core/src/recording.rs:221,240: theProviderRecord.api_key_sourcefield and its initializer.jev.rs(config_snapshotwith the:102api_key_source logic),openai/decision.rs,runtime_decision.rs, anddecision_support.rs:61(DecisionEndpoint::snapshotplus the now-unusedheaders()).provider_handle.rs: theapi_key_sourcelocal and field, andHandleDecisionModel.ProviderHandleis now a plain forwarder over the resolved provider. The placeholder key itself stays for R.5.bindings/node/src/types/ProviderRecord.ts:apiKeySource?was removed by regenerating ts-rs (gen_ts_types.py).--checkpasses. The generator also strips trailing whitespace in the regenerated file.git grep -n "config_snapshot\|api_key_source\|apiKeySource" -- ':!*.md'finds onlyscripts/check_provider_boundaries.sh(rules, R.5) and the three newapiKeySource-absent assertions below.Test changes (assertions changed, no test deleted; cargo count unchanged)
decision_recording_test.rs:91(changed):("apiKeySource","explicit")is nowprovider.get("apiKeySource").is_none(). ThebaseUrlcheck next to it also changed, from "ends with /v1/systemone" to "absent", because the record no longer carries it.decision_handle_test.rs:146(changed):apiKeySource == "explicit"is now absent. TheproviderOptions.headersredaction checks in the same test became "baseUrl/providerOptionsabsent". The raw-secret-not-in-file checks are kept.decision_handle_test.rs:83(config_snapshot_matches_model_identity, rewritten, nowrecorded_identity_matches_model_identity): it builds the recorddecidenow writes (ProviderRecord::from_model). It asserts provider / providerId / modelId match the model, and thatapiKeySourceandbaseUrlare absent.decision_handle_test.rs:184(keyless placeholder test, removed assertion): theconfig_snapshot().api_key_source == "none"check is gone. The wire assertion (Bearer not-needed) stays until R.5.decision_handle_test.rsrecorded_explicit_auth_headers_are_redacted(changed, not on the original list): it assertedproviderOptions.headers=[REDACTED]. It now asserts the provider record has noproviderOptions. The raw-secret-not-in-file checks are kept.runtime_decision_test.rs:608(rewritten): the record used forrebuild_decision_provideris nowProviderRecord::from_model(...), the same identitydeciderecords, and theapi_key_source == "none"assert is dropped. Rebuilding through the registry still passes for all 6 local runtimes.runtime_decision_test.rs:616(removed assertion):api_key_source == "explicit". The following:622check, "explicit key is not in the recording, so rebuilding without a registration fails", now usesfrom_model.Update (f5e72b0):
base_url,profileandprovider_optionsremoved tooaimux-providers/tests/fixtures/jev_systemone_live.jsonl, and they hold identity only. Thefixtures/aisdkproviderOptionsand the cassettes are not ProviderRecords.ProviderRecordis notdeny_unknown_fields.ProviderRecord::redactedand the feat: support official decision providers, candidate scoring, and native media arcships/aimux#226-onlyredact_provider_optionshelper.ProviderRecord.tsis now{providerId, provider, modelId}, andgen_ts_types.py --checkpasses.recording::tests::provider_record_ignores_removed_snapshot_fields: JSON withbaseUrl/apiKeySource/profile/providerOptionsstill deserializes into a ProviderRecord and re-serializes as identity only, so old recordings still load and replay.rfc/, docs and*.md) leaves only the absence-asserting tests and that test's input JSON. The"profile"keys inprovider_registry.jsonare registry rows, unrelated.api_key_sourcereferences; thedecision_capabilitieshits there are the capabilities API and are untouched.Results vs R.0 (local linux x64; new and renamed test names confirmed in the log)
Go/Java/Kotlin/Swift/Flutter were not run locally.
Review follow-up