jarviscore-framework 0.1.1__tar.gz → 0.2.1__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.2.1/PKG-INFO +144 -0
- jarviscore_framework-0.2.1/README.md +101 -0
- jarviscore_framework-0.2.1/examples/autoagent_distributed_example.py +211 -0
- jarviscore_framework-0.2.1/examples/custom_profile_decorator.py +134 -0
- jarviscore_framework-0.2.1/examples/custom_profile_wrap.py +168 -0
- jarviscore_framework-0.2.1/examples/customagent_distributed_example.py +362 -0
- jarviscore_framework-0.2.1/examples/customagent_p2p_example.py +730 -0
- jarviscore_framework-0.2.1/jarviscore/__init__.py +99 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/adapter/__init__.py +15 -9
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/adapter/decorator.py +23 -19
- jarviscore_framework-0.2.1/jarviscore/adapter/wrapper.py +303 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/cli/scaffold.py +1 -1
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/cli/smoketest.py +3 -2
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/core/agent.py +44 -1
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/core/mesh.py +196 -35
- jarviscore_framework-0.2.1/jarviscore/data/examples/autoagent_distributed_example.py +211 -0
- jarviscore_framework-0.2.1/jarviscore/data/examples/customagent_distributed_example.py +362 -0
- jarviscore_framework-0.2.1/jarviscore/data/examples/customagent_p2p_example.py +730 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/docs/API_REFERENCE.md +264 -51
- jarviscore_framework-0.2.1/jarviscore/docs/AUTOAGENT_GUIDE.md +198 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/docs/CONFIGURATION.md +35 -21
- jarviscore_framework-0.2.1/jarviscore/docs/CUSTOMAGENT_GUIDE.md +1362 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/docs/GETTING_STARTED.md +107 -14
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/docs/TROUBLESHOOTING.md +145 -7
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/docs/USER_GUIDE.md +138 -361
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/orchestration/engine.py +20 -8
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/p2p/__init__.py +10 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/p2p/coordinator.py +129 -0
- jarviscore_framework-0.2.1/jarviscore/p2p/messages.py +87 -0
- jarviscore_framework-0.2.1/jarviscore/p2p/peer_client.py +576 -0
- jarviscore_framework-0.2.1/jarviscore/p2p/peer_tool.py +268 -0
- jarviscore_framework-0.2.1/jarviscore_framework.egg-info/PKG-INFO +144 -0
- jarviscore_framework-0.2.1/jarviscore_framework.egg-info/SOURCES.txt +137 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore_framework.egg-info/top_level.txt +1 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/pyproject.toml +6 -7
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-558779ed_560ebc37.py +7 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-5ed3609e_560ebc37.py +7 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-66da0356_43970bb9.py +25 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-7a2fac83_583709d9.py +36 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-888b670f_aa235863.py +9 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-9ca5f642_aa235863.py +9 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-bfd90775_560ebc37.py +7 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-e95d2f7d_aa235863.py +9 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/data_generator-f60ca8a2_327eb8c2.py +29 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-02adf9ee_958658d9.py +19 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-0706fb57_5df13441.py +23 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-153c9c4a_ba59c918.py +83 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-287e61c0_41daa793.py +18 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-2967af5a_863c2cc6.py +17 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-303ca6d6_5df13441.py +23 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-308a4afd_cbf5064d.py +73 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-353f16e2_0968bcf5.py +18 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-3c22475a_41daa793.py +17 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-5bac1029_0968bcf5.py +18 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-640f76b2_9198780b.py +19 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-752fa7ea_863c2cc6.py +17 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-baf9ef39_0968bcf5.py +18 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-bc8b2a2f_5df13441.py +23 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-c31e4686_41daa793.py +18 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-cc84c84c_863c2cc6.py +17 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-dd7c7144_9198780b.py +19 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/mathematician-e671c256_41ea4487.py +74 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/report_generator-1a878fcc_18d44bdc.py +47 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/report_generator-25c1c331_cea57d0d.py +35 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/report_generator-37552117_e711c2b9.py +35 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/report_generator-bc662768_e711c2b9.py +35 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/report_generator-d6c0e76b_5e7722ec.py +44 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/report_generator-f270fb02_680529c3.py +44 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/text_processor-11393b14_4370d3ed.py +40 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/text_processor-7d02dfc3_d3b569be.py +37 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/text_processor-8adb5e32_9168c5fe.py +13 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/text_processor-c58ffc19_78b4ceac.py +42 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/text_processor-cd5977b1_9168c5fe.py +13 -0
- jarviscore_framework-0.2.1/test_logs/code_registry/functions/text_processor-ec1c8773_9168c5fe.py +13 -0
- jarviscore_framework-0.2.1/tests/test_01_analyst_standalone.py +124 -0
- jarviscore_framework-0.2.1/tests/test_02_assistant_standalone.py +164 -0
- jarviscore_framework-0.2.1/tests/test_03_analyst_with_framework.py +945 -0
- jarviscore_framework-0.2.1/tests/test_04_assistant_with_framework.py +1002 -0
- jarviscore_framework-0.2.1/tests/test_05_integration.py +1301 -0
- jarviscore_framework-0.2.1/tests/test_06_real_llm_integration.py +760 -0
- jarviscore_framework-0.2.1/tests/test_07_distributed_single_node.py +578 -0
- jarviscore_framework-0.2.1/tests/test_08_distributed_multi_node.py +454 -0
- jarviscore_framework-0.2.1/tests/test_09_distributed_autoagent.py +509 -0
- jarviscore_framework-0.2.1/tests/test_10_distributed_customagent.py +787 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_mesh.py +35 -4
- jarviscore_framework-0.1.1/PKG-INFO +0 -137
- jarviscore_framework-0.1.1/README.md +0 -93
- jarviscore_framework-0.1.1/TESTING_GUIDE.md +0 -420
- jarviscore_framework-0.1.1/jarviscore/__init__.py +0 -86
- jarviscore_framework-0.1.1/jarviscore_framework.egg-info/PKG-INFO +0 -137
- jarviscore_framework-0.1.1/jarviscore_framework.egg-info/SOURCES.txt +0 -75
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/.env.example +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/LICENSE +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/MANIFEST.in +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/examples/calculator_agent_example.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/examples/multi_agent_workflow.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/examples/research_agent_example.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/cli/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/cli/__main__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/cli/check.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/config/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/config/settings.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/context/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/context/dependency.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/context/jarvis_context.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/context/memory.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/core/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/core/profile.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/data/.env.example +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/data/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/data/examples/calculator_agent_example.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/data/examples/multi_agent_workflow.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/data/examples/research_agent_example.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/code_registry.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/generator.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/llm.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/repair.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/result_handler.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/sandbox.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/execution/search.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/orchestration/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/orchestration/claimer.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/orchestration/dependency.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/orchestration/status.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/p2p/broadcaster.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/p2p/keepalive.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/p2p/swim_manager.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/profiles/__init__.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/profiles/autoagent.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore/profiles/customagent.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore_framework.egg-info/dependency_links.txt +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/jarviscore_framework.egg-info/requires.txt +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/setup.cfg +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/conftest.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_agent.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_autoagent.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_autoagent_day4.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_context.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_customagent.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_decorator.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_integration.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_llm_fallback.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_p2p_integration.py +0 -0
- {jarviscore_framework-0.1.1 → jarviscore_framework-0.2.1}/tests/test_remote_sandbox.py +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jarviscore-framework
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Build autonomous AI agents in 3 lines of code. Production-ready orchestration with P2P mesh networking.
|
|
5
|
+
Author-email: Ruth Mutua <mutuandinda82@gmail.com>, Muyukani Kizito <muyukani@prescottdata.io>
|
|
6
|
+
Maintainer-email: Prescott Data <info@prescottdata.io>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/Prescott-Data/jarviscore-framework
|
|
9
|
+
Project-URL: Documentation, https://github.com/Prescott-Data/jarviscore-framework/tree/main/jarviscore/docs
|
|
10
|
+
Project-URL: Repository, https://github.com/Prescott-Data/jarviscore-framework
|
|
11
|
+
Project-URL: Issues, https://github.com/Prescott-Data/jarviscore-framework/issues
|
|
12
|
+
Keywords: agents,p2p,llm,distributed,workflow,orchestration
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
24
|
+
Requires-Dist: swim-p2p
|
|
25
|
+
Requires-Dist: pyzmq
|
|
26
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
27
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
28
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
29
|
+
Requires-Dist: anthropic>=0.18.0
|
|
30
|
+
Requires-Dist: openai>=1.0.0
|
|
31
|
+
Requires-Dist: google-genai>=1.0.0
|
|
32
|
+
Requires-Dist: httpx>=0.25.0
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
37
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
40
|
+
Provides-Extra: all
|
|
41
|
+
Requires-Dist: jarviscore[dev]; extra == "all"
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
|
|
44
|
+
# JarvisCore Framework
|
|
45
|
+
|
|
46
|
+
**Build autonomous AI agents with P2P mesh networking.**
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- ✅ **AutoAgent** - LLM generates and executes code from natural language
|
|
51
|
+
- ✅ **CustomAgent** - Bring your own logic (LangChain, CrewAI, etc.)
|
|
52
|
+
- ✅ **P2P Mesh** - Agent discovery and communication via SWIM protocol
|
|
53
|
+
- ✅ **Workflow Orchestration** - Dependencies, context passing, multi-step pipelines
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install jarviscore-framework
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Setup
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Initialize project
|
|
65
|
+
python -m jarviscore.cli.scaffold --examples
|
|
66
|
+
cp .env.example .env
|
|
67
|
+
# Add your LLM API key to .env
|
|
68
|
+
|
|
69
|
+
# Validate
|
|
70
|
+
python -m jarviscore.cli.check --validate-llm
|
|
71
|
+
python -m jarviscore.cli.smoketest
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
### AutoAgent (LLM-Powered)
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from jarviscore import Mesh
|
|
80
|
+
from jarviscore.profiles import AutoAgent
|
|
81
|
+
|
|
82
|
+
class CalculatorAgent(AutoAgent):
|
|
83
|
+
role = "calculator"
|
|
84
|
+
capabilities = ["math"]
|
|
85
|
+
system_prompt = "You are a math expert. Store result in 'result'."
|
|
86
|
+
|
|
87
|
+
mesh = Mesh(mode="autonomous")
|
|
88
|
+
mesh.add(CalculatorAgent)
|
|
89
|
+
await mesh.start()
|
|
90
|
+
|
|
91
|
+
results = await mesh.workflow("calc", [
|
|
92
|
+
{"agent": "calculator", "task": "Calculate factorial of 10"}
|
|
93
|
+
])
|
|
94
|
+
print(results[0]["output"]) # 3628800
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### CustomAgent (Your Code)
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from jarviscore import Mesh
|
|
101
|
+
from jarviscore.profiles import CustomAgent
|
|
102
|
+
|
|
103
|
+
class ProcessorAgent(CustomAgent):
|
|
104
|
+
role = "processor"
|
|
105
|
+
capabilities = ["processing"]
|
|
106
|
+
|
|
107
|
+
async def execute_task(self, task):
|
|
108
|
+
data = task.get("params", {}).get("data", [])
|
|
109
|
+
return {"status": "success", "output": [x * 2 for x in data]}
|
|
110
|
+
|
|
111
|
+
mesh = Mesh(mode="distributed", config={'bind_port': 7950})
|
|
112
|
+
mesh.add(ProcessorAgent)
|
|
113
|
+
await mesh.start()
|
|
114
|
+
|
|
115
|
+
results = await mesh.workflow("demo", [
|
|
116
|
+
{"agent": "processor", "task": "Process", "params": {"data": [1, 2, 3]}}
|
|
117
|
+
])
|
|
118
|
+
print(results[0]["output"]) # [2, 4, 6]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Execution Modes
|
|
122
|
+
|
|
123
|
+
| Mode | Profile | Use Case |
|
|
124
|
+
|------|---------|----------|
|
|
125
|
+
| `autonomous` | AutoAgent | Single machine, LLM code generation |
|
|
126
|
+
| `p2p` | CustomAgent | Agent-to-agent communication, swarms |
|
|
127
|
+
| `distributed` | CustomAgent | Multi-node workflows + P2P |
|
|
128
|
+
|
|
129
|
+
## Documentation
|
|
130
|
+
|
|
131
|
+
- [User Guide](jarviscore/docs/USER_GUIDE.md) - Complete documentation
|
|
132
|
+
- [Getting Started](jarviscore/docs/GETTING_STARTED.md) - 5-minute quickstart
|
|
133
|
+
- [AutoAgent Guide](jarviscore/docs/AUTOAGENT_GUIDE.md) - LLM-powered agents
|
|
134
|
+
- [CustomAgent Guide](jarviscore/docs/CUSTOMAGENT_GUIDE.md) - Bring your own code
|
|
135
|
+
- [API Reference](jarviscore/docs/API_REFERENCE.md) - Detailed API docs
|
|
136
|
+
- [Configuration](jarviscore/docs/CONFIGURATION.md) - Settings reference
|
|
137
|
+
|
|
138
|
+
## Version
|
|
139
|
+
|
|
140
|
+
**0.2.1**
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT License
|
|
@@ -0,0 +1,101 @@
|
|
|
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 (LangChain, CrewAI, etc.)
|
|
9
|
+
- ✅ **P2P Mesh** - Agent discovery and communication via SWIM protocol
|
|
10
|
+
- ✅ **Workflow Orchestration** - Dependencies, context passing, multi-step pipelines
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install jarviscore-framework
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Initialize project
|
|
22
|
+
python -m jarviscore.cli.scaffold --examples
|
|
23
|
+
cp .env.example .env
|
|
24
|
+
# Add your LLM API key to .env
|
|
25
|
+
|
|
26
|
+
# Validate
|
|
27
|
+
python -m jarviscore.cli.check --validate-llm
|
|
28
|
+
python -m jarviscore.cli.smoketest
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### AutoAgent (LLM-Powered)
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from jarviscore import Mesh
|
|
37
|
+
from jarviscore.profiles import AutoAgent
|
|
38
|
+
|
|
39
|
+
class CalculatorAgent(AutoAgent):
|
|
40
|
+
role = "calculator"
|
|
41
|
+
capabilities = ["math"]
|
|
42
|
+
system_prompt = "You are a math expert. Store result in 'result'."
|
|
43
|
+
|
|
44
|
+
mesh = Mesh(mode="autonomous")
|
|
45
|
+
mesh.add(CalculatorAgent)
|
|
46
|
+
await mesh.start()
|
|
47
|
+
|
|
48
|
+
results = await mesh.workflow("calc", [
|
|
49
|
+
{"agent": "calculator", "task": "Calculate factorial of 10"}
|
|
50
|
+
])
|
|
51
|
+
print(results[0]["output"]) # 3628800
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### CustomAgent (Your Code)
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from jarviscore import Mesh
|
|
58
|
+
from jarviscore.profiles import CustomAgent
|
|
59
|
+
|
|
60
|
+
class ProcessorAgent(CustomAgent):
|
|
61
|
+
role = "processor"
|
|
62
|
+
capabilities = ["processing"]
|
|
63
|
+
|
|
64
|
+
async def execute_task(self, task):
|
|
65
|
+
data = task.get("params", {}).get("data", [])
|
|
66
|
+
return {"status": "success", "output": [x * 2 for x in data]}
|
|
67
|
+
|
|
68
|
+
mesh = Mesh(mode="distributed", config={'bind_port': 7950})
|
|
69
|
+
mesh.add(ProcessorAgent)
|
|
70
|
+
await mesh.start()
|
|
71
|
+
|
|
72
|
+
results = await mesh.workflow("demo", [
|
|
73
|
+
{"agent": "processor", "task": "Process", "params": {"data": [1, 2, 3]}}
|
|
74
|
+
])
|
|
75
|
+
print(results[0]["output"]) # [2, 4, 6]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Execution Modes
|
|
79
|
+
|
|
80
|
+
| Mode | Profile | Use Case |
|
|
81
|
+
|------|---------|----------|
|
|
82
|
+
| `autonomous` | AutoAgent | Single machine, LLM code generation |
|
|
83
|
+
| `p2p` | CustomAgent | Agent-to-agent communication, swarms |
|
|
84
|
+
| `distributed` | CustomAgent | Multi-node workflows + P2P |
|
|
85
|
+
|
|
86
|
+
## Documentation
|
|
87
|
+
|
|
88
|
+
- [User Guide](jarviscore/docs/USER_GUIDE.md) - Complete documentation
|
|
89
|
+
- [Getting Started](jarviscore/docs/GETTING_STARTED.md) - 5-minute quickstart
|
|
90
|
+
- [AutoAgent Guide](jarviscore/docs/AUTOAGENT_GUIDE.md) - LLM-powered agents
|
|
91
|
+
- [CustomAgent Guide](jarviscore/docs/CUSTOMAGENT_GUIDE.md) - Bring your own code
|
|
92
|
+
- [API Reference](jarviscore/docs/API_REFERENCE.md) - Detailed API docs
|
|
93
|
+
- [Configuration](jarviscore/docs/CONFIGURATION.md) - Settings reference
|
|
94
|
+
|
|
95
|
+
## Version
|
|
96
|
+
|
|
97
|
+
**0.2.1**
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
MIT License
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AutoAgent Distributed Mode Example
|
|
3
|
+
|
|
4
|
+
Demonstrates AutoAgent in distributed mode, which combines:
|
|
5
|
+
- P2P network layer (SWIM protocol, ZMQ messaging)
|
|
6
|
+
- Workflow orchestration (step execution, dependencies)
|
|
7
|
+
|
|
8
|
+
This is ideal for multi-node deployments where agents can:
|
|
9
|
+
- Execute on different machines
|
|
10
|
+
- Discover each other via SWIM
|
|
11
|
+
- Run orchestrated workflows across the network
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
python examples/autoagent_distributed_example.py
|
|
15
|
+
|
|
16
|
+
Prerequisites:
|
|
17
|
+
- .env file with LLM API key (CLAUDE_API_KEY, etc.)
|
|
18
|
+
"""
|
|
19
|
+
import asyncio
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
24
|
+
|
|
25
|
+
from jarviscore import Mesh
|
|
26
|
+
from jarviscore.profiles import AutoAgent
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
30
|
+
# AUTOAGENT DEFINITIONS
|
|
31
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
32
|
+
|
|
33
|
+
class DataCollectorAgent(AutoAgent):
|
|
34
|
+
"""Collects and generates data."""
|
|
35
|
+
role = "collector"
|
|
36
|
+
capabilities = ["data_collection", "sampling"]
|
|
37
|
+
system_prompt = """
|
|
38
|
+
You are a data collection specialist. Generate sample datasets
|
|
39
|
+
based on specifications. Use Python's standard library only.
|
|
40
|
+
Store results in a variable named 'result' as a dictionary.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class DataProcessorAgent(AutoAgent):
|
|
45
|
+
"""Processes and transforms data."""
|
|
46
|
+
role = "processor"
|
|
47
|
+
capabilities = ["data_processing", "transformation"]
|
|
48
|
+
system_prompt = """
|
|
49
|
+
You are a data processing expert. Transform and clean datasets.
|
|
50
|
+
Apply filters, aggregations, and transformations as needed.
|
|
51
|
+
Use Python's standard library only. Store results in 'result'.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ReportWriterAgent(AutoAgent):
|
|
56
|
+
"""Generates reports from processed data."""
|
|
57
|
+
role = "reporter"
|
|
58
|
+
capabilities = ["reporting", "documentation"]
|
|
59
|
+
system_prompt = """
|
|
60
|
+
You are a technical writer. Create clear, well-formatted reports
|
|
61
|
+
from data. Use markdown formatting. Store the report in 'result'.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
66
|
+
# MAIN EXAMPLE
|
|
67
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
68
|
+
|
|
69
|
+
async def main():
|
|
70
|
+
"""Run AutoAgent distributed mode example."""
|
|
71
|
+
print("\n" + "="*70)
|
|
72
|
+
print("JarvisCore: AutoAgent in Distributed Mode")
|
|
73
|
+
print("="*70)
|
|
74
|
+
|
|
75
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
76
|
+
# KEY DIFFERENCE: mode="distributed" with P2P configuration
|
|
77
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
78
|
+
mesh = Mesh(
|
|
79
|
+
mode="distributed", # Enables P2P + Workflow Engine
|
|
80
|
+
config={
|
|
81
|
+
# P2P Network Configuration
|
|
82
|
+
'bind_host': '127.0.0.1', # Interface to bind to
|
|
83
|
+
'bind_port': 7950, # SWIM protocol port (ZMQ uses +1000)
|
|
84
|
+
'node_name': 'autoagent-node',
|
|
85
|
+
|
|
86
|
+
# For multi-node: uncomment to join existing cluster
|
|
87
|
+
# 'seed_nodes': '192.168.1.10:7950,192.168.1.11:7950',
|
|
88
|
+
|
|
89
|
+
# AutoAgent Configuration
|
|
90
|
+
'execution_timeout': 60, # Max seconds per task
|
|
91
|
+
'max_repair_attempts': 2, # Auto-repair on failure
|
|
92
|
+
'log_directory': './logs', # Result storage
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Add agents - same as autonomous mode
|
|
97
|
+
mesh.add(DataCollectorAgent)
|
|
98
|
+
mesh.add(DataProcessorAgent)
|
|
99
|
+
mesh.add(ReportWriterAgent)
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
await mesh.start()
|
|
103
|
+
|
|
104
|
+
print("\n[INFO] Mesh started in DISTRIBUTED mode")
|
|
105
|
+
print(f" - P2P Coordinator: Active (port {mesh.config.get('bind_port', 7950)})")
|
|
106
|
+
print(f" - Workflow Engine: Active")
|
|
107
|
+
print(f" - Agents: {len(mesh.agents)}")
|
|
108
|
+
|
|
109
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
110
|
+
# WORKFLOW EXECUTION - Same API as autonomous mode
|
|
111
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
112
|
+
print("\n" + "-"*70)
|
|
113
|
+
print("Executing Pipeline: Collect → Process → Report")
|
|
114
|
+
print("-"*70)
|
|
115
|
+
|
|
116
|
+
results = await mesh.workflow("distributed-pipeline", [
|
|
117
|
+
{
|
|
118
|
+
"id": "collect",
|
|
119
|
+
"agent": "collector",
|
|
120
|
+
"task": "Generate a dataset of 10 products with name, price, and category"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "process",
|
|
124
|
+
"agent": "processor",
|
|
125
|
+
"task": "Calculate total value, average price, and count by category",
|
|
126
|
+
"depends_on": ["collect"]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"id": "report",
|
|
130
|
+
"agent": "reporter",
|
|
131
|
+
"task": "Create a summary report with the statistics",
|
|
132
|
+
"depends_on": ["process"]
|
|
133
|
+
}
|
|
134
|
+
])
|
|
135
|
+
|
|
136
|
+
# Display results
|
|
137
|
+
print("\n" + "="*70)
|
|
138
|
+
print("RESULTS")
|
|
139
|
+
print("="*70)
|
|
140
|
+
|
|
141
|
+
for i, result in enumerate(results):
|
|
142
|
+
step_names = ["Data Collection", "Data Processing", "Report Generation"]
|
|
143
|
+
print(f"\n{step_names[i]}:")
|
|
144
|
+
print(f" Status: {result['status']}")
|
|
145
|
+
if result['status'] == 'success':
|
|
146
|
+
output = str(result.get('output', ''))[:200]
|
|
147
|
+
print(f" Output: {output}...")
|
|
148
|
+
else:
|
|
149
|
+
print(f" Error: {result.get('error')}")
|
|
150
|
+
|
|
151
|
+
# Summary
|
|
152
|
+
successes = sum(1 for r in results if r['status'] == 'success')
|
|
153
|
+
print(f"\n{'='*70}")
|
|
154
|
+
print(f"Pipeline Complete: {successes}/{len(results)} steps successful")
|
|
155
|
+
print(f"{'='*70}")
|
|
156
|
+
|
|
157
|
+
await mesh.stop()
|
|
158
|
+
|
|
159
|
+
except Exception as e:
|
|
160
|
+
print(f"\nError: {e}")
|
|
161
|
+
import traceback
|
|
162
|
+
traceback.print_exc()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
166
|
+
# MULTI-NODE EXAMPLE (Reference)
|
|
167
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
168
|
+
|
|
169
|
+
async def multi_node_example():
|
|
170
|
+
"""
|
|
171
|
+
Example: Running agents across multiple machines.
|
|
172
|
+
|
|
173
|
+
Node 1 (seed node):
|
|
174
|
+
mesh = Mesh(mode="distributed", config={
|
|
175
|
+
'bind_host': '0.0.0.0',
|
|
176
|
+
'bind_port': 7950,
|
|
177
|
+
'node_name': 'node-1',
|
|
178
|
+
})
|
|
179
|
+
mesh.add(DataCollectorAgent)
|
|
180
|
+
await mesh.start()
|
|
181
|
+
await mesh.serve_forever() # Keep running
|
|
182
|
+
|
|
183
|
+
Node 2 (joins cluster):
|
|
184
|
+
mesh = Mesh(mode="distributed", config={
|
|
185
|
+
'bind_host': '0.0.0.0',
|
|
186
|
+
'bind_port': 7950,
|
|
187
|
+
'node_name': 'node-2',
|
|
188
|
+
'seed_nodes': '192.168.1.10:7950', # Node 1's address
|
|
189
|
+
})
|
|
190
|
+
mesh.add(DataProcessorAgent)
|
|
191
|
+
await mesh.start()
|
|
192
|
+
await mesh.serve_forever()
|
|
193
|
+
|
|
194
|
+
Node 3 (joins cluster):
|
|
195
|
+
mesh = Mesh(mode="distributed", config={
|
|
196
|
+
'bind_host': '0.0.0.0',
|
|
197
|
+
'bind_port': 7950,
|
|
198
|
+
'node_name': 'node-3',
|
|
199
|
+
'seed_nodes': '192.168.1.10:7950',
|
|
200
|
+
})
|
|
201
|
+
mesh.add(ReportWriterAgent)
|
|
202
|
+
await mesh.start()
|
|
203
|
+
await mesh.serve_forever()
|
|
204
|
+
|
|
205
|
+
Any node can now execute workflows that span all three!
|
|
206
|
+
"""
|
|
207
|
+
pass
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
if __name__ == "__main__":
|
|
211
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom Profile Example: Using @jarvis_agent Decorator
|
|
3
|
+
|
|
4
|
+
This example shows how to use the @jarvis_agent decorator to convert
|
|
5
|
+
any Python class into a JarvisCore agent without modifying the class.
|
|
6
|
+
|
|
7
|
+
Use Case: You have existing Python classes/agents and want JarvisCore
|
|
8
|
+
to handle orchestration (data handoff, dependencies, shared memory).
|
|
9
|
+
"""
|
|
10
|
+
import asyncio
|
|
11
|
+
from jarviscore import Mesh, jarvis_agent, JarvisContext
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Example 1: Simple decorator (no context needed)
|
|
15
|
+
@jarvis_agent(role="processor", capabilities=["data_processing"])
|
|
16
|
+
class DataProcessor:
|
|
17
|
+
"""Simple data processor - doubles input values."""
|
|
18
|
+
|
|
19
|
+
def run(self, data):
|
|
20
|
+
"""Process data by doubling values."""
|
|
21
|
+
if isinstance(data, list):
|
|
22
|
+
return {"processed": [x * 2 for x in data]}
|
|
23
|
+
return {"processed": data * 2}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Example 2: Decorator with context access
|
|
27
|
+
@jarvis_agent(role="aggregator", capabilities=["aggregation"])
|
|
28
|
+
class Aggregator:
|
|
29
|
+
"""Aggregates results from previous steps using JarvisContext."""
|
|
30
|
+
|
|
31
|
+
def run(self, task, ctx: JarvisContext):
|
|
32
|
+
"""
|
|
33
|
+
Access previous step results via ctx.previous().
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
task: The task description
|
|
37
|
+
ctx: JarvisContext with memory and dependency access
|
|
38
|
+
"""
|
|
39
|
+
# Get output from a specific previous step
|
|
40
|
+
processed = ctx.previous("step1")
|
|
41
|
+
|
|
42
|
+
if processed:
|
|
43
|
+
data = processed.get("processed", [])
|
|
44
|
+
return {
|
|
45
|
+
"sum": sum(data) if isinstance(data, list) else data,
|
|
46
|
+
"count": len(data) if isinstance(data, list) else 1,
|
|
47
|
+
"source_step": "step1"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {"error": "No previous data found"}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Example 3: Decorator with custom execute method
|
|
54
|
+
@jarvis_agent(role="validator", capabilities=["validation"], execute_method="validate")
|
|
55
|
+
class DataValidator:
|
|
56
|
+
"""Validates data using a custom method name."""
|
|
57
|
+
|
|
58
|
+
def validate(self, data):
|
|
59
|
+
"""Custom execute method - validates input data."""
|
|
60
|
+
if isinstance(data, list):
|
|
61
|
+
return {
|
|
62
|
+
"valid": all(isinstance(x, (int, float)) for x in data),
|
|
63
|
+
"count": len(data),
|
|
64
|
+
"type": "list"
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
"valid": isinstance(data, (int, float)),
|
|
68
|
+
"type": type(data).__name__
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def main():
|
|
73
|
+
"""Run a multi-step workflow with custom profile agents."""
|
|
74
|
+
print("=" * 60)
|
|
75
|
+
print(" Custom Profile Example: @jarvis_agent Decorator")
|
|
76
|
+
print("=" * 60)
|
|
77
|
+
|
|
78
|
+
# Create mesh in autonomous mode
|
|
79
|
+
mesh = Mesh(mode="autonomous")
|
|
80
|
+
|
|
81
|
+
# Add our decorated agents
|
|
82
|
+
mesh.add(DataProcessor)
|
|
83
|
+
mesh.add(Aggregator)
|
|
84
|
+
mesh.add(DataValidator)
|
|
85
|
+
|
|
86
|
+
# Start the mesh
|
|
87
|
+
await mesh.start()
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
# Execute a multi-step workflow
|
|
91
|
+
print("\nExecuting workflow with 3 steps...\n")
|
|
92
|
+
|
|
93
|
+
results = await mesh.workflow("custom-profile-demo", [
|
|
94
|
+
{
|
|
95
|
+
"id": "step1",
|
|
96
|
+
"agent": "processor",
|
|
97
|
+
"task": "Process input data",
|
|
98
|
+
"params": {"data": [1, 2, 3, 4, 5]}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "step2",
|
|
102
|
+
"agent": "aggregator",
|
|
103
|
+
"task": "Aggregate processed results",
|
|
104
|
+
"depends_on": ["step1"] # Wait for step1
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": "step3",
|
|
108
|
+
"agent": "validator",
|
|
109
|
+
"task": "Validate original data",
|
|
110
|
+
"params": {"data": [1, 2, 3, 4, 5]}
|
|
111
|
+
}
|
|
112
|
+
])
|
|
113
|
+
|
|
114
|
+
# Print results
|
|
115
|
+
print("Results:")
|
|
116
|
+
print("-" * 40)
|
|
117
|
+
|
|
118
|
+
for i, result in enumerate(results):
|
|
119
|
+
step_name = ["Processor", "Aggregator", "Validator"][i]
|
|
120
|
+
print(f"\n{step_name} (step{i+1}):")
|
|
121
|
+
print(f" Status: {result.get('status')}")
|
|
122
|
+
print(f" Output: {result.get('output')}")
|
|
123
|
+
|
|
124
|
+
print("\n" + "=" * 60)
|
|
125
|
+
print(" Workflow completed successfully!")
|
|
126
|
+
print("=" * 60)
|
|
127
|
+
|
|
128
|
+
finally:
|
|
129
|
+
# Stop the mesh
|
|
130
|
+
await mesh.stop()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
asyncio.run(main())
|