jarviscore-framework 0.3.1__py3-none-any.whl → 0.3.2__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 (31) hide show
  1. examples/customagent_cognitive_discovery_example.py +49 -8
  2. examples/customagent_distributed_example.py +140 -1
  3. examples/fastapi_integration_example.py +70 -7
  4. jarviscore/__init__.py +1 -1
  5. jarviscore/core/mesh.py +149 -0
  6. jarviscore/data/examples/customagent_cognitive_discovery_example.py +49 -8
  7. jarviscore/data/examples/customagent_distributed_example.py +140 -1
  8. jarviscore/data/examples/fastapi_integration_example.py +70 -7
  9. jarviscore/docs/API_REFERENCE.md +547 -5
  10. jarviscore/docs/CHANGELOG.md +89 -0
  11. jarviscore/docs/CONFIGURATION.md +1 -1
  12. jarviscore/docs/CUSTOMAGENT_GUIDE.md +347 -2
  13. jarviscore/docs/TROUBLESHOOTING.md +1 -1
  14. jarviscore/docs/USER_GUIDE.md +286 -5
  15. jarviscore/p2p/coordinator.py +36 -7
  16. jarviscore/p2p/messages.py +13 -0
  17. jarviscore/p2p/peer_client.py +355 -23
  18. jarviscore/p2p/peer_tool.py +17 -11
  19. jarviscore/profiles/customagent.py +9 -2
  20. jarviscore/testing/__init__.py +35 -0
  21. jarviscore/testing/mocks.py +578 -0
  22. {jarviscore_framework-0.3.1.dist-info → jarviscore_framework-0.3.2.dist-info}/METADATA +2 -2
  23. {jarviscore_framework-0.3.1.dist-info → jarviscore_framework-0.3.2.dist-info}/RECORD +31 -24
  24. tests/test_17_session_context.py +489 -0
  25. tests/test_18_mesh_diagnostics.py +465 -0
  26. tests/test_19_async_requests.py +516 -0
  27. tests/test_20_load_balancing.py +546 -0
  28. tests/test_21_mock_testing.py +776 -0
  29. {jarviscore_framework-0.3.1.dist-info → jarviscore_framework-0.3.2.dist-info}/WHEEL +0 -0
  30. {jarviscore_framework-0.3.1.dist-info → jarviscore_framework-0.3.2.dist-info}/licenses/LICENSE +0 -0
  31. {jarviscore_framework-0.3.1.dist-info → jarviscore_framework-0.3.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,465 @@
1
+ """
2
+ Test 18: Mesh Diagnostics (Feature F5)
3
+
4
+ Tests the mesh.get_diagnostics() method:
5
+ - Diagnostics before mesh.start()
6
+ - Diagnostics in autonomous mode
7
+ - Diagnostics in P2P mode
8
+ - Connectivity status values
9
+ - Local agents structure
10
+
11
+ Run with: pytest tests/test_18_mesh_diagnostics.py -v -s
12
+ """
13
+ import asyncio
14
+ import sys
15
+ import pytest
16
+ import logging
17
+ from unittest.mock import MagicMock, patch
18
+
19
+ sys.path.insert(0, '.')
20
+
21
+ # Setup logging
22
+ logging.basicConfig(level=logging.INFO)
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ # =============================================================================
27
+ # TEST: DIAGNOSTICS STRUCTURE
28
+ # =============================================================================
29
+
30
+ class TestDiagnosticsStructure:
31
+ """Test diagnostics returns expected structure."""
32
+
33
+ @pytest.mark.asyncio
34
+ async def test_diagnostics_has_required_keys(self):
35
+ """Test diagnostics contains all required top-level keys."""
36
+ from jarviscore import Mesh
37
+ from jarviscore.profiles import CustomAgent
38
+
39
+ class TestAgent(CustomAgent):
40
+ role = "test_agent"
41
+ capabilities = ["testing"]
42
+
43
+ async def on_peer_request(self, msg):
44
+ return {}
45
+
46
+ mesh = Mesh(mode="autonomous")
47
+ mesh.add(TestAgent)
48
+ await mesh.start()
49
+
50
+ try:
51
+ diag = mesh.get_diagnostics()
52
+
53
+ assert "local_node" in diag
54
+ assert "known_peers" in diag
55
+ assert "local_agents" in diag
56
+ assert "connectivity_status" in diag
57
+ finally:
58
+ await mesh.stop()
59
+
60
+ @pytest.mark.asyncio
61
+ async def test_local_node_structure(self):
62
+ """Test local_node contains expected fields."""
63
+ from jarviscore import Mesh
64
+ from jarviscore.profiles import CustomAgent
65
+
66
+ class TestAgent(CustomAgent):
67
+ role = "node_test"
68
+ capabilities = ["testing"]
69
+
70
+ async def on_peer_request(self, msg):
71
+ return {}
72
+
73
+ mesh = Mesh(mode="autonomous")
74
+ mesh.add(TestAgent)
75
+ await mesh.start()
76
+
77
+ try:
78
+ diag = mesh.get_diagnostics()
79
+ local_node = diag["local_node"]
80
+
81
+ assert "mode" in local_node
82
+ assert "started" in local_node
83
+ assert "agent_count" in local_node
84
+ assert local_node["mode"] == "autonomous"
85
+ assert local_node["started"] is True
86
+ assert local_node["agent_count"] == 1
87
+ finally:
88
+ await mesh.stop()
89
+
90
+ @pytest.mark.asyncio
91
+ async def test_local_agents_structure(self):
92
+ """Test local_agents contains proper agent info."""
93
+ from jarviscore import Mesh
94
+ from jarviscore.profiles import CustomAgent
95
+
96
+ class AgentA(CustomAgent):
97
+ role = "agent_a"
98
+ capabilities = ["cap_a", "shared"]
99
+
100
+ async def on_peer_request(self, msg):
101
+ return {}
102
+
103
+ class AgentB(CustomAgent):
104
+ role = "agent_b"
105
+ capabilities = ["cap_b", "shared"]
106
+
107
+ async def on_peer_request(self, msg):
108
+ return {}
109
+
110
+ mesh = Mesh(mode="autonomous")
111
+ mesh.add(AgentA)
112
+ mesh.add(AgentB)
113
+ await mesh.start()
114
+
115
+ try:
116
+ diag = mesh.get_diagnostics()
117
+ agents = diag["local_agents"]
118
+
119
+ assert len(agents) == 2
120
+
121
+ roles = {a["role"] for a in agents}
122
+ assert "agent_a" in roles
123
+ assert "agent_b" in roles
124
+
125
+ for agent in agents:
126
+ assert "role" in agent
127
+ assert "agent_id" in agent
128
+ assert "capabilities" in agent
129
+ finally:
130
+ await mesh.stop()
131
+
132
+
133
+ # =============================================================================
134
+ # TEST: DIAGNOSTICS BEFORE START
135
+ # =============================================================================
136
+
137
+ class TestDiagnosticsBeforeStart:
138
+ """Test diagnostics behavior before mesh.start()."""
139
+
140
+ def test_diagnostics_before_start_returns_not_started(self):
141
+ """Test connectivity_status is 'not_started' before start()."""
142
+ from jarviscore import Mesh
143
+ from jarviscore.profiles import CustomAgent
144
+
145
+ class TestAgent(CustomAgent):
146
+ role = "pre_start"
147
+ capabilities = ["testing"]
148
+
149
+ async def on_peer_request(self, msg):
150
+ return {}
151
+
152
+ mesh = Mesh(mode="autonomous")
153
+ mesh.add(TestAgent)
154
+
155
+ diag = mesh.get_diagnostics()
156
+
157
+ assert diag["connectivity_status"] == "not_started"
158
+ assert diag["local_node"]["started"] is False
159
+
160
+ def test_diagnostics_before_start_shows_registered_agents(self):
161
+ """Test local_agents shows registered agents even before start."""
162
+ from jarviscore import Mesh
163
+ from jarviscore.profiles import CustomAgent
164
+
165
+ class TestAgent(CustomAgent):
166
+ role = "registered"
167
+ capabilities = ["cap1", "cap2"]
168
+
169
+ async def on_peer_request(self, msg):
170
+ return {}
171
+
172
+ mesh = Mesh(mode="autonomous")
173
+ mesh.add(TestAgent)
174
+
175
+ diag = mesh.get_diagnostics()
176
+
177
+ assert len(diag["local_agents"]) == 1
178
+ assert diag["local_agents"][0]["role"] == "registered"
179
+
180
+
181
+ # =============================================================================
182
+ # TEST: CONNECTIVITY STATUS VALUES
183
+ # =============================================================================
184
+
185
+ class TestConnectivityStatus:
186
+ """Test connectivity_status values."""
187
+
188
+ @pytest.mark.asyncio
189
+ async def test_autonomous_mode_local_only(self):
190
+ """Test autonomous mode reports 'local_only' status."""
191
+ from jarviscore import Mesh
192
+ from jarviscore.profiles import CustomAgent
193
+
194
+ class TestAgent(CustomAgent):
195
+ role = "local_agent"
196
+ capabilities = ["testing"]
197
+
198
+ async def on_peer_request(self, msg):
199
+ return {}
200
+
201
+ mesh = Mesh(mode="autonomous")
202
+ mesh.add(TestAgent)
203
+ await mesh.start()
204
+
205
+ try:
206
+ diag = mesh.get_diagnostics()
207
+ # Autonomous mode without P2P coordinator should be local_only
208
+ assert diag["connectivity_status"] in ["local_only", "healthy"]
209
+ finally:
210
+ await mesh.stop()
211
+
212
+ def test_not_started_status(self):
213
+ """Test 'not_started' status before mesh.start()."""
214
+ from jarviscore import Mesh
215
+
216
+ mesh = Mesh(mode="autonomous")
217
+ diag = mesh.get_diagnostics()
218
+
219
+ assert diag["connectivity_status"] == "not_started"
220
+
221
+
222
+ # =============================================================================
223
+ # TEST: MOCK MESH DIAGNOSTICS
224
+ # =============================================================================
225
+
226
+ class TestMockMeshDiagnostics:
227
+ """Test MockMesh.get_diagnostics() compatibility."""
228
+
229
+ @pytest.mark.asyncio
230
+ async def test_mock_mesh_diagnostics_structure(self):
231
+ """Test MockMesh returns compatible diagnostics structure."""
232
+ from jarviscore.testing import MockMesh
233
+ from jarviscore.profiles import CustomAgent
234
+
235
+ class TestAgent(CustomAgent):
236
+ role = "mock_agent"
237
+ capabilities = ["mock_cap"]
238
+
239
+ async def on_peer_request(self, msg):
240
+ return {}
241
+
242
+ mesh = MockMesh()
243
+ mesh.add(TestAgent)
244
+ await mesh.start()
245
+
246
+ try:
247
+ diag = mesh.get_diagnostics()
248
+
249
+ assert "local_node" in diag
250
+ assert "known_peers" in diag
251
+ assert "local_agents" in diag
252
+ assert "connectivity_status" in diag
253
+ finally:
254
+ await mesh.stop()
255
+
256
+ @pytest.mark.asyncio
257
+ async def test_mock_mesh_diagnostics_status(self):
258
+ """Test MockMesh returns 'mock' connectivity status."""
259
+ from jarviscore.testing import MockMesh
260
+ from jarviscore.profiles import CustomAgent
261
+
262
+ class TestAgent(CustomAgent):
263
+ role = "mock_agent"
264
+ capabilities = ["testing"]
265
+
266
+ async def on_peer_request(self, msg):
267
+ return {}
268
+
269
+ mesh = MockMesh()
270
+ mesh.add(TestAgent)
271
+ await mesh.start()
272
+
273
+ try:
274
+ diag = mesh.get_diagnostics()
275
+ assert diag["connectivity_status"] == "mock"
276
+ finally:
277
+ await mesh.stop()
278
+
279
+ @pytest.mark.asyncio
280
+ async def test_mock_mesh_local_agents_info(self):
281
+ """Test MockMesh diagnostics includes agent capabilities."""
282
+ from jarviscore.testing import MockMesh
283
+ from jarviscore.profiles import CustomAgent
284
+
285
+ class AgentWithCaps(CustomAgent):
286
+ role = "capable"
287
+ capabilities = ["analysis", "reporting", "storage"]
288
+
289
+ async def on_peer_request(self, msg):
290
+ return {}
291
+
292
+ mesh = MockMesh()
293
+ mesh.add(AgentWithCaps)
294
+ await mesh.start()
295
+
296
+ try:
297
+ diag = mesh.get_diagnostics()
298
+ agents = diag["local_agents"]
299
+
300
+ assert len(agents) == 1
301
+ assert agents[0]["role"] == "capable"
302
+ assert set(agents[0]["capabilities"]) == {"analysis", "reporting", "storage"}
303
+ finally:
304
+ await mesh.stop()
305
+
306
+
307
+ # =============================================================================
308
+ # TEST: DIAGNOSTICS WITH MULTIPLE MODES
309
+ # =============================================================================
310
+
311
+ class TestDiagnosticsWithModes:
312
+ """Test diagnostics in different mesh modes."""
313
+
314
+ @pytest.mark.asyncio
315
+ async def test_diagnostics_autonomous_mode(self):
316
+ """Test diagnostics in autonomous mode."""
317
+ from jarviscore import Mesh
318
+ from jarviscore.profiles import CustomAgent
319
+
320
+ class TestAgent(CustomAgent):
321
+ role = "auto_agent"
322
+ capabilities = ["auto"]
323
+
324
+ async def on_peer_request(self, msg):
325
+ return {}
326
+
327
+ mesh = Mesh(mode="autonomous")
328
+ mesh.add(TestAgent)
329
+ await mesh.start()
330
+
331
+ try:
332
+ diag = mesh.get_diagnostics()
333
+ assert diag["local_node"]["mode"] == "autonomous"
334
+ finally:
335
+ await mesh.stop()
336
+
337
+ @pytest.mark.asyncio
338
+ async def test_diagnostics_distributed_mode(self):
339
+ """Test diagnostics in distributed mode."""
340
+ from jarviscore import Mesh
341
+ from jarviscore.profiles import CustomAgent
342
+
343
+ class TestAgent(CustomAgent):
344
+ role = "dist_agent"
345
+ capabilities = ["distributed"]
346
+
347
+ async def on_peer_request(self, msg):
348
+ return {}
349
+
350
+ mesh = Mesh(mode="distributed", config={
351
+ "bind_host": "127.0.0.1",
352
+ "bind_port": 7950
353
+ })
354
+ mesh.add(TestAgent)
355
+ await mesh.start()
356
+
357
+ try:
358
+ diag = mesh.get_diagnostics()
359
+ assert diag["local_node"]["mode"] == "distributed"
360
+ # P2P mode should include additional diagnostics
361
+ # Note: keepalive_status may not be present depending on config
362
+ finally:
363
+ await mesh.stop()
364
+
365
+ @pytest.mark.asyncio
366
+ async def test_diagnostics_p2p_mode(self):
367
+ """Test diagnostics in p2p mode."""
368
+ from jarviscore import Mesh
369
+ from jarviscore.profiles import CustomAgent
370
+
371
+ class TestAgent(CustomAgent):
372
+ role = "p2p_agent"
373
+ capabilities = ["p2p"]
374
+
375
+ async def on_peer_request(self, msg):
376
+ return {}
377
+
378
+ mesh = Mesh(mode="p2p", config={
379
+ "bind_host": "127.0.0.1",
380
+ "bind_port": 7951
381
+ })
382
+ mesh.add(TestAgent)
383
+ await mesh.start()
384
+
385
+ try:
386
+ diag = mesh.get_diagnostics()
387
+ assert diag["local_node"]["mode"] == "p2p"
388
+ finally:
389
+ await mesh.stop()
390
+
391
+
392
+ # =============================================================================
393
+ # TEST: DIAGNOSTICS AGENT COUNT
394
+ # =============================================================================
395
+
396
+ class TestDiagnosticsAgentCount:
397
+ """Test agent count accuracy in diagnostics."""
398
+
399
+ @pytest.mark.asyncio
400
+ async def test_agent_count_single(self):
401
+ """Test agent_count with single agent."""
402
+ from jarviscore import Mesh
403
+ from jarviscore.profiles import CustomAgent
404
+
405
+ class TestAgent(CustomAgent):
406
+ role = "single"
407
+ capabilities = ["testing"]
408
+
409
+ async def on_peer_request(self, msg):
410
+ return {}
411
+
412
+ mesh = Mesh(mode="autonomous")
413
+ mesh.add(TestAgent)
414
+ await mesh.start()
415
+
416
+ try:
417
+ diag = mesh.get_diagnostics()
418
+ assert diag["local_node"]["agent_count"] == 1
419
+ finally:
420
+ await mesh.stop()
421
+
422
+ @pytest.mark.asyncio
423
+ async def test_agent_count_multiple(self):
424
+ """Test agent_count with multiple agents."""
425
+ from jarviscore import Mesh
426
+ from jarviscore.profiles import CustomAgent
427
+
428
+ class Agent1(CustomAgent):
429
+ role = "agent1"
430
+ capabilities = ["cap1"]
431
+ async def on_peer_request(self, msg):
432
+ return {}
433
+
434
+ class Agent2(CustomAgent):
435
+ role = "agent2"
436
+ capabilities = ["cap2"]
437
+ async def on_peer_request(self, msg):
438
+ return {}
439
+
440
+ class Agent3(CustomAgent):
441
+ role = "agent3"
442
+ capabilities = ["cap3"]
443
+ async def on_peer_request(self, msg):
444
+ return {}
445
+
446
+ mesh = Mesh(mode="autonomous")
447
+ mesh.add(Agent1)
448
+ mesh.add(Agent2)
449
+ mesh.add(Agent3)
450
+ await mesh.start()
451
+
452
+ try:
453
+ diag = mesh.get_diagnostics()
454
+ assert diag["local_node"]["agent_count"] == 3
455
+ assert len(diag["local_agents"]) == 3
456
+ finally:
457
+ await mesh.stop()
458
+
459
+
460
+ # =============================================================================
461
+ # RUN TESTS
462
+ # =============================================================================
463
+
464
+ if __name__ == "__main__":
465
+ pytest.main([__file__, "-v", "-s"])