fix(review): custom provider login comments, doc placement, subagent scheme test
The subagent auth-scheme lookup is now a function with a test. The failed-login span carries the same method id as the successful one. README order matches the code: the provider is saved, then the key is checked.
This commit is contained in:
1 parent
c4ef8a3779
commit
c9855c4bb6
14 files changed
+77
-52
No files matched your search
@@ -599,7 +599,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// `custom:<name>` is an API-key login; the picker rows are not loginable.
|
||||
/// `custom:<name>` logs in; picker rows cannot.
|
||||
#[test]
|
||||
fn custom_provider_method_ids_classify_as_api_key() {
|
||||
let kind = AuthMethodKind::from_id(&acp::AuthMethodId::new("custom:my-proxy"));
|
||||
|
||||
@@ -3960,8 +3960,7 @@ pub fn resolve_model_auth_facts(model_id: &str) -> ModelAuthFacts {
|
||||
},
|
||||
})
|
||||
}
|
||||
/// Auth facts of a catalog entry the caller already holds. A fetched entry
|
||||
/// exists only in the live catalog, never in a disk reload.
|
||||
/// Auth facts of a held live-catalog entry.
|
||||
pub(crate) fn auth_facts_of(entry: &ModelEntry) -> ModelAuthFacts {
|
||||
ModelAuthFacts {
|
||||
byok: if entry.has_own_credentials() {
|
||||
@@ -5286,7 +5285,7 @@ reasoning_effort = "low"
|
||||
auth_scheme: Default::default(),
|
||||
}
|
||||
}
|
||||
/// A fetched entry's scheme and BYOK status come from the entry itself.
|
||||
/// Scheme and BYOK status come from the entry.
|
||||
#[test]
|
||||
fn auth_facts_come_from_the_held_entry() {
|
||||
let mut model = test_model_entry("claude-x", "https://gw.example/v1", None, None, None);
|
||||
|
||||
@@ -9,7 +9,7 @@ const PICKER_PREFIX: &str = "custom-";
|
||||
const LOGIN_PREFIX: &str = "custom:";
|
||||
const ALL_APIS: [CustomApi; 2] = [CustomApi::OpenAi, CustomApi::Anthropic];
|
||||
|
||||
/// The picker row that starts the custom provider flow for one wire.
|
||||
/// The picker row for one wire.
|
||||
pub fn picker_method(api: CustomApi) -> acp::AuthMethod {
|
||||
acp::AuthMethod::Agent(
|
||||
acp::AuthMethodAgent::new(
|
||||
@@ -41,7 +41,7 @@ pub fn login_provider_name(id: &str) -> Option<&str> {
|
||||
id.strip_prefix(LOGIN_PREFIX)
|
||||
}
|
||||
|
||||
/// Probes the listing endpoint with the key; the error text never holds the key.
|
||||
/// Probes the listing endpoint; errors never hold the key.
|
||||
pub(crate) async fn validate_key(credentialed: &CredentialedProvider) -> Result<(), String> {
|
||||
let provider = &credentialed.provider;
|
||||
let url = provider.models_url();
|
||||
|
||||
@@ -553,7 +553,7 @@ impl MvpAgent {
|
||||
tracing::warn!(provider = name, %message, "custom provider login failed");
|
||||
emit_login_span(
|
||||
false,
|
||||
"custom-provider",
|
||||
method_id.0.as_ref(),
|
||||
None,
|
||||
Some("custom_provider_invalid_or_missing"),
|
||||
);
|
||||
@@ -561,7 +561,7 @@ impl MvpAgent {
|
||||
}
|
||||
Ok(self.finish_api_key_login(method_id).await)
|
||||
}
|
||||
/// Shared tail of an API-key login: reload config, refresh the catalog.
|
||||
/// Shared tail of an API-key login.
|
||||
async fn finish_api_key_login(&self, method_id: acp::AuthMethodId) -> AuthenticateResponse {
|
||||
// Rebuild the catalog from the on-disk config: the rebuild freshly
|
||||
// resolves platform keys (env > auth.json > config), so the key just
|
||||
|
||||
@@ -879,6 +879,20 @@ fn log_subagent_model_resolution(
|
||||
)),
|
||||
);
|
||||
}
|
||||
/// The parent model's auth scheme: its live catalog entry, else a disk lookup.
|
||||
fn parent_auth_scheme(
|
||||
available: &indexmap::IndexMap<String, crate::agent::config::ModelEntry>,
|
||||
catalog_id: &acp::ModelId,
|
||||
slug: &str,
|
||||
) -> kigi_sampler::AuthScheme {
|
||||
crate::agent::models::entry_for_slug(available, Some(catalog_id.0.as_ref()), slug)
|
||||
.map(|entry| crate::agent::config::auth_facts_of(entry).auth_scheme)
|
||||
.or_else(|| {
|
||||
crate::agent::config::try_resolve_model_credentials(slug, None).map(|r| r.auth_scheme)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Read the parent session's actual current sampling config.
|
||||
///
|
||||
/// Prefers the live state from `ChatStateHandle` (authoritative). Falls back
|
||||
@@ -897,17 +911,7 @@ async fn read_parent_sampling_config(
|
||||
creds.alpha_test_key.as_deref(),
|
||||
&cfg.base_url,
|
||||
);
|
||||
let auth_scheme = crate::agent::models::entry_for_slug(
|
||||
&ctx.available_models,
|
||||
Some(ctx.model_id.0.as_ref()),
|
||||
&cfg.model,
|
||||
)
|
||||
.map(|entry| crate::agent::config::auth_facts_of(entry).auth_scheme)
|
||||
.or_else(|| {
|
||||
crate::agent::config::try_resolve_model_credentials(&cfg.model, None)
|
||||
.map(|r| r.auth_scheme)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let auth_scheme = parent_auth_scheme(&ctx.available_models, &ctx.model_id, &cfg.model);
|
||||
// Claude Pro/Max OAuth Messages adaptation inherits from the parent
|
||||
// model's platform (claude-pro-max → true); every other platform,
|
||||
// and BYOK, → false, so the API-key paths stay byte-identical.
|
||||
@@ -2667,3 +2671,32 @@ pub(crate) fn reconcile_orphaned_subagents(
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod parent_auth_scheme_tests {
|
||||
use super::*;
|
||||
|
||||
/// A fetched Messages model exists only in the live catalog.
|
||||
#[test]
|
||||
fn a_fetched_entry_gives_its_own_scheme_to_the_child() {
|
||||
let wire: kigi_models::WireModel =
|
||||
serde_json::from_value(serde_json::json!({ "id": "claude-x" })).unwrap();
|
||||
let cfg = crate::agent::models_fetch::wire_model_to_entry(
|
||||
"gw/claude-x".into(),
|
||||
kigi_models::PlatformWireApi::Messages,
|
||||
kigi_models::PlatformKeyHeader::XApiKey,
|
||||
None,
|
||||
true,
|
||||
wire,
|
||||
"https://gw.example/v1",
|
||||
);
|
||||
let available = indexmap::IndexMap::from([(
|
||||
"gw/claude-x".to_owned(),
|
||||
crate::agent::config::ModelEntry::from_config_entry(&cfg),
|
||||
)]);
|
||||
|
||||
let scheme = parent_auth_scheme(&available, &acp::ModelId::new("gw/claude-x"), "claude-x");
|
||||
|
||||
assert_eq!(scheme, kigi_sampler::AuthScheme::XApiKey);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user