jarviscore-framework 0.3.0__tar.gz → 0.3.2__tar.gz
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.
- {jarviscore_framework-0.3.0/jarviscore_framework.egg-info → jarviscore_framework-0.3.2}/PKG-INFO +61 -46
- jarviscore_framework-0.3.2/README.md +147 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/cloud_deployment_example.py +3 -3
- jarviscore_framework-0.3.0/jarviscore/data/examples/listeneragent_cognitive_discovery_example.py → jarviscore_framework-0.3.2/examples/customagent_cognitive_discovery_example.py +55 -14
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/customagent_distributed_example.py +140 -1
- {jarviscore_framework-0.3.0/jarviscore/data → jarviscore_framework-0.3.2}/examples/fastapi_integration_example.py +74 -11
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/__init__.py +8 -11
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/cli/smoketest.py +1 -1
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/core/mesh.py +158 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/cloud_deployment_example.py +3 -3
- jarviscore_framework-0.3.2/jarviscore/data/examples/custom_profile_decorator.py +134 -0
- jarviscore_framework-0.3.2/jarviscore/data/examples/custom_profile_wrap.py +168 -0
- jarviscore_framework-0.3.0/examples/listeneragent_cognitive_discovery_example.py → jarviscore_framework-0.3.2/jarviscore/data/examples/customagent_cognitive_discovery_example.py +55 -14
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/customagent_distributed_example.py +140 -1
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2/jarviscore/data}/examples/fastapi_integration_example.py +74 -11
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/docs/API_REFERENCE.md +576 -47
- jarviscore_framework-0.3.2/jarviscore/docs/CHANGELOG.md +228 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/docs/CONFIGURATION.md +1 -1
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/docs/CUSTOMAGENT_GUIDE.md +591 -153
- jarviscore_framework-0.3.2/jarviscore/docs/GETTING_STARTED.md +657 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/docs/TROUBLESHOOTING.md +1 -1
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/docs/USER_GUIDE.md +292 -12
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/integrations/fastapi.py +4 -4
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/coordinator.py +36 -7
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/messages.py +13 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/peer_client.py +380 -21
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/peer_tool.py +17 -11
- jarviscore_framework-0.3.2/jarviscore/profiles/__init__.py +12 -0
- jarviscore_framework-0.3.0/jarviscore/profiles/listeneragent.py → jarviscore_framework-0.3.2/jarviscore/profiles/customagent.py +365 -292
- jarviscore_framework-0.3.2/jarviscore/testing/__init__.py +35 -0
- jarviscore_framework-0.3.2/jarviscore/testing/mocks.py +578 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2/jarviscore_framework.egg-info}/PKG-INFO +61 -46
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore_framework.egg-info/SOURCES.txt +11 -3
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore_framework.egg-info/requires.txt +2 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/pyproject.toml +3 -1
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_13_dx_improvements.py +37 -37
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_15_llm_cognitive_discovery.py +18 -18
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_16_unified_dx_flow.py +3 -3
- jarviscore_framework-0.3.2/tests/test_17_session_context.py +489 -0
- jarviscore_framework-0.3.2/tests/test_18_mesh_diagnostics.py +465 -0
- jarviscore_framework-0.3.2/tests/test_19_async_requests.py +516 -0
- jarviscore_framework-0.3.2/tests/test_20_load_balancing.py +546 -0
- jarviscore_framework-0.3.2/tests/test_21_mock_testing.py +776 -0
- jarviscore_framework-0.3.0/README.md +0 -134
- jarviscore_framework-0.3.0/jarviscore/docs/CHANGELOG.md +0 -97
- jarviscore_framework-0.3.0/jarviscore/docs/GETTING_STARTED.md +0 -800
- jarviscore_framework-0.3.0/jarviscore/profiles/__init__.py +0 -14
- jarviscore_framework-0.3.0/jarviscore/profiles/customagent.py +0 -137
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/.env.example +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/LICENSE +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/MANIFEST.in +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/autoagent_distributed_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/calculator_agent_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/custom_profile_decorator.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/custom_profile_wrap.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/customagent_p2p_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/multi_agent_workflow.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/research_agent_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/adapter/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/adapter/decorator.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/adapter/wrapper.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/cli/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/cli/__main__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/cli/check.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/cli/scaffold.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/config/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/config/settings.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/context/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/context/dependency.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/context/jarvis_context.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/context/memory.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/core/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/core/agent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/core/profile.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/.env.example +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/autoagent_distributed_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/calculator_agent_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/customagent_p2p_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/multi_agent_workflow.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/data/examples/research_agent_example.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/docs/AUTOAGENT_GUIDE.md +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/code_registry.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/generator.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/llm.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/repair.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/result_handler.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/sandbox.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/execution/search.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/integrations/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/orchestration/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/orchestration/claimer.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/orchestration/dependency.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/orchestration/engine.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/orchestration/status.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/__init__.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/broadcaster.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/keepalive.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/p2p/swim_manager.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore/profiles/autoagent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore_framework.egg-info/dependency_links.txt +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/jarviscore_framework.egg-info/top_level.txt +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/setup.cfg +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-558779ed_560ebc37.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-5ed3609e_560ebc37.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-66da0356_43970bb9.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-7a2fac83_583709d9.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-888b670f_aa235863.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-9ca5f642_aa235863.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-bfd90775_560ebc37.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-e95d2f7d_aa235863.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/data_generator-f60ca8a2_327eb8c2.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-02adf9ee_958658d9.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-0706fb57_5df13441.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-153c9c4a_ba59c918.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-287e61c0_41daa793.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-2967af5a_863c2cc6.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-303ca6d6_5df13441.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-308a4afd_cbf5064d.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-353f16e2_0968bcf5.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-3c22475a_41daa793.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-5bac1029_0968bcf5.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-640f76b2_9198780b.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-752fa7ea_863c2cc6.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-baf9ef39_0968bcf5.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-bc8b2a2f_5df13441.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-c31e4686_41daa793.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-cc84c84c_863c2cc6.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-dd7c7144_9198780b.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/mathematician-e671c256_41ea4487.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/report_generator-1a878fcc_18d44bdc.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/report_generator-25c1c331_cea57d0d.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/report_generator-37552117_e711c2b9.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/report_generator-bc662768_e711c2b9.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/report_generator-d6c0e76b_5e7722ec.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/report_generator-f270fb02_680529c3.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/text_processor-11393b14_4370d3ed.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/text_processor-7d02dfc3_d3b569be.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/text_processor-8adb5e32_9168c5fe.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/text_processor-c58ffc19_78b4ceac.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/text_processor-cd5977b1_9168c5fe.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/test_logs/code_registry/functions/text_processor-ec1c8773_9168c5fe.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/conftest.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_01_analyst_standalone.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_02_assistant_standalone.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_03_analyst_with_framework.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_04_assistant_with_framework.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_05_integration.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_06_real_llm_integration.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_07_distributed_single_node.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_08_distributed_multi_node.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_09_distributed_autoagent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_10_distributed_customagent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_14_cloud_deployment.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_agent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_autoagent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_autoagent_day4.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_context.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_customagent.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_decorator.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_integration.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_llm_fallback.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_mesh.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_p2p_integration.py +0 -0
- {jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/tests/test_remote_sandbox.py +0 -0
{jarviscore_framework-0.3.0/jarviscore_framework.egg-info → jarviscore_framework-0.3.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jarviscore-framework
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Build autonomous AI agents in 3 lines of code. Production-ready orchestration with P2P mesh networking.
|
|
5
5
|
Author-email: Ruth Mutua <mutuandinda82@gmail.com>, Muyukani Kizito <muyukani@prescottdata.io>
|
|
6
6
|
Maintainer-email: Prescott Data <info@prescottdata.io>
|
|
@@ -26,6 +26,8 @@ Requires-Dist: pyzmq
|
|
|
26
26
|
Requires-Dist: python-dotenv>=1.0.0
|
|
27
27
|
Requires-Dist: aiohttp>=3.9.0
|
|
28
28
|
Requires-Dist: beautifulsoup4>=4.12.0
|
|
29
|
+
Requires-Dist: fastapi>=0.104.0
|
|
30
|
+
Requires-Dist: uvicorn>=0.29.0
|
|
29
31
|
Requires-Dist: anthropic>=0.18.0
|
|
30
32
|
Requires-Dist: openai>=1.0.0
|
|
31
33
|
Requires-Dist: google-genai>=1.0.0
|
|
@@ -47,13 +49,13 @@ Dynamic: license-file
|
|
|
47
49
|
|
|
48
50
|
## Features
|
|
49
51
|
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
52
|
+
- **AutoAgent** - LLM generates and executes code from natural language
|
|
53
|
+
- **CustomAgent** - Bring your own logic with P2P message handlers
|
|
54
|
+
- **P2P Mesh** - Agent discovery and communication via SWIM protocol
|
|
55
|
+
- **Workflow Orchestration** - Dependencies, context passing, multi-step pipelines
|
|
56
|
+
- **FastAPI Integration** - 3-line setup with JarvisLifespan
|
|
57
|
+
- **Cognitive Discovery** - LLM-ready peer descriptions for autonomous delegation
|
|
58
|
+
- **Cloud Deployment** - Self-registering agents for Docker/K8s
|
|
57
59
|
|
|
58
60
|
## Installation
|
|
59
61
|
|
|
@@ -97,7 +99,26 @@ results = await mesh.workflow("calc", [
|
|
|
97
99
|
print(results[0]["output"]) # 3628800
|
|
98
100
|
```
|
|
99
101
|
|
|
100
|
-
### CustomAgent (
|
|
102
|
+
### CustomAgent + FastAPI (Recommended)
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from fastapi import FastAPI
|
|
106
|
+
from jarviscore.profiles import CustomAgent
|
|
107
|
+
from jarviscore.integrations.fastapi import JarvisLifespan
|
|
108
|
+
|
|
109
|
+
class ProcessorAgent(CustomAgent):
|
|
110
|
+
role = "processor"
|
|
111
|
+
capabilities = ["processing"]
|
|
112
|
+
|
|
113
|
+
async def on_peer_request(self, msg):
|
|
114
|
+
# Handle requests from other agents
|
|
115
|
+
return {"result": msg.data.get("task", "").upper()}
|
|
116
|
+
|
|
117
|
+
# 3 lines to integrate with FastAPI
|
|
118
|
+
app = FastAPI(lifespan=JarvisLifespan(ProcessorAgent(), mode="p2p"))
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### CustomAgent (Workflow Mode)
|
|
101
122
|
|
|
102
123
|
```python
|
|
103
124
|
from jarviscore import Mesh
|
|
@@ -121,56 +142,50 @@ results = await mesh.workflow("demo", [
|
|
|
121
142
|
print(results[0]["output"]) # [2, 4, 6]
|
|
122
143
|
```
|
|
123
144
|
|
|
124
|
-
|
|
145
|
+
## Profiles
|
|
125
146
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class ProcessorAgent(ListenerAgent):
|
|
132
|
-
role = "processor"
|
|
133
|
-
capabilities = ["processing"]
|
|
134
|
-
|
|
135
|
-
async def on_peer_request(self, msg):
|
|
136
|
-
# Handle requests from other agents
|
|
137
|
-
return {"result": msg.data.get("task", "").upper()}
|
|
138
|
-
|
|
139
|
-
# That's it - 3 lines to integrate with FastAPI
|
|
140
|
-
app = FastAPI(lifespan=JarvisLifespan(ProcessorAgent(), mode="p2p"))
|
|
141
|
-
```
|
|
147
|
+
| Profile | You Write | JarvisCore Handles |
|
|
148
|
+
|---------|-----------|-------------------|
|
|
149
|
+
| **AutoAgent** | System prompt | LLM code generation, sandboxed execution |
|
|
150
|
+
| **CustomAgent** | `on_peer_request()` and/or `execute_task()` | Mesh, discovery, routing, lifecycle |
|
|
142
151
|
|
|
143
152
|
## Execution Modes
|
|
144
153
|
|
|
145
|
-
| Mode |
|
|
146
|
-
|
|
147
|
-
| `autonomous` |
|
|
148
|
-
| `p2p` |
|
|
149
|
-
| `distributed` |
|
|
154
|
+
| Mode | Use Case |
|
|
155
|
+
|------|----------|
|
|
156
|
+
| `autonomous` | Single machine, LLM code generation (AutoAgent) |
|
|
157
|
+
| `p2p` | Agent-to-agent communication, swarms (CustomAgent) |
|
|
158
|
+
| `distributed` | Multi-node workflows + P2P (CustomAgent) |
|
|
150
159
|
|
|
151
|
-
##
|
|
160
|
+
## Framework Integration
|
|
152
161
|
|
|
153
|
-
**
|
|
154
|
-
- **ListenerAgent** - No more writing `run()` loops. Just implement `on_peer_request()` and `on_peer_notify()` handlers.
|
|
155
|
-
- **JarvisLifespan** - FastAPI integration reduced from ~100 lines to 3 lines.
|
|
156
|
-
- **Cognitive Discovery** - `peers.get_cognitive_context()` generates LLM-ready peer descriptions. No more hardcoded agent names in prompts.
|
|
162
|
+
JarvisCore is **async-first**. Best experience with async frameworks.
|
|
157
163
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
| Framework | Integration |
|
|
165
|
+
|-----------|-------------|
|
|
166
|
+
| **FastAPI** | `JarvisLifespan` (3 lines) |
|
|
167
|
+
| **aiohttp, Quart, Tornado** | Manual lifecycle (see docs) |
|
|
168
|
+
| **Flask, Django** | Background thread pattern (see docs) |
|
|
161
169
|
|
|
162
170
|
## Documentation
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
Documentation is included with the package:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
python -c "import jarviscore; print(jarviscore.__path__[0] + '/docs')"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Available guides:**
|
|
179
|
+
- `GETTING_STARTED.md` - 5-minute quickstart
|
|
180
|
+
- `CUSTOMAGENT_GUIDE.md` - CustomAgent patterns and framework integration
|
|
181
|
+
- `AUTOAGENT_GUIDE.md` - LLM-powered agents
|
|
182
|
+
- `USER_GUIDE.md` - Complete documentation
|
|
183
|
+
- `API_REFERENCE.md` - Detailed API docs
|
|
184
|
+
- `CONFIGURATION.md` - Settings reference
|
|
170
185
|
|
|
171
186
|
## Version
|
|
172
187
|
|
|
173
|
-
**0.3.
|
|
188
|
+
**0.3.2**
|
|
174
189
|
|
|
175
190
|
## License
|
|
176
191
|
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# JarvisCore Framework
|
|
2
|
+
|
|
3
|
+
**Build autonomous AI agents with P2P mesh networking.**
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **AutoAgent** - LLM generates and executes code from natural language
|
|
8
|
+
- **CustomAgent** - Bring your own logic with P2P message handlers
|
|
9
|
+
- **P2P Mesh** - Agent discovery and communication via SWIM protocol
|
|
10
|
+
- **Workflow Orchestration** - Dependencies, context passing, multi-step pipelines
|
|
11
|
+
- **FastAPI Integration** - 3-line setup with JarvisLifespan
|
|
12
|
+
- **Cognitive Discovery** - LLM-ready peer descriptions for autonomous delegation
|
|
13
|
+
- **Cloud Deployment** - Self-registering agents for Docker/K8s
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install jarviscore-framework
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Initialize project
|
|
25
|
+
python -m jarviscore.cli.scaffold --examples
|
|
26
|
+
cp .env.example .env
|
|
27
|
+
# Add your LLM API key to .env
|
|
28
|
+
|
|
29
|
+
# Validate
|
|
30
|
+
python -m jarviscore.cli.check --validate-llm
|
|
31
|
+
python -m jarviscore.cli.smoketest
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### AutoAgent (LLM-Powered)
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from jarviscore import Mesh
|
|
40
|
+
from jarviscore.profiles import AutoAgent
|
|
41
|
+
|
|
42
|
+
class CalculatorAgent(AutoAgent):
|
|
43
|
+
role = "calculator"
|
|
44
|
+
capabilities = ["math"]
|
|
45
|
+
system_prompt = "You are a math expert. Store result in 'result'."
|
|
46
|
+
|
|
47
|
+
mesh = Mesh(mode="autonomous")
|
|
48
|
+
mesh.add(CalculatorAgent)
|
|
49
|
+
await mesh.start()
|
|
50
|
+
|
|
51
|
+
results = await mesh.workflow("calc", [
|
|
52
|
+
{"agent": "calculator", "task": "Calculate factorial of 10"}
|
|
53
|
+
])
|
|
54
|
+
print(results[0]["output"]) # 3628800
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### CustomAgent + FastAPI (Recommended)
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from fastapi import FastAPI
|
|
61
|
+
from jarviscore.profiles import CustomAgent
|
|
62
|
+
from jarviscore.integrations.fastapi import JarvisLifespan
|
|
63
|
+
|
|
64
|
+
class ProcessorAgent(CustomAgent):
|
|
65
|
+
role = "processor"
|
|
66
|
+
capabilities = ["processing"]
|
|
67
|
+
|
|
68
|
+
async def on_peer_request(self, msg):
|
|
69
|
+
# Handle requests from other agents
|
|
70
|
+
return {"result": msg.data.get("task", "").upper()}
|
|
71
|
+
|
|
72
|
+
# 3 lines to integrate with FastAPI
|
|
73
|
+
app = FastAPI(lifespan=JarvisLifespan(ProcessorAgent(), mode="p2p"))
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### CustomAgent (Workflow Mode)
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from jarviscore import Mesh
|
|
80
|
+
from jarviscore.profiles import CustomAgent
|
|
81
|
+
|
|
82
|
+
class ProcessorAgent(CustomAgent):
|
|
83
|
+
role = "processor"
|
|
84
|
+
capabilities = ["processing"]
|
|
85
|
+
|
|
86
|
+
async def execute_task(self, task):
|
|
87
|
+
data = task.get("params", {}).get("data", [])
|
|
88
|
+
return {"status": "success", "output": [x * 2 for x in data]}
|
|
89
|
+
|
|
90
|
+
mesh = Mesh(mode="distributed", config={'bind_port': 7950})
|
|
91
|
+
mesh.add(ProcessorAgent)
|
|
92
|
+
await mesh.start()
|
|
93
|
+
|
|
94
|
+
results = await mesh.workflow("demo", [
|
|
95
|
+
{"agent": "processor", "task": "Process", "params": {"data": [1, 2, 3]}}
|
|
96
|
+
])
|
|
97
|
+
print(results[0]["output"]) # [2, 4, 6]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Profiles
|
|
101
|
+
|
|
102
|
+
| Profile | You Write | JarvisCore Handles |
|
|
103
|
+
|---------|-----------|-------------------|
|
|
104
|
+
| **AutoAgent** | System prompt | LLM code generation, sandboxed execution |
|
|
105
|
+
| **CustomAgent** | `on_peer_request()` and/or `execute_task()` | Mesh, discovery, routing, lifecycle |
|
|
106
|
+
|
|
107
|
+
## Execution Modes
|
|
108
|
+
|
|
109
|
+
| Mode | Use Case |
|
|
110
|
+
|------|----------|
|
|
111
|
+
| `autonomous` | Single machine, LLM code generation (AutoAgent) |
|
|
112
|
+
| `p2p` | Agent-to-agent communication, swarms (CustomAgent) |
|
|
113
|
+
| `distributed` | Multi-node workflows + P2P (CustomAgent) |
|
|
114
|
+
|
|
115
|
+
## Framework Integration
|
|
116
|
+
|
|
117
|
+
JarvisCore is **async-first**. Best experience with async frameworks.
|
|
118
|
+
|
|
119
|
+
| Framework | Integration |
|
|
120
|
+
|-----------|-------------|
|
|
121
|
+
| **FastAPI** | `JarvisLifespan` (3 lines) |
|
|
122
|
+
| **aiohttp, Quart, Tornado** | Manual lifecycle (see docs) |
|
|
123
|
+
| **Flask, Django** | Background thread pattern (see docs) |
|
|
124
|
+
|
|
125
|
+
## Documentation
|
|
126
|
+
|
|
127
|
+
Documentation is included with the package:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python -c "import jarviscore; print(jarviscore.__path__[0] + '/docs')"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Available guides:**
|
|
134
|
+
- `GETTING_STARTED.md` - 5-minute quickstart
|
|
135
|
+
- `CUSTOMAGENT_GUIDE.md` - CustomAgent patterns and framework integration
|
|
136
|
+
- `AUTOAGENT_GUIDE.md` - LLM-powered agents
|
|
137
|
+
- `USER_GUIDE.md` - Complete documentation
|
|
138
|
+
- `API_REFERENCE.md` - Detailed API docs
|
|
139
|
+
- `CONFIGURATION.md` - Settings reference
|
|
140
|
+
|
|
141
|
+
## Version
|
|
142
|
+
|
|
143
|
+
**0.3.2**
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT License
|
{jarviscore_framework-0.3.0 → jarviscore_framework-0.3.2}/examples/cloud_deployment_example.py
RENAMED
|
@@ -28,10 +28,10 @@ import sys
|
|
|
28
28
|
|
|
29
29
|
sys.path.insert(0, '.')
|
|
30
30
|
|
|
31
|
-
from jarviscore.profiles import
|
|
31
|
+
from jarviscore.profiles import CustomAgent
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
class StandaloneProcessor(
|
|
34
|
+
class StandaloneProcessor(CustomAgent):
|
|
35
35
|
"""
|
|
36
36
|
Example standalone agent that joins mesh independently.
|
|
37
37
|
|
|
@@ -143,7 +143,7 @@ async def main():
|
|
|
143
143
|
print("Listening for peer requests...")
|
|
144
144
|
print("Press Ctrl+C to stop.\n")
|
|
145
145
|
|
|
146
|
-
# Run agent (
|
|
146
|
+
# Run agent (CustomAgent's run() handles the message loop)
|
|
147
147
|
try:
|
|
148
148
|
await agent.run()
|
|
149
149
|
except asyncio.CancelledError:
|
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
CustomAgent + Cognitive Discovery Example
|
|
3
3
|
|
|
4
|
-
Demonstrates
|
|
4
|
+
Demonstrates v0.3.0 and v0.3.2 features:
|
|
5
5
|
|
|
6
|
-
1.
|
|
6
|
+
1. CustomAgent - Handler-based P2P agents (no run() loop needed)
|
|
7
7
|
- on_peer_request() handles incoming requests
|
|
8
8
|
- on_peer_notify() handles broadcast notifications
|
|
9
9
|
|
|
10
|
-
2. Cognitive Discovery - Dynamic peer awareness for LLMs
|
|
10
|
+
2. Cognitive Discovery (v0.3.0) - Dynamic peer awareness for LLMs
|
|
11
11
|
- get_cognitive_context() generates LLM-ready peer descriptions
|
|
12
12
|
- No hardcoded agent names in prompts
|
|
13
13
|
- LLM autonomously decides when to delegate
|
|
14
14
|
|
|
15
|
+
3. Session Context (v0.3.2) - Request tracking with metadata
|
|
16
|
+
- Pass context={mission_id, request_id} with peer requests
|
|
17
|
+
- Track requests across agent boundaries for debugging/tracing
|
|
18
|
+
|
|
15
19
|
Usage:
|
|
16
|
-
python examples/
|
|
20
|
+
python examples/customagent_cognitive_discovery_example.py
|
|
17
21
|
|
|
18
22
|
Prerequisites:
|
|
19
23
|
- .env file with CLAUDE_API_KEY (or other LLM provider)
|
|
20
24
|
"""
|
|
21
25
|
import asyncio
|
|
22
26
|
import sys
|
|
27
|
+
import uuid
|
|
23
28
|
from pathlib import Path
|
|
24
29
|
|
|
25
30
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
26
31
|
|
|
27
32
|
from jarviscore import Mesh
|
|
28
|
-
from jarviscore.profiles import
|
|
33
|
+
from jarviscore.profiles import CustomAgent
|
|
29
34
|
|
|
30
35
|
|
|
31
36
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
32
37
|
# SPECIALIST AGENT - Responds to requests from other agents
|
|
33
38
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
34
39
|
|
|
35
|
-
class AnalystAgent(
|
|
40
|
+
class AnalystAgent(CustomAgent):
|
|
36
41
|
"""
|
|
37
42
|
Specialist agent that handles analysis requests.
|
|
38
43
|
|
|
39
|
-
Uses
|
|
44
|
+
Uses CustomAgent profile - just implement handlers, no run() loop needed.
|
|
40
45
|
"""
|
|
41
46
|
role = "analyst"
|
|
42
47
|
capabilities = ["data_analysis", "statistics", "insights"]
|
|
@@ -45,13 +50,21 @@ class AnalystAgent(ListenerAgent):
|
|
|
45
50
|
async def on_peer_request(self, msg):
|
|
46
51
|
"""Handle incoming analysis requests."""
|
|
47
52
|
query = msg.data.get("question", msg.data.get("query", ""))
|
|
48
|
-
|
|
53
|
+
|
|
54
|
+
# v0.3.2: Access session context for request tracking
|
|
55
|
+
context = msg.context or {}
|
|
56
|
+
mission_id = context.get("mission_id", "unknown")
|
|
57
|
+
request_id = context.get("request_id", "unknown")
|
|
58
|
+
|
|
59
|
+
print(f"\n[Analyst] Received request (mission={mission_id[:8]}..., req={request_id[:8]}...)")
|
|
60
|
+
print(f"[Analyst] Query: {query[:50]}...")
|
|
49
61
|
|
|
50
62
|
# Simulate analysis (in real usage, this would use an LLM)
|
|
51
63
|
result = {
|
|
52
64
|
"analysis": f"Analysis of '{query}': The data shows positive trends.",
|
|
53
65
|
"confidence": 0.85,
|
|
54
|
-
"insights": ["Trend is upward", "Growth rate: 15%", "Recommendation: Continue"]
|
|
66
|
+
"insights": ["Trend is upward", "Growth rate: 15%", "Recommendation: Continue"],
|
|
67
|
+
"context": {"mission_id": mission_id, "request_id": request_id} # Echo back for tracing
|
|
55
68
|
}
|
|
56
69
|
|
|
57
70
|
print(f"[Analyst] Sending response with {len(result['insights'])} insights")
|
|
@@ -62,7 +75,7 @@ class AnalystAgent(ListenerAgent):
|
|
|
62
75
|
# COORDINATOR AGENT - Uses LLM with cognitive discovery
|
|
63
76
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
64
77
|
|
|
65
|
-
class CoordinatorAgent(
|
|
78
|
+
class CoordinatorAgent(CustomAgent):
|
|
66
79
|
"""
|
|
67
80
|
Coordinator agent that uses LLM with dynamic peer discovery.
|
|
68
81
|
|
|
@@ -78,6 +91,9 @@ class CoordinatorAgent(ListenerAgent):
|
|
|
78
91
|
async def setup(self):
|
|
79
92
|
await super().setup()
|
|
80
93
|
self.llm = self._create_llm_client()
|
|
94
|
+
# v0.3.2: Track missions for context propagation
|
|
95
|
+
self.mission_id = str(uuid.uuid4())
|
|
96
|
+
self.request_counter = 0
|
|
81
97
|
|
|
82
98
|
def _create_llm_client(self):
|
|
83
99
|
"""Create LLM client with fallback to mock."""
|
|
@@ -167,10 +183,22 @@ Never try to do analysis yourself - always delegate to the analyst."""
|
|
|
167
183
|
# Mock: simulate LLM deciding to delegate
|
|
168
184
|
if any(word in user_query.lower() for word in ["analyze", "analysis", "statistics", "data"]):
|
|
169
185
|
print("[Coordinator] Mock LLM decides to delegate to analyst")
|
|
186
|
+
|
|
187
|
+
# v0.3.2: Generate request context for tracking
|
|
188
|
+
self.request_counter += 1
|
|
189
|
+
request_context = {
|
|
190
|
+
"mission_id": self.mission_id,
|
|
191
|
+
"request_id": str(uuid.uuid4()),
|
|
192
|
+
"request_num": self.request_counter,
|
|
193
|
+
"source": "coordinator"
|
|
194
|
+
}
|
|
195
|
+
print(f"[Coordinator] Sending with context: mission={self.mission_id[:8]}...")
|
|
196
|
+
|
|
170
197
|
response = await self.peers.request(
|
|
171
198
|
"analyst",
|
|
172
199
|
{"question": user_query},
|
|
173
|
-
timeout=30
|
|
200
|
+
timeout=30,
|
|
201
|
+
context=request_context # v0.3.2: Pass context
|
|
174
202
|
)
|
|
175
203
|
return f"Based on the analyst's findings: {response.get('analysis', 'No response')}"
|
|
176
204
|
return f"I can help with: {user_query}"
|
|
@@ -261,12 +289,24 @@ Never try to do analysis yourself - always delegate to the analyst."""
|
|
|
261
289
|
role = args.get("role", "")
|
|
262
290
|
question = args.get("question", "")
|
|
263
291
|
|
|
292
|
+
# v0.3.2: Generate request context for tracking
|
|
293
|
+
self.request_counter += 1
|
|
294
|
+
request_context = {
|
|
295
|
+
"mission_id": self.mission_id,
|
|
296
|
+
"request_id": str(uuid.uuid4()),
|
|
297
|
+
"request_num": self.request_counter,
|
|
298
|
+
"source": "coordinator",
|
|
299
|
+
"tool": "ask_peer"
|
|
300
|
+
}
|
|
301
|
+
|
|
264
302
|
print(f"[Coordinator] Asking {role}: {question[:50]}...")
|
|
303
|
+
print(f"[Coordinator] Context: mission={self.mission_id[:8]}..., req_num={self.request_counter}")
|
|
265
304
|
|
|
266
305
|
response = await self.peers.request(
|
|
267
306
|
role,
|
|
268
307
|
{"question": question},
|
|
269
|
-
timeout=30
|
|
308
|
+
timeout=30,
|
|
309
|
+
context=request_context # v0.3.2: Pass context
|
|
270
310
|
)
|
|
271
311
|
|
|
272
312
|
return response
|
|
@@ -284,7 +324,8 @@ Never try to do analysis yourself - always delegate to the analyst."""
|
|
|
284
324
|
|
|
285
325
|
async def main():
|
|
286
326
|
print("=" * 60)
|
|
287
|
-
print("
|
|
327
|
+
print("CustomAgent + Cognitive Discovery + Session Context")
|
|
328
|
+
print("Features: v0.3.0 Cognitive Discovery, v0.3.2 Session Context")
|
|
288
329
|
print("=" * 60)
|
|
289
330
|
|
|
290
331
|
# Create mesh with both agents
|
|
@@ -6,6 +6,10 @@ Demonstrates CustomAgent in distributed mode, which combines:
|
|
|
6
6
|
- Workflow orchestration (step execution, dependencies)
|
|
7
7
|
- User-controlled execution logic (you write execute_task)
|
|
8
8
|
|
|
9
|
+
v0.3.2 Features Demonstrated:
|
|
10
|
+
- Async Requests (ask_async) - Non-blocking parallel requests to multiple agents
|
|
11
|
+
- Load Balancing (strategy="round_robin") - Distribute requests across agent instances
|
|
12
|
+
|
|
9
13
|
This is ideal for:
|
|
10
14
|
- Multi-node deployments with custom logic
|
|
11
15
|
- Integrating external frameworks (LangChain, CrewAI, etc.)
|
|
@@ -231,6 +235,7 @@ async def main():
|
|
|
231
235
|
"""Run CustomAgent distributed mode example."""
|
|
232
236
|
print("\n" + "="*70)
|
|
233
237
|
print("JarvisCore: CustomAgent in Distributed Mode")
|
|
238
|
+
print("v0.3.2: Also supports --async and --load-balance demos")
|
|
234
239
|
print("="*70)
|
|
235
240
|
|
|
236
241
|
# ─────────────────────────────────────────────────────────────────────────
|
|
@@ -358,5 +363,139 @@ async def peer_communication_example():
|
|
|
358
363
|
pass
|
|
359
364
|
|
|
360
365
|
|
|
366
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
367
|
+
# v0.3.2 FEATURES: ASYNC REQUESTS & LOAD BALANCING
|
|
368
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
369
|
+
|
|
370
|
+
async def async_requests_demo():
|
|
371
|
+
"""
|
|
372
|
+
Demonstrate v0.3.2 async requests for parallel agent communication.
|
|
373
|
+
|
|
374
|
+
ask_async() returns a Future that can be awaited later, enabling:
|
|
375
|
+
- Fire multiple requests in parallel
|
|
376
|
+
- Continue other work while waiting
|
|
377
|
+
- Gather results when needed
|
|
378
|
+
"""
|
|
379
|
+
print("\n" + "="*70)
|
|
380
|
+
print("v0.3.2 Feature: Async Requests (ask_async)")
|
|
381
|
+
print("="*70)
|
|
382
|
+
|
|
383
|
+
mesh = Mesh(mode="p2p", config={"bind_port": 7966})
|
|
384
|
+
|
|
385
|
+
# Add multiple agents
|
|
386
|
+
mesh.add(ContentResearcherAgent)
|
|
387
|
+
mesh.add(ContentWriterAgent)
|
|
388
|
+
mesh.add(ContentReviewerAgent)
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
await mesh.start()
|
|
392
|
+
|
|
393
|
+
# Get an agent with peer access
|
|
394
|
+
researcher = next((a for a in mesh.agents if a.role == "content_researcher"), None)
|
|
395
|
+
if not researcher or not researcher.peers:
|
|
396
|
+
print("Peers not available")
|
|
397
|
+
return
|
|
398
|
+
|
|
399
|
+
print("\n[Demo] Firing parallel requests to multiple agents...")
|
|
400
|
+
|
|
401
|
+
# v0.3.2: ask_async returns a Future - doesn't block!
|
|
402
|
+
future1 = researcher.peers.ask_async(
|
|
403
|
+
"content_writer",
|
|
404
|
+
{"question": "What makes good technical writing?"}
|
|
405
|
+
)
|
|
406
|
+
future2 = researcher.peers.ask_async(
|
|
407
|
+
"content_reviewer",
|
|
408
|
+
{"question": "What are common writing mistakes?"}
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
print("[Demo] Requests sent! Doing other work while waiting...")
|
|
412
|
+
await asyncio.sleep(0.1) # Simulate other work
|
|
413
|
+
|
|
414
|
+
# Gather results when ready
|
|
415
|
+
print("[Demo] Gathering results...")
|
|
416
|
+
results = await asyncio.gather(future1, future2, return_exceptions=True)
|
|
417
|
+
|
|
418
|
+
for i, result in enumerate(results):
|
|
419
|
+
if isinstance(result, Exception):
|
|
420
|
+
print(f" Request {i+1}: Error - {result}")
|
|
421
|
+
else:
|
|
422
|
+
print(f" Request {i+1}: Got response")
|
|
423
|
+
|
|
424
|
+
print("\n[Demo] Async requests complete!")
|
|
425
|
+
|
|
426
|
+
finally:
|
|
427
|
+
await mesh.stop()
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
async def load_balancing_demo():
|
|
431
|
+
"""
|
|
432
|
+
Demonstrate v0.3.2 load balancing strategies.
|
|
433
|
+
|
|
434
|
+
When multiple agents have the same capability, use strategy parameter:
|
|
435
|
+
- "random" (default): Random selection
|
|
436
|
+
- "round_robin": Distribute evenly across instances
|
|
437
|
+
"""
|
|
438
|
+
print("\n" + "="*70)
|
|
439
|
+
print("v0.3.2 Feature: Load Balancing Strategies")
|
|
440
|
+
print("="*70)
|
|
441
|
+
|
|
442
|
+
mesh = Mesh(mode="p2p", config={"bind_port": 7967})
|
|
443
|
+
|
|
444
|
+
# Add agents
|
|
445
|
+
mesh.add(ContentResearcherAgent)
|
|
446
|
+
mesh.add(ContentWriterAgent)
|
|
447
|
+
|
|
448
|
+
try:
|
|
449
|
+
await mesh.start()
|
|
450
|
+
|
|
451
|
+
researcher = next((a for a in mesh.agents if a.role == "content_researcher"), None)
|
|
452
|
+
if not researcher or not researcher.peers:
|
|
453
|
+
print("Peers not available")
|
|
454
|
+
return
|
|
455
|
+
|
|
456
|
+
print("\n[Demo] Load balancing with strategy='round_robin'")
|
|
457
|
+
print("[Demo] Sending 3 requests to 'writing' capability...")
|
|
458
|
+
|
|
459
|
+
# v0.3.2: Use discover_one() with strategy for load balancing
|
|
460
|
+
for i in range(3):
|
|
461
|
+
# round_robin distributes requests evenly across matching peers
|
|
462
|
+
# First, discover which peer to use with the strategy
|
|
463
|
+
target = researcher.peers.discover_one(
|
|
464
|
+
role="content_writer",
|
|
465
|
+
strategy="round_robin" # v0.3.2: Load balancing
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
if target:
|
|
469
|
+
# Then make the request to that specific peer
|
|
470
|
+
response = await researcher.peers.request(
|
|
471
|
+
target.role,
|
|
472
|
+
{"question": f"Request #{i+1}"},
|
|
473
|
+
timeout=10
|
|
474
|
+
)
|
|
475
|
+
print(f" Request {i+1}: Handled by {target.agent_id[:8]}...")
|
|
476
|
+
else:
|
|
477
|
+
print(f" Request {i+1}: No peer found")
|
|
478
|
+
|
|
479
|
+
print("\n[Demo] Load balancing complete!")
|
|
480
|
+
print("[Demo] In a multi-node setup with multiple writers,")
|
|
481
|
+
print(" round_robin would distribute across all instances.")
|
|
482
|
+
|
|
483
|
+
finally:
|
|
484
|
+
await mesh.stop()
|
|
485
|
+
|
|
486
|
+
|
|
361
487
|
if __name__ == "__main__":
|
|
362
|
-
|
|
488
|
+
import sys
|
|
489
|
+
|
|
490
|
+
if len(sys.argv) > 1:
|
|
491
|
+
if sys.argv[1] == "--async":
|
|
492
|
+
asyncio.run(async_requests_demo())
|
|
493
|
+
elif sys.argv[1] == "--load-balance":
|
|
494
|
+
asyncio.run(load_balancing_demo())
|
|
495
|
+
else:
|
|
496
|
+
print("Usage:")
|
|
497
|
+
print(" python customagent_distributed_example.py # Main workflow demo")
|
|
498
|
+
print(" python customagent_distributed_example.py --async # Async requests demo")
|
|
499
|
+
print(" python customagent_distributed_example.py --load-balance # Load balancing demo")
|
|
500
|
+
else:
|
|
501
|
+
asyncio.run(main())
|