mirror of
https://github.com/block/buzz.git
synced 2026-11-10 11:21:05 +00:00
fix: scope openai compatibility to buzz agent
Co-authored-by: am <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz> Signed-off-by: am <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -101,10 +101,13 @@ pub async fn get_agent_models(
|
||||
// so a build-provided provider still gets live discovery.
|
||||
let mut effective_provider =
|
||||
effective_discovery_provider(saved_provider.as_deref(), provider_env_var, &merged_env);
|
||||
effective_provider.value = crate::managed_agents::readiness::canonicalize_openai_provider_env(
|
||||
&mut merged_env,
|
||||
effective_provider.as_deref(),
|
||||
);
|
||||
if known_acp_runtime(&discovery.command).is_some_and(|runtime| runtime.id == "buzz-agent") {
|
||||
effective_provider.value =
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut merged_env,
|
||||
effective_provider.as_deref(),
|
||||
);
|
||||
}
|
||||
if let Some(models) = discover_openrouter_models(
|
||||
&state.http_client,
|
||||
&effective_provider,
|
||||
@@ -243,10 +246,13 @@ pub async fn discover_agent_models(
|
||||
runtime_meta.and_then(|meta| meta.provider_env_var),
|
||||
&merged_env,
|
||||
);
|
||||
effective_provider.value = crate::managed_agents::readiness::canonicalize_openai_provider_env(
|
||||
&mut merged_env,
|
||||
effective_provider.as_deref(),
|
||||
);
|
||||
if runtime_meta.is_some_and(|runtime| runtime.id == "buzz-agent") {
|
||||
effective_provider.value =
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut merged_env,
|
||||
effective_provider.as_deref(),
|
||||
);
|
||||
}
|
||||
|
||||
// Buzz shared compute discovery must not depend on the local OpenAI ingress: that
|
||||
// client endpoint is started only after a live target is selected.
|
||||
|
||||
@@ -20,6 +20,7 @@ pub(crate) mod git_bash;
|
||||
pub(crate) mod global_config;
|
||||
mod managed_node_paths;
|
||||
mod nest;
|
||||
pub(crate) mod openai_env;
|
||||
pub(crate) mod parallelism;
|
||||
mod persona_avatars;
|
||||
pub(crate) mod persona_events;
|
||||
|
||||
64
desktop/src-tauri/src/managed_agents/openai_env.rs
Normal file
64
desktop/src-tauri/src/managed_agents/openai_env.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub(crate) fn effective_runtime_provider(
|
||||
command: &str,
|
||||
configured_provider: Option<String>,
|
||||
env: &BTreeMap<String, String>,
|
||||
) -> Option<String> {
|
||||
if crate::managed_agents::known_acp_runtime(command)
|
||||
.is_some_and(|runtime| runtime.id == "buzz-agent")
|
||||
{
|
||||
env.get("BUZZ_AGENT_PROVIDER")
|
||||
.cloned()
|
||||
.or(configured_provider)
|
||||
} else {
|
||||
configured_provider
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn canonicalize_openai_provider_env(
|
||||
env: &mut BTreeMap<String, String>,
|
||||
provider: Option<&str>,
|
||||
) -> Option<String> {
|
||||
let mut provider = provider.map(str::trim).map(str::to_ascii_lowercase);
|
||||
if provider.as_deref() == Some("openai") {
|
||||
let official_key = env
|
||||
.get("OPENAI_API_KEY")
|
||||
.map(String::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
let legacy_key = env
|
||||
.get("OPENAI_COMPAT_API_KEY")
|
||||
.map(String::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
let has_custom_origin = env
|
||||
.get("OPENAI_COMPAT_BASE_URL")
|
||||
.map(String::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.is_some_and(|value| value.trim_end_matches('/') != "https://api.openai.com/v1");
|
||||
if legacy_key.is_some()
|
||||
&& has_custom_origin
|
||||
&& (official_key.is_none() || official_key == legacy_key)
|
||||
{
|
||||
provider = Some("openai-compat".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
match provider.as_deref() {
|
||||
Some("openai") => {
|
||||
env.remove("OPENAI_COMPAT_BASE_URL");
|
||||
env.remove("OPENAI_COMPAT_API_KEY");
|
||||
}
|
||||
Some("openai-compat") => {
|
||||
env.remove("OPENAI_API_KEY");
|
||||
env.entry("OPENAI_COMPAT_API_KEY".to_string()).or_default();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let (Some(value), Some(slot)) = (provider.as_ref(), env.get_mut("BUZZ_AGENT_PROVIDER")) {
|
||||
*slot = value.clone();
|
||||
}
|
||||
provider
|
||||
}
|
||||
@@ -269,7 +269,14 @@ fn resolve_effective_agent_env_with_def(
|
||||
);
|
||||
env.extend(user_env);
|
||||
|
||||
let _ = canonicalize_openai_provider_env(&mut env, effective_provider.as_deref());
|
||||
if crate::managed_agents::known_acp_runtime(&effective_command)
|
||||
.is_some_and(|runtime| runtime.id == "buzz-agent")
|
||||
{
|
||||
let _ = crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut env,
|
||||
effective_provider.as_deref(),
|
||||
);
|
||||
}
|
||||
|
||||
// Buzz shared compute is a native Buzz provider. Translate it to buzz-agent's
|
||||
// OpenAI-compatible transport only in the effective runtime environment.
|
||||
@@ -287,46 +294,6 @@ fn resolve_effective_agent_env_with_def(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn canonicalize_openai_provider_env(
|
||||
env: &mut BTreeMap<String, String>,
|
||||
provider: Option<&str>,
|
||||
) -> Option<String> {
|
||||
let mut provider = provider.map(str::trim).map(str::to_ascii_lowercase);
|
||||
if provider.as_deref() == Some("openai") {
|
||||
let has_official_key = env
|
||||
.get("OPENAI_API_KEY")
|
||||
.is_some_and(|value| !value.trim().is_empty());
|
||||
let has_legacy_key = env
|
||||
.get("OPENAI_COMPAT_API_KEY")
|
||||
.is_some_and(|value| !value.trim().is_empty());
|
||||
let has_custom_origin = env
|
||||
.get("OPENAI_COMPAT_BASE_URL")
|
||||
.map(String::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.is_some_and(|value| value.trim_end_matches('/') != "https://api.openai.com/v1");
|
||||
if !has_official_key && has_legacy_key && has_custom_origin {
|
||||
provider = Some("openai-compat".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
match provider.as_deref() {
|
||||
Some("openai") => {
|
||||
env.remove("OPENAI_COMPAT_BASE_URL");
|
||||
env.remove("OPENAI_COMPAT_API_KEY");
|
||||
}
|
||||
Some("openai-compat") => {
|
||||
env.remove("OPENAI_API_KEY");
|
||||
env.entry("OPENAI_COMPAT_API_KEY".to_string()).or_default();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let (Some(value), Some(slot)) = (provider.as_ref(), env.get_mut("BUZZ_AGENT_PROVIDER")) {
|
||||
*slot = value.clone();
|
||||
}
|
||||
provider
|
||||
}
|
||||
|
||||
// ── Requirement types ─────────────────────────────────────────────────────────
|
||||
/// A single missing piece of configuration, tagged with the UI surface that
|
||||
/// owns it so the UI can route each gap to the right affordance.
|
||||
|
||||
@@ -22,7 +22,10 @@ fn provider_env_canonicalization_isolates_consumers() {
|
||||
),
|
||||
]);
|
||||
let mut official = shared.clone();
|
||||
canonicalize_openai_provider_env(&mut official, Some("openai"));
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut official,
|
||||
Some("openai"),
|
||||
);
|
||||
assert_eq!(
|
||||
official.get("OPENAI_API_KEY").map(String::as_str),
|
||||
Some("official")
|
||||
@@ -31,7 +34,10 @@ fn provider_env_canonicalization_isolates_consumers() {
|
||||
assert!(!official.contains_key("OPENAI_COMPAT_BASE_URL"));
|
||||
|
||||
let mut compatible = shared;
|
||||
canonicalize_openai_provider_env(&mut compatible, Some("openai-compat"));
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut compatible,
|
||||
Some("openai-compat"),
|
||||
);
|
||||
assert!(!compatible.contains_key("OPENAI_API_KEY"));
|
||||
assert_eq!(
|
||||
compatible.get("OPENAI_COMPAT_API_KEY").map(String::as_str),
|
||||
@@ -50,7 +56,11 @@ fn inherited_legacy_custom_configuration_normalizes_per_consumer() {
|
||||
),
|
||||
]);
|
||||
assert_eq!(
|
||||
canonicalize_openai_provider_env(&mut env, Some("openai")).as_deref(),
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut env,
|
||||
Some("openai")
|
||||
)
|
||||
.as_deref(),
|
||||
Some("openai-compat")
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -60,13 +70,52 @@ fn inherited_legacy_custom_configuration_normalizes_per_consumer() {
|
||||
assert!(!env.contains_key("OPENAI_API_KEY"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copied_official_key_does_not_mask_legacy_custom_identity() {
|
||||
let mut env = BTreeMap::from([
|
||||
("BUZZ_AGENT_PROVIDER".into(), "openai".into()),
|
||||
("OPENAI_API_KEY".into(), "copied-legacy".into()),
|
||||
("OPENAI_COMPAT_API_KEY".into(), "copied-legacy".into()),
|
||||
(
|
||||
"OPENAI_COMPAT_BASE_URL".into(),
|
||||
"https://gateway.example/v1".into(),
|
||||
),
|
||||
]);
|
||||
assert_eq!(
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut env,
|
||||
Some("openai")
|
||||
)
|
||||
.as_deref(),
|
||||
Some("openai-compat")
|
||||
);
|
||||
assert!(!env.contains_key("OPENAI_API_KEY"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_buzz_harness_keeps_its_configured_provider() {
|
||||
let env = BTreeMap::from([("BUZZ_AGENT_PROVIDER".into(), "openai-compat".into())]);
|
||||
assert_eq!(
|
||||
crate::managed_agents::openai_env::effective_runtime_provider(
|
||||
"goose",
|
||||
Some("openai".into()),
|
||||
&env,
|
||||
)
|
||||
.as_deref(),
|
||||
Some("openai")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyless_compatible_provider_gets_explicit_blank_credential() {
|
||||
let mut env = BTreeMap::from([(
|
||||
"OPENAI_COMPAT_BASE_URL".into(),
|
||||
"http://localhost:11434/v1".into(),
|
||||
)]);
|
||||
canonicalize_openai_provider_env(&mut env, Some("openai-compat"));
|
||||
crate::managed_agents::openai_env::canonicalize_openai_provider_env(
|
||||
&mut env,
|
||||
Some("openai-compat"),
|
||||
);
|
||||
assert_eq!(
|
||||
env.get("OPENAI_COMPAT_API_KEY").map(String::as_str),
|
||||
Some("")
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use tauri::AppHandle;
|
||||
|
||||
use super::agent_env::{build_buzz_agent_provider_defaults, idle_pool_sleep_env};
|
||||
|
||||
use super::openai_env::effective_runtime_provider;
|
||||
use crate::{
|
||||
managed_agents::{
|
||||
append_log_marker, known_acp_runtime, login_shell_path, managed_agent_log_path,
|
||||
@@ -204,7 +204,7 @@ pub fn build_managed_agent_summary(
|
||||
personas,
|
||||
global_config,
|
||||
);
|
||||
let (effective_model, effective_provider, effective_prompt, model_source) = match effective_cfg
|
||||
let (effective_model, configured_provider, effective_prompt, model_source) = match effective_cfg
|
||||
{
|
||||
crate::managed_agents::effective_config::EffectiveConfigResult::Resolved(cfg) => {
|
||||
let source = cfg.model.source.clone();
|
||||
@@ -293,6 +293,8 @@ pub fn build_managed_agent_summary(
|
||||
env: Default::default(),
|
||||
}
|
||||
});
|
||||
let effective_provider =
|
||||
effective_runtime_provider(&descriptor.command, configured_provider, &descriptor.env);
|
||||
let effective_mcp_command = known_acp_runtime(&descriptor.command)
|
||||
.and_then(|r| r.mcp_command)
|
||||
.unwrap_or("")
|
||||
@@ -711,11 +713,9 @@ pub fn spawn_agent_child(
|
||||
let mesh_model_id = effective_cfg.relay_mesh_model_id();
|
||||
let effective_prompt = effective_cfg.system_prompt.value;
|
||||
let effective_model = effective_cfg.model.value;
|
||||
let effective_provider = descriptor
|
||||
.env
|
||||
.get("BUZZ_AGENT_PROVIDER")
|
||||
.cloned()
|
||||
.or(effective_cfg.provider.value);
|
||||
let configured_provider = effective_cfg.provider.value;
|
||||
let effective_provider =
|
||||
effective_runtime_provider(&descriptor.command, configured_provider, &descriptor.env);
|
||||
|
||||
if let Some(prompt) = &effective_prompt {
|
||||
command.env("BUZZ_ACP_SYSTEM_PROMPT", prompt);
|
||||
|
||||
@@ -291,12 +291,18 @@ pub(crate) fn prospective_spawn_config_snapshot(
|
||||
// definition) resolves as if all three were absent: `spawn_agent_child`
|
||||
// refuses to spawn an orphan regardless, and `eligible_restart_diff`
|
||||
// suppresses the badge for one.
|
||||
let (prompt, model, provider) = match resolve_effective_config(record, personas, global) {
|
||||
EffectiveConfigResult::Resolved(cfg) => {
|
||||
(cfg.system_prompt.value, cfg.model.value, cfg.provider.value)
|
||||
}
|
||||
EffectiveConfigResult::OrphanedInstance { .. } => (None, None, None),
|
||||
};
|
||||
let (prompt, model, configured_provider) =
|
||||
match resolve_effective_config(record, personas, global) {
|
||||
EffectiveConfigResult::Resolved(cfg) => {
|
||||
(cfg.system_prompt.value, cfg.model.value, cfg.provider.value)
|
||||
}
|
||||
EffectiveConfigResult::OrphanedInstance { .. } => (None, None, None),
|
||||
};
|
||||
let provider = crate::managed_agents::openai_env::effective_runtime_provider(
|
||||
&descriptor.command,
|
||||
configured_provider,
|
||||
&descriptor.env,
|
||||
);
|
||||
|
||||
SpawnConfigSnapshot::from_inputs(SpawnConfigInputs {
|
||||
record,
|
||||
|
||||
@@ -34,6 +34,29 @@ fn snapshot(
|
||||
snapshot_with_policy(record, personas, teams, workspace_relay, global, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_custom_buzz_agent_snapshot_uses_runtime_provider_identity() {
|
||||
let mut rec = record();
|
||||
rec.runtime = Some("buzz-agent".into());
|
||||
rec.provider = Some("openai".into());
|
||||
rec.env_vars
|
||||
.insert("OPENAI_COMPAT_API_KEY".into(), "shared-key".into());
|
||||
rec.env_vars.insert(
|
||||
"OPENAI_COMPAT_BASE_URL".into(),
|
||||
"https://gateway.example/v1".into(),
|
||||
);
|
||||
let global = GlobalAgentConfig {
|
||||
env_vars: BTreeMap::from([("OPENAI_API_KEY".into(), "shared-key".into())]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let value = snapshot(&rec, &[], &[], "wss://ws.example", &global);
|
||||
assert_eq!(
|
||||
value.get("provider").and_then(serde_json::Value::as_str),
|
||||
Some("openai-compat")
|
||||
);
|
||||
}
|
||||
|
||||
/// `snapshot` with the fixed no-persona/no-team/default-global shape the effort
|
||||
/// tests share, so their call sites read as `snap(&record)` instead of wrapping.
|
||||
fn snap(record: &ManagedAgentRecord) -> serde_json::Value {
|
||||
|
||||
@@ -235,56 +235,79 @@ fn classify_endpoint(endpoint: Option<&str>) -> Result<Identity, String> {
|
||||
})
|
||||
}
|
||||
|
||||
fn is_buzz_agent_consumer(record: &ManagedAgentRecord, defs: &[AgentDefinition]) -> bool {
|
||||
crate::managed_agents::known_acp_runtime(&crate::managed_agents::record_agent_command(
|
||||
record, defs,
|
||||
))
|
||||
.is_some_and(|runtime| runtime.id == "buzz-agent")
|
||||
}
|
||||
|
||||
fn global_defaults_target_buzz_agent(store: &Store) -> bool {
|
||||
match store.global.preferred_runtime.as_deref().map(str::trim) {
|
||||
Some("") | None => true,
|
||||
Some(runtime_id) => crate::managed_agents::known_acp_runtime_exact(runtime_id)
|
||||
.is_some_and(|runtime| runtime.id == "buzz-agent"),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_consumers(store: &Store) -> Result<Vec<Consumer>, String> {
|
||||
let defs = definitions(store);
|
||||
let has_managed_buzz_agent = store
|
||||
.records
|
||||
.iter()
|
||||
.filter(|record| !record.pubkey.is_empty())
|
||||
.any(|record| is_buzz_agent_consumer(record, &defs));
|
||||
let mut consumers = Vec::new();
|
||||
if let Some(provider) = store
|
||||
.global
|
||||
.provider
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.filter(|value| {
|
||||
matches!(
|
||||
value.to_ascii_lowercase().as_str(),
|
||||
"openai" | "openai-compat"
|
||||
)
|
||||
})
|
||||
{
|
||||
let endpoint = store
|
||||
if !has_managed_buzz_agent && global_defaults_target_buzz_agent(store) {
|
||||
if let Some(provider) = store
|
||||
.global
|
||||
.env_vars
|
||||
.get(OPENAI_COMPAT_BASE_URL)
|
||||
.map(|value| ResolvedValue {
|
||||
value: value.clone(),
|
||||
owner: Owner::Global,
|
||||
.provider
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.filter(|value| {
|
||||
matches!(
|
||||
value.to_ascii_lowercase().as_str(),
|
||||
"openai" | "openai-compat"
|
||||
)
|
||||
})
|
||||
{
|
||||
let endpoint = store
|
||||
.global
|
||||
.env_vars
|
||||
.get(OPENAI_COMPAT_BASE_URL)
|
||||
.map(|value| ResolvedValue {
|
||||
value: value.clone(),
|
||||
owner: Owner::Global,
|
||||
});
|
||||
consumers.push(Consumer {
|
||||
label: "global defaults".into(),
|
||||
record_index: None,
|
||||
provider: provider.to_ascii_lowercase(),
|
||||
provider_owner: Owner::Global,
|
||||
identity: classify_endpoint(endpoint.as_ref().map(|value| value.value.as_str()))?,
|
||||
endpoint,
|
||||
legacy_key: store
|
||||
.global
|
||||
.env_vars
|
||||
.get(OPENAI_COMPAT_API_KEY)
|
||||
.map(|value| ResolvedValue {
|
||||
value: value.clone(),
|
||||
owner: Owner::Global,
|
||||
}),
|
||||
official_key: store.global.env_vars.get(OPENAI_API_KEY).map(|value| {
|
||||
ResolvedValue {
|
||||
value: value.clone(),
|
||||
owner: Owner::Global,
|
||||
}
|
||||
}),
|
||||
});
|
||||
consumers.push(Consumer {
|
||||
label: "global defaults".into(),
|
||||
record_index: None,
|
||||
provider: provider.to_ascii_lowercase(),
|
||||
provider_owner: Owner::Global,
|
||||
identity: classify_endpoint(endpoint.as_ref().map(|value| value.value.as_str()))?,
|
||||
endpoint,
|
||||
legacy_key: store
|
||||
.global
|
||||
.env_vars
|
||||
.get(OPENAI_COMPAT_API_KEY)
|
||||
.map(|value| ResolvedValue {
|
||||
value: value.clone(),
|
||||
owner: Owner::Global,
|
||||
}),
|
||||
official_key: store
|
||||
.global
|
||||
.env_vars
|
||||
.get(OPENAI_API_KEY)
|
||||
.map(|value| ResolvedValue {
|
||||
value: value.clone(),
|
||||
owner: Owner::Global,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
for (index, record) in store.records.iter().enumerate() {
|
||||
if record.pubkey.is_empty() || !is_buzz_agent_consumer(record, &defs) {
|
||||
continue;
|
||||
}
|
||||
let def = selected_definition(record, &defs);
|
||||
if record.persona_id.is_some() && def.is_none() {
|
||||
return Err(format!(
|
||||
@@ -354,6 +377,7 @@ fn collect_consumers(store: &Store) -> Result<Vec<Consumer>, String> {
|
||||
});
|
||||
}
|
||||
if consumers.is_empty()
|
||||
&& global_defaults_target_buzz_agent(store)
|
||||
&& [OPENAI_COMPAT_API_KEY, OPENAI_COMPAT_BASE_URL]
|
||||
.iter()
|
||||
.any(|key| store.global.env_vars.contains_key(*key))
|
||||
|
||||
@@ -239,6 +239,75 @@ fn unrelated_consumer_does_not_claim_global_openai_credential() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shared_global_legacy_key_supports_official_and_custom_buzz_agents() {
|
||||
let global = GlobalAgentConfig {
|
||||
provider: Some("openai".into()),
|
||||
env_vars: BTreeMap::from([(OPENAI_COMPAT_API_KEY.into(), "shared-key".into())]),
|
||||
..Default::default()
|
||||
};
|
||||
let official = record("official", "official");
|
||||
let mut custom = record("custom", "custom");
|
||||
custom.env_vars.insert(
|
||||
OPENAI_COMPAT_BASE_URL.into(),
|
||||
"https://gateway.example/v1".into(),
|
||||
);
|
||||
|
||||
let (store, before) = plan_store(Store {
|
||||
global,
|
||||
records: vec![official, custom],
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
store
|
||||
.global
|
||||
.env_vars
|
||||
.get(OPENAI_API_KEY)
|
||||
.map(String::as_str),
|
||||
Some("shared-key")
|
||||
);
|
||||
verify_post_split(&before, &store).unwrap();
|
||||
|
||||
let defs = definitions(&store);
|
||||
let custom_descriptor = crate::managed_agents::resolve_effective_harness_descriptor(
|
||||
&store.records[1],
|
||||
&defs,
|
||||
&store.global,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
custom_descriptor
|
||||
.env
|
||||
.get("BUZZ_AGENT_PROVIDER")
|
||||
.map(String::as_str),
|
||||
Some("openai-compat")
|
||||
);
|
||||
assert!(!custom_descriptor.env.contains_key(OPENAI_API_KEY));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goose_records_are_not_openai_migration_consumers() {
|
||||
let global = GlobalAgentConfig {
|
||||
provider: Some("openai".into()),
|
||||
preferred_runtime: Some("goose".into()),
|
||||
env_vars: BTreeMap::from([
|
||||
(OPENAI_COMPAT_API_KEY.into(), "goose-owned".into()),
|
||||
(
|
||||
OPENAI_COMPAT_BASE_URL.into(),
|
||||
"https://gateway.example/v1".into(),
|
||||
),
|
||||
]),
|
||||
..Default::default()
|
||||
};
|
||||
let mut goose = record("goose", "goose");
|
||||
goose.runtime = Some("goose".into());
|
||||
goose.provider = Some("openai".into());
|
||||
|
||||
let store = planned(global.clone(), vec![goose.clone()]).unwrap();
|
||||
assert_eq!(store.global, global);
|
||||
assert_eq!(store.records[0].provider, goose.provider);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linked_provider_snapshot_is_ignored_and_definition_is_mutated() {
|
||||
let mut def = definition("shared");
|
||||
|
||||
Reference in New Issue
Block a user