mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
Add Inception Labs (Mercury) provider
Register Inception Labs' Mercury diffusion LLM as a new provider using the OpenAI-compatible adapter at api.inceptionlabs.ai. Adds mercury and mercury-coder to the model catalog and wires up all exhaustive match arms across arc-llm, arc-agent, and arc-attractor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d37d2c8f49
commit
cbb94ae9b2
10 changed files with 84 additions and 13 deletions
|
|
@ -2,6 +2,7 @@ export ANTHROPIC_API_KEY=
|
|||
export BRAVE_SEARCH_API_KEY=
|
||||
export DAYTONA_API_KEY=
|
||||
export GEMINI_API_KEY=
|
||||
export INCEPTION_API_KEY=
|
||||
export KIMI_API_KEY=
|
||||
export MINIMAX_API_KEY=
|
||||
export OPENAI_API_KEY=
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub struct AgentArgs {
|
|||
/// Task prompt
|
||||
pub prompt: String,
|
||||
|
||||
/// LLM provider (anthropic, openai, gemini, kimi, zai, minimax)
|
||||
/// LLM provider (anthropic, openai, gemini, kimi, zai, minimax, inception)
|
||||
#[arg(long, default_value = "anthropic")]
|
||||
pub provider: String,
|
||||
|
||||
|
|
@ -78,6 +78,7 @@ fn default_model(provider: Provider) -> &'static str {
|
|||
Provider::Kimi => "kimi-k2.5",
|
||||
Provider::Zai => "glm-4.7",
|
||||
Provider::Minimax => "minimax-m2.5",
|
||||
Provider::Inception => "mercury",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +160,7 @@ fn summarizer_model_id(provider: Provider) -> ModelId {
|
|||
Provider::Kimi => ModelId::new(Provider::Kimi, "kimi-k2.5"),
|
||||
Provider::Zai => ModelId::new(Provider::Zai, "glm-4.7"),
|
||||
Provider::Minimax => ModelId::new(Provider::Minimax, "minimax-m2.5"),
|
||||
Provider::Inception => ModelId::new(Provider::Inception, "mercury"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +176,7 @@ fn build_profile(provider: Provider, model: &str, llm_client: Option<Client>) ->
|
|||
let summarizer = build_summarizer(provider, llm_client);
|
||||
match provider {
|
||||
Provider::OpenAi => Box::new(OpenAiProfile::with_summarizer(model, summarizer)),
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax => Box::new(
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => Box::new(
|
||||
OpenAiProfile::with_summarizer(model, summarizer).with_provider(provider),
|
||||
),
|
||||
Provider::Gemini => Box::new(GeminiProfile::with_summarizer(model, summarizer)),
|
||||
|
|
@ -192,6 +194,7 @@ fn validate_api_key(provider: Provider) -> bool {
|
|||
Provider::Kimi => std::env::var("KIMI_API_KEY").is_ok(),
|
||||
Provider::Zai => std::env::var("ZAI_API_KEY").is_ok(),
|
||||
Provider::Minimax => std::env::var("MINIMAX_API_KEY").is_ok(),
|
||||
Provider::Inception => std::env::var("INCEPTION_API_KEY").is_ok(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -400,7 +403,7 @@ pub async fn run_with_args(args: AgentArgs) -> anyhow::Result<()> {
|
|||
Provider::OpenAi => {
|
||||
Arc::new(OpenAiProfile::with_summarizer(&factory_model, child_summarizer))
|
||||
}
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax => Arc::new(
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => Arc::new(
|
||||
OpenAiProfile::with_summarizer(&factory_model, child_summarizer)
|
||||
.with_provider(provider),
|
||||
),
|
||||
|
|
@ -650,6 +653,11 @@ mod tests {
|
|||
assert_eq!(default_model(Provider::Minimax), "minimax-m2.5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_inception() {
|
||||
assert_eq!(default_model(Provider::Inception), "mercury");
|
||||
}
|
||||
|
||||
// build_tool_approval non-interactive tests
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub async fn discover_project_docs(
|
|||
|
||||
let candidate_filenames: Vec<&str> = match provider {
|
||||
Provider::Anthropic => vec!["AGENTS.md", "CLAUDE.md"],
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax => {
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => {
|
||||
vec!["AGENTS.md", ".codex/instructions.md"]
|
||||
}
|
||||
Provider::Gemini => vec!["AGENTS.md", "GEMINI.md"],
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use arc_llm::provider::{ModelId, Provider};
|
|||
|
||||
fn summarizer_model_id(provider: Provider) -> ModelId {
|
||||
match provider {
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax => {
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => {
|
||||
ModelId::new(Provider::OpenAi, "gpt-4o-mini")
|
||||
}
|
||||
Provider::Gemini => ModelId::new(Provider::Gemini, "gemini-2.0-flash"),
|
||||
|
|
@ -32,7 +32,7 @@ fn build_profile(provider: Provider, model: &str, client: &Client) -> Box<dyn Pr
|
|||
match provider {
|
||||
Provider::Anthropic => Box::new(AnthropicProfile::with_summarizer(model, summarizer)),
|
||||
Provider::OpenAi => Box::new(OpenAiProfile::with_summarizer(model, summarizer)),
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax => Box::new(
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => Box::new(
|
||||
OpenAiProfile::with_summarizer(model, summarizer).with_provider(provider),
|
||||
),
|
||||
Provider::Gemini => Box::new(GeminiProfile::with_summarizer(model, summarizer)),
|
||||
|
|
@ -60,7 +60,7 @@ async fn make_session(provider: Provider, model: &str, cwd: &Path) -> Session {
|
|||
Provider::OpenAi => {
|
||||
Arc::new(OpenAiProfile::with_summarizer(&factory_model, summarizer))
|
||||
}
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax => Arc::new(
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => Arc::new(
|
||||
OpenAiProfile::with_summarizer(&factory_model, summarizer)
|
||||
.with_provider(provider),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ impl AgentBackend {
|
|||
let factory: SessionFactory = Arc::new(move || {
|
||||
let child_profile: Arc<dyn ProviderProfile> = match factory_provider {
|
||||
Provider::OpenAi => Arc::new(OpenAiProfile::new(&factory_model)),
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax => Arc::new(
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => Arc::new(
|
||||
OpenAiProfile::new(&factory_model).with_provider(factory_provider),
|
||||
),
|
||||
Provider::Gemini => Arc::new(GeminiProfile::new(&factory_model)),
|
||||
|
|
@ -104,7 +104,7 @@ impl AgentBackend {
|
|||
fn build_profile(&self) -> Box<dyn ProviderProfile> {
|
||||
match self.provider {
|
||||
Provider::OpenAi => Box::new(OpenAiProfile::new(&self.model)),
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax => {
|
||||
Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => {
|
||||
Box::new(OpenAiProfile::new(&self.model).with_provider(self.provider))
|
||||
}
|
||||
Provider::Gemini => Box::new(GeminiProfile::new(&self.model)),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub fn cli_command_for_provider(provider: Provider, model: &str, prompt_file: &s
|
|||
String::new()
|
||||
} else {
|
||||
match provider {
|
||||
Provider::OpenAi | Provider::Gemini | Provider::Kimi | Provider::Zai | Provider::Minimax => {
|
||||
Provider::OpenAi | Provider::Gemini | Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => {
|
||||
format!(" -m {model}")
|
||||
}
|
||||
Provider::Anthropic => format!(" --model {model}"),
|
||||
|
|
@ -39,7 +39,7 @@ pub fn cli_command_for_provider(provider: Provider, model: &str, prompt_file: &s
|
|||
};
|
||||
match provider {
|
||||
// --full-auto: sandboxed auto-execution, escalates on request
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax => {
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => {
|
||||
format!("codex exec --json --full-auto{model_flag} < {prompt_file}")
|
||||
}
|
||||
// --yolo: auto-approve all tool calls
|
||||
|
|
@ -176,7 +176,7 @@ fn parse_gemini_json(output: &str) -> Option<CliResponse> {
|
|||
/// Parse CLI output, choosing the right parser based on provider.
|
||||
pub fn parse_cli_response(provider: Provider, output: &str) -> Option<CliResponse> {
|
||||
match provider {
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax => {
|
||||
Provider::OpenAi | Provider::Kimi | Provider::Zai | Provider::Minimax | Provider::Inception => {
|
||||
parse_codex_ndjson(output)
|
||||
}
|
||||
Provider::Gemini => parse_gemini_json(output),
|
||||
|
|
|
|||
|
|
@ -154,5 +154,31 @@
|
|||
"input_cost_per_million": null,
|
||||
"output_cost_per_million": null,
|
||||
"aliases": ["minimax"]
|
||||
},
|
||||
{
|
||||
"id": "mercury",
|
||||
"provider": "inception",
|
||||
"display_name": "Mercury",
|
||||
"context_window": 32768,
|
||||
"max_output": null,
|
||||
"supports_tools": true,
|
||||
"supports_vision": false,
|
||||
"supports_reasoning": false,
|
||||
"input_cost_per_million": null,
|
||||
"output_cost_per_million": null,
|
||||
"aliases": []
|
||||
},
|
||||
{
|
||||
"id": "mercury-coder",
|
||||
"provider": "inception",
|
||||
"display_name": "Mercury Coder",
|
||||
"context_window": 32768,
|
||||
"max_output": null,
|
||||
"supports_tools": true,
|
||||
"supports_vision": false,
|
||||
"supports_reasoning": false,
|
||||
"input_cost_per_million": null,
|
||||
"output_cost_per_million": null,
|
||||
"aliases": []
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ mod tests {
|
|||
#[test]
|
||||
fn list_models_all() {
|
||||
let models = list_models(None);
|
||||
assert_eq!(models.len(), 12);
|
||||
assert_eq!(models.len(), 14);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -106,6 +106,22 @@ mod tests {
|
|||
assert_eq!(m.provider, "minimax");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mercury_in_catalog() {
|
||||
let m = get_model_info("mercury").unwrap();
|
||||
assert_eq!(m.provider, "inception");
|
||||
assert_eq!(m.context_window, 32768);
|
||||
assert!(m.supports_tools);
|
||||
assert!(!m.supports_vision);
|
||||
assert!(!m.supports_reasoning);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mercury_coder_in_catalog() {
|
||||
let m = get_model_info("mercury-coder").unwrap();
|
||||
assert_eq!(m.provider, "inception");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_info_costs() {
|
||||
let claude = get_model_info("claude-opus-4-6").unwrap();
|
||||
|
|
|
|||
|
|
@ -93,6 +93,12 @@ impl Client {
|
|||
.with_name("minimax");
|
||||
client.register_provider(Arc::new(adapter)).await?;
|
||||
}
|
||||
if let Ok(key) = std::env::var("INCEPTION_API_KEY") {
|
||||
let adapter =
|
||||
providers::OpenAiCompatibleAdapter::new(key, "https://api.inceptionlabs.ai/v1")
|
||||
.with_name("inception");
|
||||
client.register_provider(Arc::new(adapter)).await?;
|
||||
}
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ pub enum Provider {
|
|||
Kimi,
|
||||
Zai,
|
||||
Minimax,
|
||||
Inception,
|
||||
}
|
||||
|
||||
impl Provider {
|
||||
|
|
@ -34,6 +35,7 @@ impl Provider {
|
|||
Self::Kimi => "kimi",
|
||||
Self::Zai => "zai",
|
||||
Self::Minimax => "minimax",
|
||||
Self::Inception => "inception",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +57,7 @@ impl FromStr for Provider {
|
|||
"kimi" => Ok(Self::Kimi),
|
||||
"zai" => Ok(Self::Zai),
|
||||
"minimax" => Ok(Self::Minimax),
|
||||
"inception" | "inception_labs" => Ok(Self::Inception),
|
||||
other => Err(format!("unknown provider: {other}")),
|
||||
}
|
||||
}
|
||||
|
|
@ -182,4 +185,15 @@ mod tests {
|
|||
fn minimax_as_str() {
|
||||
assert_eq!(Provider::Minimax.as_str(), "minimax");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_inception() {
|
||||
assert_eq!("inception".parse::<Provider>().unwrap(), Provider::Inception);
|
||||
assert_eq!("inception_labs".parse::<Provider>().unwrap(), Provider::Inception);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inception_as_str() {
|
||||
assert_eq!(Provider::Inception.as_str(), "inception");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue