Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ def _build_parser() -> argparse.ArgumentParser:
'--provider',
type=str,
default=None,
help='Override the provider (anthropic, openai, zai, minimax, openrouter, deepseek)',
help='Override the provider (anthropic, openai, zai, minimax, openrouter, deepseek, meta)',
)
noninteractive.add_argument(
'--allowed-tools',
Expand Down
30 changes: 30 additions & 0 deletions src/models/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,36 @@ class ModelConfig:
max_output_tokens=8_192,
supports_cache=True,
),
# Meta Muse Spark 1.1 (api.meta.ai, OpenAI-compatible). Muse Spark is a
# server-side reasoning model (usage reports ``reasoning_tokens``); like
# DeepSeek/GLM it exposes no Anthropic-style thinking blocks (the
# ``thinking=`` kwarg is gated on ``is_anthropic`` in query.py), so the
# capability flags keep their defaults. Pricing lives in
# ``services/pricing.py`` (single source) — the cost_* fields are unset.
# A future ``muse-spark-2.x`` would prefix-match this row via
# ``get_model_config`` (base ``muse-spark``); register such variants
# explicitly, as the DeepSeek/GLM rows above note.
#
# context_window=1_048_576 (2^20): Meta's documented window — the
# api.meta.ai overview page states 1,048,576 tokens. Same 1M-class tier as
# the DeepSeek-V4 / GLM-5.2 rows above.
#
# max_output_tokens=16_384 is NOT sent as the wire ``max_tokens``:
# query.py forwards ``resolve_max_output_tokens()`` only for
# Anthropic/Minimax providers; OpenAI-compatible providers send no cap and
# rely on the server default (verified — a ~2.3K-token answer returns
# ``finish_reason="stop"``, not truncated). The value's only live effect is
# the auto-compact output reservation (``token_warning`` -> ``autocompact``,
# clamped at 20_000); 16_384 reserves more output headroom than DeepSeek/
# GLM's 8_192, which suits a model that spends part of its budget on
# reasoning tokens.
"muse-spark-1.1": ModelConfig(
model_id="muse-spark-1.1",
display_name="Muse Spark 1.1",
context_window=1_048_576,
max_output_tokens=16_384,
supports_cache=True,
),
}


Expand Down
13 changes: 13 additions & 0 deletions src/providers/openai_compatible_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,19 @@ def resolved_class_name(self) -> str:
env_vars=("DEEPINFRA_API_KEY", "DEEPINFRA_TOKEN"),
aliases=("deep-infra", "deep_infra"),
),
# Meta's first-party API (api.meta.ai) — not a DeepSeek gateway; it serves
# its own ``muse-spark-1.1`` reasoning model over the OpenAI-compatible
# ``/v1/chat/completions`` endpoint (Bearer auth). ``muse``/``muse-spark``
# aliases mirror how ``kimi`` aliases ``moonshot``.
ProviderSpec(
id="meta",
label="Meta",
default_base_url="https://api.meta.ai/v1",
default_model="muse-spark-1.1",
available_models=("muse-spark-1.1",),
env_vars=("META_API_KEY", "META_AI_API_KEY"),
aliases=("meta-ai", "meta_ai", "muse", "muse-spark"),
),
)


Expand Down
20 changes: 20 additions & 0 deletions src/services/pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,24 @@
"cache_creation": 0.435 / 1_000_000,
"cache_read": 0.003625 / 1_000_000,
}
# Meta Muse Spark 1.1 (api.meta.ai, OpenAI-compatible). Meta's published rates:
# $1.25/M input, $4.25/M output, $0.15/M cached input. OpenAI-style caching has
# no separate cache-write charge, so ``cache_creation`` mirrors ``input``.
# NOTE: the generic OpenAI-compat usage builder does not (yet) map
# ``prompt_tokens_details.cached_tokens`` onto ``cache_read_input_tokens`` —
# only the hand-written DeepSeek provider does — so today ``cache_read`` is
# inert for Meta: cached input is billed at the full input rate in the cost
# display, an over-estimate on the cached portion ($1.25 vs $0.15/M, ~8x).
# The displayed cost is thus a safe upper bound, consistent with the other
# registry providers; wiring the mapping into ``_build_usage_dict`` is a
# separate change (it would affect all OpenAI-compat providers). The real
# cache-read rate is recorded here for when that lands.
_TIER_MUSE_SPARK = {
"input": 1.25 / 1_000_000,
"output": 4.25 / 1_000_000,
"cache_creation": 1.25 / 1_000_000,
"cache_read": 0.15 / 1_000_000,
}


# Exact-match table — keyed by canonical model name. Order DOESN'T matter
Expand Down Expand Up @@ -106,6 +124,8 @@
# every proxied model is priced at its upstream rate.
"deepseek-v4-flash": _TIER_DEEPSEEK_FLASH,
"deepseek-v4-pro": _TIER_DEEPSEEK_PRO,
# Meta Muse Spark (api.meta.ai)
"muse-spark-1.1": _TIER_MUSE_SPARK,
}


Expand Down
4 changes: 3 additions & 1 deletion tests/test_provider_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
build_provider_class,
)

# The 18 OpenAI-compatible providers added via the registry.
# The 19 OpenAI-compatible providers added via the registry.
EXPECTED_NEW_PROVIDERS = {
"nvidia-nim",
"atlascloud",
Expand All @@ -46,6 +46,7 @@
"together",
"stepfun",
"deepinfra",
"meta",
}

# A sample of (id -> (base_url, default_model)) — each vendor's published
Expand All @@ -58,6 +59,7 @@
"deepinfra": ("https://api.deepinfra.com/v1/openai", "deepseek-ai/DeepSeek-V4-Pro"),
"stepfun": ("https://api.stepfun.ai/v1", "step-3.7-flash"),
"siliconflow-cn": ("https://api.siliconflow.cn/v1", "deepseek-ai/DeepSeek-V4-Pro"),
"meta": ("https://api.meta.ai/v1", "muse-spark-1.1"),
}


Expand Down
Loading