jarviscore-framework 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/calculator_agent_example.py +77 -0
- examples/multi_agent_workflow.py +132 -0
- examples/research_agent_example.py +76 -0
- jarviscore/__init__.py +54 -0
- jarviscore/cli/__init__.py +7 -0
- jarviscore/cli/__main__.py +33 -0
- jarviscore/cli/check.py +404 -0
- jarviscore/cli/smoketest.py +371 -0
- jarviscore/config/__init__.py +7 -0
- jarviscore/config/settings.py +128 -0
- jarviscore/core/__init__.py +7 -0
- jarviscore/core/agent.py +163 -0
- jarviscore/core/mesh.py +463 -0
- jarviscore/core/profile.py +64 -0
- jarviscore/docs/API_REFERENCE.md +932 -0
- jarviscore/docs/CONFIGURATION.md +753 -0
- jarviscore/docs/GETTING_STARTED.md +600 -0
- jarviscore/docs/TROUBLESHOOTING.md +424 -0
- jarviscore/docs/USER_GUIDE.md +983 -0
- jarviscore/execution/__init__.py +94 -0
- jarviscore/execution/code_registry.py +298 -0
- jarviscore/execution/generator.py +268 -0
- jarviscore/execution/llm.py +430 -0
- jarviscore/execution/repair.py +283 -0
- jarviscore/execution/result_handler.py +332 -0
- jarviscore/execution/sandbox.py +555 -0
- jarviscore/execution/search.py +281 -0
- jarviscore/orchestration/__init__.py +18 -0
- jarviscore/orchestration/claimer.py +101 -0
- jarviscore/orchestration/dependency.py +143 -0
- jarviscore/orchestration/engine.py +292 -0
- jarviscore/orchestration/status.py +96 -0
- jarviscore/p2p/__init__.py +23 -0
- jarviscore/p2p/broadcaster.py +353 -0
- jarviscore/p2p/coordinator.py +364 -0
- jarviscore/p2p/keepalive.py +361 -0
- jarviscore/p2p/swim_manager.py +290 -0
- jarviscore/profiles/__init__.py +6 -0
- jarviscore/profiles/autoagent.py +264 -0
- jarviscore/profiles/customagent.py +137 -0
- jarviscore_framework-0.1.0.dist-info/METADATA +136 -0
- jarviscore_framework-0.1.0.dist-info/RECORD +55 -0
- jarviscore_framework-0.1.0.dist-info/WHEEL +5 -0
- jarviscore_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
- jarviscore_framework-0.1.0.dist-info/top_level.txt +3 -0
- tests/conftest.py +44 -0
- tests/test_agent.py +165 -0
- tests/test_autoagent.py +140 -0
- tests/test_autoagent_day4.py +186 -0
- tests/test_customagent.py +248 -0
- tests/test_integration.py +293 -0
- tests/test_llm_fallback.py +185 -0
- tests/test_mesh.py +356 -0
- tests/test_p2p_integration.py +375 -0
- tests/test_remote_sandbox.py +116 -0
tests/test_agent.py
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for Agent base class.
|
|
3
|
+
"""
|
|
4
|
+
import pytest
|
|
5
|
+
from jarviscore.core.agent import Agent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Test agent implementations
|
|
9
|
+
class ValidAgent(Agent):
|
|
10
|
+
"""Valid agent for testing."""
|
|
11
|
+
role = "test_agent"
|
|
12
|
+
capabilities = ["testing", "validation"]
|
|
13
|
+
|
|
14
|
+
async def execute_task(self, task):
|
|
15
|
+
return {"status": "success", "output": "test result"}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NoRoleAgent(Agent):
|
|
19
|
+
"""Agent without role (should fail validation)."""
|
|
20
|
+
capabilities = ["testing"]
|
|
21
|
+
|
|
22
|
+
async def execute_task(self, task):
|
|
23
|
+
return {"status": "success"}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NoCapabilitiesAgent(Agent):
|
|
27
|
+
"""Agent without capabilities (should fail validation)."""
|
|
28
|
+
role = "no_caps"
|
|
29
|
+
|
|
30
|
+
async def execute_task(self, task):
|
|
31
|
+
return {"status": "success"}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestAgentInitialization:
|
|
35
|
+
"""Test agent initialization and validation."""
|
|
36
|
+
|
|
37
|
+
def test_valid_agent_creation(self):
|
|
38
|
+
"""Test creating a valid agent."""
|
|
39
|
+
agent = ValidAgent()
|
|
40
|
+
|
|
41
|
+
assert agent.role == "test_agent"
|
|
42
|
+
assert agent.capabilities == ["testing", "validation"]
|
|
43
|
+
assert agent.agent_id.startswith("test_agent-")
|
|
44
|
+
assert len(agent.agent_id.split("-")[1]) == 8 # 8-char UUID
|
|
45
|
+
|
|
46
|
+
def test_agent_with_custom_id(self):
|
|
47
|
+
"""Test creating agent with custom ID."""
|
|
48
|
+
agent = ValidAgent(agent_id="custom-agent-123")
|
|
49
|
+
|
|
50
|
+
assert agent.agent_id == "custom-agent-123"
|
|
51
|
+
assert agent.role == "test_agent"
|
|
52
|
+
|
|
53
|
+
def test_agent_without_role_fails(self):
|
|
54
|
+
"""Test that agent without role raises ValueError."""
|
|
55
|
+
with pytest.raises(ValueError) as exc_info:
|
|
56
|
+
NoRoleAgent()
|
|
57
|
+
|
|
58
|
+
assert "must define 'role' class attribute" in str(exc_info.value)
|
|
59
|
+
|
|
60
|
+
def test_agent_without_capabilities_fails(self):
|
|
61
|
+
"""Test that agent without capabilities raises ValueError."""
|
|
62
|
+
with pytest.raises(ValueError) as exc_info:
|
|
63
|
+
NoCapabilitiesAgent()
|
|
64
|
+
|
|
65
|
+
assert "must define 'capabilities' class attribute" in str(exc_info.value)
|
|
66
|
+
|
|
67
|
+
def test_agent_mesh_initially_none(self):
|
|
68
|
+
"""Test that agent._mesh is initially None."""
|
|
69
|
+
agent = ValidAgent()
|
|
70
|
+
assert agent._mesh is None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class TestAgentTaskHandling:
|
|
74
|
+
"""Test agent task handling capabilities."""
|
|
75
|
+
|
|
76
|
+
def test_can_handle_by_role(self):
|
|
77
|
+
"""Test agent can handle task by role."""
|
|
78
|
+
agent = ValidAgent()
|
|
79
|
+
|
|
80
|
+
task = {"role": "test_agent", "task": "Do something"}
|
|
81
|
+
assert agent.can_handle(task) is True
|
|
82
|
+
|
|
83
|
+
def test_can_handle_by_capability(self):
|
|
84
|
+
"""Test agent can handle task by capability."""
|
|
85
|
+
agent = ValidAgent()
|
|
86
|
+
|
|
87
|
+
task1 = {"capability": "testing", "task": "Run tests"}
|
|
88
|
+
assert agent.can_handle(task1) is True
|
|
89
|
+
|
|
90
|
+
task2 = {"capability": "validation", "task": "Validate data"}
|
|
91
|
+
assert agent.can_handle(task2) is True
|
|
92
|
+
|
|
93
|
+
def test_cannot_handle_wrong_role(self):
|
|
94
|
+
"""Test agent rejects task with wrong role."""
|
|
95
|
+
agent = ValidAgent()
|
|
96
|
+
|
|
97
|
+
task = {"role": "different_agent", "task": "Do something"}
|
|
98
|
+
assert agent.can_handle(task) is False
|
|
99
|
+
|
|
100
|
+
def test_cannot_handle_wrong_capability(self):
|
|
101
|
+
"""Test agent rejects task with wrong capability."""
|
|
102
|
+
agent = ValidAgent()
|
|
103
|
+
|
|
104
|
+
task = {"capability": "unknown_capability", "task": "Do something"}
|
|
105
|
+
assert agent.can_handle(task) is False
|
|
106
|
+
|
|
107
|
+
def test_can_handle_no_role_or_capability(self):
|
|
108
|
+
"""Test agent behavior when task has no role or capability."""
|
|
109
|
+
agent = ValidAgent()
|
|
110
|
+
|
|
111
|
+
task = {"task": "Do something"}
|
|
112
|
+
assert agent.can_handle(task) is False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class TestAgentExecution:
|
|
116
|
+
"""Test agent task execution."""
|
|
117
|
+
|
|
118
|
+
@pytest.mark.asyncio
|
|
119
|
+
async def test_execute_task_implementation(self):
|
|
120
|
+
"""Test that execute_task can be called and returns result."""
|
|
121
|
+
agent = ValidAgent()
|
|
122
|
+
|
|
123
|
+
task = {"task": "Test task"}
|
|
124
|
+
result = await agent.execute_task(task)
|
|
125
|
+
|
|
126
|
+
assert result["status"] == "success"
|
|
127
|
+
assert result["output"] == "test result"
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class TestAgentLifecycle:
|
|
131
|
+
"""Test agent setup and teardown lifecycle."""
|
|
132
|
+
|
|
133
|
+
@pytest.mark.asyncio
|
|
134
|
+
async def test_setup_hook(self):
|
|
135
|
+
"""Test agent setup hook."""
|
|
136
|
+
agent = ValidAgent()
|
|
137
|
+
await agent.setup() # Should not raise
|
|
138
|
+
|
|
139
|
+
@pytest.mark.asyncio
|
|
140
|
+
async def test_teardown_hook(self):
|
|
141
|
+
"""Test agent teardown hook."""
|
|
142
|
+
agent = ValidAgent()
|
|
143
|
+
await agent.teardown() # Should not raise
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class TestAgentRepresentation:
|
|
147
|
+
"""Test agent string representations."""
|
|
148
|
+
|
|
149
|
+
def test_repr(self):
|
|
150
|
+
"""Test agent __repr__."""
|
|
151
|
+
agent = ValidAgent(agent_id="test-123")
|
|
152
|
+
repr_str = repr(agent)
|
|
153
|
+
|
|
154
|
+
assert "ValidAgent" in repr_str
|
|
155
|
+
assert "test-123" in repr_str
|
|
156
|
+
assert "test_agent" in repr_str
|
|
157
|
+
assert "testing" in repr_str
|
|
158
|
+
|
|
159
|
+
def test_str(self):
|
|
160
|
+
"""Test agent __str__."""
|
|
161
|
+
agent = ValidAgent(agent_id="test-123")
|
|
162
|
+
str_repr = str(agent)
|
|
163
|
+
|
|
164
|
+
assert "test_agent" in str_repr
|
|
165
|
+
assert "test-123" in str_repr
|
tests/test_autoagent.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for AutoAgent profile.
|
|
3
|
+
"""
|
|
4
|
+
import pytest
|
|
5
|
+
from jarviscore.profiles.autoagent import AutoAgent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ValidAutoAgent(AutoAgent):
|
|
9
|
+
"""Valid AutoAgent for testing."""
|
|
10
|
+
role = "test_auto"
|
|
11
|
+
capabilities = ["testing"]
|
|
12
|
+
system_prompt = "You are a test agent that performs testing tasks."
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NoPromptAutoAgent(AutoAgent):
|
|
16
|
+
"""AutoAgent without system_prompt (should fail)."""
|
|
17
|
+
role = "no_prompt"
|
|
18
|
+
capabilities = ["testing"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestAutoAgentInitialization:
|
|
22
|
+
"""Test AutoAgent initialization."""
|
|
23
|
+
|
|
24
|
+
def test_valid_autoagent_creation(self):
|
|
25
|
+
"""Test creating a valid AutoAgent."""
|
|
26
|
+
agent = ValidAutoAgent()
|
|
27
|
+
|
|
28
|
+
assert agent.role == "test_auto"
|
|
29
|
+
assert agent.capabilities == ["testing"]
|
|
30
|
+
assert agent.system_prompt == "You are a test agent that performs testing tasks."
|
|
31
|
+
|
|
32
|
+
def test_autoagent_without_system_prompt_fails(self):
|
|
33
|
+
"""Test that AutoAgent without system_prompt raises ValueError."""
|
|
34
|
+
with pytest.raises(ValueError) as exc_info:
|
|
35
|
+
NoPromptAutoAgent()
|
|
36
|
+
|
|
37
|
+
assert "must define 'system_prompt'" in str(exc_info.value)
|
|
38
|
+
|
|
39
|
+
def test_autoagent_execution_components_initially_none(self):
|
|
40
|
+
"""Test that execution components are initially None."""
|
|
41
|
+
agent = ValidAutoAgent()
|
|
42
|
+
|
|
43
|
+
assert agent.llm is None
|
|
44
|
+
assert agent.codegen is None
|
|
45
|
+
assert agent.sandbox is None
|
|
46
|
+
assert agent.repair is None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TestAutoAgentSetup:
|
|
50
|
+
"""Test AutoAgent setup."""
|
|
51
|
+
|
|
52
|
+
@pytest.mark.asyncio
|
|
53
|
+
async def test_autoagent_setup(self):
|
|
54
|
+
"""Test AutoAgent setup hook."""
|
|
55
|
+
agent = ValidAutoAgent()
|
|
56
|
+
await agent.setup()
|
|
57
|
+
|
|
58
|
+
# Day 1: Just verify it runs without error
|
|
59
|
+
# Day 4: Will test actual LLM initialization
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class TestAutoAgentExecution:
|
|
63
|
+
"""Test AutoAgent task execution."""
|
|
64
|
+
|
|
65
|
+
@pytest.mark.asyncio
|
|
66
|
+
async def test_execute_task_without_setup_fails(self):
|
|
67
|
+
"""Test AutoAgent execute_task fails gracefully without setup."""
|
|
68
|
+
agent = ValidAutoAgent()
|
|
69
|
+
|
|
70
|
+
task = {"task": "Test task description"}
|
|
71
|
+
result = await agent.execute_task(task)
|
|
72
|
+
|
|
73
|
+
# Day 4: Should fail gracefully when components not initialized
|
|
74
|
+
assert result["status"] == "failure"
|
|
75
|
+
assert "Fatal error" in result.get("error", "")
|
|
76
|
+
|
|
77
|
+
@pytest.mark.asyncio
|
|
78
|
+
async def test_execute_task_with_mock_components(self):
|
|
79
|
+
"""Test AutoAgent with mocked execution components."""
|
|
80
|
+
from unittest.mock import Mock, AsyncMock
|
|
81
|
+
|
|
82
|
+
agent = ValidAutoAgent()
|
|
83
|
+
|
|
84
|
+
# Mock the execution components
|
|
85
|
+
agent.codegen = Mock()
|
|
86
|
+
agent.codegen.generate = AsyncMock(return_value="result = 42")
|
|
87
|
+
|
|
88
|
+
agent.sandbox = Mock()
|
|
89
|
+
agent.sandbox.execute = AsyncMock(return_value={
|
|
90
|
+
"status": "success",
|
|
91
|
+
"output": 42
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
agent.repair = Mock() # Not called if execution succeeds
|
|
95
|
+
|
|
96
|
+
# Mock result handler (Phase 1)
|
|
97
|
+
agent.result_handler = Mock()
|
|
98
|
+
agent.result_handler.process_result = Mock(return_value={
|
|
99
|
+
'result_id': 'test-result-id',
|
|
100
|
+
'status': 'success'
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
# Mock code registry (Phase 3)
|
|
104
|
+
agent.code_registry = Mock()
|
|
105
|
+
agent.code_registry.register = Mock(return_value='test-function-id')
|
|
106
|
+
|
|
107
|
+
task = {"task": "Calculate 21 * 2"}
|
|
108
|
+
result = await agent.execute_task(task)
|
|
109
|
+
|
|
110
|
+
# Should succeed with mocked components
|
|
111
|
+
assert result["status"] == "success"
|
|
112
|
+
assert result["output"] == 42
|
|
113
|
+
assert result["code"] == "result = 42"
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class TestAutoAgentInheritance:
|
|
117
|
+
"""Test AutoAgent inheritance from Profile and Agent."""
|
|
118
|
+
|
|
119
|
+
def test_autoagent_inherits_agent_methods(self):
|
|
120
|
+
"""Test that AutoAgent inherits Agent methods."""
|
|
121
|
+
agent = ValidAutoAgent()
|
|
122
|
+
|
|
123
|
+
# Should have Agent methods
|
|
124
|
+
assert hasattr(agent, "can_handle")
|
|
125
|
+
assert hasattr(agent, "execute_task")
|
|
126
|
+
assert hasattr(agent, "setup")
|
|
127
|
+
assert hasattr(agent, "teardown")
|
|
128
|
+
|
|
129
|
+
def test_autoagent_can_handle_tasks(self):
|
|
130
|
+
"""Test that AutoAgent can check task compatibility."""
|
|
131
|
+
agent = ValidAutoAgent()
|
|
132
|
+
|
|
133
|
+
task1 = {"role": "test_auto", "task": "Do something"}
|
|
134
|
+
assert agent.can_handle(task1) is True
|
|
135
|
+
|
|
136
|
+
task2 = {"capability": "testing", "task": "Run tests"}
|
|
137
|
+
assert agent.can_handle(task2) is True
|
|
138
|
+
|
|
139
|
+
task3 = {"role": "different", "task": "Won't handle"}
|
|
140
|
+
assert agent.can_handle(task3) is False
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for Day 4: AutoAgent with Code Generation
|
|
3
|
+
|
|
4
|
+
Tests the complete execution pipeline:
|
|
5
|
+
- LLM client initialization
|
|
6
|
+
- Code generation
|
|
7
|
+
- Sandbox execution
|
|
8
|
+
- Autonomous repair
|
|
9
|
+
"""
|
|
10
|
+
import pytest
|
|
11
|
+
import asyncio
|
|
12
|
+
from jarviscore.profiles import AutoAgent
|
|
13
|
+
from jarviscore.execution import (
|
|
14
|
+
create_llm_client,
|
|
15
|
+
create_search_client,
|
|
16
|
+
create_code_generator,
|
|
17
|
+
create_sandbox_executor,
|
|
18
|
+
create_autonomous_repair
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SimpleAgent(AutoAgent):
|
|
23
|
+
"""Test agent for unit tests."""
|
|
24
|
+
role = "test_agent"
|
|
25
|
+
capabilities = ["testing"]
|
|
26
|
+
system_prompt = "You are a test agent."
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_autoagent_initialization():
|
|
30
|
+
"""Test AutoAgent can be instantiated."""
|
|
31
|
+
agent = SimpleAgent()
|
|
32
|
+
assert agent.role == "test_agent"
|
|
33
|
+
assert agent.capabilities == ["testing"]
|
|
34
|
+
assert agent.system_prompt == "You are a test agent."
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@pytest.mark.asyncio
|
|
38
|
+
async def test_execution_components_creation():
|
|
39
|
+
"""Test all execution components can be created."""
|
|
40
|
+
# LLM client (no config, just instantiation test)
|
|
41
|
+
llm = create_llm_client({})
|
|
42
|
+
assert llm is not None
|
|
43
|
+
|
|
44
|
+
# Search client
|
|
45
|
+
search = create_search_client()
|
|
46
|
+
assert search is not None
|
|
47
|
+
|
|
48
|
+
# Code generator
|
|
49
|
+
codegen = create_code_generator(llm, search)
|
|
50
|
+
assert codegen is not None
|
|
51
|
+
|
|
52
|
+
# Sandbox executor
|
|
53
|
+
sandbox = create_sandbox_executor(timeout=60, search_client=search)
|
|
54
|
+
assert sandbox is not None
|
|
55
|
+
|
|
56
|
+
# Autonomous repair
|
|
57
|
+
repair = create_autonomous_repair(codegen)
|
|
58
|
+
assert repair is not None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@pytest.mark.asyncio
|
|
62
|
+
async def test_sandbox_simple_execution():
|
|
63
|
+
"""Test sandbox can execute simple code."""
|
|
64
|
+
from jarviscore.execution import SandboxExecutor
|
|
65
|
+
|
|
66
|
+
sandbox = SandboxExecutor(timeout=10)
|
|
67
|
+
|
|
68
|
+
code = """
|
|
69
|
+
# Simple calculation
|
|
70
|
+
result = 2 + 2
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
result = await sandbox.execute(code)
|
|
74
|
+
|
|
75
|
+
assert result['status'] == 'success'
|
|
76
|
+
assert result['output'] == 4
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@pytest.mark.asyncio
|
|
80
|
+
async def test_sandbox_async_execution():
|
|
81
|
+
"""Test sandbox can execute async code."""
|
|
82
|
+
from jarviscore.execution import SandboxExecutor
|
|
83
|
+
|
|
84
|
+
sandbox = SandboxExecutor(timeout=10)
|
|
85
|
+
|
|
86
|
+
code = """
|
|
87
|
+
import asyncio
|
|
88
|
+
|
|
89
|
+
async def main():
|
|
90
|
+
await asyncio.sleep(0.01)
|
|
91
|
+
return 42
|
|
92
|
+
|
|
93
|
+
# The result will be extracted by sandbox's _execute_async
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
result = await sandbox.execute(code)
|
|
97
|
+
|
|
98
|
+
assert result['status'] == 'success'
|
|
99
|
+
assert result['output'] == 42
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@pytest.mark.asyncio
|
|
103
|
+
async def test_sandbox_error_handling():
|
|
104
|
+
"""Test sandbox properly handles errors."""
|
|
105
|
+
from jarviscore.execution import SandboxExecutor
|
|
106
|
+
|
|
107
|
+
sandbox = SandboxExecutor(timeout=10)
|
|
108
|
+
|
|
109
|
+
code = """
|
|
110
|
+
# This will raise an error
|
|
111
|
+
result = 1 / 0
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
result = await sandbox.execute(code)
|
|
115
|
+
|
|
116
|
+
assert result['status'] == 'failure'
|
|
117
|
+
assert 'ZeroDivisionError' in result.get('error_type', '')
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@pytest.mark.asyncio
|
|
121
|
+
async def test_code_generator_validation():
|
|
122
|
+
"""Test code generator validates syntax."""
|
|
123
|
+
from jarviscore.execution import CodeGenerator, UnifiedLLMClient
|
|
124
|
+
|
|
125
|
+
llm = UnifiedLLMClient({})
|
|
126
|
+
codegen = CodeGenerator(llm, None)
|
|
127
|
+
|
|
128
|
+
# Test syntax validation
|
|
129
|
+
valid_code = "result = 42"
|
|
130
|
+
codegen._validate_code(valid_code) # Should not raise
|
|
131
|
+
|
|
132
|
+
invalid_code = "result = if 42"
|
|
133
|
+
with pytest.raises(ValueError):
|
|
134
|
+
codegen._validate_code(invalid_code)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@pytest.mark.asyncio
|
|
138
|
+
async def test_code_generator_cleaning():
|
|
139
|
+
"""Test code generator cleans markdown blocks."""
|
|
140
|
+
from jarviscore.execution import CodeGenerator, UnifiedLLMClient
|
|
141
|
+
|
|
142
|
+
llm = UnifiedLLMClient({})
|
|
143
|
+
codegen = CodeGenerator(llm, None)
|
|
144
|
+
|
|
145
|
+
# Test cleaning markdown blocks
|
|
146
|
+
markdown_code = """
|
|
147
|
+
```python
|
|
148
|
+
result = 42
|
|
149
|
+
```
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
cleaned = codegen._clean_code(markdown_code)
|
|
153
|
+
assert cleaned == "result = 42"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def test_autoagent_requires_system_prompt():
|
|
157
|
+
"""Test AutoAgent requires system_prompt."""
|
|
158
|
+
with pytest.raises(ValueError) as exc_info:
|
|
159
|
+
class BadAgent(AutoAgent):
|
|
160
|
+
role = "bad"
|
|
161
|
+
capabilities = ["test"]
|
|
162
|
+
# Missing system_prompt
|
|
163
|
+
|
|
164
|
+
BadAgent()
|
|
165
|
+
|
|
166
|
+
assert "system_prompt" in str(exc_info.value)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@pytest.mark.asyncio
|
|
170
|
+
async def test_search_client_initialization():
|
|
171
|
+
"""Test search client can be created and initialized."""
|
|
172
|
+
from jarviscore.execution import InternetSearch
|
|
173
|
+
|
|
174
|
+
search = InternetSearch()
|
|
175
|
+
await search.initialize()
|
|
176
|
+
|
|
177
|
+
assert search.session is not None
|
|
178
|
+
assert not search.session.closed
|
|
179
|
+
|
|
180
|
+
await search.close()
|
|
181
|
+
assert search.session is None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
if __name__ == "__main__":
|
|
185
|
+
# Run tests with pytest
|
|
186
|
+
pytest.main([__file__, "-v"])
|