feat: configure role-specific models

This commit is contained in:
2026-09-18 19:22:37 +09:00
parent 986540411e
commit 19ee757880
11 changed files with 150 additions and 8 deletions
+17
View File
@@ -213,6 +213,8 @@ pub struct MemoryExtractionProfileConfigPartial {
#[serde(default)]
pub model: Option<ModelManifest>,
#[serde(default)]
pub reasoning: Option<ReasoningControl>,
#[serde(default)]
pub threshold: Option<u64>,
#[serde(default)]
pub worker_max_turns: Option<u32>,
@@ -262,6 +264,7 @@ impl MemoryExtractionProfileConfigPartial {
Self {
enabled: other.enabled.or(self.enabled),
model: other.model.or(self.model),
reasoning: other.reasoning.or(self.reasoning),
threshold: other.threshold.or(self.threshold),
worker_max_turns: other.worker_max_turns.or(self.worker_max_turns),
}
@@ -407,6 +410,7 @@ impl From<MemoryFeatureConfigPartial> for ResolvedMemoryFeatureConfig {
extraction: MemoryExtractionProfileConfig {
enabled: extraction.enabled.unwrap_or(true),
model: extraction.model,
reasoning: extraction.reasoning,
threshold: extraction.threshold.or(Some(50_000)),
worker_max_turns: extraction
.worker_max_turns
@@ -432,6 +436,7 @@ impl From<ResolvedMemoryFeatureConfig> for MemoryFeatureConfigPartial {
extraction: Some(MemoryExtractionProfileConfigPartial {
enabled: Some(value.profile.extraction.enabled),
model: value.profile.extraction.model,
reasoning: value.profile.extraction.reasoning,
threshold: value.profile.extraction.threshold,
worker_max_turns: value.profile.extraction.worker_max_turns,
}),
@@ -1920,9 +1925,13 @@ inject_summary = false
[feature.memory.extraction]
enabled = true
reasoning = "medium"
threshold = 42000
worker_max_turns = 2
[feature.memory.extraction.model]
ref = "codex-oauth/gpt-5.6-luna"
[feature.memory.consolidation]
request_enabled = false
"#,
@@ -1935,6 +1944,14 @@ request_enabled = false
assert_eq!(memory.consolidation.unwrap().request_enabled, Some(false));
let extraction = memory.extraction.unwrap();
assert_eq!(extraction.enabled, Some(true));
assert_eq!(
extraction.reasoning,
Some(ReasoningControl::Effort(ReasoningEffort::Medium))
);
assert_eq!(
extraction.model.and_then(|model| model.ref_),
Some("codex-oauth/gpt-5.6-luna".to_string())
);
assert_eq!(extraction.threshold, Some(42_000));
assert_eq!(extraction.worker_max_turns, Some(2));
}
+2
View File
@@ -267,6 +267,7 @@ impl Default for MemoryResidentProfileConfig {
pub struct MemoryExtractionProfileConfig {
pub enabled: bool,
pub model: Option<ModelManifest>,
pub reasoning: Option<ReasoningControl>,
pub threshold: Option<u64>,
pub worker_max_turns: Option<u32>,
}
@@ -276,6 +277,7 @@ impl Default for MemoryExtractionProfileConfig {
Self {
enabled: true,
model: None,
reasoning: None,
threshold: Some(50_000),
worker_max_turns: defaults::MEMORY_EXTRACT_WORKER_MAX_TURNS,
}
+60
View File
@@ -1230,6 +1230,66 @@ mod tests {
}
}
#[test]
fn builtin_profiles_pin_role_models_and_reasoning() {
use crate::model::{ReasoningControl, ReasoningEffort};
let tmp = TempDir::new().unwrap();
let resolve = |name: &str| {
ProfileResolver::new()
.with_workspace_base(tmp.path())
.resolve(
&ProfileSelector::source_named(ProfileRegistrySource::Builtin, name),
ProfileResolveOptions::with_worker_name(format!("{name}-worker")),
)
.unwrap()
};
let companion = resolve("companion");
assert_eq!(
companion.manifest.model.ref_.as_deref(),
Some("codex-oauth/gpt-6-astra")
);
assert_eq!(
companion.manifest.engine.reasoning,
Some(ReasoningControl::Effort(ReasoningEffort::High))
);
for name in ["coder", "reviewer"] {
let role = resolve(name);
assert_eq!(
role.manifest.model.ref_.as_deref(),
Some("codex-oauth/gpt-5.6-sol")
);
assert_eq!(
role.manifest.engine.reasoning,
Some(ReasoningControl::Effort(ReasoningEffort::High))
);
let extraction = &role.manifest.feature.memory.profile.extraction;
assert_eq!(
extraction
.model
.as_ref()
.and_then(|model| model.ref_.as_deref()),
Some("codex-oauth/gpt-5.6-luna")
);
assert_eq!(
extraction.reasoning,
Some(ReasoningControl::Effort(ReasoningEffort::Medium))
);
}
let consolidation = resolve("memory-consolidation");
assert_eq!(
consolidation.manifest.model.ref_.as_deref(),
Some("codex-oauth/gpt-5.6-luna")
);
assert_eq!(
consolidation.manifest.engine.reasoning,
Some(ReasoningControl::Effort(ReasoningEffort::Medium))
);
}
#[test]
fn profile_rejects_workspace_memory_snapshot_authority_fields() {
let tmp = TempDir::new().unwrap();