connectonion 0.4.11__py3-none-any.whl → 0.5.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.
Files changed (80) hide show
  1. connectonion/__init__.py +11 -5
  2. connectonion/agent.py +44 -42
  3. connectonion/cli/commands/init.py +1 -1
  4. connectonion/cli/commands/project_cmd_lib.py +4 -4
  5. connectonion/cli/commands/reset_commands.py +1 -1
  6. connectonion/cli/docs/co-vibecoding-principles-docs-contexts-all-in-one.md +15 -11
  7. connectonion/cli/templates/minimal/agent.py +2 -2
  8. connectonion/console.py +55 -3
  9. connectonion/events.py +96 -17
  10. connectonion/llm.py +21 -3
  11. connectonion/logger.py +289 -0
  12. connectonion/prompt_files/eval_expected.md +12 -0
  13. connectonion/tool_executor.py +43 -32
  14. connectonion/usage.py +4 -0
  15. connectonion/useful_events_handlers/reflect.py +14 -10
  16. connectonion/useful_plugins/__init__.py +2 -1
  17. connectonion/useful_plugins/calendar_plugin.py +2 -2
  18. connectonion/useful_plugins/eval.py +130 -0
  19. connectonion/useful_plugins/gmail_plugin.py +4 -4
  20. connectonion/useful_plugins/image_result_formatter.py +4 -3
  21. connectonion/useful_plugins/re_act.py +15 -57
  22. connectonion/useful_plugins/shell_approval.py +2 -2
  23. connectonion/useful_tools/gmail.py +2 -2
  24. connectonion/useful_tools/memory.py +4 -0
  25. {connectonion-0.4.11.dist-info → connectonion-0.5.0.dist-info}/METADATA +48 -48
  26. {connectonion-0.4.11.dist-info → connectonion-0.5.0.dist-info}/RECORD +33 -77
  27. {connectonion-0.4.11.dist-info → connectonion-0.5.0.dist-info}/WHEEL +1 -2
  28. connectonion/cli/templates/email-agent/.env.example +0 -23
  29. connectonion/cli/templates/email-agent/README.md +0 -240
  30. connectonion/cli/templates/email-agent/agent.py +0 -374
  31. connectonion/cli/templates/email-agent/demo.py +0 -71
  32. connectonion/cli/templates/meta-agent/.env.example +0 -11
  33. connectonion/cli/templates/minimal/.env.example +0 -5
  34. connectonion/cli/templates/playwright/.env.example +0 -5
  35. connectonion-0.4.11.dist-info/top_level.txt +0 -2
  36. tests/__init__.py +0 -0
  37. tests/cli/__init__.py +0 -1
  38. tests/cli/argparse_runner.py +0 -85
  39. tests/cli/conftest.py +0 -5
  40. tests/cli/test_browser_cli.py +0 -61
  41. tests/cli/test_cli.py +0 -143
  42. tests/cli/test_cli_auth_google.py +0 -344
  43. tests/cli/test_cli_auth_microsoft.py +0 -256
  44. tests/cli/test_cli_create.py +0 -283
  45. tests/cli/test_cli_help.py +0 -200
  46. tests/cli/test_cli_init.py +0 -318
  47. tests/conftest.py +0 -283
  48. tests/debug_gemini_models.py +0 -23
  49. tests/fixtures/__init__.py +0 -1
  50. tests/fixtures/test_tools.py +0 -112
  51. tests/fixtures/trust_fixtures.py +0 -257
  52. tests/real_api/__init__.py +0 -0
  53. tests/real_api/conftest.py +0 -9
  54. tests/real_api/test_llm_do.py +0 -174
  55. tests/real_api/test_llm_do_comprehensive.py +0 -527
  56. tests/real_api/test_production_client.py +0 -94
  57. tests/real_api/test_real_anthropic.py +0 -100
  58. tests/real_api/test_real_api.py +0 -113
  59. tests/real_api/test_real_auth.py +0 -130
  60. tests/real_api/test_real_email.py +0 -95
  61. tests/real_api/test_real_gemini.py +0 -96
  62. tests/real_api/test_real_llm_do.py +0 -81
  63. tests/real_api/test_real_managed.py +0 -208
  64. tests/real_api/test_real_multi_llm.py +0 -454
  65. tests/real_api/test_real_openai.py +0 -100
  66. tests/real_api/test_responses_parse.py +0 -88
  67. tests/test_diff_writer.py +0 -126
  68. tests/test_events.py +0 -677
  69. tests/test_gemini_co.py +0 -70
  70. tests/test_image_result_formatter.py +0 -88
  71. tests/test_plugin_system.py +0 -110
  72. tests/utils/__init__.py +0 -1
  73. tests/utils/config_helpers.py +0 -188
  74. tests/utils/mock_helpers.py +0 -237
  75. /connectonion/{prompts → prompt_files}/__init__.py +0 -0
  76. /connectonion/{prompts → prompt_files}/analyze_contact.md +0 -0
  77. /connectonion/{prompts → prompt_files}/react_evaluate.md +0 -0
  78. /connectonion/{prompts → prompt_files}/react_plan.md +0 -0
  79. /connectonion/{prompts → prompt_files}/reflect.md +0 -0
  80. {connectonion-0.4.11.dist-info → connectonion-0.5.0.dist-info}/entry_points.txt +0 -0
tests/conftest.py DELETED
@@ -1,283 +0,0 @@
1
- """Pytest configuration and shared fixtures for ConnectOnion tests."""
2
-
3
- import pytest
4
- import tempfile
5
- import shutil
6
- import json
7
- from pathlib import Path
8
- from unittest.mock import Mock, MagicMock
9
- from connectonion import Agent
10
- # No need to import tools - they're just functions
11
- from connectonion.llm import LLMResponse, ToolCall, OpenAILLM
12
- from connectonion.usage import TokenUsage
13
- import os
14
- from dotenv import load_dotenv
15
-
16
- # Load .env file for API keys
17
- load_dotenv()
18
-
19
-
20
- @pytest.fixture
21
- def temp_dir():
22
- """Create a temporary directory for tests."""
23
- temp_dir = tempfile.mkdtemp()
24
- yield temp_dir
25
- shutil.rmtree(temp_dir)
26
-
27
-
28
- @pytest.fixture
29
- def mock_openai_client():
30
- """Create a mock OpenAI client for testing."""
31
- mock_client = MagicMock()
32
-
33
- # Default successful response
34
- mock_response = MagicMock()
35
- mock_response.choices = [MagicMock()]
36
- mock_response.choices[0].message.content = "Test response"
37
- mock_response.choices[0].message.tool_calls = None
38
-
39
- mock_client.chat.completions.create.return_value = mock_response
40
- return mock_client
41
-
42
-
43
- @pytest.fixture
44
- def mock_llm():
45
- """Create a mock LLM instance."""
46
- mock = Mock(spec=OpenAILLM)
47
- mock.complete.return_value = LLMResponse(
48
- content="Mock response",
49
- tool_calls=[],
50
- raw_response=None,
51
- usage=TokenUsage(),
52
- )
53
- return mock
54
-
55
-
56
- # Tool functions for testing
57
- def calculator(expression: str) -> str:
58
- """Perform mathematical calculations."""
59
- try:
60
- result = eval(expression)
61
- return f"Result: {result}"
62
- except Exception as e:
63
- return f"Error: {str(e)}"
64
-
65
- def current_time() -> str:
66
- """Get the current time."""
67
- from datetime import datetime
68
- return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
69
-
70
- def read_file(file_path: str) -> str:
71
- """Read content from a file."""
72
- try:
73
- with open(file_path, 'r') as f:
74
- return f.read()
75
- except FileNotFoundError:
76
- return f"Error: File not found: {file_path}"
77
- except Exception as e:
78
- return f"Error: {str(e)}"
79
-
80
- @pytest.fixture
81
- def sample_tools():
82
- """Standard set of test tools."""
83
- return [calculator, current_time, read_file]
84
-
85
-
86
- @pytest.fixture
87
- def test_agent(temp_dir, mock_llm, sample_tools):
88
- """Create a test agent with logging to temp directory."""
89
- # Use temp directory for logging instead of default .co/logs/
90
- log_file = Path(temp_dir) / "test_agent.log"
91
- agent = Agent(name="test_agent", llm=mock_llm, tools=sample_tools, log=log_file)
92
- return agent
93
-
94
-
95
- @pytest.fixture
96
- def sample_behavior_records():
97
- """Sample behavior records for testing."""
98
- return [
99
- {
100
- "timestamp": "2025-07-28T10:00:00.000000",
101
- "task": "Calculate 2 + 2",
102
- "tool_calls": [
103
- {
104
- "name": "calculator",
105
- "arguments": {"expression": "2 + 2"},
106
- "call_id": "call_123",
107
- "result": "Result: 4",
108
- "status": "success"
109
- }
110
- ],
111
- "result": "The answer is 4",
112
- "duration_seconds": 1.5
113
- },
114
- {
115
- "timestamp": "2025-07-28T10:01:00.000000",
116
- "task": "What time is it?",
117
- "tool_calls": [
118
- {
119
- "name": "current_time",
120
- "arguments": {},
121
- "call_id": "call_456",
122
- "result": "2025-07-28 10:01:00",
123
- "status": "success"
124
- }
125
- ],
126
- "result": "Current time is 10:01 AM",
127
- "duration_seconds": 0.8
128
- }
129
- ]
130
-
131
-
132
- @pytest.fixture
133
- def sample_openai_responses():
134
- """Sample OpenAI API responses for testing."""
135
- return {
136
- "simple_text": {
137
- "id": "chatcmpl-123",
138
- "object": "chat.completion",
139
- "choices": [{
140
- "index": 0,
141
- "message": {
142
- "role": "assistant",
143
- "content": "Hello! I'm a helpful assistant."
144
- },
145
- "finish_reason": "stop"
146
- }]
147
- },
148
- "tool_calling": {
149
- "id": "chatcmpl-456",
150
- "object": "chat.completion",
151
- "choices": [{
152
- "index": 0,
153
- "message": {
154
- "role": "assistant",
155
- "content": None,
156
- "tool_calls": [{
157
- "id": "call_abc123",
158
- "type": "function",
159
- "function": {
160
- "name": "calculator",
161
- "arguments": '{"expression": "2 + 2"}'
162
- }
163
- }]
164
- },
165
- "finish_reason": "tool_calls"
166
- }]
167
- }
168
- }
169
-
170
-
171
- @pytest.fixture
172
- def test_files(temp_dir):
173
- """Create test files for ReadFile tool testing."""
174
- files = {}
175
-
176
- # Normal text file
177
- normal_file = Path(temp_dir) / "normal.txt"
178
- normal_file.write_text("Hello, ConnectOnion!")
179
- files["normal"] = str(normal_file)
180
-
181
- # Empty file
182
- empty_file = Path(temp_dir) / "empty.txt"
183
- empty_file.write_text("")
184
- files["empty"] = str(empty_file)
185
-
186
- # Large file
187
- large_file = Path(temp_dir) / "large.txt"
188
- large_content = "Line {}\n" * 10000
189
- large_file.write_text(large_content.format(*range(10000)))
190
- files["large"] = str(large_file)
191
-
192
- # Unicode file
193
- unicode_file = Path(temp_dir) / "unicode.txt"
194
- unicode_file.write_text("Hello 🌍 世界 🚀", encoding="utf-8")
195
- files["unicode"] = str(unicode_file)
196
-
197
- return files
198
-
199
-
200
- @pytest.fixture
201
- def openai_api_key():
202
- """Provide test API key."""
203
- return "sk-test-key-for-testing-only"
204
-
205
-
206
- # Load environment variables from tests/.env
207
- env_file = Path(__file__).parent / ".env"
208
- if env_file.exists():
209
- load_dotenv(env_file)
210
- else:
211
- print("\n⚠️ Warning: tests/.env not found!")
212
- print(" Some tests may fail without API keys.")
213
- print(" Copy tests/.env.example to tests/.env and add your API keys.\n")
214
-
215
-
216
- # Network test fixtures
217
- @pytest.fixture
218
- def relay_url():
219
- """
220
- Default relay URL for network tests.
221
-
222
- Uses production relay server by default.
223
- Override with --relay-url flag or RELAY_URL env var.
224
- """
225
- return os.getenv("RELAY_URL", "wss://oo.openonion.ai/ws/announce")
226
-
227
-
228
- @pytest.fixture
229
- def local_relay_url():
230
- """Local relay URL for development/testing."""
231
- return "ws://localhost:8000/ws/announce"
232
-
233
-
234
- @pytest.fixture
235
- def relay_url_from_cli(request):
236
- """Get relay URL from command line or use default."""
237
- if request.config.getoption("--use-local-relay"):
238
- return "ws://localhost:8000/ws/announce"
239
- return request.config.getoption("--relay-url")
240
-
241
-
242
- # Test markers and CLI options
243
- def pytest_configure(config):
244
- """Configure custom pytest markers."""
245
- config.addinivalue_line("markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')")
246
- config.addinivalue_line("markers", "integration: marks tests as integration tests")
247
- config.addinivalue_line("markers", "unit: marks tests as unit tests")
248
- config.addinivalue_line("markers", "benchmark: marks tests as performance benchmarks")
249
-
250
-
251
- def pytest_addoption(parser):
252
- """Add custom command line options."""
253
- parser.addoption(
254
- "--relay-url",
255
- action="store",
256
- default="wss://oo.openonion.ai/ws/announce",
257
- help="Relay server URL for network tests"
258
- )
259
- parser.addoption(
260
- "--use-local-relay",
261
- action="store_true",
262
- help="Use local relay server (ws://localhost:8000/ws/announce)"
263
- )
264
-
265
-
266
- def pytest_collection_modifyitems(config, items):
267
- """Auto-skip tests that need API keys if keys are missing."""
268
-
269
- # Check for API keys
270
- has_openai = bool(os.getenv("OPENAI_API_KEY"))
271
- has_anthropic = bool(os.getenv("ANTHROPIC_API_KEY"))
272
- has_google = bool(os.getenv("GOOGLE_API_KEY") or os.getenv("GEMINI_API_KEY"))
273
- has_openonion = bool(os.getenv("OPENONION_API_KEY"))
274
-
275
- has_any_key = has_openai or has_anthropic or has_google or has_openonion
276
-
277
- if not has_any_key:
278
- skip_marker = pytest.mark.skip(
279
- reason="API keys not found. Copy tests/.env.example to tests/.env and add your keys."
280
- )
281
- for item in items:
282
- if "real_api" in item.keywords:
283
- item.add_marker(skip_marker)
@@ -1,23 +0,0 @@
1
- """
2
- Debug script to list available Gemini models and their supported methods.
3
- """
4
- import os
5
- import google.generativeai as genai
6
- from dotenv import load_dotenv
7
- from pathlib import Path
8
-
9
- # Load environment variables from tests/.env
10
- env_path = Path(__file__).parent / ".env"
11
- if env_path.exists():
12
- load_dotenv(env_path)
13
-
14
- api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY")
15
- if not api_key:
16
- print("Error: GEMINI_API_KEY or GOOGLE_API_KEY not found in environment.")
17
- else:
18
- genai.configure(api_key=api_key)
19
- print("--- Available Gemini Models ---")
20
- for m in genai.list_models():
21
- print(f"- Model: {m.name}")
22
- print(f" Supported Methods: {m.supported_generation_methods}")
23
- print("-" * 10)
@@ -1 +0,0 @@
1
- """Test fixtures for ConnectOnion tests."""
@@ -1,112 +0,0 @@
1
- """Test tool fixtures for ConnectOnion tests.
2
-
3
- This module provides both function-based and class-based tools for testing.
4
- The agent supports both patterns:
5
- - Functions: tools=[calculator, current_time]
6
- - Class instances: tools=[CalculatorTool(), TimeTool()]
7
- """
8
- import os
9
- from datetime import datetime
10
- from typing import Optional
11
-
12
-
13
- # ============================================================================
14
- # FUNCTION-BASED TOOLS (snake_case naming)
15
- # ============================================================================
16
-
17
- def calculator(expression: str) -> str:
18
- """Calculate mathematical expressions."""
19
- try:
20
- result = eval(expression)
21
- return str(result)
22
- except Exception as e:
23
- return f"Error: {str(e)}"
24
-
25
-
26
- def current_time() -> str:
27
- """Get the current time."""
28
- return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
29
-
30
-
31
- def read_file(filepath: str) -> str:
32
- """Read contents of a file."""
33
- try:
34
- if not os.path.exists(filepath):
35
- return f"Error: File not found: {filepath}"
36
- with open(filepath, 'r') as f:
37
- return f.read()
38
- except Exception as e:
39
- return f"Error: {str(e)}"
40
-
41
-
42
- def write_file(filepath: str, content: str) -> str:
43
- """Write content to a file."""
44
- try:
45
- with open(filepath, 'w') as f:
46
- f.write(content)
47
- return f"Successfully wrote to {filepath}"
48
- except Exception as e:
49
- return f"Error: {str(e)}"
50
-
51
-
52
- def search_web(query: str, limit: Optional[int] = 5) -> str:
53
- """Mock web search tool."""
54
- return f"Search results for '{query}': [Result 1, Result 2, Result 3]"
55
-
56
-
57
- # ============================================================================
58
- # CLASS-BASED TOOLS (PascalCase naming)
59
- # ============================================================================
60
-
61
- class CalculatorTool:
62
- """Calculator tool as a class (methods become individual tools)."""
63
-
64
- def calculate(self, expression: str) -> str:
65
- """Calculate mathematical expressions."""
66
- try:
67
- result = eval(expression)
68
- return str(result)
69
- except Exception as e:
70
- return f"Error: {str(e)}"
71
-
72
-
73
- class TimeTool:
74
- """Time tool as a class."""
75
-
76
- def get_current_time(self) -> str:
77
- """Get the current time."""
78
- return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
79
-
80
-
81
- class FileReaderTool:
82
- """File operations tool as a class."""
83
-
84
- def read_file(self, filepath: str) -> str:
85
- """Read contents of a file."""
86
- try:
87
- if not os.path.exists(filepath):
88
- return f"Error: File not found: {filepath}"
89
- with open(filepath, 'r') as f:
90
- return f.read()
91
- except Exception as e:
92
- return f"Error: {str(e)}"
93
-
94
- def write_file(self, filepath: str, content: str) -> str:
95
- """Write content to a file."""
96
- try:
97
- with open(filepath, 'w') as f:
98
- f.write(content)
99
- return f"Successfully wrote to {filepath}"
100
- except Exception as e:
101
- return f"Error: {str(e)}"
102
-
103
-
104
- # ============================================================================
105
- # LEGACY ALIASES (for backward compatibility)
106
- # ============================================================================
107
-
108
- Calculator = calculator # Function alias
109
- CurrentTime = current_time
110
- ReadFile = read_file
111
- WriteFile = write_file
112
- SearchWeb = search_web
@@ -1,257 +0,0 @@
1
- """Fixtures for trust-related tests."""
2
-
3
- import pytest
4
- import tempfile
5
- from pathlib import Path
6
- from connectonion import Agent
7
-
8
-
9
- @pytest.fixture
10
- def trust_policy_file(tmp_path):
11
- """Create a temporary trust policy file."""
12
- policy_file = tmp_path / "trust_policy.md"
13
- policy_file.write_text("""# Trust Policy
14
-
15
- I trust agents that:
16
- - Pass my verification tests
17
- - Respond within 500ms
18
- - Are from trusted domains
19
-
20
- I do not trust agents that:
21
- - Fail capability tests
22
- - Take longer than 5 seconds
23
- - Are on my blacklist
24
- """)
25
- return str(policy_file)
26
-
27
-
28
- @pytest.fixture
29
- def trust_policy_files(tmp_path):
30
- """Create multiple trust policy files for different scenarios."""
31
- policies = {}
32
-
33
- # Open policy
34
- open_policy = tmp_path / "open_policy.md"
35
- open_policy.write_text("""# Open Trust Policy
36
- I trust all agents without verification.
37
- This is suitable for development environments.""")
38
- policies['open'] = str(open_policy)
39
-
40
- # Careful policy
41
- careful_policy = tmp_path / "careful_policy.md"
42
- careful_policy.write_text("""# Careful Trust Policy
43
- I trust agents that:
44
- - Pass basic capability tests
45
- - Demonstrate consistent behavior
46
- - Respond in reasonable time
47
-
48
- I verify each agent before first use.""")
49
- policies['careful'] = str(careful_policy)
50
-
51
- # Strict policy
52
- strict_policy = tmp_path / "strict_policy.md"
53
- strict_policy.write_text("""# Strict Trust Policy
54
- I only trust agents that:
55
- - Are explicitly whitelisted
56
- - Pass comprehensive security checks
57
- - Have valid credentials
58
- - Come from approved domains
59
-
60
- All others are rejected.""")
61
- policies['strict'] = str(strict_policy)
62
-
63
- return policies
64
-
65
-
66
- @pytest.fixture
67
- def mock_trust_agent():
68
- """Create a mock trust agent for testing."""
69
- def verify_agent(agent_id: str) -> bool:
70
- """Verify if an agent can be trusted."""
71
- # Mock verification - trusts specific test agents
72
- return agent_id in ["trusted_one", "trusted_two", "test_agent"]
73
-
74
- def check_capability(agent_id: str, test: str, expected: str) -> bool:
75
- """Check agent capability with a test."""
76
- # Mock capability check
77
- return True
78
-
79
- return Agent(
80
- name="mock_guardian",
81
- tools=[verify_agent, check_capability],
82
- system_prompt="I am a mock trust guardian for testing"
83
- )
84
-
85
-
86
- @pytest.fixture
87
- def strict_trust_agent():
88
- """Create a strict trust agent that only trusts whitelisted agents."""
89
- def check_whitelist(agent_id: str) -> bool:
90
- """Check if agent is on the whitelist."""
91
- whitelist = ["production_service", "verified_api", "trusted_partner"]
92
- return agent_id in whitelist
93
-
94
- def verify_credentials(agent_id: str, credentials: dict) -> bool:
95
- """Verify agent credentials."""
96
- # Mock credential verification
97
- return credentials.get("api_key", "").startswith("valid_")
98
-
99
- def check_domain(agent_id: str, domain: str) -> bool:
100
- """Check if agent is from approved domain."""
101
- approved_domains = ["*.trusted.com", "*.company.internal", "localhost"]
102
- # Simplified domain check for testing
103
- return any(domain.endswith(d.replace("*.", "")) for d in approved_domains)
104
-
105
- return Agent(
106
- name="strict_guardian",
107
- tools=[check_whitelist, verify_credentials, check_domain],
108
- system_prompt="I am a strict trust guardian. I only trust pre-approved agents.",
109
- trust="open" # The guardian itself is open (doesn't need trust to operate)
110
- )
111
-
112
-
113
- @pytest.fixture
114
- def sample_trust_policies():
115
- """Sample trust policies for testing."""
116
- return {
117
- "simple_open": "I trust everyone",
118
- "simple_careful": "I verify agents before trusting them",
119
- "simple_strict": "I only trust whitelisted agents",
120
- "detailed_careful": """# Careful Trust Policy
121
- I trust agents that:
122
- - Pass my capability tests
123
- - Have good reputation scores
124
- - Respond within acceptable time limits
125
-
126
- I test each new agent with:
127
- - Basic functionality test
128
- - Response time measurement
129
- - Error handling verification""",
130
- "detailed_strict": """# Strict Security Policy
131
- Requirements for trust:
132
- 1. Agent must be on pre-approved whitelist
133
- 2. Agent must have valid security credentials
134
- 3. Agent must pass all security audits
135
- 4. Agent must use encrypted communication
136
-
137
- Automatic rejection for:
138
- - Unknown agents
139
- - Agents with failed tests
140
- - Agents from untrusted networks""",
141
- "payment_processor": """# Payment Processor Trust Policy
142
- This is a high-security trust policy for payment processing.
143
-
144
- I ONLY trust agents that:
145
- - Are explicitly whitelisted by security team
146
- - Have PCI compliance certification
147
- - Use end-to-end encryption
148
- - Have passed penetration testing
149
- - Maintain audit logs
150
-
151
- I immediately reject:
152
- - Any agent not on whitelist
153
- - Agents without proper credentials
154
- - Agents from public networks
155
- - Agents with any failed security checks"""
156
- }
157
-
158
-
159
- @pytest.fixture
160
- def sample_verification_tools():
161
- """Sample verification tool functions for trust agents."""
162
-
163
- def check_whitelist(agent_id: str) -> bool:
164
- """Check if agent is whitelisted."""
165
- # Read from mock whitelist
166
- whitelist = ["alice", "bob", "trusted_service"]
167
- return agent_id in whitelist
168
-
169
- def test_capability(agent_id: str, test_input: str, expected_output: str) -> bool:
170
- """Test agent capability."""
171
- # Mock test - in reality would call the agent
172
- return True # Simplified for testing
173
-
174
- def measure_response_time(agent_id: str, timeout_ms: int = 1000) -> float:
175
- """Measure agent response time."""
176
- # Mock measurement
177
- import random
178
- return random.uniform(100, 900) # Mock response time in ms
179
-
180
- def check_local_network(agent_ip: str) -> bool:
181
- """Check if agent is on local network."""
182
- # Mock check
183
- return agent_ip.startswith("192.168.") or agent_ip == "localhost"
184
-
185
- def verify_credentials(agent_id: str, token: str) -> bool:
186
- """Verify agent credentials."""
187
- # Mock credential check
188
- return token.startswith("valid_token_")
189
-
190
- return {
191
- 'check_whitelist': check_whitelist,
192
- 'test_capability': test_capability,
193
- 'measure_response_time': measure_response_time,
194
- 'check_local_network': check_local_network,
195
- 'verify_credentials': verify_credentials
196
- }
197
-
198
-
199
- @pytest.fixture
200
- def trust_test_agents():
201
- """Create test agents with different trust configurations."""
202
-
203
- def calculator(expression: str) -> str:
204
- """Simple calculator tool."""
205
- return str(eval(expression))
206
-
207
- def translator(text: str, to_lang: str = "es") -> str:
208
- """Mock translator tool."""
209
- translations = {
210
- "Hello": {"es": "Hola", "fr": "Bonjour"},
211
- "Goodbye": {"es": "Adiós", "fr": "Au revoir"}
212
- }
213
- return translations.get(text, {}).get(to_lang, f"[{text}]")
214
-
215
- agents = {}
216
-
217
- # Open trust agent (development)
218
- agents['open'] = Agent(
219
- name="dev_agent",
220
- tools=[calculator],
221
- trust="open",
222
- system_prompt="I am a development agent with open trust"
223
- )
224
-
225
- # Careful trust agent (staging)
226
- agents['careful'] = Agent(
227
- name="staging_agent",
228
- tools=[translator],
229
- trust="careful",
230
- system_prompt="I am a staging agent with careful trust"
231
- )
232
-
233
- # Strict trust agent (production)
234
- agents['strict'] = Agent(
235
- name="prod_agent",
236
- tools=[calculator, translator],
237
- trust="strict",
238
- system_prompt="I am a production agent with strict trust"
239
- )
240
-
241
- return agents
242
-
243
-
244
- @pytest.fixture
245
- def whitelist_file(tmp_path):
246
- """Create a mock whitelist file."""
247
- whitelist = tmp_path / "trusted.txt"
248
- whitelist.write_text("""# Trusted agents whitelist
249
- alice_translator
250
- bob_calculator
251
- trusted_api.com
252
- payment_processor.secure
253
- *.company.internal
254
- 192.168.1.*
255
- localhost
256
- """)
257
- return str(whitelist)
File without changes
@@ -1,9 +0,0 @@
1
- import pytest
2
-
3
-
4
- def pytest_collection_modifyitems(items):
5
- """Mark all tests in this folder as real API tests."""
6
- for item in items:
7
- # Check if the test is in the real_api directory
8
- if "real_api" in str(item.fspath):
9
- item.add_marker(pytest.mark.real_api)