providers now per-agent: z.ai rides, bifrost stays home
Vanguard gets his own inference pipe. z.ai GLM Coding Plan, /paas/v4. BifrostClient learned to leave versioned URLs alone. ProviderRegistry dispatches per agent; every engine asks who it's talking to before dialing. Annie and Hal none the wiser.
This commit is contained in:
parent
19b8566e4d
commit
80bfb3a599
15 changed files with 326 additions and 57 deletions
|
|
@ -37,6 +37,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::bridge::bifrost::{ChatCompletionRequest, Message};
|
||||
use crate::bridge::LlmProvider;
|
||||
use crate::bridge::ProviderRegistry;
|
||||
use crate::core::config::{ArchivistConfig, SynthesisElement};
|
||||
use crate::core::memory::MemoryRepo;
|
||||
use crate::server::AgentInventory;
|
||||
|
|
@ -95,7 +96,7 @@ impl SynthesisReport {
|
|||
|
||||
pub struct ArchivistEngine {
|
||||
agents: Arc<AgentInventory>,
|
||||
bifrost: Arc<dyn LlmProvider>,
|
||||
providers: Arc<ProviderRegistry>,
|
||||
rate_delay: Arc<AtomicU64>,
|
||||
config: ArchivistConfig,
|
||||
/// Subconscious model handle — used to resolve `compression_model: "auto"`.
|
||||
|
|
@ -105,24 +106,35 @@ pub struct ArchivistEngine {
|
|||
impl ArchivistEngine {
|
||||
pub fn new(
|
||||
agents: Arc<AgentInventory>,
|
||||
bifrost: Arc<dyn LlmProvider>,
|
||||
providers: Arc<ProviderRegistry>,
|
||||
rate_delay: Arc<AtomicU64>,
|
||||
config: ArchivistConfig,
|
||||
subconscious_model: Option<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
agents,
|
||||
bifrost,
|
||||
providers,
|
||||
rate_delay,
|
||||
config,
|
||||
subconscious_model,
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve the compression model. `"auto"` (or empty) falls back to the
|
||||
/// subconscious model, then to a sensible default. A real capability-aware
|
||||
/// auto-selection algorithm is deferred (task Phase 4).
|
||||
fn resolve_model(&self) -> String {
|
||||
/// Resolve the compression model. The agent's own
|
||||
/// `_souveraine.archivist_model` override wins outright. Otherwise the
|
||||
/// configured `compression_model` is used, with `"auto"` (or empty)
|
||||
/// falling back to the subconscious model, then a sensible default.
|
||||
/// A real capability-aware auto-selection algorithm is deferred.
|
||||
async fn resolve_model(&self, agent_id: &str) -> String {
|
||||
if let Some(per_agent) = self
|
||||
.agents
|
||||
.get(agent_id)
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|a| a.souveraine.archivist_model.clone())
|
||||
{
|
||||
return per_agent;
|
||||
}
|
||||
let configured = self.config.compression_model.trim();
|
||||
if configured.is_empty() || configured.eq_ignore_ascii_case("auto") {
|
||||
self.subconscious_model
|
||||
|
|
@ -197,9 +209,16 @@ impl ArchivistEngine {
|
|||
let raw = format_journal_input(&entries);
|
||||
let approx_tokens_compressed = raw.len() / 4;
|
||||
|
||||
let model = self.resolve_model();
|
||||
let model = self.resolve_model(agent_id).await;
|
||||
let llm: Arc<dyn LlmProvider> = self
|
||||
.agents
|
||||
.get(agent_id)
|
||||
.await
|
||||
.ok()
|
||||
.map(|a| self.providers.for_agent(&a))
|
||||
.unwrap_or_else(|| self.providers.default_provider());
|
||||
let synthesis = self
|
||||
.run_synthesis(&model, &raw, start_date, end_date)
|
||||
.run_synthesis(&llm, &model, &raw, start_date, end_date)
|
||||
.await?;
|
||||
|
||||
let output_label = format!("{SYNTHESIS_DIR}/{end_date}");
|
||||
|
|
@ -229,6 +248,7 @@ impl ArchivistEngine {
|
|||
/// No tool loop — the Archivist produces a record, it doesn't act.
|
||||
async fn run_synthesis(
|
||||
&self,
|
||||
llm: &Arc<dyn LlmProvider>,
|
||||
model: &str,
|
||||
raw_journal: &str,
|
||||
start: NaiveDate,
|
||||
|
|
@ -253,7 +273,7 @@ impl ArchivistEngine {
|
|||
};
|
||||
|
||||
tracing::info!(model = %model, "archivist synthesis call starting");
|
||||
let (response, strain) = self.bifrost.chat_completion_with_strain(request).await?;
|
||||
let (response, strain) = llm.chat_completion_with_strain(request).await?;
|
||||
|
||||
for event in &strain {
|
||||
if let crate::bridge::bifrost::InferenceStrain::Transient { status, model, .. } = event {
|
||||
|
|
|
|||
Loading…
Reference in a new issue