mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-28 13:26:48 +00:00
582 lines
21 KiB
Python
582 lines
21 KiB
Python
"""Tests for configuration, hardware detection, and engine recommendation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from openjarvis.core.config import (
|
|
AgentConfig,
|
|
ChannelConfig,
|
|
EngineConfig,
|
|
GpuInfo,
|
|
HardwareInfo,
|
|
IntelligenceConfig,
|
|
JarvisConfig,
|
|
LearningConfig,
|
|
SandboxConfig,
|
|
SchedulerConfig,
|
|
SecurityConfig,
|
|
WhatsAppBaileysChannelConfig,
|
|
generate_default_toml,
|
|
load_config,
|
|
recommend_engine,
|
|
)
|
|
|
|
|
|
class TestDefaults:
|
|
def test_jarvis_config_defaults(self) -> None:
|
|
cfg = JarvisConfig()
|
|
assert cfg.engine.default == "ollama"
|
|
assert cfg.memory.default_backend == "sqlite"
|
|
assert cfg.telemetry.enabled is True
|
|
|
|
def test_engine_config_defaults(self) -> None:
|
|
ec = EngineConfig()
|
|
# Nested configs
|
|
assert ec.ollama.host == ""
|
|
assert ec.vllm.host == "http://localhost:8000"
|
|
assert ec.sglang.host == "http://localhost:30000"
|
|
assert ec.llamacpp.host == "http://localhost:8080"
|
|
assert ec.lemonade.host == "http://localhost:13305"
|
|
assert ec.llamacpp.binary_path == ""
|
|
# Backward-compat properties still work
|
|
assert ec.ollama_host == ""
|
|
assert ec.vllm_host == "http://localhost:8000"
|
|
assert ec.lemonade_host == "http://localhost:13305"
|
|
|
|
|
|
class TestRecommendEngine:
|
|
def test_no_gpu(self) -> None:
|
|
hw = HardwareInfo(platform="linux")
|
|
assert recommend_engine(hw) == "llamacpp"
|
|
|
|
def test_apple_silicon(self) -> None:
|
|
hw = HardwareInfo(
|
|
platform="darwin",
|
|
gpu=GpuInfo(vendor="apple", name="Apple M2 Max"),
|
|
)
|
|
assert recommend_engine(hw) == "mlx"
|
|
|
|
def test_nvidia_datacenter(self) -> None:
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
gpu=GpuInfo(vendor="nvidia", name="NVIDIA A100-SXM4-80GB", vram_gb=80),
|
|
)
|
|
assert recommend_engine(hw) == "vllm"
|
|
|
|
def test_nvidia_consumer(self) -> None:
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
gpu=GpuInfo(vendor="nvidia", name="NVIDIA GeForce RTX 4090", vram_gb=24),
|
|
)
|
|
assert recommend_engine(hw) == "ollama"
|
|
|
|
def test_amd(self) -> None:
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
gpu=GpuInfo(vendor="amd", name="Radeon RX 7900 XTX"),
|
|
)
|
|
assert recommend_engine(hw) == "lemonade"
|
|
|
|
|
|
class TestTomlLoading:
|
|
def test_load_missing_file_uses_defaults(self, tmp_path: Path) -> None:
|
|
cfg = load_config(tmp_path / "nonexistent.toml")
|
|
assert isinstance(cfg, JarvisConfig)
|
|
# engine default is derived from detected hardware — just ensure it's a string
|
|
assert isinstance(cfg.engine.default, str)
|
|
|
|
def test_load_overrides(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[engine]\ndefault = "vllm"\n\n[memory]\ndefault_backend = "faiss"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.engine.default == "vllm"
|
|
assert cfg.memory.default_backend == "faiss"
|
|
|
|
def test_loads_nested_lemonade_host_override(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[engine]\ndefault = "lemonade"\n\n'
|
|
'[engine.lemonade]\nhost = "http://custom-lemonade:19000"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.engine.default == "lemonade"
|
|
assert cfg.engine.lemonade.host == "http://custom-lemonade:19000"
|
|
assert cfg.engine.lemonade_host == "http://custom-lemonade:19000"
|
|
|
|
|
|
class TestGenerateToml:
|
|
def test_contains_engine_section(self) -> None:
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
cpu_brand="Intel Xeon",
|
|
cpu_count=16,
|
|
ram_gb=64.0,
|
|
gpu=GpuInfo(vendor="nvidia", name="NVIDIA H100", vram_gb=80),
|
|
)
|
|
toml = generate_default_toml(hw)
|
|
assert "[engine]" in toml
|
|
assert 'default = "vllm"' in toml
|
|
assert "H100" in toml
|
|
|
|
|
|
class TestSecurityConfig:
|
|
def test_security_config_defaults(self) -> None:
|
|
sc = SecurityConfig()
|
|
assert sc.enabled is True
|
|
assert sc.scan_input is True
|
|
assert sc.scan_output is True
|
|
assert sc.mode == "redact"
|
|
assert sc.secret_scanner is True
|
|
assert sc.pii_scanner is True
|
|
assert sc.enforce_tool_confirmation is True
|
|
|
|
def test_security_config_on_jarvis_config(self) -> None:
|
|
cfg = JarvisConfig()
|
|
assert isinstance(cfg.security, SecurityConfig)
|
|
|
|
def test_security_config_loads_from_toml(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text('[security]\nmode = "block"\nscan_input = false\n')
|
|
cfg = load_config(toml_file)
|
|
assert cfg.security.mode == "block"
|
|
assert cfg.security.scan_input is False
|
|
|
|
def test_security_config_in_default_toml(self) -> None:
|
|
output = generate_default_toml(HardwareInfo())
|
|
assert "[security]" in output
|
|
|
|
|
|
class TestChannelConfig:
|
|
def test_channel_config_defaults(self) -> None:
|
|
cc = ChannelConfig()
|
|
assert cc.enabled is False
|
|
assert cc.default_agent == "simple"
|
|
|
|
def test_channel_config_on_jarvis_config(self) -> None:
|
|
cfg = JarvisConfig()
|
|
assert isinstance(cfg.channel, ChannelConfig)
|
|
|
|
def test_channel_config_loads_from_toml(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[channel]\nenabled = true\ndefault_channel = "telegram"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.channel.enabled is True
|
|
assert cfg.channel.default_channel == "telegram"
|
|
|
|
def test_channel_config_in_default_toml(self) -> None:
|
|
output = generate_default_toml(HardwareInfo())
|
|
assert "[channel]" in output
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# New config structure tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestIntelligenceGenerationDefaults:
|
|
def test_generation_fields_exist(self) -> None:
|
|
ic = IntelligenceConfig()
|
|
assert ic.temperature == 0.7
|
|
assert ic.max_tokens == 1024
|
|
assert ic.top_p == 0.9
|
|
assert ic.top_k == 40
|
|
assert ic.repetition_penalty == 1.0
|
|
assert ic.stop_sequences == ""
|
|
|
|
def test_custom_generation_values(self) -> None:
|
|
ic = IntelligenceConfig(temperature=0.3, max_tokens=512, top_p=0.5)
|
|
assert ic.temperature == 0.3
|
|
assert ic.max_tokens == 512
|
|
assert ic.top_p == 0.5
|
|
|
|
|
|
class TestAgentConfigNew:
|
|
def test_new_fields(self) -> None:
|
|
ac = AgentConfig()
|
|
assert ac.objective == ""
|
|
assert ac.system_prompt == ""
|
|
assert ac.system_prompt_path == ""
|
|
assert ac.context_from_memory is True
|
|
assert ac.tools == ""
|
|
assert ac.max_turns == 10
|
|
|
|
def test_default_tools_backward_compat(self) -> None:
|
|
ac = AgentConfig()
|
|
ac.default_tools = "calculator,think"
|
|
assert ac.tools == "calculator,think"
|
|
assert ac.default_tools == "calculator,think"
|
|
|
|
def test_no_temperature_or_max_tokens(self) -> None:
|
|
ac = AgentConfig()
|
|
assert (
|
|
not hasattr(ac.__class__, "temperature")
|
|
or isinstance(getattr(ac.__class__, "temperature", None), property) is False
|
|
)
|
|
|
|
|
|
class TestNestedEngineConfig:
|
|
def test_nested_access(self) -> None:
|
|
ec = EngineConfig()
|
|
assert ec.ollama.host == ""
|
|
assert ec.vllm.host == "http://localhost:8000"
|
|
assert ec.sglang.host == "http://localhost:30000"
|
|
assert ec.llamacpp.host == "http://localhost:8080"
|
|
assert ec.lemonade.host == "http://localhost:13305"
|
|
assert ec.llamacpp.binary_path == ""
|
|
|
|
def test_backward_compat_setter(self) -> None:
|
|
ec = EngineConfig()
|
|
ec.ollama_host = "http://custom:1234"
|
|
assert ec.ollama.host == "http://custom:1234"
|
|
assert ec.ollama_host == "http://custom:1234"
|
|
|
|
def test_llamacpp_path_compat(self) -> None:
|
|
ec = EngineConfig()
|
|
ec.llamacpp_path = "/usr/bin/llama-server"
|
|
assert ec.llamacpp.binary_path == "/usr/bin/llama-server"
|
|
|
|
def test_loads_nested_toml(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[engine]\ndefault = "vllm"\n\n'
|
|
'[engine.ollama]\nhost = "http://custom:11434"\n\n'
|
|
'[engine.llamacpp]\nbinary_path = "/opt/llama"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.engine.default == "vllm"
|
|
assert cfg.engine.ollama.host == "http://custom:11434"
|
|
assert cfg.engine.llamacpp.binary_path == "/opt/llama"
|
|
|
|
def test_loads_old_flat_toml(self, tmp_path: Path) -> None:
|
|
"""Old flat engine keys still work via backward-compat properties."""
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[engine]\ndefault = "ollama"\n'
|
|
'ollama_host = "http://old:11434"\n'
|
|
'vllm_host = "http://old:8000"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.engine.ollama.host == "http://old:11434"
|
|
assert cfg.engine.vllm.host == "http://old:8000"
|
|
|
|
def test_loads_old_flat_lemonade_host(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[engine]\ndefault = "lemonade"\n'
|
|
'lemonade_host = "http://legacy-lemonade:19191"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.engine.default == "lemonade"
|
|
assert cfg.engine.lemonade.host == "http://legacy-lemonade:19191"
|
|
assert cfg.engine.lemonade_host == "http://legacy-lemonade:19191"
|
|
|
|
|
|
class TestNestedLearningConfig:
|
|
def test_defaults(self) -> None:
|
|
lc = LearningConfig()
|
|
assert lc.enabled is False
|
|
assert lc.update_interval == 100
|
|
assert lc.auto_update is False
|
|
assert lc.routing.policy == "heuristic"
|
|
assert lc.routing.min_samples == 5
|
|
assert lc.intelligence.policy == "none"
|
|
assert lc.agent.policy == "none"
|
|
assert lc.metrics.accuracy_weight == 0.6
|
|
assert lc.metrics.latency_weight == 0.2
|
|
|
|
def test_backward_compat_default_policy(self) -> None:
|
|
lc = LearningConfig()
|
|
assert lc.default_policy == "heuristic"
|
|
lc.default_policy = "grpo"
|
|
assert lc.routing.policy == "grpo"
|
|
|
|
def test_backward_compat_intelligence_policy(self) -> None:
|
|
lc = LearningConfig()
|
|
lc.intelligence_policy = "sft"
|
|
assert lc.intelligence.policy == "sft"
|
|
|
|
def test_backward_compat_agent_policy(self) -> None:
|
|
lc = LearningConfig()
|
|
lc.agent_policy = "agent_advisor"
|
|
assert lc.agent.policy == "agent_advisor"
|
|
|
|
def test_backward_compat_reward_weights(self) -> None:
|
|
lc = LearningConfig()
|
|
lc.reward_weights = "latency=0.4,cost=0.3"
|
|
assert lc.metrics.latency_weight == 0.4
|
|
assert lc.metrics.cost_weight == 0.3
|
|
|
|
def test_loads_nested_toml(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
"[learning]\nenabled = true\nupdate_interval = 50\n\n"
|
|
'[learning.routing]\npolicy = "learned"\n\n'
|
|
"[learning.metrics]\nlatency_weight = 0.5\n"
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.learning.enabled is True
|
|
assert cfg.learning.update_interval == 50
|
|
assert cfg.learning.routing.policy == "learned"
|
|
assert cfg.learning.metrics.latency_weight == 0.5
|
|
|
|
def test_loads_old_flat_learning_toml(self, tmp_path: Path) -> None:
|
|
"""Old flat learning keys still work via backward-compat properties."""
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[learning]\ndefault_policy = "grpo"\n'
|
|
'intelligence_policy = "sft"\n'
|
|
'reward_weights = "latency=0.5"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.learning.routing.policy == "grpo"
|
|
assert cfg.learning.intelligence.policy == "sft"
|
|
assert cfg.learning.metrics.latency_weight == 0.5
|
|
|
|
|
|
class TestBackwardCompatMigration:
|
|
def test_agent_temperature_migrates_to_intelligence(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text("[agent]\ntemperature = 0.3\nmax_tokens = 512\n")
|
|
cfg = load_config(toml_file)
|
|
assert cfg.intelligence.temperature == 0.3
|
|
assert cfg.intelligence.max_tokens == 512
|
|
|
|
def test_memory_context_injection_migrates_to_agent(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text("[memory]\ncontext_injection = false\n")
|
|
cfg = load_config(toml_file)
|
|
assert cfg.agent.context_from_memory is False
|
|
|
|
def test_tools_storage_context_injection_migrates(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[tools.storage]\ncontext_injection = false\ndefault_backend = "faiss"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.agent.context_from_memory is False
|
|
assert cfg.tools.storage.default_backend == "faiss"
|
|
|
|
|
|
class TestGenerateDefaultTomlNew:
|
|
def test_nested_engine_sections(self) -> None:
|
|
hw = HardwareInfo()
|
|
toml_str = generate_default_toml(hw)
|
|
assert "[engine.ollama]" in toml_str
|
|
assert "[engine.vllm]" in toml_str
|
|
assert "[engine.sglang]" in toml_str
|
|
|
|
def test_intelligence_generation_params(self) -> None:
|
|
hw = HardwareInfo()
|
|
toml_str = generate_default_toml(hw)
|
|
assert "temperature = 0.7" in toml_str
|
|
assert "max_tokens = 1024" in toml_str
|
|
|
|
def test_agent_new_fields(self) -> None:
|
|
hw = HardwareInfo()
|
|
toml_str = generate_default_toml(hw)
|
|
assert "context_from_memory = true" in toml_str
|
|
|
|
def test_learning_nested_sections(self) -> None:
|
|
hw = HardwareInfo()
|
|
toml_str = generate_default_toml(hw)
|
|
assert "[learning.routing]" in toml_str
|
|
assert 'policy = "heuristic"' in toml_str
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Sandbox config tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestSandboxConfig:
|
|
def test_defaults(self) -> None:
|
|
sc = SandboxConfig()
|
|
assert sc.enabled is False
|
|
assert sc.image == "openjarvis-sandbox:latest"
|
|
assert sc.timeout == 300
|
|
assert sc.workspace == ""
|
|
assert sc.mount_allowlist_path == ""
|
|
assert sc.max_concurrent == 5
|
|
assert sc.runtime == "docker"
|
|
|
|
def test_custom_values(self) -> None:
|
|
sc = SandboxConfig(
|
|
enabled=True,
|
|
image="custom:v2",
|
|
timeout=600,
|
|
runtime="podman",
|
|
)
|
|
assert sc.enabled is True
|
|
assert sc.image == "custom:v2"
|
|
assert sc.timeout == 600
|
|
assert sc.runtime == "podman"
|
|
|
|
def test_on_jarvis_config(self) -> None:
|
|
cfg = JarvisConfig()
|
|
assert isinstance(cfg.sandbox, SandboxConfig)
|
|
assert cfg.sandbox.enabled is False
|
|
|
|
def test_loads_from_toml(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
'[sandbox]\nenabled = true\ntimeout = 600\nruntime = "podman"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.sandbox.enabled is True
|
|
assert cfg.sandbox.timeout == 600
|
|
assert cfg.sandbox.runtime == "podman"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Scheduler config tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestSchedulerConfig:
|
|
def test_defaults(self) -> None:
|
|
sc = SchedulerConfig()
|
|
assert sc.enabled is False
|
|
assert sc.poll_interval == 60
|
|
assert sc.db_path == ""
|
|
|
|
def test_custom_values(self) -> None:
|
|
sc = SchedulerConfig(enabled=True, poll_interval=30, db_path="/tmp/sched.db")
|
|
assert sc.enabled is True
|
|
assert sc.poll_interval == 30
|
|
assert sc.db_path == "/tmp/sched.db"
|
|
|
|
def test_on_jarvis_config(self) -> None:
|
|
cfg = JarvisConfig()
|
|
assert isinstance(cfg.scheduler, SchedulerConfig)
|
|
assert cfg.scheduler.enabled is False
|
|
|
|
def test_loads_from_toml(self, tmp_path: Path) -> None:
|
|
toml_file = tmp_path / "config.toml"
|
|
toml_file.write_text(
|
|
"[scheduler]\nenabled = true\npoll_interval = 30\n"
|
|
'db_path = "/tmp/sched.db"\n'
|
|
)
|
|
cfg = load_config(toml_file)
|
|
assert cfg.scheduler.enabled is True
|
|
assert cfg.scheduler.poll_interval == 30
|
|
assert cfg.scheduler.db_path == "/tmp/sched.db"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WhatsApp Baileys channel config tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestApplyTomlSectionListNormalization:
|
|
def test_apply_toml_section_list_to_str_field(self) -> None:
|
|
"""TOML arrays assigned to str-typed fields should be joined with ','."""
|
|
from openjarvis.core.config import ToolsConfig, _apply_toml_section
|
|
|
|
target = ToolsConfig()
|
|
tools = ["code_interpreter", "web_search", "file_read"]
|
|
_apply_toml_section(target, {"enabled": tools})
|
|
assert isinstance(target.enabled, str)
|
|
assert target.enabled == "code_interpreter,web_search,file_read"
|
|
|
|
def test_apply_toml_section_list_to_property_setter(self) -> None:
|
|
"""TOML arrays passed to backward-compat property setters should be
|
|
normalized to comma-separated strings, not passed as raw lists."""
|
|
from openjarvis.core.config import _apply_toml_section
|
|
|
|
target = LearningConfig()
|
|
_apply_toml_section(
|
|
target,
|
|
{
|
|
"reward_weights": ["accuracy=0.8", "latency=0.2"],
|
|
},
|
|
)
|
|
assert target.metrics.accuracy_weight == 0.8
|
|
assert target.metrics.latency_weight == 0.2
|
|
|
|
def test_apply_toml_section_agent_tools_list(self) -> None:
|
|
"""Agent tools should work as a TOML array."""
|
|
from openjarvis.core.config import _apply_toml_section
|
|
|
|
target = AgentConfig()
|
|
_apply_toml_section(
|
|
target,
|
|
{
|
|
"tools": ["web_search", "http_request", "file_read"],
|
|
},
|
|
)
|
|
assert isinstance(target.tools, str)
|
|
assert target.tools == "web_search,http_request,file_read"
|
|
|
|
|
|
class TestWhatsAppBaileysChannelConfig:
|
|
def test_defaults(self) -> None:
|
|
wc = WhatsAppBaileysChannelConfig()
|
|
assert wc.auth_dir == ""
|
|
assert wc.assistant_name == "Jarvis"
|
|
assert wc.assistant_has_own_number is False
|
|
|
|
def test_custom_values(self) -> None:
|
|
wc = WhatsAppBaileysChannelConfig(
|
|
auth_dir="/tmp/wa",
|
|
assistant_name="Andy",
|
|
assistant_has_own_number=True,
|
|
)
|
|
assert wc.auth_dir == "/tmp/wa"
|
|
assert wc.assistant_name == "Andy"
|
|
assert wc.assistant_has_own_number is True
|
|
|
|
def test_on_channel_config(self) -> None:
|
|
cc = ChannelConfig()
|
|
assert isinstance(cc.whatsapp_baileys, WhatsAppBaileysChannelConfig)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Mining config integration tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_mining_config_absent_means_none(tmp_path):
|
|
from openjarvis.core.config import load_config
|
|
cfg_path = tmp_path / "config.toml"
|
|
cfg_path.write_text("") # empty config
|
|
cfg = load_config(cfg_path)
|
|
assert cfg.mining is None
|
|
|
|
|
|
def test_mining_config_solo_parsed(tmp_path):
|
|
from pathlib import Path
|
|
|
|
from openjarvis.core.config import load_config
|
|
from openjarvis.mining._stubs import SoloTarget
|
|
|
|
src = Path(__file__).parent.parent / "mining" / "fixtures" / "config_minimal.toml"
|
|
target = tmp_path / "config.toml"
|
|
target.write_text(src.read_text())
|
|
cfg = load_config(target)
|
|
assert cfg.mining is not None
|
|
assert cfg.mining.provider == "vllm-pearl"
|
|
assert cfg.mining.wallet_address == "prl1qexampleaddress"
|
|
assert isinstance(cfg.mining.submit_target, SoloTarget)
|
|
assert cfg.mining.submit_target.pearld_rpc_url == "http://localhost:44107"
|
|
assert cfg.mining.fee_bps == 0
|
|
assert cfg.mining.extra["model"] == "pearl-ai/Llama-3.3-70B-Instruct-pearl"
|
|
|
|
|
|
def test_mining_config_pool_parsed_as_pool_target(tmp_path):
|
|
from pathlib import Path
|
|
|
|
from openjarvis.core.config import load_config
|
|
from openjarvis.mining._stubs import PoolTarget
|
|
|
|
src = Path(__file__).parent.parent / "mining" / "fixtures" / "config_pool_v2.toml"
|
|
target = tmp_path / "config.toml"
|
|
target.write_text(src.read_text())
|
|
cfg = load_config(target)
|
|
assert isinstance(cfg.mining.submit_target, PoolTarget)
|
|
assert cfg.mining.submit_target.url == "https://pool.openjarvis.ai/submit"
|