jarviscore-framework 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/calculator_agent_example.py +77 -0
- examples/multi_agent_workflow.py +132 -0
- examples/research_agent_example.py +76 -0
- jarviscore/__init__.py +54 -0
- jarviscore/cli/__init__.py +7 -0
- jarviscore/cli/__main__.py +33 -0
- jarviscore/cli/check.py +404 -0
- jarviscore/cli/smoketest.py +371 -0
- jarviscore/config/__init__.py +7 -0
- jarviscore/config/settings.py +128 -0
- jarviscore/core/__init__.py +7 -0
- jarviscore/core/agent.py +163 -0
- jarviscore/core/mesh.py +463 -0
- jarviscore/core/profile.py +64 -0
- jarviscore/docs/API_REFERENCE.md +932 -0
- jarviscore/docs/CONFIGURATION.md +753 -0
- jarviscore/docs/GETTING_STARTED.md +600 -0
- jarviscore/docs/TROUBLESHOOTING.md +424 -0
- jarviscore/docs/USER_GUIDE.md +983 -0
- jarviscore/execution/__init__.py +94 -0
- jarviscore/execution/code_registry.py +298 -0
- jarviscore/execution/generator.py +268 -0
- jarviscore/execution/llm.py +430 -0
- jarviscore/execution/repair.py +283 -0
- jarviscore/execution/result_handler.py +332 -0
- jarviscore/execution/sandbox.py +555 -0
- jarviscore/execution/search.py +281 -0
- jarviscore/orchestration/__init__.py +18 -0
- jarviscore/orchestration/claimer.py +101 -0
- jarviscore/orchestration/dependency.py +143 -0
- jarviscore/orchestration/engine.py +292 -0
- jarviscore/orchestration/status.py +96 -0
- jarviscore/p2p/__init__.py +23 -0
- jarviscore/p2p/broadcaster.py +353 -0
- jarviscore/p2p/coordinator.py +364 -0
- jarviscore/p2p/keepalive.py +361 -0
- jarviscore/p2p/swim_manager.py +290 -0
- jarviscore/profiles/__init__.py +6 -0
- jarviscore/profiles/autoagent.py +264 -0
- jarviscore/profiles/customagent.py +137 -0
- jarviscore_framework-0.1.0.dist-info/METADATA +136 -0
- jarviscore_framework-0.1.0.dist-info/RECORD +55 -0
- jarviscore_framework-0.1.0.dist-info/WHEEL +5 -0
- jarviscore_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
- jarviscore_framework-0.1.0.dist-info/top_level.txt +3 -0
- tests/conftest.py +44 -0
- tests/test_agent.py +165 -0
- tests/test_autoagent.py +140 -0
- tests/test_autoagent_day4.py +186 -0
- tests/test_customagent.py +248 -0
- tests/test_integration.py +293 -0
- tests/test_llm_fallback.py +185 -0
- tests/test_mesh.py +356 -0
- tests/test_p2p_integration.py +375 -0
- tests/test_remote_sandbox.py +116 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Calculator Agent Example - Simple Math Operations
|
|
3
|
+
|
|
4
|
+
Demonstrates AutoAgent with code generation for mathematical tasks.
|
|
5
|
+
Zero configuration required - just define the agent and run.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python examples/calculator_agent_example.py
|
|
9
|
+
"""
|
|
10
|
+
import asyncio
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# Add parent directory to path
|
|
15
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
16
|
+
|
|
17
|
+
from jarviscore import Mesh
|
|
18
|
+
from jarviscore.profiles import AutoAgent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CalculatorAgent(AutoAgent):
|
|
22
|
+
"""Math expert agent that generates code to solve problems."""
|
|
23
|
+
role = "calculator"
|
|
24
|
+
capabilities = ["math", "calculation", "arithmetic"]
|
|
25
|
+
system_prompt = """
|
|
26
|
+
You are a math expert. Generate Python code to solve mathematical problems.
|
|
27
|
+
Store the final answer in a variable named 'result'.
|
|
28
|
+
Use standard math operations and the math module when needed.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def main():
|
|
33
|
+
"""Run calculator agent examples."""
|
|
34
|
+
print("\n" + "="*60)
|
|
35
|
+
print("JarvisCore: Calculator Agent Example")
|
|
36
|
+
print("="*60)
|
|
37
|
+
|
|
38
|
+
# Zero-config: Framework auto-detects LLM from .env
|
|
39
|
+
# Tries: Claude → Azure → Gemini → vLLM (based on .env)
|
|
40
|
+
# Or pass custom config dict to override
|
|
41
|
+
|
|
42
|
+
# Create mesh and add agent (reads from .env automatically)
|
|
43
|
+
mesh = Mesh(mode="autonomous")
|
|
44
|
+
mesh.add(CalculatorAgent)
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
await mesh.start()
|
|
48
|
+
print("✓ Mesh started successfully\n")
|
|
49
|
+
|
|
50
|
+
# Example 1: Simple calculation
|
|
51
|
+
print("Example 1: Calculate factorial of 10")
|
|
52
|
+
print("-" * 60)
|
|
53
|
+
|
|
54
|
+
results = await mesh.workflow("factorial", [
|
|
55
|
+
{
|
|
56
|
+
"agent": "calculator",
|
|
57
|
+
"task": "Calculate the factorial of 10"
|
|
58
|
+
}
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
result = results[0]
|
|
62
|
+
print(f"Status: {result['status']}")
|
|
63
|
+
print(f"Result: {result.get('output')}")
|
|
64
|
+
print(f"Repairs needed: {result.get('repairs', 0)}")
|
|
65
|
+
print(f"Generated code:\n{result.get('code', 'N/A')}\n")
|
|
66
|
+
|
|
67
|
+
await mesh.stop()
|
|
68
|
+
print("✓ Mesh stopped\n")
|
|
69
|
+
|
|
70
|
+
except Exception as e:
|
|
71
|
+
print(f"\n✗ Error: {e}")
|
|
72
|
+
import traceback
|
|
73
|
+
traceback.print_exc()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Multi-Agent Workflow Example
|
|
3
|
+
|
|
4
|
+
Demonstrates multiple AutoAgents collaborating on a workflow with dependencies.
|
|
5
|
+
Shows how agents can pass data between steps automatically.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python examples/multi_agent_workflow.py
|
|
9
|
+
"""
|
|
10
|
+
import asyncio
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# Add parent directory to path
|
|
15
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
16
|
+
|
|
17
|
+
from jarviscore import Mesh
|
|
18
|
+
from jarviscore.profiles import AutoAgent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DataGeneratorAgent(AutoAgent):
|
|
22
|
+
"""Generates sample data."""
|
|
23
|
+
role = "generator"
|
|
24
|
+
capabilities = ["data_generation", "random_data"]
|
|
25
|
+
system_prompt = """
|
|
26
|
+
You are a data generator. Create sample datasets based on specifications.
|
|
27
|
+
Use Python's random module or create structured data.
|
|
28
|
+
Store the generated data in a variable named 'result'.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DataAnalyzerAgent(AutoAgent):
|
|
33
|
+
"""Analyzes data and computes statistics."""
|
|
34
|
+
role = "analyzer"
|
|
35
|
+
capabilities = ["data_analysis", "statistics"]
|
|
36
|
+
system_prompt = """
|
|
37
|
+
You are a data analyst. Analyze datasets and compute statistics.
|
|
38
|
+
Calculate mean, median, standard deviation, and find patterns.
|
|
39
|
+
Store your analysis results in a variable named 'result'.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ReportGeneratorAgent(AutoAgent):
|
|
44
|
+
"""Creates formatted reports."""
|
|
45
|
+
role = "reporter"
|
|
46
|
+
capabilities = ["report_generation", "formatting"]
|
|
47
|
+
system_prompt = """
|
|
48
|
+
You are a report generator. Create well-formatted reports from data.
|
|
49
|
+
Generate markdown or plain text reports with clear sections.
|
|
50
|
+
Store the formatted report in a variable named 'result'.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def main():
|
|
55
|
+
"""Run multi-agent workflow."""
|
|
56
|
+
print("\n" + "="*60)
|
|
57
|
+
print("JarvisCore: Multi-Agent Workflow Example")
|
|
58
|
+
print("="*60)
|
|
59
|
+
|
|
60
|
+
# Zero-config: Reads from .env automatically
|
|
61
|
+
# Framework tries: Claude → Azure → Gemini → vLLM
|
|
62
|
+
|
|
63
|
+
# Create mesh with all agents
|
|
64
|
+
mesh = Mesh(mode="autonomous")
|
|
65
|
+
mesh.add(DataGeneratorAgent)
|
|
66
|
+
mesh.add(DataAnalyzerAgent)
|
|
67
|
+
mesh.add(ReportGeneratorAgent)
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
await mesh.start()
|
|
71
|
+
print(f"✓ Mesh started with {len(mesh.agents)} agents\n")
|
|
72
|
+
|
|
73
|
+
print("Workflow: Generate → Analyze → Report")
|
|
74
|
+
print("-" * 60)
|
|
75
|
+
|
|
76
|
+
# Execute 3-step workflow with dependencies
|
|
77
|
+
results = await mesh.workflow("data-pipeline", [
|
|
78
|
+
{
|
|
79
|
+
"id": "generate",
|
|
80
|
+
"agent": "generator",
|
|
81
|
+
"task": "Generate a list of 20 random numbers between 1 and 100"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "analyze",
|
|
85
|
+
"agent": "analyzer",
|
|
86
|
+
"task": "Calculate mean, median, min, max, and standard deviation of the data",
|
|
87
|
+
"depends_on": ["generate"] # Waits for generator to complete
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "report",
|
|
91
|
+
"agent": "reporter",
|
|
92
|
+
"task": "Create a formatted report with the statistics",
|
|
93
|
+
"depends_on": ["analyze"] # Waits for analyzer to complete
|
|
94
|
+
}
|
|
95
|
+
])
|
|
96
|
+
|
|
97
|
+
# Display results
|
|
98
|
+
print("\n" + "="*60)
|
|
99
|
+
print("RESULTS")
|
|
100
|
+
print("="*60)
|
|
101
|
+
|
|
102
|
+
print(f"\nStep 1 - Data Generation:")
|
|
103
|
+
print(f" Status: {results[0]['status']}")
|
|
104
|
+
print(f" Output: {results[0].get('output')}")
|
|
105
|
+
|
|
106
|
+
print(f"\nStep 2 - Data Analysis:")
|
|
107
|
+
print(f" Status: {results[1]['status']}")
|
|
108
|
+
print(f" Output: {results[1].get('output')}")
|
|
109
|
+
|
|
110
|
+
print(f"\nStep 3 - Report Generation:")
|
|
111
|
+
print(f" Status: {results[2]['status']}")
|
|
112
|
+
print(f" Report:\n{results[2].get('output')}")
|
|
113
|
+
|
|
114
|
+
print(f"\n" + "="*60)
|
|
115
|
+
print("WORKFLOW SUMMARY")
|
|
116
|
+
print("="*60)
|
|
117
|
+
total_repairs = sum(r.get('repairs', 0) for r in results)
|
|
118
|
+
print(f"Total steps: {len(results)}")
|
|
119
|
+
print(f"Successful: {sum(1 for r in results if r['status'] == 'success')}")
|
|
120
|
+
print(f"Total repairs: {total_repairs}")
|
|
121
|
+
|
|
122
|
+
await mesh.stop()
|
|
123
|
+
print("\n✓ Workflow completed\n")
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
print(f"\n✗ Error: {e}")
|
|
127
|
+
import traceback
|
|
128
|
+
traceback.print_exc()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Research Agent Example - Internet Search & Data Extraction
|
|
3
|
+
|
|
4
|
+
Demonstrates AutoAgent with internet search capabilities.
|
|
5
|
+
Agent automatically gets access to web search tools (DuckDuckGo).
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python examples/research_agent_example.py
|
|
9
|
+
"""
|
|
10
|
+
import asyncio
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# Add parent directory to path
|
|
15
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
16
|
+
|
|
17
|
+
from jarviscore import Mesh
|
|
18
|
+
from jarviscore.profiles import AutoAgent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ResearchAgent(AutoAgent):
|
|
22
|
+
"""Research assistant with internet access."""
|
|
23
|
+
role = "researcher"
|
|
24
|
+
capabilities = ["research", "web_search", "information_gathering"]
|
|
25
|
+
system_prompt = """
|
|
26
|
+
You are a research assistant with internet access.
|
|
27
|
+
Search the web for information and provide concise summaries.
|
|
28
|
+
Use the 'search' object available in your code:
|
|
29
|
+
- await search.search(query, max_results=5)
|
|
30
|
+
- await search.extract_content(url)
|
|
31
|
+
- await search.search_and_extract(query, num_results=3)
|
|
32
|
+
Store your findings in a variable named 'result'.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def main():
|
|
37
|
+
"""Run research agent example."""
|
|
38
|
+
print("\n" + "="*60)
|
|
39
|
+
print("JarvisCore: Research Agent Example")
|
|
40
|
+
print("="*60)
|
|
41
|
+
|
|
42
|
+
# Zero-config: Reads from .env automatically
|
|
43
|
+
# Framework auto-detects: Claude → Azure → Gemini → vLLM
|
|
44
|
+
mesh = Mesh(mode="autonomous")
|
|
45
|
+
mesh.add(ResearchAgent)
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
await mesh.start()
|
|
49
|
+
print("✓ Mesh started with internet search enabled\n")
|
|
50
|
+
|
|
51
|
+
print("Example: Research Python asyncio")
|
|
52
|
+
print("-" * 60)
|
|
53
|
+
|
|
54
|
+
results = await mesh.workflow("research-asyncio", [
|
|
55
|
+
{
|
|
56
|
+
"agent": "researcher",
|
|
57
|
+
"task": "Search for 'Python asyncio tutorial' and summarize the top 2 results"
|
|
58
|
+
}
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
result = results[0]
|
|
62
|
+
print(f"Status: {result['status']}")
|
|
63
|
+
print(f"Summary:\n{result.get('output')}")
|
|
64
|
+
print(f"\nRepairs needed: {result.get('repairs', 0)}")
|
|
65
|
+
|
|
66
|
+
await mesh.stop()
|
|
67
|
+
print("\n✓ Research completed\n")
|
|
68
|
+
|
|
69
|
+
except Exception as e:
|
|
70
|
+
print(f"\n✗ Error: {e}")
|
|
71
|
+
import traceback
|
|
72
|
+
traceback.print_exc()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
asyncio.run(main())
|
jarviscore/__init__.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JarvisCore - P2P Distributed Agent Framework
|
|
3
|
+
|
|
4
|
+
A production-grade framework for building autonomous agent systems with:
|
|
5
|
+
- Event-sourced state management (crash recovery, HITL support)
|
|
6
|
+
- P2P coordination via SWIM protocol
|
|
7
|
+
- Two execution profiles:
|
|
8
|
+
* AutoAgent: LLM code generation (3 lines of user code)
|
|
9
|
+
* CustomAgent: Framework-agnostic (LangChain, MCP, raw Python)
|
|
10
|
+
|
|
11
|
+
Quick Start:
|
|
12
|
+
from jarviscore import Mesh, AutoAgent
|
|
13
|
+
|
|
14
|
+
class ScraperAgent(AutoAgent):
|
|
15
|
+
role = "scraper"
|
|
16
|
+
capabilities = ["web_scraping"]
|
|
17
|
+
system_prompt = "You are an expert web scraper..."
|
|
18
|
+
|
|
19
|
+
mesh = Mesh(mode="autonomous")
|
|
20
|
+
mesh.add(ScraperAgent)
|
|
21
|
+
await mesh.start()
|
|
22
|
+
|
|
23
|
+
results = await mesh.workflow("my-workflow", [
|
|
24
|
+
{"agent": "scraper", "task": "Scrape example.com"}
|
|
25
|
+
])
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
__version__ = "0.1.0"
|
|
29
|
+
__author__ = "JarvisCore Contributors"
|
|
30
|
+
__license__ = "MIT"
|
|
31
|
+
|
|
32
|
+
# Core classes
|
|
33
|
+
from jarviscore.core.agent import Agent
|
|
34
|
+
from jarviscore.core.profile import Profile
|
|
35
|
+
from jarviscore.core.mesh import Mesh, MeshMode
|
|
36
|
+
|
|
37
|
+
# Execution profiles
|
|
38
|
+
from jarviscore.profiles.autoagent import AutoAgent
|
|
39
|
+
from jarviscore.profiles.customagent import CustomAgent
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
# Version
|
|
43
|
+
"__version__",
|
|
44
|
+
|
|
45
|
+
# Core
|
|
46
|
+
"Agent",
|
|
47
|
+
"Profile",
|
|
48
|
+
"Mesh",
|
|
49
|
+
"MeshMode",
|
|
50
|
+
|
|
51
|
+
# Profiles
|
|
52
|
+
"AutoAgent",
|
|
53
|
+
"CustomAgent",
|
|
54
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI entry point for JarvisCore commands.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
python -m jarviscore.cli.check
|
|
6
|
+
python -m jarviscore.cli.smoketest
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
def main():
|
|
12
|
+
if len(sys.argv) < 2:
|
|
13
|
+
print("Usage: python -m jarviscore.cli <command>")
|
|
14
|
+
print("\nAvailable commands:")
|
|
15
|
+
print(" check - Health check and validation")
|
|
16
|
+
print(" smoketest - Quick smoke test")
|
|
17
|
+
sys.exit(1)
|
|
18
|
+
|
|
19
|
+
command = sys.argv[1]
|
|
20
|
+
sys.argv = [sys.argv[0]] + sys.argv[2:] # Remove command from argv
|
|
21
|
+
|
|
22
|
+
if command == 'check':
|
|
23
|
+
from .check import main as check_main
|
|
24
|
+
check_main()
|
|
25
|
+
elif command == 'smoketest':
|
|
26
|
+
from .smoketest import main as smoketest_main
|
|
27
|
+
smoketest_main()
|
|
28
|
+
else:
|
|
29
|
+
print(f"Unknown command: {command}")
|
|
30
|
+
sys.exit(1)
|
|
31
|
+
|
|
32
|
+
if __name__ == '__main__':
|
|
33
|
+
main()
|