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
12 changes: 6 additions & 6 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ def register(ctx) -> None:
class MuseCodeSubscriptionProfile(ProviderProfile):
"""Meta Model API via the Muse Code subscription."""

_NON_CHAT_PREFIXES = ("muse-image-", "muse-voice-")
# Allowlist: this provider serves the Muse Spark chat family. The live
# endpoint also returns other families (sam-*, muse-image-*,
# muse-voice-*) that are not usable as chat models — a denylist
# would leak the next such family, so only muse-spark-* is admitted.
_CHAT_FAMILY_PREFIX = "muse-spark-"

def fetch_models(
self,
Expand All @@ -112,11 +116,7 @@ def fetch_models(
)
if live is None:
return None
return [
m
for m in live
if not any(m.startswith(p) for p in self._NON_CHAT_PREFIXES)
]
return [m for m in live if m.startswith(self._CHAT_FAMILY_PREFIX)]

def build_api_kwargs_extras(
self,
Expand Down
3 changes: 2 additions & 1 deletion plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name: muse-code-subscription
kind: model-provider
version: 0.2.1
version: 0.2.2
description: Muse Spark in Hermes billed to the Muse Code monthly login (device-code login, no API key)
author: TheStreamCode
license: MIT
homepage: https://github.com/TheStreamCode/hermes-muse-code
tags: [meta, muse-spark, subscription]
requires_hermes: ">=0.21.3"


15 changes: 12 additions & 3 deletions tests/test_muse_code_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,24 @@ def test_reasoning_effort_mapping(tmp_path, monkeypatch):
)


def test_fetch_models_filters_non_chat(tmp_path, monkeypatch):
def test_fetch_models_admits_only_muse_spark(tmp_path, monkeypatch):
monkeypatch.setenv("MUSE_CODE_SUB_CREDENTIALS", str(tmp_path / "c.json"))
_, registered = _load_plugin()
profile = registered["muse-code"]
live = ["muse-spark-1.3", "muse-image-1.0", "muse-voice-transcribe-1.0"]
live = [
"muse-spark-1.3",
"muse-spark-1.2-contributor",
"sam-3.1",
"muse-image-1.0",
"muse-voice-transcribe-1.0",
]
with patch.object(
type(profile).__mro__[1], "fetch_models", return_value=live
):
assert profile.fetch_models(api_key="k") == ["muse-spark-1.3"]
assert profile.fetch_models(api_key="k") == [
"muse-spark-1.3",
"muse-spark-1.2-contributor",
]
with patch.object(
type(profile).__mro__[1], "fetch_models", return_value=None
):
Expand Down
Loading