2026-03-09 21:54:04 -04:00
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
# ── Index ─────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-02-26 23:39:13 -05:00
|
|
|
|
2026-02-19 19:05:01 +00:00
|
|
|
def test_index_returns_200(client):
|
|
|
|
|
response = client.get("/")
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_index_contains_title(client):
|
|
|
|
|
response = client.get("/")
|
2026-03-05 19:45:38 -05:00
|
|
|
assert "MISSION CONTROL" in response.text
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_index_contains_chat_interface(client):
|
|
|
|
|
response = client.get("/")
|
2026-03-05 19:45:38 -05:00
|
|
|
# Agent panel loads dynamically via HTMX; verify the trigger attribute is present
|
|
|
|
|
assert 'hx-get="/agents/default/panel"' in response.text
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# ── Health ────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-02-26 23:39:13 -05:00
|
|
|
|
2026-02-19 19:05:01 +00:00
|
|
|
def test_health_endpoint_ok(client):
|
2026-02-26 23:39:13 -05:00
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.health.check_ollama",
|
|
|
|
|
new_callable=AsyncMock,
|
|
|
|
|
return_value=True,
|
|
|
|
|
):
|
2026-02-19 19:05:01 +00:00
|
|
|
response = client.get("/health")
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
data = response.json()
|
|
|
|
|
assert data["status"] == "ok"
|
|
|
|
|
assert data["services"]["ollama"] == "up"
|
Claude/remove persona system f vgt m (#126)
* Remove persona system, identity, and all Timmy references
Strip the codebase to pure orchestration logic:
- Delete TIMMY_IDENTITY.md and memory/self/identity.md
- Gut brain/identity.py to no-op stubs (empty returns)
- Remove all system prompts reinforcing Timmy's character, faith,
sovereignty, sign-off ("Sir, affirmative"), and agent roster
- Replace identity-laden prompts with generic local-AI-assistant prompts
- Remove "You work for Timmy" from all sub-agent system prompts
- Rename PersonaTools → AgentTools, PERSONA_TOOLKITS → AGENT_TOOLKITS
- Replace "timmy" agent ID with "orchestrator" across routes, marketplace,
tools catalog, and orchestrator class
- Strip Timmy references from config comments, templates, telegram bot,
chat API, and dashboard UI
- Delete tests/brain/test_identity.py entirely
- Fix all test assertions that checked for persona identity content
729 tests pass (2 pre-existing failures in test_calm.py unrelated).
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
* Add Taskosaur (PM + AI task execution) to docker-compose
Spins up Taskosaur alongside the dashboard on `docker compose up`:
- postgres:16-alpine (port 5432, Taskosaur DB)
- redis:7-alpine (Bull queue backend)
- taskosaur (ports 3000 API / 3001 UI)
- dashboard now depends_on taskosaur healthy
- TASKOSAUR_API_URL injected into dashboard environment
Dashboard can reach Taskosaur at http://taskosaur:3000/api on the
internal network. Frontend UI accessible at http://localhost:3001.
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 12:00:49 -05:00
|
|
|
assert "agents" in data
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_health_endpoint_ollama_down(client):
|
2026-02-26 23:39:13 -05:00
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.health.check_ollama",
|
|
|
|
|
new_callable=AsyncMock,
|
|
|
|
|
return_value=False,
|
|
|
|
|
):
|
2026-02-19 19:05:01 +00:00
|
|
|
response = client.get("/health")
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert response.json()["services"]["ollama"] == "down"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_health_status_panel_ollama_up(client):
|
2026-02-26 23:39:13 -05:00
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.health.check_ollama",
|
|
|
|
|
new_callable=AsyncMock,
|
|
|
|
|
return_value=True,
|
|
|
|
|
):
|
2026-02-19 19:05:01 +00:00
|
|
|
response = client.get("/health/status")
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert "UP" in response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_health_status_panel_ollama_down(client):
|
2026-02-26 23:39:13 -05:00
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.health.check_ollama",
|
|
|
|
|
new_callable=AsyncMock,
|
|
|
|
|
return_value=False,
|
|
|
|
|
):
|
2026-02-19 19:05:01 +00:00
|
|
|
response = client.get("/health/status")
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert "DOWN" in response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ── Agents ────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-02-26 23:39:13 -05:00
|
|
|
|
2026-02-19 19:05:01 +00:00
|
|
|
def test_agents_list(client):
|
|
|
|
|
response = client.get("/agents")
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
data = response.json()
|
|
|
|
|
assert "agents" in data
|
|
|
|
|
ids = [a["id"] for a in data["agents"]]
|
2026-03-05 19:45:38 -05:00
|
|
|
assert "default" in ids
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
def test_agents_list_metadata(client):
|
2026-03-11 18:36:42 -04:00
|
|
|
from config import settings
|
|
|
|
|
|
2026-02-19 19:05:01 +00:00
|
|
|
response = client.get("/agents")
|
2026-03-05 19:45:38 -05:00
|
|
|
agent = next(a for a in response.json()["agents"] if a["id"] == "default")
|
|
|
|
|
assert agent["name"] == "Agent"
|
2026-03-11 18:36:42 -04:00
|
|
|
assert agent["model"] == settings.ollama_model
|
2026-03-05 19:45:38 -05:00
|
|
|
assert agent["type"] == "local"
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# ── Chat ──────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-02-26 23:39:13 -05:00
|
|
|
|
2026-03-09 21:54:04 -04:00
|
|
|
def _mock_run(content="Operational and ready."):
|
|
|
|
|
"""Create a mock RunOutput for a completed run."""
|
|
|
|
|
run = MagicMock()
|
|
|
|
|
run.content = content
|
|
|
|
|
run.status = "COMPLETED"
|
|
|
|
|
run.active_requirements = []
|
|
|
|
|
return run
|
|
|
|
|
|
|
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
def test_chat_agent_success(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
with patch("dashboard.routes.agents.chat_with_tools", return_value=_mock_run()):
|
2026-03-05 19:45:38 -05:00
|
|
|
response = client.post("/agents/default/chat", data={"message": "status?"})
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert "status?" in response.text
|
Claude/remove persona system f vgt m (#126)
* Remove persona system, identity, and all Timmy references
Strip the codebase to pure orchestration logic:
- Delete TIMMY_IDENTITY.md and memory/self/identity.md
- Gut brain/identity.py to no-op stubs (empty returns)
- Remove all system prompts reinforcing Timmy's character, faith,
sovereignty, sign-off ("Sir, affirmative"), and agent roster
- Replace identity-laden prompts with generic local-AI-assistant prompts
- Remove "You work for Timmy" from all sub-agent system prompts
- Rename PersonaTools → AgentTools, PERSONA_TOOLKITS → AGENT_TOOLKITS
- Replace "timmy" agent ID with "orchestrator" across routes, marketplace,
tools catalog, and orchestrator class
- Strip Timmy references from config comments, templates, telegram bot,
chat API, and dashboard UI
- Delete tests/brain/test_identity.py entirely
- Fix all test assertions that checked for persona identity content
729 tests pass (2 pre-existing failures in test_calm.py unrelated).
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
* Add Taskosaur (PM + AI task execution) to docker-compose
Spins up Taskosaur alongside the dashboard on `docker compose up`:
- postgres:16-alpine (port 5432, Taskosaur DB)
- redis:7-alpine (Bull queue backend)
- taskosaur (ports 3000 API / 3001 UI)
- dashboard now depends_on taskosaur healthy
- TASKOSAUR_API_URL injected into dashboard environment
Dashboard can reach Taskosaur at http://taskosaur:3000/api on the
internal network. Frontend UI accessible at http://localhost:3001.
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 12:00:49 -05:00
|
|
|
assert "Operational" in response.text
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
def test_chat_agent_shows_user_message(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
with patch("dashboard.routes.agents.chat_with_tools", return_value=_mock_run("Acknowledged.")):
|
2026-03-05 19:45:38 -05:00
|
|
|
response = client.post("/agents/default/chat", data={"message": "hello there"})
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
assert "hello there" in response.text
|
|
|
|
|
|
|
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
def test_chat_agent_ollama_offline(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
# When Ollama is unreachable, chat shows the user message + error.
|
|
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.agents.chat_with_tools",
|
|
|
|
|
side_effect=Exception("Ollama unreachable"),
|
|
|
|
|
):
|
|
|
|
|
response = client.post("/agents/default/chat", data={"message": "ping"})
|
2026-02-19 19:05:01 +00:00
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert "ping" in response.text
|
|
|
|
|
|
|
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
def test_chat_agent_requires_message(client):
|
|
|
|
|
response = client.post("/agents/default/chat", data={})
|
2026-02-19 19:05:01 +00:00
|
|
|
assert response.status_code == 422
|
2026-02-20 14:00:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# ── History ────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-02-26 23:39:13 -05:00
|
|
|
|
2026-02-20 14:00:16 +00:00
|
|
|
def test_history_empty_shows_init_message(client):
|
2026-03-05 19:45:38 -05:00
|
|
|
response = client.get("/agents/default/history")
|
2026-02-20 14:00:16 +00:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert "Mission Control initialized" in response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_history_records_user_and_agent_messages(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.agents.chat_with_tools", return_value=_mock_run("I am operational.")
|
|
|
|
|
):
|
2026-03-05 19:45:38 -05:00
|
|
|
client.post("/agents/default/chat", data={"message": "status check"})
|
2026-02-20 14:00:16 +00:00
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
response = client.get("/agents/default/history")
|
2026-02-20 14:00:16 +00:00
|
|
|
assert "status check" in response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_history_records_error_when_offline(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
with patch(
|
|
|
|
|
"dashboard.routes.agents.chat_with_tools",
|
|
|
|
|
side_effect=Exception("Ollama unreachable"),
|
|
|
|
|
):
|
|
|
|
|
client.post("/agents/default/chat", data={"message": "ping"})
|
2026-02-20 14:00:16 +00:00
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
response = client.get("/agents/default/history")
|
2026-02-20 14:00:16 +00:00
|
|
|
assert "ping" in response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_history_clear_resets_to_init_message(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
with patch("dashboard.routes.agents.chat_with_tools", return_value=_mock_run("Acknowledged.")):
|
2026-03-05 19:45:38 -05:00
|
|
|
client.post("/agents/default/chat", data={"message": "hello"})
|
2026-02-20 14:00:16 +00:00
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
response = client.delete("/agents/default/history")
|
2026-02-20 14:00:16 +00:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert "Mission Control initialized" in response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_history_empty_after_clear(client):
|
2026-03-09 21:54:04 -04:00
|
|
|
with patch("dashboard.routes.agents.chat_with_tools", return_value=_mock_run("OK.")):
|
2026-03-05 19:45:38 -05:00
|
|
|
client.post("/agents/default/chat", data={"message": "test"})
|
2026-02-20 14:00:16 +00:00
|
|
|
|
2026-03-05 19:45:38 -05:00
|
|
|
client.delete("/agents/default/history")
|
|
|
|
|
response = client.get("/agents/default/history")
|
2026-02-20 14:00:16 +00:00
|
|
|
assert "test" not in response.text
|
|
|
|
|
assert "Mission Control initialized" in response.text
|