Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/biocheming_agendao.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
62 KiB
JSON

{"repo": "biocheming/agendao", "files": {"crates/agendao-cli/src/config_cmd.rs": {"db8cfaf1d17750914500f948c6316a6925297545": {"t": 1785745878.2490134, "n": 6900, "h": "377b9cead5cb7f79", "c": "use std::collections::BTreeMap;\n\nuse agendao_config::loader::load_config;\nuse chrono::{Local, TimeZone};\n\nuse crate::api_client::{\n CliApiClient, ConfigPolicyValidationEffect, ConfigPolicyValidationItem,\n ConfigPolicyValidationOwner, ConfigPolicyValidationScopeKind, ConfigPolicyValidationSeverity,\n ConfigPolicyValidationSnapshot,\n};\nuse crate::cli::{ConfigCommands, ConfigOutputArgs, ConfigOutputFormat};\nuse crate::server_lifecycle::CliRuntimeContext;\n\npub(super) async fn handle_config_command(\n action: Option<ConfigCommands>,\n runtime_context: &CliRuntimeContext,\n) -> anyhow::Result<()> {\n match action {\n None => show_config(),\n Some(ConfigCommands::Validation { output }) => {\n show_config_validation(runtime_context, &output).await\n }\n }\n}\n\nfn show_config() -> anyhow::Result<()> {\n let current_dir = std::env::current_dir()?;\n let config = load_config(&current_dir)?;\n\n println!(\"\\n╔══════════════════════════════════════════╗\");\n println!(\"║ Configuration ║\");\n println!(\"╚══════════════════════════════════════════╝\\n\");\n\n if let Some(ref model) = config.model {\n println!(\"Default model: {}\", model);\n }\n\n if let Some(ref default_agent) = config.default_agent {\n println!(\"Default agent: {}\", default_agent);\n }\n\n if !config.instructions.is_empty() {\n println!(\"\\nInstructions:\");\n for inst in &config.instructions {\n println!(\" - {}\", inst);\n }\n }\n\n println!(\"\\nWorking directory: {}\", current_dir.display());\n\n println!(\"\\nEnvironment variables:\");\n let env_vars = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"GROQ_API_KEY\",\n \"XAI_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"COHERE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"PERPLEXITY_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"GOOGLE_VERTEX_API_KEY\",\n \"AZURE_OPENAI_API_KEY\",\n \"AWS_ACCESS_KEY_ID\",\n ];\n\n for var in env_vars {\n let status = if std::env::var(var).is_ok() {\n \"✓ set\"\n } else {\n \"✗ not set\"\n };\n println!(\" {}: {}\", var, status);\n }\n\n Ok(())\n}\n\nasync fn show_config_validation(\n runtime_context: &CliRuntimeContext,\n output: &ConfigOutputArgs,\n) -> anyhow::Result<()> {\n let client = config_client(runtime_context).await?;\n let snapshot = client.get_config_validation().await?;\n\n if matches!(output.format, ConfigOutputFormat::Json) {\n println!(\"{}\", serde_json::to_string_pretty(&snapshot)?);\n return Ok(());\n }\n\n print_config_validation_snapshot(&snapshot);\n Ok(())\n}\n\nasync fn config_client(runtime_context: &CliRuntimeContext) -> anyhow::Result<CliApiClient> {\n let base_url = runtime_context.discover_or_start_server(None).await?;\n Ok(CliApiClient::new(base_url))\n}\n\nfn print_config_validation_snapshot(snapshot: &ConfigPolicyValidationSnapshot) {\n println!(\"Config validation\");\n println!(\" Source: /config/validation\");\n for line in config_validation_lines(snapshot) {\n println!(\"{line}\");\n }\n}\n\nfn config_validation_lines(snapshot: &ConfigPolicyValidationSnapshot) -> Vec<String> {\n let error_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Error)\n .count();\n let warning_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Warning)\n .count();\n\n let mut lines = vec![\n format!(\"Revision: {}\", snapshot.revision),\n format!(\"Generated: {}\", format_timestamp(snapshot.generated_at_ms)),\n format!(\n \"Findings: {} ({} errors, {} warnings)\",\n snapshot.reports.len(),\n error_count,\n warning_count\n ),\n ];\n\n if snapshot.reports.is_empty() {\n lines.push(String::new());\n lines\n .push(\"No validation findings are present in the current config snapshot.\".to_string());\n return lines;\n }\n\n let mut grouped: BTreeMap<ConfigPolicyValidationOwner, Vec<&ConfigPolicyValidationItem>> =\n BTreeMap::new();\n for item in &snapshot.reports {\n grouped.entry(item.owner).or_default().push(item);\n }\n\n for (owner, items) in grouped {\n lines.push(String::new());\n lines.push(format!(\"{} ({})\", owner_label(owner), items.len()));\n for item in items {\n lines.push(format!(\n \" - [{}] {} · {}\",\n severity_label(item.severity),\n item.code,\n item.path\n ));\n lines.push(format!(\n \" Scope: {}\",\n scope_label(item.scope.kind, item.scope.subject_id.as_deref())\n ));\n lines.push(format!(\" Effect: {}\", effect_label(item.effect)));\n lines.push(format!(\" Message: {}\", item.message));\n if let Some(fallback) = item.fallback.as_deref() {\n lines.push(format!(\" Fallback: {}\", fallback));\n }\n }\n }\n\n lines\n}\n\nfn owner_label(owner: ConfigPolicyValidationOwner) -> &'static str {\n match owner {\n ConfigPolicyValidationOwner::Scheduler => \"Scheduler\",\n ConfigPolicyValidationOwner::SkillTree => \"Skill Tree\",\n ConfigPolicyValidationOwner::ProviderProfile => \"Provider Profile\",\n ConfigPolicyValidationOwner::ExternalAdapter => \"External Adapter\",\n }\n}\n\nfn severity_label(severity: ConfigPolicyValidationSeverity) -> &'static str {\n match severity {\n ConfigPolicyValidationSeverity::Warning => \"warning\",\n ConfigPolicyValidationSeverity::Error => \"error\",\n }\n}\n\nfn effect_label(effect: ConfigPolicyValidationEffect) -> &'static str {\n match effect {\n ConfigPolicyValidationEffect::SoftFallback => \"soft fallback\",\n ConfigPolicyValidationEffect::FailClosedBootstrap => \"fail-closed bootstrap\",\n ConfigPolicyValidationEffect::FailClosedRequestGate => \"fail-closed request gate\",\n }\n}\n\nfn scope_label(kind: ConfigPolicyValidationScopeKind, subject_id: Option<&str>) -> String {\n let base = match kind {\n ConfigPolicyValidationScopeKind::SchedulerPath => \"scheduler path\",\n ConfigPolicyValidationScopeKind::SkillTree => \"skill tree\",\n ConfigPolicyValidationScopeKind::Provider => \"provider\",\n ConfigPolicyValidationScopeKind::ExternalAdapter => \"external adapter\",\n };\n match subject_id {\n Some(id) if !id.is_empty() => format!(\"{base} · {id}\"),\n _ => base.to_string(),\n }\n}\n\nfn format_timestamp(ts: i64) -> String {\n match Local.timestamp_millis_opt(ts).single() {\n Some(dt) => dt.to_rfc3339(),\n None => ts.to_string(),\n }\n}\n"}, "bda456a54da682028f6c039db09b2f3ee37c6c0a": {"t": 1785757492.1867495, "n": 6900, "h": "377b9cead5cb7f79", "c": "use std::collections::BTreeMap;\n\nuse agendao_config::loader::load_config;\nuse chrono::{Local, TimeZone};\n\nuse crate::api_client::{\n CliApiClient, ConfigPolicyValidationEffect, ConfigPolicyValidationItem,\n ConfigPolicyValidationOwner, ConfigPolicyValidationScopeKind, ConfigPolicyValidationSeverity,\n ConfigPolicyValidationSnapshot,\n};\nuse crate::cli::{ConfigCommands, ConfigOutputArgs, ConfigOutputFormat};\nuse crate::server_lifecycle::CliRuntimeContext;\n\npub(super) async fn handle_config_command(\n action: Option<ConfigCommands>,\n runtime_context: &CliRuntimeContext,\n) -> anyhow::Result<()> {\n match action {\n None => show_config(),\n Some(ConfigCommands::Validation { output }) => {\n show_config_validation(runtime_context, &output).await\n }\n }\n}\n\nfn show_config() -> anyhow::Result<()> {\n let current_dir = std::env::current_dir()?;\n let config = load_config(&current_dir)?;\n\n println!(\"\\n╔══════════════════════════════════════════╗\");\n println!(\"║ Configuration ║\");\n println!(\"╚══════════════════════════════════════════╝\\n\");\n\n if let Some(ref model) = config.model {\n println!(\"Default model: {}\", model);\n }\n\n if let Some(ref default_agent) = config.default_agent {\n println!(\"Default agent: {}\", default_agent);\n }\n\n if !config.instructions.is_empty() {\n println!(\"\\nInstructions:\");\n for inst in &config.instructions {\n println!(\" - {}\", inst);\n }\n }\n\n println!(\"\\nWorking directory: {}\", current_dir.display());\n\n println!(\"\\nEnvironment variables:\");\n let env_vars = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"GROQ_API_KEY\",\n \"XAI_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"COHERE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"PERPLEXITY_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"GOOGLE_VERTEX_API_KEY\",\n \"AZURE_OPENAI_API_KEY\",\n \"AWS_ACCESS_KEY_ID\",\n ];\n\n for var in env_vars {\n let status = if std::env::var(var).is_ok() {\n \"✓ set\"\n } else {\n \"✗ not set\"\n };\n println!(\" {}: {}\", var, status);\n }\n\n Ok(())\n}\n\nasync fn show_config_validation(\n runtime_context: &CliRuntimeContext,\n output: &ConfigOutputArgs,\n) -> anyhow::Result<()> {\n let client = config_client(runtime_context).await?;\n let snapshot = client.get_config_validation().await?;\n\n if matches!(output.format, ConfigOutputFormat::Json) {\n println!(\"{}\", serde_json::to_string_pretty(&snapshot)?);\n return Ok(());\n }\n\n print_config_validation_snapshot(&snapshot);\n Ok(())\n}\n\nasync fn config_client(runtime_context: &CliRuntimeContext) -> anyhow::Result<CliApiClient> {\n let base_url = runtime_context.discover_or_start_server(None).await?;\n Ok(CliApiClient::new(base_url))\n}\n\nfn print_config_validation_snapshot(snapshot: &ConfigPolicyValidationSnapshot) {\n println!(\"Config validation\");\n println!(\" Source: /config/validation\");\n for line in config_validation_lines(snapshot) {\n println!(\"{line}\");\n }\n}\n\nfn config_validation_lines(snapshot: &ConfigPolicyValidationSnapshot) -> Vec<String> {\n let error_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Error)\n .count();\n let warning_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Warning)\n .count();\n\n let mut lines = vec![\n format!(\"Revision: {}\", snapshot.revision),\n format!(\"Generated: {}\", format_timestamp(snapshot.generated_at_ms)),\n format!(\n \"Findings: {} ({} errors, {} warnings)\",\n snapshot.reports.len(),\n error_count,\n warning_count\n ),\n ];\n\n if snapshot.reports.is_empty() {\n lines.push(String::new());\n lines\n .push(\"No validation findings are present in the current config snapshot.\".to_string());\n return lines;\n }\n\n let mut grouped: BTreeMap<ConfigPolicyValidationOwner, Vec<&ConfigPolicyValidationItem>> =\n BTreeMap::new();\n for item in &snapshot.reports {\n grouped.entry(item.owner).or_default().push(item);\n }\n\n for (owner, items) in grouped {\n lines.push(String::new());\n lines.push(format!(\"{} ({})\", owner_label(owner), items.len()));\n for item in items {\n lines.push(format!(\n \" - [{}] {} · {}\",\n severity_label(item.severity),\n item.code,\n item.path\n ));\n lines.push(format!(\n \" Scope: {}\",\n scope_label(item.scope.kind, item.scope.subject_id.as_deref())\n ));\n lines.push(format!(\" Effect: {}\", effect_label(item.effect)));\n lines.push(format!(\" Message: {}\", item.message));\n if let Some(fallback) = item.fallback.as_deref() {\n lines.push(format!(\" Fallback: {}\", fallback));\n }\n }\n }\n\n lines\n}\n\nfn owner_label(owner: ConfigPolicyValidationOwner) -> &'static str {\n match owner {\n ConfigPolicyValidationOwner::Scheduler => \"Scheduler\",\n ConfigPolicyValidationOwner::SkillTree => \"Skill Tree\",\n ConfigPolicyValidationOwner::ProviderProfile => \"Provider Profile\",\n ConfigPolicyValidationOwner::ExternalAdapter => \"External Adapter\",\n }\n}\n\nfn severity_label(severity: ConfigPolicyValidationSeverity) -> &'static str {\n match severity {\n ConfigPolicyValidationSeverity::Warning => \"warning\",\n ConfigPolicyValidationSeverity::Error => \"error\",\n }\n}\n\nfn effect_label(effect: ConfigPolicyValidationEffect) -> &'static str {\n match effect {\n ConfigPolicyValidationEffect::SoftFallback => \"soft fallback\",\n ConfigPolicyValidationEffect::FailClosedBootstrap => \"fail-closed bootstrap\",\n ConfigPolicyValidationEffect::FailClosedRequestGate => \"fail-closed request gate\",\n }\n}\n\nfn scope_label(kind: ConfigPolicyValidationScopeKind, subject_id: Option<&str>) -> String {\n let base = match kind {\n ConfigPolicyValidationScopeKind::SchedulerPath => \"scheduler path\",\n ConfigPolicyValidationScopeKind::SkillTree => \"skill tree\",\n ConfigPolicyValidationScopeKind::Provider => \"provider\",\n ConfigPolicyValidationScopeKind::ExternalAdapter => \"external adapter\",\n };\n match subject_id {\n Some(id) if !id.is_empty() => format!(\"{base} · {id}\"),\n _ => base.to_string(),\n }\n}\n\nfn format_timestamp(ts: i64) -> String {\n match Local.timestamp_millis_opt(ts).single() {\n Some(dt) => dt.to_rfc3339(),\n None => ts.to_string(),\n }\n}\n"}, "a5943ac646ea8050dd1644c89da34d1be0322d11": {"t": 1785757493.4883275, "n": 6942, "h": "379da02d190bd0a5", "c": "use std::collections::BTreeMap;\n\nuse agendao_config::loader::load_config;\nuse chrono::{Local, TimeZone};\n\nuse crate::api_client::{\n CliApiClient, ConfigPolicyValidationEffect, ConfigPolicyValidationItem,\n ConfigPolicyValidationOwner, ConfigPolicyValidationScopeKind, ConfigPolicyValidationSeverity,\n ConfigPolicyValidationSnapshot,\n};\nuse crate::cli::{ConfigCommands, ConfigOutputArgs, ConfigOutputFormat};\nuse crate::server_lifecycle::FrontendRuntimeContext;\n\npub(crate) async fn handle_config_command(\n action: Option<ConfigCommands>,\n runtime_context: &FrontendRuntimeContext,\n) -> anyhow::Result<()> {\n match action {\n None => show_config(),\n Some(ConfigCommands::Validation { output }) => {\n show_config_validation(runtime_context, &output).await\n }\n }\n}\n\npub(crate) fn show_config() -> anyhow::Result<()> {\n let current_dir = std::env::current_dir()?;\n let config = load_config(&current_dir)?;\n\n println!(\"\\n╔══════════════════════════════════════════╗\");\n println!(\"║ Configuration ║\");\n println!(\"╚══════════════════════════════════════════╝\\n\");\n\n if let Some(ref model) = config.model {\n println!(\"Default model: {}\", model);\n }\n\n if let Some(ref default_agent) = config.default_agent {\n println!(\"Default agent: {}\", default_agent);\n }\n\n if !config.instructions.is_empty() {\n println!(\"\\nInstructions:\");\n for inst in &config.instructions {\n println!(\" - {}\", inst);\n }\n }\n\n println!(\"\\nWorking directory: {}\", current_dir.display());\n\n println!(\"\\nEnvironment variables:\");\n let env_vars = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"GROQ_API_KEY\",\n \"XAI_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"COHERE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"PERPLEXITY_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"GOOGLE_VERTEX_API_KEY\",\n \"AZURE_OPENAI_API_KEY\",\n \"AWS_ACCESS_KEY_ID\",\n ];\n\n for var in env_vars {\n let status = if std::env::var(var).is_ok() {\n \"✓ set\"\n } else {\n \"✗ not set\"\n };\n println!(\" {}: {}\", var, status);\n }\n\n Ok(())\n}\n\nasync fn show_config_validation(\n runtime_context: &FrontendRuntimeContext,\n output: &ConfigOutputArgs,\n) -> anyhow::Result<()> {\n let client = config_client(runtime_context).await?;\n let snapshot = client.get_config_validation().await?;\n\n if matches!(output.format, ConfigOutputFormat::Json) {\n println!(\"{}\", serde_json::to_string_pretty(&snapshot)?);\n return Ok(());\n }\n\n print_config_validation_snapshot(&snapshot);\n Ok(())\n}\n\nasync fn config_client(runtime_context: &FrontendRuntimeContext) -> anyhow::Result<CliApiClient> {\n let base_url = runtime_context.discover_or_start_server(None).await?;\n Ok(CliApiClient::new(base_url))\n}\n\nfn print_config_validation_snapshot(snapshot: &ConfigPolicyValidationSnapshot) {\n println!(\"Config validation\");\n println!(\" Source: /config/validation\");\n for line in config_validation_lines(snapshot) {\n println!(\"{line}\");\n }\n}\n\npub(crate) fn config_validation_lines(snapshot: &ConfigPolicyValidationSnapshot) -> Vec<String> {\n let error_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Error)\n .count();\n let warning_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Warning)\n .count();\n\n let mut lines = vec![\n format!(\"Revision: {}\", snapshot.revision),\n format!(\"Generated: {}\", format_timestamp(snapshot.generated_at_ms)),\n format!(\n \"Findings: {} ({} errors, {} warnings)\",\n snapshot.reports.len(),\n error_count,\n warning_count\n ),\n ];\n\n if snapshot.reports.is_empty() {\n lines.push(String::new());\n lines\n .push(\"No validation findings are present in the current config snapshot.\".to_string());\n return lines;\n }\n\n let mut grouped: BTreeMap<ConfigPolicyValidationOwner, Vec<&ConfigPolicyValidationItem>> =\n BTreeMap::new();\n for item in &snapshot.reports {\n grouped.entry(item.owner).or_default().push(item);\n }\n\n for (owner, items) in grouped {\n lines.push(String::new());\n lines.push(format!(\"{} ({})\", owner_label(owner), items.len()));\n for item in items {\n lines.push(format!(\n \" - [{}] {} · {}\",\n severity_label(item.severity),\n item.code,\n item.path\n ));\n lines.push(format!(\n \" Scope: {}\",\n scope_label(item.scope.kind, item.scope.subject_id.as_deref())\n ));\n lines.push(format!(\" Effect: {}\", effect_label(item.effect)));\n lines.push(format!(\" Message: {}\", item.message));\n if let Some(fallback) = item.fallback.as_deref() {\n lines.push(format!(\" Fallback: {}\", fallback));\n }\n }\n }\n\n lines\n}\n\nfn owner_label(owner: ConfigPolicyValidationOwner) -> &'static str {\n match owner {\n ConfigPolicyValidationOwner::Scheduler => \"Scheduler\",\n ConfigPolicyValidationOwner::SkillTree => \"Skill Tree\",\n ConfigPolicyValidationOwner::ProviderProfile => \"Provider Profile\",\n ConfigPolicyValidationOwner::ExternalAdapter => \"External Adapter\",\n }\n}\n\nfn severity_label(severity: ConfigPolicyValidationSeverity) -> &'static str {\n match severity {\n ConfigPolicyValidationSeverity::Warning => \"warning\",\n ConfigPolicyValidationSeverity::Error => \"error\",\n }\n}\n\nfn effect_label(effect: ConfigPolicyValidationEffect) -> &'static str {\n match effect {\n ConfigPolicyValidationEffect::SoftFallback => \"soft fallback\",\n ConfigPolicyValidationEffect::FailClosedBootstrap => \"fail-closed bootstrap\",\n ConfigPolicyValidationEffect::FailClosedRequestGate => \"fail-closed request gate\",\n }\n}\n\nfn scope_label(kind: ConfigPolicyValidationScopeKind, subject_id: Option<&str>) -> String {\n let base = match kind {\n ConfigPolicyValidationScopeKind::SchedulerPath => \"scheduler path\",\n ConfigPolicyValidationScopeKind::SkillTree => \"skill tree\",\n ConfigPolicyValidationScopeKind::Provider => \"provider\",\n ConfigPolicyValidationScopeKind::ExternalAdapter => \"external adapter\",\n };\n match subject_id {\n Some(id) if !id.is_empty() => format!(\"{base} · {id}\"),\n _ => base.to_string(),\n }\n}\n\nfn format_timestamp(ts: i64) -> String {\n match Local.timestamp_millis_opt(ts).single() {\n Some(dt) => dt.to_rfc3339(),\n None => ts.to_string(),\n }\n}\n"}, "b364654540148104b81628d6f8ca5c3f6023b824": {"t": 1785757494.7448766, "n": 6942, "h": "d2c579cd21487436", "c": "use std::collections::BTreeMap;\n\nuse chrono::{Local, TimeZone};\nuse agendao_config::loader::load_config;\n\nuse crate::api_client::{\n CliApiClient, ConfigPolicyValidationEffect, ConfigPolicyValidationItem,\n ConfigPolicyValidationOwner, ConfigPolicyValidationScopeKind, ConfigPolicyValidationSeverity,\n ConfigPolicyValidationSnapshot,\n};\nuse crate::cli::{ConfigCommands, ConfigOutputArgs, ConfigOutputFormat};\nuse crate::server_lifecycle::FrontendRuntimeContext;\n\npub(crate) async fn handle_config_command(\n action: Option<ConfigCommands>,\n runtime_context: &FrontendRuntimeContext,\n) -> anyhow::Result<()> {\n match action {\n None => show_config(),\n Some(ConfigCommands::Validation { output }) => {\n show_config_validation(runtime_context, &output).await\n }\n }\n}\n\npub(crate) fn show_config() -> anyhow::Result<()> {\n let current_dir = std::env::current_dir()?;\n let config = load_config(&current_dir)?;\n\n println!(\"\\n╔══════════════════════════════════════════╗\");\n println!(\"║ Configuration ║\");\n println!(\"╚══════════════════════════════════════════╝\\n\");\n\n if let Some(ref model) = config.model {\n println!(\"Default model: {}\", model);\n }\n\n if let Some(ref default_agent) = config.default_agent {\n println!(\"Default agent: {}\", default_agent);\n }\n\n if !config.instructions.is_empty() {\n println!(\"\\nInstructions:\");\n for inst in &config.instructions {\n println!(\" - {}\", inst);\n }\n }\n\n println!(\"\\nWorking directory: {}\", current_dir.display());\n\n println!(\"\\nEnvironment variables:\");\n let env_vars = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"GROQ_API_KEY\",\n \"XAI_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"COHERE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"PERPLEXITY_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"GOOGLE_VERTEX_API_KEY\",\n \"AZURE_OPENAI_API_KEY\",\n \"AWS_ACCESS_KEY_ID\",\n ];\n\n for var in env_vars {\n let status = if std::env::var(var).is_ok() {\n \"✓ set\"\n } else {\n \"✗ not set\"\n };\n println!(\" {}: {}\", var, status);\n }\n\n Ok(())\n}\n\nasync fn show_config_validation(\n runtime_context: &FrontendRuntimeContext,\n output: &ConfigOutputArgs,\n) -> anyhow::Result<()> {\n let client = config_client(runtime_context).await?;\n let snapshot = client.get_config_validation().await?;\n\n if matches!(output.format, ConfigOutputFormat::Json) {\n println!(\"{}\", serde_json::to_string_pretty(&snapshot)?);\n return Ok(());\n }\n\n print_config_validation_snapshot(&snapshot);\n Ok(())\n}\n\nasync fn config_client(runtime_context: &FrontendRuntimeContext) -> anyhow::Result<CliApiClient> {\n let base_url = runtime_context.discover_or_start_server(None).await?;\n Ok(CliApiClient::new(base_url))\n}\n\nfn print_config_validation_snapshot(snapshot: &ConfigPolicyValidationSnapshot) {\n println!(\"Config validation\");\n println!(\" Source: /config/validation\");\n for line in config_validation_lines(snapshot) {\n println!(\"{line}\");\n }\n}\n\npub(crate) fn config_validation_lines(snapshot: &ConfigPolicyValidationSnapshot) -> Vec<String> {\n let error_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Error)\n .count();\n let warning_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Warning)\n .count();\n\n let mut lines = vec![\n format!(\"Revision: {}\", snapshot.revision),\n format!(\"Generated: {}\", format_timestamp(snapshot.generated_at_ms)),\n format!(\n \"Findings: {} ({} errors, {} warnings)\",\n snapshot.reports.len(),\n error_count,\n warning_count\n ),\n ];\n\n if snapshot.reports.is_empty() {\n lines.push(String::new());\n lines\n .push(\"No validation findings are present in the current config snapshot.\".to_string());\n return lines;\n }\n\n let mut grouped: BTreeMap<ConfigPolicyValidationOwner, Vec<&ConfigPolicyValidationItem>> =\n BTreeMap::new();\n for item in &snapshot.reports {\n grouped.entry(item.owner).or_default().push(item);\n }\n\n for (owner, items) in grouped {\n lines.push(String::new());\n lines.push(format!(\"{} ({})\", owner_label(owner), items.len()));\n for item in items {\n lines.push(format!(\n \" - [{}] {} · {}\",\n severity_label(item.severity),\n item.code,\n item.path\n ));\n lines.push(format!(\n \" Scope: {}\",\n scope_label(item.scope.kind, item.scope.subject_id.as_deref())\n ));\n lines.push(format!(\" Effect: {}\", effect_label(item.effect)));\n lines.push(format!(\" Message: {}\", item.message));\n if let Some(fallback) = item.fallback.as_deref() {\n lines.push(format!(\" Fallback: {}\", fallback));\n }\n }\n }\n\n lines\n}\n\nfn owner_label(owner: ConfigPolicyValidationOwner) -> &'static str {\n match owner {\n ConfigPolicyValidationOwner::Scheduler => \"Scheduler\",\n ConfigPolicyValidationOwner::SkillTree => \"Skill Tree\",\n ConfigPolicyValidationOwner::ProviderProfile => \"Provider Profile\",\n ConfigPolicyValidationOwner::ExternalAdapter => \"External Adapter\",\n }\n}\n\nfn severity_label(severity: ConfigPolicyValidationSeverity) -> &'static str {\n match severity {\n ConfigPolicyValidationSeverity::Warning => \"warning\",\n ConfigPolicyValidationSeverity::Error => \"error\",\n }\n}\n\nfn effect_label(effect: ConfigPolicyValidationEffect) -> &'static str {\n match effect {\n ConfigPolicyValidationEffect::SoftFallback => \"soft fallback\",\n ConfigPolicyValidationEffect::FailClosedBootstrap => \"fail-closed bootstrap\",\n ConfigPolicyValidationEffect::FailClosedRequestGate => \"fail-closed request gate\",\n }\n}\n\nfn scope_label(kind: ConfigPolicyValidationScopeKind, subject_id: Option<&str>) -> String {\n let base = match kind {\n ConfigPolicyValidationScopeKind::SchedulerPath => \"scheduler path\",\n ConfigPolicyValidationScopeKind::SkillTree => \"skill tree\",\n ConfigPolicyValidationScopeKind::Provider => \"provider\",\n ConfigPolicyValidationScopeKind::ExternalAdapter => \"external adapter\",\n };\n match subject_id {\n Some(id) if !id.is_empty() => format!(\"{base} · {id}\"),\n _ => base.to_string(),\n }\n}\n\nfn format_timestamp(ts: i64) -> String {\n match Local.timestamp_millis_opt(ts).single() {\n Some(dt) => dt.to_rfc3339(),\n None => ts.to_string(),\n }\n}\n"}, "bbb4169b72e012a6617222479e77c600d0636685": {"t": 1786068331.2580557, "n": 6900, "h": "377b9cead5cb7f79", "c": "use std::collections::BTreeMap;\n\nuse agendao_config::loader::load_config;\nuse chrono::{Local, TimeZone};\n\nuse crate::api_client::{\n CliApiClient, ConfigPolicyValidationEffect, ConfigPolicyValidationItem,\n ConfigPolicyValidationOwner, ConfigPolicyValidationScopeKind, ConfigPolicyValidationSeverity,\n ConfigPolicyValidationSnapshot,\n};\nuse crate::cli::{ConfigCommands, ConfigOutputArgs, ConfigOutputFormat};\nuse crate::server_lifecycle::CliRuntimeContext;\n\npub(super) async fn handle_config_command(\n action: Option<ConfigCommands>,\n runtime_context: &CliRuntimeContext,\n) -> anyhow::Result<()> {\n match action {\n None => show_config(),\n Some(ConfigCommands::Validation { output }) => {\n show_config_validation(runtime_context, &output).await\n }\n }\n}\n\nfn show_config() -> anyhow::Result<()> {\n let current_dir = std::env::current_dir()?;\n let config = load_config(&current_dir)?;\n\n println!(\"\\n╔══════════════════════════════════════════╗\");\n println!(\"║ Configuration ║\");\n println!(\"╚══════════════════════════════════════════╝\\n\");\n\n if let Some(ref model) = config.model {\n println!(\"Default model: {}\", model);\n }\n\n if let Some(ref default_agent) = config.default_agent {\n println!(\"Default agent: {}\", default_agent);\n }\n\n if !config.instructions.is_empty() {\n println!(\"\\nInstructions:\");\n for inst in &config.instructions {\n println!(\" - {}\", inst);\n }\n }\n\n println!(\"\\nWorking directory: {}\", current_dir.display());\n\n println!(\"\\nEnvironment variables:\");\n let env_vars = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"GROQ_API_KEY\",\n \"XAI_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"COHERE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"PERPLEXITY_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"GOOGLE_VERTEX_API_KEY\",\n \"AZURE_OPENAI_API_KEY\",\n \"AWS_ACCESS_KEY_ID\",\n ];\n\n for var in env_vars {\n let status = if std::env::var(var).is_ok() {\n \"✓ set\"\n } else {\n \"✗ not set\"\n };\n println!(\" {}: {}\", var, status);\n }\n\n Ok(())\n}\n\nasync fn show_config_validation(\n runtime_context: &CliRuntimeContext,\n output: &ConfigOutputArgs,\n) -> anyhow::Result<()> {\n let client = config_client(runtime_context).await?;\n let snapshot = client.get_config_validation().await?;\n\n if matches!(output.format, ConfigOutputFormat::Json) {\n println!(\"{}\", serde_json::to_string_pretty(&snapshot)?);\n return Ok(());\n }\n\n print_config_validation_snapshot(&snapshot);\n Ok(())\n}\n\nasync fn config_client(runtime_context: &CliRuntimeContext) -> anyhow::Result<CliApiClient> {\n let base_url = runtime_context.discover_or_start_server(None).await?;\n Ok(CliApiClient::new(base_url))\n}\n\nfn print_config_validation_snapshot(snapshot: &ConfigPolicyValidationSnapshot) {\n println!(\"Config validation\");\n println!(\" Source: /config/validation\");\n for line in config_validation_lines(snapshot) {\n println!(\"{line}\");\n }\n}\n\nfn config_validation_lines(snapshot: &ConfigPolicyValidationSnapshot) -> Vec<String> {\n let error_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Error)\n .count();\n let warning_count = snapshot\n .reports\n .iter()\n .filter(|item| item.severity == ConfigPolicyValidationSeverity::Warning)\n .count();\n\n let mut lines = vec![\n format!(\"Revision: {}\", snapshot.revision),\n format!(\"Generated: {}\", format_timestamp(snapshot.generated_at_ms)),\n format!(\n \"Findings: {} ({} errors, {} warnings)\",\n snapshot.reports.len(),\n error_count,\n warning_count\n ),\n ];\n\n if snapshot.reports.is_empty() {\n lines.push(String::new());\n lines\n .push(\"No validation findings are present in the current config snapshot.\".to_string());\n return lines;\n }\n\n let mut grouped: BTreeMap<ConfigPolicyValidationOwner, Vec<&ConfigPolicyValidationItem>> =\n BTreeMap::new();\n for item in &snapshot.reports {\n grouped.entry(item.owner).or_default().push(item);\n }\n\n for (owner, items) in grouped {\n lines.push(String::new());\n lines.push(format!(\"{} ({})\", owner_label(owner), items.len()));\n for item in items {\n lines.push(format!(\n \" - [{}] {} · {}\",\n severity_label(item.severity),\n item.code,\n item.path\n ));\n lines.push(format!(\n \" Scope: {}\",\n scope_label(item.scope.kind, item.scope.subject_id.as_deref())\n ));\n lines.push(format!(\" Effect: {}\", effect_label(item.effect)));\n lines.push(format!(\" Message: {}\", item.message));\n if let Some(fallback) = item.fallback.as_deref() {\n lines.push(format!(\" Fallback: {}\", fallback));\n }\n }\n }\n\n lines\n}\n\nfn owner_label(owner: ConfigPolicyValidationOwner) -> &'static str {\n match owner {\n ConfigPolicyValidationOwner::Scheduler => \"Scheduler\",\n ConfigPolicyValidationOwner::SkillTree => \"Skill Tree\",\n ConfigPolicyValidationOwner::ProviderProfile => \"Provider Profile\",\n ConfigPolicyValidationOwner::ExternalAdapter => \"External Adapter\",\n }\n}\n\nfn severity_label(severity: ConfigPolicyValidationSeverity) -> &'static str {\n match severity {\n ConfigPolicyValidationSeverity::Warning => \"warning\",\n ConfigPolicyValidationSeverity::Error => \"error\",\n }\n}\n\nfn effect_label(effect: ConfigPolicyValidationEffect) -> &'static str {\n match effect {\n ConfigPolicyValidationEffect::SoftFallback => \"soft fallback\",\n ConfigPolicyValidationEffect::FailClosedBootstrap => \"fail-closed bootstrap\",\n ConfigPolicyValidationEffect::FailClosedRequestGate => \"fail-closed request gate\",\n }\n}\n\nfn scope_label(kind: ConfigPolicyValidationScopeKind, subject_id: Option<&str>) -> String {\n let base = match kind {\n ConfigPolicyValidationScopeKind::SchedulerPath => \"scheduler path\",\n ConfigPolicyValidationScopeKind::SkillTree => \"skill tree\",\n ConfigPolicyValidationScopeKind::Provider => \"provider\",\n ConfigPolicyValidationScopeKind::ExternalAdapter => \"external adapter\",\n };\n match subject_id {\n Some(id) if !id.is_empty() => format!(\"{base} · {id}\"),\n _ => base.to_string(),\n }\n}\n\nfn format_timestamp(ts: i64) -> String {\n match Local.timestamp_millis_opt(ts).single() {\n Some(dt) => dt.to_rfc3339(),\n None => ts.to_string(),\n }\n}\n"}}, "crates/agendao-provider/tests/protocol_test.rs": {"db8cfaf1d17750914500f948c6316a6925297545": {"t": 1785746255.4551988, "n": 7923, "h": "f43da4de440d6bab", "c": "use agendao_provider::{\n create_provider_adapter, create_provider_adapter_for_profile, ChatRequest, ProviderAdapter,\n ProviderConfig, ProviderProfileResolver, ProviderRuntimeAdapter,\n};\nuse std::collections::HashMap;\n\n#[test]\nfn test_adapter_from_profile_ethnopic_family() {\n let adapter = adapter_from_resolved_profile(\"ethnopic\", \"@ai-sdk/anthropic\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Ethnopic);\n}\n\n#[test]\nfn test_adapter_from_profile_ethnopic_alias() {\n let adapter = adapter_from_resolved_profile(\"ethnopic\", \"ethnopic-compatible\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Ethnopic);\n}\n\n#[test]\nfn test_adapter_from_profile_openai() {\n let adapter = adapter_from_resolved_profile(\"openai\", \"@ai-sdk/openai\");\n assert_eq!(adapter, ProviderRuntimeAdapter::CloseAiCompatible);\n}\n\n#[test]\nfn test_adapter_from_profile_closeai_and_openai_aliases() {\n assert_eq!(\n adapter_from_resolved_profile(\"custom-closeai\", \"closeai-compatible\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n assert_eq!(\n adapter_from_resolved_profile(\"custom-closeai\", \"openai-compatible\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_adapter_from_profile_openrouter_and_perplexity() {\n assert_eq!(\n adapter_from_resolved_profile(\"openrouter\", \"@openrouter/ai-sdk-provider\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n assert_eq!(\n adapter_from_resolved_profile(\"perplexity\", \"@ai-sdk/perplexity\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_adapter_from_profile_unknown_defaults_to_closeai_compatible() {\n let adapter = adapter_from_resolved_profile(\"custom\", \"@custom/unknown-provider\");\n assert_eq!(adapter, ProviderRuntimeAdapter::CloseAiCompatible);\n}\n\n#[test]\nfn test_adapter_from_profile_vertex() {\n let adapter = adapter_from_resolved_profile(\"google-vertex\", \"@ai-sdk/google-vertex\");\n assert_eq!(adapter, ProviderRuntimeAdapter::VertexGemini);\n}\n\n#[test]\nfn test_adapter_from_profile_google() {\n let adapter = adapter_from_resolved_profile(\"google\", \"@ai-sdk/google\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Gemini);\n}\n\n#[test]\nfn test_adapter_from_profile_bedrock() {\n let adapter = adapter_from_resolved_profile(\"amazon-bedrock\", \"@ai-sdk/bedrock\");\n assert_eq!(adapter, ProviderRuntimeAdapter::BedrockConverse);\n}\n\n#[test]\nfn test_adapter_from_profile_github_copilot() {\n let adapter = adapter_from_resolved_profile(\"github-copilot\", \"@ai-sdk/github-copilot\");\n assert_eq!(adapter, ProviderRuntimeAdapter::GitHubCopilotCloseAi);\n}\n\n#[test]\nfn test_adapter_from_profile_gitlab() {\n let adapter = adapter_from_resolved_profile(\"gitlab\", \"@ai-sdk/gitlab\");\n assert_eq!(adapter, ProviderRuntimeAdapter::GitLabCloseAi);\n}\n\n#[test]\nfn test_adapter_resolution_is_case_insensitive() {\n assert_eq!(\n adapter_from_resolved_profile(\"ethnopic\", \"@AI-SDK/ANTHROPIC\"),\n ProviderRuntimeAdapter::Ethnopic\n );\n assert_eq!(\n adapter_from_resolved_profile(\"openai\", \"@Ai-Sdk/Openai\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\nfn adapter_from_resolved_profile(provider_id: &str, npm: &str) -> ProviderRuntimeAdapter {\n let options = HashMap::new();\n let profile = ProviderProfileResolver::resolve_with_npm(provider_id, npm, &options);\n ProviderRuntimeAdapter::from_profile(&profile)\n}\n\n#[test]\nfn test_adapter_display_labels() {\n assert_eq!(ProviderRuntimeAdapter::Ethnopic.to_string(), \"ethnopic\");\n assert_eq!(\n ProviderRuntimeAdapter::CloseAiCompatible.to_string(),\n \"closeai-compatible\"\n );\n}\n\n#[test]\nfn test_adapter_from_profile_projects_vendor_specific_adapters() {\n let options = HashMap::new();\n let gitlab =\n ProviderProfileResolver::resolve_with_npm(\"gitlab\", \"@gitlab/gitlab-ai-provider\", &options);\n let copilot = ProviderProfileResolver::resolve_with_npm(\n \"github-copilot\",\n \"@ai-sdk/github-copilot\",\n &options,\n );\n let vertex = ProviderProfileResolver::resolve_with_npm(\n \"google-vertex\",\n \"@ai-sdk/google-vertex\",\n &options,\n );\n let closeai = ProviderProfileResolver::resolve_with_npm(\n \"custom-closeai\",\n \"@ai-sdk/openai-compatible\",\n &options,\n );\n\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&gitlab),\n ProviderRuntimeAdapter::GitLabCloseAi\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&copilot),\n ProviderRuntimeAdapter::GitHubCopilotCloseAi\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&vertex),\n ProviderRuntimeAdapter::VertexGemini\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&closeai),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_provider_config_basic() {\n let config = ProviderConfig {\n provider_id: \"deepseek\".to_string(),\n base_url: \"https://api.deepseek.com/chat/completions\".to_string(),\n api_key: \"sk-test\".to_string(),\n headers: HashMap::new(),\n options: HashMap::new(),\n };\n\n assert_eq!(config.provider_id, \"deepseek\");\n assert_eq!(config.base_url, \"https://api.deepseek.com/chat/completions\");\n}\n\n#[test]\nfn test_provider_config_with_custom_headers() {\n let mut headers = HashMap::new();\n headers.insert(\n \"HTTP-Referer\".to_string(),\n \"https://opencode.ai/\".to_string(),\n );\n headers.insert(\"X-Title\".to_string(), \"opencode\".to_string());\n\n let config = ProviderConfig {\n provider_id: \"openrouter\".to_string(),\n base_url: \"https://openrouter.ai/api/v1/chat/completions\".to_string(),\n api_key: \"sk-or-...\".to_string(),\n headers,\n options: HashMap::new(),\n };\n\n assert_eq!(\n config.headers.get(\"HTTP-Referer\").expect(\"header\"),\n \"https://opencode.ai/\"\n );\n}\n\n#[test]\nfn test_provider_config_with_options() {\n let mut options = HashMap::new();\n options.insert(\"endpoint_path\".to_string(), serde_json::json!(\"/v2/chat\"));\n\n let config = ProviderConfig {\n provider_id: \"cohere\".to_string(),\n base_url: \"https://api.cohere.ai\".to_string(),\n api_key: \"sk-cohere\".to_string(),\n headers: HashMap::new(),\n options,\n };\n\n assert_eq!(\n config.options.get(\"endpoint_path\").expect(\"option\"),\n \"/v2/chat\"\n );\n}\n\nstruct MockProviderAdapter;\n\n#[async_trait::async_trait]\nimpl ProviderAdapter for MockProviderAdapter {\n async fn chat(\n &self,\n _client: &reqwest::Client,\n _config: &ProviderConfig,\n _request: ChatRequest,\n ) -> Result<agendao_provider::ChatResponse, agendao_provider::ProviderError> {\n unimplemented!()\n }\n\n async fn chat_stream(\n &self,\n _client: &reqwest::Client,\n _config: &ProviderConfig,\n _request: ChatRequest,\n ) -> Result<agendao_provider::StreamResult, agendao_provider::ProviderError> {\n unimplemented!()\n }\n}\n\n#[test]\nfn test_provider_adapter_trait_bounds() {\n fn assert_send_sync<T: Send + Sync>() {}\n assert_send_sync::<MockProviderAdapter>();\n}\n\n#[test]\nfn test_create_provider_adapter_closeai_compatible() {\n let adapter = create_provider_adapter(ProviderRuntimeAdapter::CloseAiCompatible);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n\n#[test]\nfn test_create_provider_adapter_ethnopic() {\n let adapter = create_provider_adapter(ProviderRuntimeAdapter::Ethnopic);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n\n#[test]\nfn test_create_provider_adapter_for_profile() {\n let options = HashMap::new();\n let profile =\n ProviderProfileResolver::resolve_with_npm(\"ethnopic\", \"@ai-sdk/anthropic\", &options);\n let adapter = create_provider_adapter_for_profile(&profile);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n"}, "b364654540148104b81628d6f8ca5c3f6023b824": {"t": 1785757493.2735186, "n": 7923, "h": "f43da4de440d6bab", "c": "use agendao_provider::{\n create_provider_adapter, create_provider_adapter_for_profile, ChatRequest, ProviderAdapter,\n ProviderConfig, ProviderProfileResolver, ProviderRuntimeAdapter,\n};\nuse std::collections::HashMap;\n\n#[test]\nfn test_adapter_from_profile_ethnopic_family() {\n let adapter = adapter_from_resolved_profile(\"ethnopic\", \"@ai-sdk/anthropic\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Ethnopic);\n}\n\n#[test]\nfn test_adapter_from_profile_ethnopic_alias() {\n let adapter = adapter_from_resolved_profile(\"ethnopic\", \"ethnopic-compatible\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Ethnopic);\n}\n\n#[test]\nfn test_adapter_from_profile_openai() {\n let adapter = adapter_from_resolved_profile(\"openai\", \"@ai-sdk/openai\");\n assert_eq!(adapter, ProviderRuntimeAdapter::CloseAiCompatible);\n}\n\n#[test]\nfn test_adapter_from_profile_closeai_and_openai_aliases() {\n assert_eq!(\n adapter_from_resolved_profile(\"custom-closeai\", \"closeai-compatible\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n assert_eq!(\n adapter_from_resolved_profile(\"custom-closeai\", \"openai-compatible\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_adapter_from_profile_openrouter_and_perplexity() {\n assert_eq!(\n adapter_from_resolved_profile(\"openrouter\", \"@openrouter/ai-sdk-provider\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n assert_eq!(\n adapter_from_resolved_profile(\"perplexity\", \"@ai-sdk/perplexity\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_adapter_from_profile_unknown_defaults_to_closeai_compatible() {\n let adapter = adapter_from_resolved_profile(\"custom\", \"@custom/unknown-provider\");\n assert_eq!(adapter, ProviderRuntimeAdapter::CloseAiCompatible);\n}\n\n#[test]\nfn test_adapter_from_profile_vertex() {\n let adapter = adapter_from_resolved_profile(\"google-vertex\", \"@ai-sdk/google-vertex\");\n assert_eq!(adapter, ProviderRuntimeAdapter::VertexGemini);\n}\n\n#[test]\nfn test_adapter_from_profile_google() {\n let adapter = adapter_from_resolved_profile(\"google\", \"@ai-sdk/google\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Gemini);\n}\n\n#[test]\nfn test_adapter_from_profile_bedrock() {\n let adapter = adapter_from_resolved_profile(\"amazon-bedrock\", \"@ai-sdk/bedrock\");\n assert_eq!(adapter, ProviderRuntimeAdapter::BedrockConverse);\n}\n\n#[test]\nfn test_adapter_from_profile_github_copilot() {\n let adapter = adapter_from_resolved_profile(\"github-copilot\", \"@ai-sdk/github-copilot\");\n assert_eq!(adapter, ProviderRuntimeAdapter::GitHubCopilotCloseAi);\n}\n\n#[test]\nfn test_adapter_from_profile_gitlab() {\n let adapter = adapter_from_resolved_profile(\"gitlab\", \"@ai-sdk/gitlab\");\n assert_eq!(adapter, ProviderRuntimeAdapter::GitLabCloseAi);\n}\n\n#[test]\nfn test_adapter_resolution_is_case_insensitive() {\n assert_eq!(\n adapter_from_resolved_profile(\"ethnopic\", \"@AI-SDK/ANTHROPIC\"),\n ProviderRuntimeAdapter::Ethnopic\n );\n assert_eq!(\n adapter_from_resolved_profile(\"openai\", \"@Ai-Sdk/Openai\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\nfn adapter_from_resolved_profile(provider_id: &str, npm: &str) -> ProviderRuntimeAdapter {\n let options = HashMap::new();\n let profile = ProviderProfileResolver::resolve_with_npm(provider_id, npm, &options);\n ProviderRuntimeAdapter::from_profile(&profile)\n}\n\n#[test]\nfn test_adapter_display_labels() {\n assert_eq!(ProviderRuntimeAdapter::Ethnopic.to_string(), \"ethnopic\");\n assert_eq!(\n ProviderRuntimeAdapter::CloseAiCompatible.to_string(),\n \"closeai-compatible\"\n );\n}\n\n#[test]\nfn test_adapter_from_profile_projects_vendor_specific_adapters() {\n let options = HashMap::new();\n let gitlab =\n ProviderProfileResolver::resolve_with_npm(\"gitlab\", \"@gitlab/gitlab-ai-provider\", &options);\n let copilot = ProviderProfileResolver::resolve_with_npm(\n \"github-copilot\",\n \"@ai-sdk/github-copilot\",\n &options,\n );\n let vertex = ProviderProfileResolver::resolve_with_npm(\n \"google-vertex\",\n \"@ai-sdk/google-vertex\",\n &options,\n );\n let closeai = ProviderProfileResolver::resolve_with_npm(\n \"custom-closeai\",\n \"@ai-sdk/openai-compatible\",\n &options,\n );\n\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&gitlab),\n ProviderRuntimeAdapter::GitLabCloseAi\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&copilot),\n ProviderRuntimeAdapter::GitHubCopilotCloseAi\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&vertex),\n ProviderRuntimeAdapter::VertexGemini\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&closeai),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_provider_config_basic() {\n let config = ProviderConfig {\n provider_id: \"deepseek\".to_string(),\n base_url: \"https://api.deepseek.com/chat/completions\".to_string(),\n api_key: \"sk-test\".to_string(),\n headers: HashMap::new(),\n options: HashMap::new(),\n };\n\n assert_eq!(config.provider_id, \"deepseek\");\n assert_eq!(config.base_url, \"https://api.deepseek.com/chat/completions\");\n}\n\n#[test]\nfn test_provider_config_with_custom_headers() {\n let mut headers = HashMap::new();\n headers.insert(\n \"HTTP-Referer\".to_string(),\n \"https://opencode.ai/\".to_string(),\n );\n headers.insert(\"X-Title\".to_string(), \"opencode\".to_string());\n\n let config = ProviderConfig {\n provider_id: \"openrouter\".to_string(),\n base_url: \"https://openrouter.ai/api/v1/chat/completions\".to_string(),\n api_key: \"sk-or-...\".to_string(),\n headers,\n options: HashMap::new(),\n };\n\n assert_eq!(\n config.headers.get(\"HTTP-Referer\").expect(\"header\"),\n \"https://opencode.ai/\"\n );\n}\n\n#[test]\nfn test_provider_config_with_options() {\n let mut options = HashMap::new();\n options.insert(\"endpoint_path\".to_string(), serde_json::json!(\"/v2/chat\"));\n\n let config = ProviderConfig {\n provider_id: \"cohere\".to_string(),\n base_url: \"https://api.cohere.ai\".to_string(),\n api_key: \"sk-cohere\".to_string(),\n headers: HashMap::new(),\n options,\n };\n\n assert_eq!(\n config.options.get(\"endpoint_path\").expect(\"option\"),\n \"/v2/chat\"\n );\n}\n\nstruct MockProviderAdapter;\n\n#[async_trait::async_trait]\nimpl ProviderAdapter for MockProviderAdapter {\n async fn chat(\n &self,\n _client: &reqwest::Client,\n _config: &ProviderConfig,\n _request: ChatRequest,\n ) -> Result<agendao_provider::ChatResponse, agendao_provider::ProviderError> {\n unimplemented!()\n }\n\n async fn chat_stream(\n &self,\n _client: &reqwest::Client,\n _config: &ProviderConfig,\n _request: ChatRequest,\n ) -> Result<agendao_provider::StreamResult, agendao_provider::ProviderError> {\n unimplemented!()\n }\n}\n\n#[test]\nfn test_provider_adapter_trait_bounds() {\n fn assert_send_sync<T: Send + Sync>() {}\n assert_send_sync::<MockProviderAdapter>();\n}\n\n#[test]\nfn test_create_provider_adapter_closeai_compatible() {\n let adapter = create_provider_adapter(ProviderRuntimeAdapter::CloseAiCompatible);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n\n#[test]\nfn test_create_provider_adapter_ethnopic() {\n let adapter = create_provider_adapter(ProviderRuntimeAdapter::Ethnopic);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n\n#[test]\nfn test_create_provider_adapter_for_profile() {\n let options = HashMap::new();\n let profile =\n ProviderProfileResolver::resolve_with_npm(\"ethnopic\", \"@ai-sdk/anthropic\", &options);\n let adapter = create_provider_adapter_for_profile(&profile);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n"}, "bbb4169b72e012a6617222479e77c600d0636685": {"t": 1786068398.840058, "n": 7923, "h": "f43da4de440d6bab", "c": "use agendao_provider::{\n create_provider_adapter, create_provider_adapter_for_profile, ChatRequest, ProviderAdapter,\n ProviderConfig, ProviderProfileResolver, ProviderRuntimeAdapter,\n};\nuse std::collections::HashMap;\n\n#[test]\nfn test_adapter_from_profile_ethnopic_family() {\n let adapter = adapter_from_resolved_profile(\"ethnopic\", \"@ai-sdk/anthropic\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Ethnopic);\n}\n\n#[test]\nfn test_adapter_from_profile_ethnopic_alias() {\n let adapter = adapter_from_resolved_profile(\"ethnopic\", \"ethnopic-compatible\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Ethnopic);\n}\n\n#[test]\nfn test_adapter_from_profile_openai() {\n let adapter = adapter_from_resolved_profile(\"openai\", \"@ai-sdk/openai\");\n assert_eq!(adapter, ProviderRuntimeAdapter::CloseAiCompatible);\n}\n\n#[test]\nfn test_adapter_from_profile_closeai_and_openai_aliases() {\n assert_eq!(\n adapter_from_resolved_profile(\"custom-closeai\", \"closeai-compatible\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n assert_eq!(\n adapter_from_resolved_profile(\"custom-closeai\", \"openai-compatible\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_adapter_from_profile_openrouter_and_perplexity() {\n assert_eq!(\n adapter_from_resolved_profile(\"openrouter\", \"@openrouter/ai-sdk-provider\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n assert_eq!(\n adapter_from_resolved_profile(\"perplexity\", \"@ai-sdk/perplexity\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_adapter_from_profile_unknown_defaults_to_closeai_compatible() {\n let adapter = adapter_from_resolved_profile(\"custom\", \"@custom/unknown-provider\");\n assert_eq!(adapter, ProviderRuntimeAdapter::CloseAiCompatible);\n}\n\n#[test]\nfn test_adapter_from_profile_vertex() {\n let adapter = adapter_from_resolved_profile(\"google-vertex\", \"@ai-sdk/google-vertex\");\n assert_eq!(adapter, ProviderRuntimeAdapter::VertexGemini);\n}\n\n#[test]\nfn test_adapter_from_profile_google() {\n let adapter = adapter_from_resolved_profile(\"google\", \"@ai-sdk/google\");\n assert_eq!(adapter, ProviderRuntimeAdapter::Gemini);\n}\n\n#[test]\nfn test_adapter_from_profile_bedrock() {\n let adapter = adapter_from_resolved_profile(\"amazon-bedrock\", \"@ai-sdk/bedrock\");\n assert_eq!(adapter, ProviderRuntimeAdapter::BedrockConverse);\n}\n\n#[test]\nfn test_adapter_from_profile_github_copilot() {\n let adapter = adapter_from_resolved_profile(\"github-copilot\", \"@ai-sdk/github-copilot\");\n assert_eq!(adapter, ProviderRuntimeAdapter::GitHubCopilotCloseAi);\n}\n\n#[test]\nfn test_adapter_from_profile_gitlab() {\n let adapter = adapter_from_resolved_profile(\"gitlab\", \"@ai-sdk/gitlab\");\n assert_eq!(adapter, ProviderRuntimeAdapter::GitLabCloseAi);\n}\n\n#[test]\nfn test_adapter_resolution_is_case_insensitive() {\n assert_eq!(\n adapter_from_resolved_profile(\"ethnopic\", \"@AI-SDK/ANTHROPIC\"),\n ProviderRuntimeAdapter::Ethnopic\n );\n assert_eq!(\n adapter_from_resolved_profile(\"openai\", \"@Ai-Sdk/Openai\"),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\nfn adapter_from_resolved_profile(provider_id: &str, npm: &str) -> ProviderRuntimeAdapter {\n let options = HashMap::new();\n let profile = ProviderProfileResolver::resolve_with_npm(provider_id, npm, &options);\n ProviderRuntimeAdapter::from_profile(&profile)\n}\n\n#[test]\nfn test_adapter_display_labels() {\n assert_eq!(ProviderRuntimeAdapter::Ethnopic.to_string(), \"ethnopic\");\n assert_eq!(\n ProviderRuntimeAdapter::CloseAiCompatible.to_string(),\n \"closeai-compatible\"\n );\n}\n\n#[test]\nfn test_adapter_from_profile_projects_vendor_specific_adapters() {\n let options = HashMap::new();\n let gitlab =\n ProviderProfileResolver::resolve_with_npm(\"gitlab\", \"@gitlab/gitlab-ai-provider\", &options);\n let copilot = ProviderProfileResolver::resolve_with_npm(\n \"github-copilot\",\n \"@ai-sdk/github-copilot\",\n &options,\n );\n let vertex = ProviderProfileResolver::resolve_with_npm(\n \"google-vertex\",\n \"@ai-sdk/google-vertex\",\n &options,\n );\n let closeai = ProviderProfileResolver::resolve_with_npm(\n \"custom-closeai\",\n \"@ai-sdk/openai-compatible\",\n &options,\n );\n\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&gitlab),\n ProviderRuntimeAdapter::GitLabCloseAi\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&copilot),\n ProviderRuntimeAdapter::GitHubCopilotCloseAi\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&vertex),\n ProviderRuntimeAdapter::VertexGemini\n );\n assert_eq!(\n ProviderRuntimeAdapter::from_profile(&closeai),\n ProviderRuntimeAdapter::CloseAiCompatible\n );\n}\n\n#[test]\nfn test_provider_config_basic() {\n let config = ProviderConfig {\n provider_id: \"deepseek\".to_string(),\n base_url: \"https://api.deepseek.com/chat/completions\".to_string(),\n api_key: \"sk-test\".to_string(),\n headers: HashMap::new(),\n options: HashMap::new(),\n };\n\n assert_eq!(config.provider_id, \"deepseek\");\n assert_eq!(config.base_url, \"https://api.deepseek.com/chat/completions\");\n}\n\n#[test]\nfn test_provider_config_with_custom_headers() {\n let mut headers = HashMap::new();\n headers.insert(\n \"HTTP-Referer\".to_string(),\n \"https://opencode.ai/\".to_string(),\n );\n headers.insert(\"X-Title\".to_string(), \"opencode\".to_string());\n\n let config = ProviderConfig {\n provider_id: \"openrouter\".to_string(),\n base_url: \"https://openrouter.ai/api/v1/chat/completions\".to_string(),\n api_key: \"sk-or-...\".to_string(),\n headers,\n options: HashMap::new(),\n };\n\n assert_eq!(\n config.headers.get(\"HTTP-Referer\").expect(\"header\"),\n \"https://opencode.ai/\"\n );\n}\n\n#[test]\nfn test_provider_config_with_options() {\n let mut options = HashMap::new();\n options.insert(\"endpoint_path\".to_string(), serde_json::json!(\"/v2/chat\"));\n\n let config = ProviderConfig {\n provider_id: \"cohere\".to_string(),\n base_url: \"https://api.cohere.ai\".to_string(),\n api_key: \"sk-cohere\".to_string(),\n headers: HashMap::new(),\n options,\n };\n\n assert_eq!(\n config.options.get(\"endpoint_path\").expect(\"option\"),\n \"/v2/chat\"\n );\n}\n\nstruct MockProviderAdapter;\n\n#[async_trait::async_trait]\nimpl ProviderAdapter for MockProviderAdapter {\n async fn chat(\n &self,\n _client: &reqwest::Client,\n _config: &ProviderConfig,\n _request: ChatRequest,\n ) -> Result<agendao_provider::ChatResponse, agendao_provider::ProviderError> {\n unimplemented!()\n }\n\n async fn chat_stream(\n &self,\n _client: &reqwest::Client,\n _config: &ProviderConfig,\n _request: ChatRequest,\n ) -> Result<agendao_provider::StreamResult, agendao_provider::ProviderError> {\n unimplemented!()\n }\n}\n\n#[test]\nfn test_provider_adapter_trait_bounds() {\n fn assert_send_sync<T: Send + Sync>() {}\n assert_send_sync::<MockProviderAdapter>();\n}\n\n#[test]\nfn test_create_provider_adapter_closeai_compatible() {\n let adapter = create_provider_adapter(ProviderRuntimeAdapter::CloseAiCompatible);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n\n#[test]\nfn test_create_provider_adapter_ethnopic() {\n let adapter = create_provider_adapter(ProviderRuntimeAdapter::Ethnopic);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n\n#[test]\nfn test_create_provider_adapter_for_profile() {\n let options = HashMap::new();\n let profile =\n ProviderProfileResolver::resolve_with_npm(\"ethnopic\", \"@ai-sdk/anthropic\", &options);\n let adapter = create_provider_adapter_for_profile(&profile);\n let _arc: std::sync::Arc<dyn ProviderAdapter> = adapter;\n}\n"}}}}