feat: introduce Rig agent runtime migration
This commit is contained in:
+46
-3
@@ -874,10 +874,27 @@ pub struct OpenAIModelConfig {
|
||||
description = "Optional provider hint (e.g. anthropic, openai, google) for icon display."
|
||||
)]
|
||||
pub provider: Option<String>,
|
||||
#[serde(default)]
|
||||
#[schemars(
|
||||
description = "Route this model through Galaxy's Rig runtime. This is an opt-in migration path."
|
||||
)]
|
||||
pub use_rig: bool,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(
|
||||
description = "Whether this endpoint accepts system-role messages. Set false for ChatGPT-backed LiteLLM models that reject them."
|
||||
)]
|
||||
pub supports_system_messages: Option<bool>,
|
||||
}
|
||||
|
||||
impl settings_value::SettingsValue for OpenAIModelConfig {}
|
||||
|
||||
impl OpenAIModelConfig {
|
||||
pub fn supports_system_messages(&self) -> bool {
|
||||
self.supports_system_messages
|
||||
.unwrap_or_else(|| !self.model_id.starts_with("codex-gpt-"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for a single OpenAI-compatible provider endpoint.
|
||||
///
|
||||
/// Multiple providers can be configured simultaneously (e.g. LiteLLM for cloud models,
|
||||
@@ -901,6 +918,30 @@ pub struct OpenAIProviderConfig {
|
||||
|
||||
impl settings_value::SettingsValue for OpenAIProviderConfig {}
|
||||
|
||||
const INITIAL_LITELLM_BASE_URL: &str = "https://ai.ryserve.net/v1";
|
||||
const INITIAL_RIG_MODEL_ID: &str = "codex-gpt-5.6-sol-xhigh";
|
||||
|
||||
fn default_openai_providers() -> Vec<OpenAIProviderConfig> {
|
||||
vec![OpenAIProviderConfig {
|
||||
name: "LiteLLM (ai.ryserve.net)".to_string(),
|
||||
base_url: INITIAL_LITELLM_BASE_URL.to_string(),
|
||||
// Credentials are deliberately never committed. Set this locally in
|
||||
// ~/.galaxy/settings.toml before sending a request.
|
||||
api_key: None,
|
||||
models: vec![OpenAIModelConfig {
|
||||
model_id: INITIAL_RIG_MODEL_ID.to_string(),
|
||||
display_name: "Codex GPT-5.6 SOL (xhigh)".to_string(),
|
||||
vision_supported: false,
|
||||
context_size: default_context_size(),
|
||||
max_input_tokens: None,
|
||||
max_output_tokens: None,
|
||||
provider: Some("openai".to_string()),
|
||||
use_rig: true,
|
||||
supports_system_messages: Some(false),
|
||||
}],
|
||||
}]
|
||||
}
|
||||
|
||||
/// Cached metadata and runtime session options for an ACP agent.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, schemars::JsonSchema)]
|
||||
pub struct AcpAgentSettings {
|
||||
@@ -1447,7 +1488,7 @@ define_settings_group!(AISettings, settings: [
|
||||
// Whether the OpenAI-compatible (LiteLLM) provider is enabled.
|
||||
openai_enabled: OpenAIEnabled {
|
||||
type: bool,
|
||||
default: false,
|
||||
default: true,
|
||||
supported_platforms: SupportedPlatforms::DESKTOP,
|
||||
sync_to_cloud: SyncToCloud::Globally(RespectUserSyncSetting::Yes),
|
||||
private: false,
|
||||
@@ -1498,9 +1539,11 @@ define_settings_group!(AISettings, settings: [
|
||||
// Each provider has its own name, base_url, api_key, and model list.
|
||||
openai_providers: OpenAIProviders {
|
||||
type: Vec<OpenAIProviderConfig>,
|
||||
default: Vec::new(),
|
||||
default: default_openai_providers(),
|
||||
supported_platforms: SupportedPlatforms::DESKTOP,
|
||||
sync_to_cloud: SyncToCloud::Globally(RespectUserSyncSetting::Yes),
|
||||
// Provider entries may contain API keys, so the complete setting must
|
||||
// remain local even when preference sync is enabled.
|
||||
sync_to_cloud: SyncToCloud::Never,
|
||||
private: false,
|
||||
toml_path: "ai.providers",
|
||||
description: "Multiple OpenAI-compatible provider endpoints (e.g. LiteLLM, Ollama, local models).",
|
||||
|
||||
@@ -345,6 +345,37 @@ fn test_toolbar_command_map_roundtrip() {
|
||||
assert_eq!(original, restored);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initial_litellm_provider_maps_codex_model_to_rig_without_a_committed_key() {
|
||||
let providers = default_openai_providers();
|
||||
|
||||
assert_eq!(providers.len(), 1);
|
||||
let provider = &providers[0];
|
||||
assert_eq!(provider.base_url, INITIAL_LITELLM_BASE_URL);
|
||||
assert_eq!(provider.api_key, None);
|
||||
assert_eq!(provider.models.len(), 1);
|
||||
let model = &provider.models[0];
|
||||
assert_eq!(model.model_id, INITIAL_RIG_MODEL_ID);
|
||||
assert_eq!(model.use_rig, true);
|
||||
assert_eq!(model.supports_system_messages, Some(false));
|
||||
assert_eq!(model.supports_system_messages(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn codex_litellm_model_infers_missing_system_message_capability() {
|
||||
let mut model = default_openai_providers().remove(0).models.remove(0);
|
||||
model.supports_system_messages = None;
|
||||
|
||||
assert_eq!(model.supports_system_messages(), false);
|
||||
|
||||
model.model_id = "gpt-4o".to_string();
|
||||
assert_eq!(model.supports_system_messages(), true);
|
||||
|
||||
model.model_id = INITIAL_RIG_MODEL_ID.to_string();
|
||||
model.supports_system_messages = Some(true);
|
||||
assert_eq!(model.supports_system_messages(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_toolbar_command_map_matched_agent() {
|
||||
App::test((), |mut app| async move {
|
||||
|
||||
Reference in New Issue
Block a user