modelsとprovidersをカタログ化
This commit is contained in:
@@ -683,11 +683,28 @@ where
|
||||
St: Store,
|
||||
{
|
||||
let manifest = pod.manifest();
|
||||
let provider = match manifest.model.scheme {
|
||||
manifest::SchemeKind::Anthropic => "anthropic",
|
||||
manifest::SchemeKind::OpenaiChat => "openai_chat",
|
||||
manifest::SchemeKind::OpenaiResponses => "openai_responses",
|
||||
manifest::SchemeKind::Gemini => "gemini",
|
||||
// `build_client` がここに到達する前に同じマニフェストで成功している
|
||||
// ため、カタログ解決も必ず通る。念のため失敗時は "unknown" に落とす。
|
||||
let resolved = provider::catalog::resolve_model_manifest(&manifest.model).ok();
|
||||
let (provider_name, model_id) = match resolved {
|
||||
Some(cfg) => {
|
||||
let name = match cfg.scheme {
|
||||
manifest::SchemeKind::Anthropic => "anthropic",
|
||||
manifest::SchemeKind::OpenaiChat => "openai_chat",
|
||||
manifest::SchemeKind::OpenaiResponses => "openai_responses",
|
||||
manifest::SchemeKind::Gemini => "gemini",
|
||||
};
|
||||
(name.to_string(), cfg.model_id)
|
||||
}
|
||||
None => (
|
||||
"unknown".to_string(),
|
||||
manifest
|
||||
.model
|
||||
.ref_
|
||||
.clone()
|
||||
.or_else(|| manifest.model.model_id.clone())
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
};
|
||||
// The tool list mirrors what `spawn()` registers on the Worker:
|
||||
// builtin filesystem tools plus the pod-orchestration tools.
|
||||
@@ -708,8 +725,8 @@ where
|
||||
protocol::Greeting {
|
||||
pod_name: manifest.pod.name.clone(),
|
||||
cwd: pod.pwd().display().to_string(),
|
||||
provider: provider.into(),
|
||||
model: manifest.model.model_id.clone(),
|
||||
provider: provider_name,
|
||||
model: model_id,
|
||||
scope_summary: pod.scope().summary(),
|
||||
tools: tool_names,
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ name = "overlay-name"
|
||||
// overlay layer so later calls win. This also exercises the
|
||||
// scope union across layers (two allow rules).
|
||||
assert_eq!(manifest.pod.name, "overlay-name");
|
||||
assert_eq!(manifest.model.model_id, "project-model");
|
||||
assert_eq!(manifest.model.model_id.as_deref(), Some("project-model"));
|
||||
assert_eq!(manifest.scope.allow.len(), 2);
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ model_id = "project-model"
|
||||
.unwrap();
|
||||
|
||||
// project layer overrides user layer on model.model_id
|
||||
assert_eq!(manifest.model.model_id, "project-model");
|
||||
assert_eq!(manifest.model.model_id.as_deref(), Some("project-model"));
|
||||
// user layer provides the rest
|
||||
assert_eq!(manifest.pod.name, "from-user");
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ pub use factory::{FactoryError, PodFactory};
|
||||
pub use notifier::Notifier;
|
||||
pub use hook::{Hook, HookEventKind, HookRegistryBuilder};
|
||||
pub use manifest::{
|
||||
AuthRef, ModelConfig, PodManifest, PodManifestConfig, PodMetaConfig, Scope, SchemeKind,
|
||||
AuthRef, ModelManifest, PodManifest, PodManifestConfig, PodMetaConfig, Scope, SchemeKind,
|
||||
};
|
||||
pub use pod::{Pod, PodError, PodRunResult, apply_worker_manifest};
|
||||
pub use prompt_loader::PromptLoader;
|
||||
|
||||
+28
-20
@@ -14,8 +14,8 @@ use std::time::Duration;
|
||||
use async_trait::async_trait;
|
||||
use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput};
|
||||
use manifest::{
|
||||
ModelConfig, ModelConfigPartial, Permission, PodManifestConfig, PodMetaConfig, ScopeConfig,
|
||||
ScopeRule, WorkerManifestConfig,
|
||||
ModelManifest, Permission, PodManifestConfig, PodMetaConfig, ScopeConfig, ScopeRule,
|
||||
WorkerManifestConfig,
|
||||
};
|
||||
use protocol::Method;
|
||||
use protocol::stream::JsonLineWriter;
|
||||
@@ -118,7 +118,7 @@ pub struct SpawnPodTool {
|
||||
/// Pod's overlay TOML so the child does not need its own provider
|
||||
/// configuration in the manifest cascade. Per-spawn override is
|
||||
/// out of scope here (see `tickets/spawn-inherit-provider.md`).
|
||||
spawner_model: ModelConfig,
|
||||
spawner_model: ModelManifest,
|
||||
}
|
||||
|
||||
impl SpawnPodTool {
|
||||
@@ -129,7 +129,7 @@ impl SpawnPodTool {
|
||||
spawner_pwd: PathBuf,
|
||||
registry: Arc<SpawnedPodRegistry>,
|
||||
parent_socket: Option<PathBuf>,
|
||||
spawner_model: ModelConfig,
|
||||
spawner_model: ModelManifest,
|
||||
) -> Self {
|
||||
Self {
|
||||
spawner_name,
|
||||
@@ -350,20 +350,14 @@ fn build_overlay_toml(
|
||||
name: &str,
|
||||
instruction: &str,
|
||||
scope_allow: &[ScopeRule],
|
||||
model: &ModelConfig,
|
||||
model: &ModelManifest,
|
||||
) -> Result<String, toml::ser::Error> {
|
||||
let overlay = PodManifestConfig {
|
||||
pod: PodMetaConfig {
|
||||
name: Some(name.to_string()),
|
||||
prompt_pack: None,
|
||||
},
|
||||
model: ModelConfigPartial {
|
||||
scheme: Some(model.scheme),
|
||||
base_url: model.base_url.clone(),
|
||||
model_id: Some(model.model_id.clone()),
|
||||
auth: Some(model.auth.clone()),
|
||||
capability: model.capability.clone(),
|
||||
},
|
||||
model: model.clone(),
|
||||
worker: WorkerManifestConfig {
|
||||
instruction: Some(instruction.to_string()),
|
||||
..Default::default()
|
||||
@@ -460,7 +454,7 @@ pub fn spawn_pod_tool(
|
||||
spawner_pwd: PathBuf,
|
||||
registry: Arc<SpawnedPodRegistry>,
|
||||
parent_socket: Option<PathBuf>,
|
||||
spawner_model: ModelConfig,
|
||||
spawner_model: ModelManifest,
|
||||
) -> ToolDefinition {
|
||||
Arc::new(move || {
|
||||
let schema = schemars::schema_for!(SpawnPodInput);
|
||||
@@ -487,16 +481,16 @@ mod tests {
|
||||
use manifest::{AuthRef, SchemeKind};
|
||||
|
||||
#[test]
|
||||
fn overlay_inherits_spawner_model() {
|
||||
let model = ModelConfig {
|
||||
scheme: SchemeKind::Anthropic,
|
||||
fn overlay_inherits_inline_spawner_model() {
|
||||
let model = ModelManifest {
|
||||
scheme: Some(SchemeKind::Anthropic),
|
||||
base_url: Some("https://example.test".into()),
|
||||
model_id: "claude-sonnet-4".into(),
|
||||
auth: AuthRef::ApiKey {
|
||||
model_id: Some("claude-sonnet-4".into()),
|
||||
auth: Some(AuthRef::ApiKey {
|
||||
env: None,
|
||||
file: Some(PathBuf::from("/etc/keys/anthropic")),
|
||||
},
|
||||
capability: None,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let toml_str = build_overlay_toml("child", "$insomnia/default", &[], &model).unwrap();
|
||||
@@ -511,4 +505,18 @@ mod tests {
|
||||
};
|
||||
assert_eq!(file.as_deref(), Some(Path::new("/etc/keys/anthropic")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overlay_inherits_ref_spawner_model() {
|
||||
let model = ModelManifest {
|
||||
ref_: Some("anthropic/claude-sonnet-4-6".into()),
|
||||
..Default::default()
|
||||
};
|
||||
let toml_str = build_overlay_toml("child", "$insomnia/default", &[], &model).unwrap();
|
||||
let parsed = PodManifestConfig::from_toml(&toml_str).unwrap();
|
||||
assert_eq!(
|
||||
parsed.model.ref_.as_deref(),
|
||||
Some("anthropic/claude-sonnet-4-6")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
|
||||
use llm_worker::tool::{ToolError, ToolOutput};
|
||||
use manifest::{AuthRef, ModelConfig, Permission, SchemeKind, ScopeRule};
|
||||
use manifest::{AuthRef, ModelManifest, Permission, SchemeKind, ScopeRule};
|
||||
use pod::runtime_dir::{RuntimeDir, SpawnedPodRecord};
|
||||
use pod::scope_lock::{self, LockFileGuard};
|
||||
use pod::spawn_pod::spawn_pod_tool;
|
||||
@@ -134,14 +134,15 @@ fn which_true() -> String {
|
||||
|
||||
/// Tests don't exercise the model — they intercept the spawned
|
||||
/// child via a mock socket — but `spawn_pod_tool` needs a value to
|
||||
/// embed in the overlay TOML. Any well-formed `ModelConfig` works.
|
||||
fn dummy_model() -> ModelConfig {
|
||||
ModelConfig {
|
||||
scheme: SchemeKind::Anthropic,
|
||||
/// embed in the overlay TOML. Any well-formed `ModelManifest` works.
|
||||
fn dummy_model() -> ModelManifest {
|
||||
ModelManifest {
|
||||
scheme: Some(SchemeKind::Anthropic),
|
||||
base_url: None,
|
||||
model_id: "claude-test".into(),
|
||||
auth: AuthRef::None,
|
||||
model_id: Some("claude-test".into()),
|
||||
auth: Some(AuthRef::None),
|
||||
capability: None,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user