jarviscore-framework 0.1.0__py3-none-any.whl → 0.2.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/autoagent_distributed_example.py +211 -0
- examples/custom_profile_decorator.py +134 -0
- examples/custom_profile_wrap.py +168 -0
- examples/customagent_distributed_example.py +362 -0
- examples/customagent_p2p_example.py +347 -0
- jarviscore/__init__.py +60 -15
- jarviscore/adapter/__init__.py +40 -0
- jarviscore/adapter/decorator.py +336 -0
- jarviscore/adapter/wrapper.py +303 -0
- jarviscore/cli/check.py +18 -13
- jarviscore/cli/scaffold.py +178 -0
- jarviscore/cli/smoketest.py +3 -2
- jarviscore/context/__init__.py +40 -0
- jarviscore/context/dependency.py +160 -0
- jarviscore/context/jarvis_context.py +207 -0
- jarviscore/context/memory.py +155 -0
- jarviscore/core/agent.py +44 -1
- jarviscore/core/mesh.py +196 -35
- jarviscore/data/.env.example +146 -0
- jarviscore/data/__init__.py +7 -0
- jarviscore/data/examples/autoagent_distributed_example.py +211 -0
- jarviscore/data/examples/calculator_agent_example.py +77 -0
- jarviscore/data/examples/customagent_distributed_example.py +362 -0
- jarviscore/data/examples/customagent_p2p_example.py +347 -0
- jarviscore/data/examples/multi_agent_workflow.py +132 -0
- jarviscore/data/examples/research_agent_example.py +76 -0
- jarviscore/docs/API_REFERENCE.md +264 -51
- jarviscore/docs/AUTOAGENT_GUIDE.md +198 -0
- jarviscore/docs/CONFIGURATION.md +41 -23
- jarviscore/docs/CUSTOMAGENT_GUIDE.md +415 -0
- jarviscore/docs/GETTING_STARTED.md +113 -17
- jarviscore/docs/TROUBLESHOOTING.md +155 -13
- jarviscore/docs/USER_GUIDE.md +144 -363
- jarviscore/execution/llm.py +23 -16
- jarviscore/orchestration/engine.py +20 -8
- jarviscore/p2p/__init__.py +10 -0
- jarviscore/p2p/coordinator.py +129 -0
- jarviscore/p2p/messages.py +87 -0
- jarviscore/p2p/peer_client.py +576 -0
- jarviscore/p2p/peer_tool.py +268 -0
- jarviscore_framework-0.2.0.dist-info/METADATA +143 -0
- jarviscore_framework-0.2.0.dist-info/RECORD +132 -0
- {jarviscore_framework-0.1.0.dist-info → jarviscore_framework-0.2.0.dist-info}/WHEEL +1 -1
- {jarviscore_framework-0.1.0.dist-info → jarviscore_framework-0.2.0.dist-info}/top_level.txt +1 -0
- test_logs/code_registry/functions/data_generator-558779ed_560ebc37.py +7 -0
- test_logs/code_registry/functions/data_generator-5ed3609e_560ebc37.py +7 -0
- test_logs/code_registry/functions/data_generator-66da0356_43970bb9.py +25 -0
- test_logs/code_registry/functions/data_generator-7a2fac83_583709d9.py +36 -0
- test_logs/code_registry/functions/data_generator-888b670f_aa235863.py +9 -0
- test_logs/code_registry/functions/data_generator-9ca5f642_aa235863.py +9 -0
- test_logs/code_registry/functions/data_generator-bfd90775_560ebc37.py +7 -0
- test_logs/code_registry/functions/data_generator-e95d2f7d_aa235863.py +9 -0
- test_logs/code_registry/functions/data_generator-f60ca8a2_327eb8c2.py +29 -0
- test_logs/code_registry/functions/mathematician-02adf9ee_958658d9.py +19 -0
- test_logs/code_registry/functions/mathematician-0706fb57_5df13441.py +23 -0
- test_logs/code_registry/functions/mathematician-153c9c4a_ba59c918.py +83 -0
- test_logs/code_registry/functions/mathematician-287e61c0_41daa793.py +18 -0
- test_logs/code_registry/functions/mathematician-2967af5a_863c2cc6.py +17 -0
- test_logs/code_registry/functions/mathematician-303ca6d6_5df13441.py +23 -0
- test_logs/code_registry/functions/mathematician-308a4afd_cbf5064d.py +73 -0
- test_logs/code_registry/functions/mathematician-353f16e2_0968bcf5.py +18 -0
- test_logs/code_registry/functions/mathematician-3c22475a_41daa793.py +17 -0
- test_logs/code_registry/functions/mathematician-5bac1029_0968bcf5.py +18 -0
- test_logs/code_registry/functions/mathematician-640f76b2_9198780b.py +19 -0
- test_logs/code_registry/functions/mathematician-752fa7ea_863c2cc6.py +17 -0
- test_logs/code_registry/functions/mathematician-baf9ef39_0968bcf5.py +18 -0
- test_logs/code_registry/functions/mathematician-bc8b2a2f_5df13441.py +23 -0
- test_logs/code_registry/functions/mathematician-c31e4686_41daa793.py +18 -0
- test_logs/code_registry/functions/mathematician-cc84c84c_863c2cc6.py +17 -0
- test_logs/code_registry/functions/mathematician-dd7c7144_9198780b.py +19 -0
- test_logs/code_registry/functions/mathematician-e671c256_41ea4487.py +74 -0
- test_logs/code_registry/functions/report_generator-1a878fcc_18d44bdc.py +47 -0
- test_logs/code_registry/functions/report_generator-25c1c331_cea57d0d.py +35 -0
- test_logs/code_registry/functions/report_generator-37552117_e711c2b9.py +35 -0
- test_logs/code_registry/functions/report_generator-bc662768_e711c2b9.py +35 -0
- test_logs/code_registry/functions/report_generator-d6c0e76b_5e7722ec.py +44 -0
- test_logs/code_registry/functions/report_generator-f270fb02_680529c3.py +44 -0
- test_logs/code_registry/functions/text_processor-11393b14_4370d3ed.py +40 -0
- test_logs/code_registry/functions/text_processor-7d02dfc3_d3b569be.py +37 -0
- test_logs/code_registry/functions/text_processor-8adb5e32_9168c5fe.py +13 -0
- test_logs/code_registry/functions/text_processor-c58ffc19_78b4ceac.py +42 -0
- test_logs/code_registry/functions/text_processor-cd5977b1_9168c5fe.py +13 -0
- test_logs/code_registry/functions/text_processor-ec1c8773_9168c5fe.py +13 -0
- tests/test_01_analyst_standalone.py +124 -0
- tests/test_02_assistant_standalone.py +164 -0
- tests/test_03_analyst_with_framework.py +945 -0
- tests/test_04_assistant_with_framework.py +1002 -0
- tests/test_05_integration.py +1301 -0
- tests/test_06_real_llm_integration.py +760 -0
- tests/test_07_distributed_single_node.py +578 -0
- tests/test_08_distributed_multi_node.py +454 -0
- tests/test_09_distributed_autoagent.py +509 -0
- tests/test_10_distributed_customagent.py +787 -0
- tests/test_context.py +467 -0
- tests/test_decorator.py +622 -0
- tests/test_mesh.py +35 -4
- jarviscore_framework-0.1.0.dist-info/METADATA +0 -136
- jarviscore_framework-0.1.0.dist-info/RECORD +0 -55
- {jarviscore_framework-0.1.0.dist-info → jarviscore_framework-0.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# JARVISCORE FRAMEWORK CONFIGURATION
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# Copy this file to .env and fill in your values
|
|
5
|
+
# All settings are optional - framework provides sensible defaults
|
|
6
|
+
# Standard environment variable names (no JARVISCORE_ prefix)
|
|
7
|
+
|
|
8
|
+
# =============================================================================
|
|
9
|
+
# LLM CONFIGURATION (Zero-Config with Automatic Fallback)
|
|
10
|
+
# =============================================================================
|
|
11
|
+
# Framework tries providers in order: Claude → vLLM → Azure → Gemini
|
|
12
|
+
# At least ONE provider must be configured for AutoAgent to work
|
|
13
|
+
|
|
14
|
+
# --- Anthropic Claude ---
|
|
15
|
+
# Standard: CLAUDE_API_KEY or ANTHROPIC_API_KEY
|
|
16
|
+
# CLAUDE_API_KEY=your-anthropic-api-key
|
|
17
|
+
# CLAUDE_ENDPOINT=https://api.anthropic.com # Optional: custom endpoint
|
|
18
|
+
# CLAUDE_MODEL=claude-sonnet-4
|
|
19
|
+
|
|
20
|
+
# --- vLLM (Local/Self-Hosted) ---
|
|
21
|
+
# Recommended for development and cost-effective production
|
|
22
|
+
# LLM_ENDPOINT=http://localhost:8000
|
|
23
|
+
# LLM_MODEL=Qwen/Qwen2.5-Coder-32B-Instruct
|
|
24
|
+
|
|
25
|
+
# --- Azure OpenAI ---
|
|
26
|
+
# Standard: AZURE_API_KEY or AZURE_OPENAI_KEY
|
|
27
|
+
# AZURE_API_KEY=your-azure-openai-key
|
|
28
|
+
# AZURE_ENDPOINT=https://your-resource.openai.azure.com
|
|
29
|
+
# AZURE_DEPLOYMENT=gpt-4o
|
|
30
|
+
# AZURE_API_VERSION=2024-02-15-preview
|
|
31
|
+
|
|
32
|
+
# --- Google Gemini ---
|
|
33
|
+
# GEMINI_API_KEY=your-gemini-api-key
|
|
34
|
+
# GEMINI_MODEL=gemini-1.5-flash
|
|
35
|
+
# GEMINI_TEMPERATURE=0.1
|
|
36
|
+
# GEMINI_TIMEOUT=30.0
|
|
37
|
+
|
|
38
|
+
# Common LLM Settings
|
|
39
|
+
# LLM_TIMEOUT=120.0
|
|
40
|
+
# LLM_TEMPERATURE=0.7
|
|
41
|
+
|
|
42
|
+
# =============================================================================
|
|
43
|
+
# EXECUTION SETTINGS
|
|
44
|
+
# =============================================================================
|
|
45
|
+
# Sandbox execution and code generation limits
|
|
46
|
+
|
|
47
|
+
# Maximum execution time for generated code (seconds)
|
|
48
|
+
EXECUTION_TIMEOUT=300
|
|
49
|
+
|
|
50
|
+
# Maximum number of autonomous repair attempts
|
|
51
|
+
MAX_REPAIR_ATTEMPTS=3
|
|
52
|
+
|
|
53
|
+
# Maximum retries for failed operations
|
|
54
|
+
MAX_RETRIES=3
|
|
55
|
+
|
|
56
|
+
# =============================================================================
|
|
57
|
+
# SANDBOX CONFIGURATION (Phase 2)
|
|
58
|
+
# =============================================================================
|
|
59
|
+
# Sandbox execution mode: "local" (in-process) or "remote" (service)
|
|
60
|
+
# Default: local (for development)
|
|
61
|
+
# Production: remote (uses JarvisCore's Azure Container Apps sandbox)
|
|
62
|
+
SANDBOX_MODE=local
|
|
63
|
+
|
|
64
|
+
# Remote sandbox service URL (provided by JarvisCore)
|
|
65
|
+
# Azure Container Apps sandbox service - no setup required!
|
|
66
|
+
# Uncomment and set SANDBOX_MODE=remote to use it
|
|
67
|
+
# SANDBOX_SERVICE_URL=https://browser-task-executor.bravesea-3f5f7e75.eastus.azurecontainerapps.io
|
|
68
|
+
|
|
69
|
+
# =============================================================================
|
|
70
|
+
# STORAGE CONFIGURATION (Phase 1)
|
|
71
|
+
# =============================================================================
|
|
72
|
+
# Directory for result storage and code registry
|
|
73
|
+
LOG_DIRECTORY=./logs
|
|
74
|
+
|
|
75
|
+
# =============================================================================
|
|
76
|
+
# P2P CONFIGURATION (For Distributed Mode)
|
|
77
|
+
# =============================================================================
|
|
78
|
+
# Required only if using mesh in distributed mode
|
|
79
|
+
# Autonomous mode works without P2P
|
|
80
|
+
|
|
81
|
+
# Enable P2P mesh networking
|
|
82
|
+
P2P_ENABLED=true
|
|
83
|
+
|
|
84
|
+
# Node identification
|
|
85
|
+
NODE_NAME=jarviscore-node-1
|
|
86
|
+
|
|
87
|
+
# Bind address and port for P2P communication
|
|
88
|
+
BIND_HOST=127.0.0.1
|
|
89
|
+
BIND_PORT=7946
|
|
90
|
+
|
|
91
|
+
# Seed nodes to join existing mesh (comma-separated)
|
|
92
|
+
# Example: 192.168.1.100:7946,192.168.1.101:7946
|
|
93
|
+
# SEED_NODES=
|
|
94
|
+
|
|
95
|
+
# ZeroMQ port offset (P2P messaging)
|
|
96
|
+
ZMQ_PORT_OFFSET=1000
|
|
97
|
+
|
|
98
|
+
# Transport type: udp, tcp, or hybrid
|
|
99
|
+
TRANSPORT_TYPE=hybrid
|
|
100
|
+
|
|
101
|
+
# =============================================================================
|
|
102
|
+
# KEEPALIVE SETTINGS (P2P Health Monitoring)
|
|
103
|
+
# =============================================================================
|
|
104
|
+
|
|
105
|
+
# Enable smart keepalive (suppresses when active)
|
|
106
|
+
KEEPALIVE_ENABLED=true
|
|
107
|
+
|
|
108
|
+
# Keepalive interval (seconds)
|
|
109
|
+
KEEPALIVE_INTERVAL=90
|
|
110
|
+
|
|
111
|
+
# Keepalive timeout (seconds)
|
|
112
|
+
KEEPALIVE_TIMEOUT=10
|
|
113
|
+
|
|
114
|
+
# Activity suppression window (seconds)
|
|
115
|
+
# If agent is actively working, suppress keepalive for this duration
|
|
116
|
+
ACTIVITY_SUPPRESS_WINDOW=60
|
|
117
|
+
|
|
118
|
+
# =============================================================================
|
|
119
|
+
# LOGGING
|
|
120
|
+
# =============================================================================
|
|
121
|
+
# Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
122
|
+
LOG_LEVEL=INFO
|
|
123
|
+
|
|
124
|
+
# =============================================================================
|
|
125
|
+
# EXAMPLES
|
|
126
|
+
# =============================================================================
|
|
127
|
+
|
|
128
|
+
# Example 1: Local development with vLLM
|
|
129
|
+
# LLM_ENDPOINT=http://localhost:8000
|
|
130
|
+
# LLM_MODEL=Qwen/Qwen2.5-Coder-32B-Instruct
|
|
131
|
+
# P2P_ENABLED=false
|
|
132
|
+
|
|
133
|
+
# Example 2: Production with Azure OpenAI + P2P mesh
|
|
134
|
+
# AZURE_API_KEY=sk-...
|
|
135
|
+
# AZURE_ENDPOINT=https://my-resource.openai.azure.com
|
|
136
|
+
# AZURE_DEPLOYMENT=gpt-4o
|
|
137
|
+
# P2P_ENABLED=true
|
|
138
|
+
# BIND_HOST=0.0.0.0
|
|
139
|
+
# BIND_PORT=7946
|
|
140
|
+
# SEED_NODES=192.168.1.100:7946
|
|
141
|
+
|
|
142
|
+
# Example 3: Zero-config (use defaults)
|
|
143
|
+
# Just don't set any variables and framework will:
|
|
144
|
+
# - Try to detect available LLM providers
|
|
145
|
+
# - Use sensible defaults for all settings
|
|
146
|
+
# - Work in autonomous mode (no P2P)
|
|
@@ -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,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())
|