| """Tests Maris AI projektu aģenta helperiem.""" |
|
|
| from __future__ import annotations |
|
|
| import json |
| from pathlib import Path |
|
|
| import pytest |
|
|
| from maris_core.space_agent import ( |
| SPACE_AGENT_MODEL_DEFAULT, |
| SPACE_AGENT_SPACE_REPO_DEFAULT, |
| SpaceAgentChatRequest, |
| SpaceAgentToolCall, |
| build_space_agent_messages, |
| execute_space_agent_tool, |
| generate_space_agent_reply, |
| get_space_agent_runtime_info, |
| resolve_space_agent_models, |
| ) |
|
|
|
|
| def test_space_agent_runtime_defaults_are_stable(monkeypatch) -> None: |
| monkeypatch.delenv("HF_SPACE_ASSISTANT_MODEL", raising=False) |
| monkeypatch.delenv("HF_SPACE_REPO", raising=False) |
| monkeypatch.delenv("HF_SPACE_ASSISTANT_MODELS", raising=False) |
|
|
| runtime = get_space_agent_runtime_info() |
|
|
| assert runtime.model == SPACE_AGENT_MODEL_DEFAULT |
| assert runtime.default_model == SPACE_AGENT_MODEL_DEFAULT |
| assert runtime.space_repo == SPACE_AGENT_SPACE_REPO_DEFAULT |
| assert SPACE_AGENT_MODEL_DEFAULT in runtime.available_models |
| assert "model_dataset_playbook" in runtime.tool_names |
| assert "browser_capabilities" in runtime.tool_names |
| assert "persona_catalog" in runtime.tool_names |
| assert "read_workspace_file" in runtime.tool_names |
| assert "write_workspace_file" in runtime.tool_names |
| assert "workspace_command_catalog" in runtime.tool_names |
| assert any(item["title"] == "Model & dataset fixer" for item in runtime.capabilities) |
| assert runtime.command_presets |
| assert runtime.command_presets[0]["items"] |
|
|
|
|
| def test_build_space_agent_messages_includes_system_prompt_and_history() -> None: |
| request = SpaceAgentChatRequest( |
| message="Palīdzi ar manu Maris darba telpu", |
| model="MarisUK/Codex", |
| task_mode="code", |
| history=[ |
| {"role": "user", "content": "Sveiks"}, |
| {"role": "assistant", "content": "Sveiks!"}, |
| ], |
| ) |
|
|
| messages = build_space_agent_messages(request) |
|
|
| assert messages[0]["role"] == "system" |
| assert "MarisUK/Codex" in messages[0]["content"] |
| assert "Maris AI Project Operator" in messages[0]["content"] |
| assert "model_dataset_playbook" in messages[0]["content"] |
| assert "audit → validate → evaluate → fix → train → sync" in messages[0]["content"] |
| assert "`code`" in messages[0]["content"] |
| assert messages[-1] == {"role": "user", "content": "Palīdzi ar manu Maris darba telpu"} |
| assert messages[1]["content"] == "Sveiks" |
|
|
|
|
| class _DummyClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
| self.models: list[str] = [] |
|
|
| def chat_completion(self, **kwargs: object) -> dict[str, object]: |
| self.models.append(str(kwargs["model"])) |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": "Profesionāla atbilde par Maris darba telpas konfigurāciju.", |
| } |
| } |
| ] |
| } |
|
|
|
|
| def test_generate_space_agent_reply_uses_hf_client_when_available() -> None: |
| request = SpaceAgentChatRequest( |
| message="Sakārto manu Space", |
| model="MarisUK/Codex", |
| ) |
|
|
| response = generate_space_agent_reply(request, client_factory=_DummyClient, token="hf_test") |
|
|
| assert response.model == "MarisUK/Codex" |
| assert response.used_fallback is False |
| assert "Profesionāla atbilde" in response.response |
| assert response.task_mode == "chat" |
|
|
|
|
| def test_generate_space_agent_reply_uses_hf_inference_space_runtime_config( |
| monkeypatch, |
| ) -> None: |
| captured_kwargs: dict[str, object] = {} |
|
|
| class _ConfiguredClient: |
| def __init__(self, **kwargs: object) -> None: |
| captured_kwargs.update(kwargs) |
|
|
| def chat_completion(self, **kwargs: object) -> dict[str, object]: |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": f"Atbilde no {kwargs['model']}", |
| } |
| } |
| ] |
| } |
|
|
| monkeypatch.setenv("HF_INFERENCE_API_KEY", "hf_inference_secret") |
|
|
| response = generate_space_agent_reply( |
| SpaceAgentChatRequest(message="Sakārto manu Space"), |
| client_factory=_ConfiguredClient, |
| ) |
|
|
| assert response.model == SPACE_AGENT_MODEL_DEFAULT |
| assert captured_kwargs == { |
| "provider": "hf-inference", |
| "base_url": "https://api-inference.huggingface.co", |
| "token": "hf_inference_secret", |
| } |
|
|
|
|
| class _ToolCallingClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
| self.calls = 0 |
|
|
| def chat_completion(self, **_: object) -> dict[str, object]: |
| self.calls += 1 |
| if self.calls == 1: |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": ( |
| '{"mode":"tool","tool_calls":[' |
| '{"name":"project_runtime","arguments":{}},' |
| '{"name":"sync_commands","arguments":{}}' |
| "]}" |
| ) |
| } |
| } |
| ] |
| } |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": '{"mode":"final","response":"Izmanto sync komandu un publicē Space profesionāli."}' |
| } |
| } |
| ] |
| } |
|
|
|
|
| class _MultiStepToolCallingClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
| self.calls = 0 |
|
|
| def chat_completion(self, **_: object) -> dict[str, object]: |
| self.calls += 1 |
| if self.calls == 1: |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": ( |
| '{"mode":"tool","tool_calls":[' |
| '{"name":"list_huggingface_repo_files","arguments":' |
| '{"repo_id":"MarisUK/maris-ai-master","repo_type":"model"}}' |
| "]}" |
| ) |
| } |
| } |
| ] |
| } |
| if self.calls == 2: |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": ( |
| '{"mode":"tool","tool_calls":[' |
| '{"name":"read_huggingface_repo_file","arguments":' |
| '{"repo_id":"MarisUK/maris-ai-master","repo_type":"model","path":"README.md"}},' |
| '{"name":"write_huggingface_repo_file","arguments":' |
| '{"repo_id":"MarisUK/maris-ai-master","repo_type":"model","path":"README.md",' |
| '"content":"salabots modelis","commit_message":"Fix model README"}}' |
| "]}" |
| ) |
| } |
| } |
| ] |
| } |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": ( |
| '{"mode":"final","response":"Pārbaudīju modeli, salaboju README un saglabāju izmaiņas."}' |
| ) |
| } |
| } |
| ] |
| } |
|
|
|
|
| def test_execute_space_agent_tool_returns_runtime_payload() -> None: |
| result = execute_space_agent_tool(SpaceAgentToolCall(name="project_runtime", arguments={})) |
|
|
| assert result["model"] == SPACE_AGENT_MODEL_DEFAULT |
| assert result["space_repo"] == SPACE_AGENT_SPACE_REPO_DEFAULT |
|
|
|
|
| def test_execute_space_agent_tool_returns_model_dataset_playbook() -> None: |
| result = execute_space_agent_tool( |
| SpaceAgentToolCall(name="model_dataset_playbook", arguments={}) |
| ) |
|
|
| assert result["dataset_repo"] |
| assert result["model_repo"] |
| assert result["space_repo"] |
| assert "latest_agent_principles" in result |
| assert "recommended_loop" in result |
| assert "validate_dataset" in result["repo_commands"] |
| assert any( |
| "HF_TOKEN" in item or "MARIS_REPO_TOKEN" in item for item in result["required_setup"] |
| ) |
|
|
|
|
| def test_execute_space_agent_tool_returns_browser_capabilities() -> None: |
| result = execute_space_agent_tool(SpaceAgentToolCall(name="browser_capabilities", arguments={})) |
|
|
| assert result["provider"] == "playwright" |
| assert "extract_text" in result["supported_actions"] |
|
|
|
|
| def test_execute_space_agent_tool_returns_workspace_command_catalog() -> None: |
| result = execute_space_agent_tool( |
| SpaceAgentToolCall(name="workspace_command_catalog", arguments={}) |
| ) |
|
|
| assert result["presets"] |
| assert any(group["category"] == "python" for group in result["presets"]) |
| assert any( |
| item["id"] == "frontend-build" for group in result["presets"] for item in group["items"] |
| ) |
|
|
|
|
| def test_execute_space_agent_tool_returns_persona_catalog() -> None: |
| result = execute_space_agent_tool(SpaceAgentToolCall(name="persona_catalog", arguments={})) |
|
|
| assert result["default_persona_id"] == "assistant" |
| assert any(persona["id"] == "teacher" for persona in result["personas"]) |
|
|
|
|
| def test_execute_space_agent_tool_can_list_huggingface_repos(monkeypatch) -> None: |
| class FakeRepo: |
| def __init__(self, repo_id: str) -> None: |
| self.id = repo_id |
|
|
| class FakeApi: |
| def list_models(self, **_: object): |
| return [FakeRepo("MarisUK/maris-ai-master")] |
|
|
| def list_datasets(self, **_: object): |
| return [] |
|
|
| def list_spaces(self, **_: object): |
| return [FakeRepo("MarisUK/maris.ai.agent")] |
|
|
| monkeypatch.setattr("maris_core.space_agent._get_hf_api_client", lambda: FakeApi()) |
|
|
| result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="list_huggingface_repos", arguments={"repo_type": "all", "limit": 5} |
| ) |
| ) |
|
|
| assert result["owner"] == "MarisUK" |
| assert any(entry["id"] == "MarisUK/maris-ai-master" for entry in result["entries"]) |
| assert any(entry["repo_type"] == "space" for entry in result["entries"]) |
|
|
|
|
| def test_execute_space_agent_tool_can_read_and_write_huggingface_repo_files( |
| monkeypatch, tmp_path: Path |
| ) -> None: |
| uploaded: list[dict[str, object]] = [] |
| downloaded = tmp_path / "README.md" |
| downloaded.write_text("hf saturs", encoding="utf-8") |
|
|
| class FakeApi: |
| def upload_file(self, **kwargs: object) -> None: |
| uploaded.append(kwargs) |
|
|
| def list_repo_files(self, **_: object): |
| return ["README.md", "app.py"] |
|
|
| monkeypatch.setattr("maris_core.space_agent._get_hf_api_client", lambda: FakeApi()) |
| monkeypatch.setattr( |
| "maris_core.space_agent._download_hf_repo_file", |
| lambda **_: str(downloaded), |
| ) |
|
|
| listing = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="list_huggingface_repo_files", |
| arguments={"repo_id": "MarisUK/maris.ai.agent", "repo_type": "space"}, |
| ) |
| ) |
| assert "README.md" in listing["entries"] |
|
|
| read_result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="read_huggingface_repo_file", |
| arguments={ |
| "repo_id": "MarisUK/maris.ai.agent", |
| "repo_type": "space", |
| "path": "README.md", |
| }, |
| ) |
| ) |
| assert read_result["content"] == "hf saturs" |
|
|
| write_result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="write_huggingface_repo_file", |
| arguments={ |
| "repo_id": "MarisUK/maris.ai.agent", |
| "repo_type": "space", |
| "path": "README.md", |
| "content": "jauns hf saturs", |
| "commit_message": "Update README", |
| }, |
| ) |
| ) |
| assert write_result["saved"] is True |
| assert uploaded[0]["repo_id"] == "MarisUK/maris.ai.agent" |
| assert uploaded[0]["path_in_repo"] == "README.md" |
|
|
|
|
| def test_execute_space_agent_tool_can_list_read_and_write_workspace_files(tmp_path: Path) -> None: |
| workspace = tmp_path / "workspace" |
| workspace.mkdir() |
| existing_file = workspace / "notes.txt" |
| existing_file.write_text("sākotnējais saturs", encoding="utf-8") |
|
|
| listing = execute_space_agent_tool( |
| SpaceAgentToolCall(name="list_workspace", arguments={"path": "."}), |
| context={"workspace_root": str(workspace)}, |
| ) |
| assert listing["path"] == "." |
| assert any(entry["path"] == "notes.txt" for entry in listing["entries"]) |
|
|
| read_result = execute_space_agent_tool( |
| SpaceAgentToolCall(name="read_workspace_file", arguments={"path": "notes.txt"}), |
| context={"workspace_root": str(workspace)}, |
| ) |
| assert read_result["content"] == "sākotnējais saturs" |
|
|
| write_result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="write_workspace_file", |
| arguments={"path": "nested/todo.txt", "content": "jauns saturs"}, |
| ), |
| context={"workspace_root": str(workspace)}, |
| ) |
| assert write_result["saved"] is True |
| assert write_result["operation"] == "create" |
| assert "+++ b/nested/todo.txt" in write_result["diff"] |
| assert (workspace / "nested" / "todo.txt").read_text(encoding="utf-8") == "jauns saturs" |
|
|
|
|
| def test_execute_space_agent_tool_stages_workspace_write_when_approval_required( |
| tmp_path: Path, |
| ) -> None: |
| workspace = tmp_path / "workspace" |
| workspace.mkdir() |
| staged_payloads: list[dict[str, object]] = [] |
|
|
| result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="write_workspace_file", |
| arguments={"path": "notes.txt", "content": "jauns saturs"}, |
| ), |
| context={ |
| "workspace_root": str(workspace), |
| "require_workspace_approval": True, |
| "task_mode": "code", |
| "stage_workspace_write": lambda payload: ( |
| staged_payloads.append(payload) |
| or {"proposal_id": "workspace-1", "status": "pending", "diff": "draft diff"} |
| ), |
| }, |
| ) |
|
|
| assert result["requires_approval"] is True |
| assert result["saved"] is False |
| assert result["saved_to_draft"] is True |
| assert result["proposal_id"] == "workspace-1" |
| assert result["diff"] == "draft diff" |
| assert (workspace / "notes.txt").read_text(encoding="utf-8") == "jauns saturs" |
| assert staged_payloads[0]["task_mode"] == "code" |
|
|
|
|
| def test_execute_space_agent_tool_stages_huggingface_write_when_approval_required() -> None: |
| staged_payloads: list[dict[str, object]] = [] |
|
|
| result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="write_huggingface_repo_file", |
| arguments={ |
| "repo_id": "MarisUK/maris.ai.agent", |
| "repo_type": "space", |
| "path": "README.md", |
| "content": "jauns saturs", |
| "commit_message": "Update README", |
| }, |
| ), |
| context={ |
| "require_publish_approval": True, |
| "task_mode": "design", |
| "stage_hf_write": lambda payload: ( |
| staged_payloads.append(payload) |
| or {"proposal_id": "proposal-1", "status": "pending"} |
| ), |
| }, |
| ) |
|
|
| assert result["requires_approval"] is True |
| assert result["saved"] is False |
| assert result["proposal_id"] == "proposal-1" |
| assert result["status"] == "pending" |
| assert staged_payloads[0]["task_mode"] == "design" |
|
|
|
|
| def test_execute_space_agent_tool_runs_workspace_command_with_context_runner() -> None: |
| result = execute_space_agent_tool( |
| SpaceAgentToolCall( |
| name="run_workspace_command", |
| arguments={"command": "python -m pytest tests/test_space_agent.py"}, |
| ), |
| context={ |
| "workspace_command_runner": lambda arguments: { |
| "ok": True, |
| "command_display": arguments["command"], |
| "exit_code": 0, |
| } |
| }, |
| ) |
|
|
| assert result["ok"] is True |
| assert result["command_display"] == "python -m pytest tests/test_space_agent.py" |
| assert result["exit_code"] == 0 |
|
|
|
|
| def test_execute_space_agent_tool_blocks_paths_outside_workspace(tmp_path: Path) -> None: |
| workspace = tmp_path / "workspace" |
| workspace.mkdir() |
|
|
| with pytest.raises(ValueError): |
| execute_space_agent_tool( |
| SpaceAgentToolCall(name="read_workspace_file", arguments={"path": "../secret.txt"}), |
| context={"workspace_root": str(workspace)}, |
| ) |
|
|
|
|
| def test_generate_space_agent_reply_supports_tool_calling_roundtrip() -> None: |
| request = SpaceAgentChatRequest(message="Kā man syncot Space?", tool_calling=True) |
|
|
| response = generate_space_agent_reply( |
| request, |
| client_factory=_ToolCallingClient, |
| tool_context={"training_status": {"running": False}}, |
| ) |
|
|
| assert response.used_fallback is False |
| assert response.response == "Izmanto sync komandu un publicē Space profesionāli." |
| assert response.task_mode == "chat" |
| assert [tool_call.name for tool_call in response.tool_calls] == [ |
| "project_runtime", |
| "sync_commands", |
| ] |
| assert any(event["type"] == "tool_call" for event in response.events) |
| assert response.events[-1]["type"] == "final" |
|
|
|
|
| def test_generate_space_agent_reply_supports_multi_step_model_fix( |
| monkeypatch, tmp_path: Path |
| ) -> None: |
| downloaded = tmp_path / "README.md" |
| downloaded.write_text("vecs saturs", encoding="utf-8") |
| staged: list[dict[str, object]] = [] |
|
|
| class FakeApi: |
| def list_repo_files(self, **_: object): |
| return ["README.md", "config.json"] |
|
|
| monkeypatch.setattr("maris_core.space_agent._get_hf_api_client", lambda: FakeApi()) |
| monkeypatch.setattr( |
| "maris_core.space_agent._download_hf_repo_file", |
| lambda **_: str(downloaded), |
| ) |
|
|
| response = generate_space_agent_reply( |
| SpaceAgentChatRequest(message="Pārbaudi manu modeli un salabo to."), |
| client_factory=_MultiStepToolCallingClient, |
| tool_context={ |
| "require_publish_approval": True, |
| "task_mode": "improve", |
| "stage_hf_write": lambda payload: ( |
| staged.append(payload) or {"proposal_id": "approval-1", "status": "pending"} |
| ), |
| }, |
| ) |
|
|
| assert response.response == "Pārbaudīju modeli, salaboju README un saglabāju izmaiņas." |
| assert [tool_call.name for tool_call in response.tool_calls] == [ |
| "list_huggingface_repo_files", |
| "read_huggingface_repo_file", |
| "write_huggingface_repo_file", |
| ] |
| assert staged[0]["repo_id"] == "MarisUK/maris-ai-master" |
| assert staged[0]["path"] == "README.md" |
| assert staged[0]["commit_message"] == "Fix model README" |
| assert staged[0]["content"] == "salabots modelis" |
| assert any( |
| event["type"] == "tool_result" and event["tool_name"] == "write_huggingface_repo_file" |
| for event in response.events |
| ) |
| assert response.change_previews[0]["requires_approval"] is True |
|
|
|
|
| class _FailingClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
|
|
| def chat_completion(self, **_: object) -> dict[str, object]: |
| raise OSError("offline") |
|
|
|
|
| class _StopIterationChoices: |
| def __bool__(self) -> bool: |
| return True |
|
|
| def __getitem__(self, index: int) -> object: |
| raise StopIteration(index) |
|
|
| def __iter__(self): |
| return iter(()) |
|
|
|
|
| class _MalformedChoicesClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
|
|
| def chat_completion(self, **_: object) -> dict[str, object]: |
| return {"choices": _StopIterationChoices()} |
|
|
|
|
| class _RetryAcrossModelsClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
| self.chat_models: list[str] = [] |
|
|
| def chat_completion(self, **kwargs: object) -> dict[str, object]: |
| model = str(kwargs["model"]) |
| self.chat_models.append(model) |
| if model == "broken/model": |
| raise OSError("broken") |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": "Profesionāli pārbaudīju MarisUK saturu un varu turpināt ar labojumiem." |
| } |
| } |
| ] |
| } |
|
|
|
|
| class _MissingChatCompletionClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
|
|
|
|
| class _RuntimeErrorChatClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
|
|
| def chat_completion(self, **_: object) -> dict[str, object]: |
| raise RuntimeError("provider rejected chat completion") |
|
|
|
|
| class _TextModelCompatibilityClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
| self.captured_messages: list[list[dict[str, str]]] = [] |
|
|
| def chat_completion(self, **kwargs: object) -> dict[str, object]: |
| self.captured_messages.append(list(kwargs["messages"])) |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": json.dumps( |
| { |
| "mode": "final", |
| "response": "Strādāju tiešā teksta režīmā ar Maris modeli.", |
| }, |
| ensure_ascii=False, |
| ), |
| } |
| } |
| ] |
| } |
|
|
|
|
| class _ToolFailureRecoveryClient: |
| def __init__(self, token: str | None = None) -> None: |
| self.token = token |
| self.calls = 0 |
|
|
| def chat_completion(self, **_: object) -> dict[str, object]: |
| self.calls += 1 |
| if self.calls == 1: |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": ( |
| '{"mode":"tool","tool_calls":[' |
| '{"name":"read_workspace_file","arguments":{"path":"README.md"}}' |
| "]}" |
| ) |
| } |
| } |
| ] |
| } |
| return { |
| "choices": [ |
| { |
| "message": { |
| "content": ( |
| '{"mode":"final","response":"Pārbaudīju rīka kļūdu un turpinu bez iekšējas kļūdas."}' |
| ) |
| } |
| } |
| ] |
| } |
|
|
|
|
| def test_space_agent_accepts_external_hf_model_ids() -> None: |
| request = SpaceAgentChatRequest(message="Sakārto manu Space", model="MarisUK/maris-ai-master") |
|
|
| assert request.model == "MarisUK/maris-ai-master" |
|
|
|
|
| def test_space_agent_rejects_malformed_model_ids() -> None: |
| with pytest.raises(ValueError): |
| SpaceAgentChatRequest(message="Sakārto manu Space", model="bad model") |
|
|
|
|
| def test_resolve_space_agent_models_uses_only_explicit_request_model(monkeypatch) -> None: |
| monkeypatch.setenv("MARIS_AGENT_MODEL", "MarisUK/maris-ai-master") |
| monkeypatch.setenv("MARIS_AGENT_MODELS", "meta-llama/Llama-3.3-70B-Instruct") |
|
|
| models = resolve_space_agent_models("deepseek-ai/DeepSeek-V3.2") |
|
|
| assert models == ("deepseek-ai/DeepSeek-V3.2",) |
|
|
|
|
| def test_generate_space_agent_reply_raises_when_chat_completion_returns_malformed_choices() -> None: |
| request = SpaceAgentChatRequest(message="Pārbaudi manu Space konfigurāciju") |
|
|
| with pytest.raises(RuntimeError, match="nevarēja pieslēgties modelim"): |
| generate_space_agent_reply(request, client_factory=_MalformedChoicesClient) |
|
|
|
|
| def test_generate_space_agent_reply_uses_requested_model_without_hidden_retry() -> None: |
| response = generate_space_agent_reply( |
| SpaceAgentChatRequest( |
| message="Auditē manu MarisUK Space un sagatavo profesionālu atbildi.", |
| model="Qwen/Qwen3-Coder-480B-A35B-Instruct", |
| ), |
| client_factory=_RetryAcrossModelsClient, |
| ) |
|
|
| assert response.model == "Qwen/Qwen3-Coder-480B-A35B-Instruct" |
| assert response.used_fallback is False |
| assert "Profesionāli pārbaudīju" in response.response |
|
|
|
|
| def test_generate_space_agent_reply_raises_when_chat_completion_is_missing() -> None: |
| with pytest.raises(RuntimeError, match="nevarēja pieslēgties modelim"): |
| generate_space_agent_reply( |
| SpaceAgentChatRequest(message="Pārbaudi manu Space konfigurāciju"), |
| client_factory=_MissingChatCompletionClient, |
| ) |
|
|
|
|
| def test_generate_space_agent_reply_raises_after_runtime_error_chat_completion() -> None: |
| with pytest.raises(RuntimeError, match="provider rejected chat completion"): |
| generate_space_agent_reply( |
| SpaceAgentChatRequest(message="Pārbaudi manu Space konfigurāciju"), |
| client_factory=_RuntimeErrorChatClient, |
| ) |
|
|
|
|
| def test_generate_space_agent_reply_surfaces_tool_errors_without_internal_failure() -> None: |
| response = generate_space_agent_reply( |
| SpaceAgentChatRequest(message="Nolasi README un pasaki ko redzi."), |
| client_factory=_ToolFailureRecoveryClient, |
| ) |
|
|
| assert response.response == "Pārbaudīju rīka kļūdu un turpinu bez iekšējas kļūdas." |
| assert any(event["type"] == "tool_error" for event in response.events) |
| assert any(tool_call.name == "read_workspace_file" for tool_call in response.tool_calls) |
|
|
|
|
| def test_maris_text_model_uses_simple_mode() -> None: |
| client = _TextModelCompatibilityClient() |
| response = generate_space_agent_reply( |
| SpaceAgentChatRequest( |
| message="Palīdzi man saprast Space konfigurāciju.", |
| model="MarisUK/maris-ai-text", |
| tool_calling=True, |
| ), |
| client_factory=lambda token=None: client, |
| ) |
|
|
| assert response.response == "Strādāju tiešā teksta režīmā ar Maris modeli." |
| assert response.tool_calls == [] |
| assert response.used_fallback is False |
| assert any("vienkāršotu tiešās atbildes ceļu" in event["message"] for event in response.events) |
| assert client.captured_messages |
| assert "Atbildi tikai ar JSON" not in client.captured_messages[0][0]["content"] |
| assert "Domā kā senior programmētājs" not in client.captured_messages[0][0]["content"] |
|
|
|
|
| def test_generate_space_agent_reply_raises_direct_model_error_on_failure() -> None: |
| request = SpaceAgentChatRequest(message="Deploy manu agent space") |
|
|
| with pytest.raises(RuntimeError, match="offline"): |
| generate_space_agent_reply( |
| request, |
| client_factory=_FailingClient, |
| tool_context={"training_status": {"progress": {"label": "Gaida startu"}}}, |
| ) |
|
|