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,932 @@
|
|
|
1
|
+
# JarvisCore API Reference
|
|
2
|
+
|
|
3
|
+
Complete API documentation for JarvisCore framework components.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Core Components](#core-components)
|
|
10
|
+
- [Mesh](#mesh)
|
|
11
|
+
- [Agent](#agent)
|
|
12
|
+
- [Profile](#profile)
|
|
13
|
+
2. [Agent Profiles](#agent-profiles)
|
|
14
|
+
- [AutoAgent](#autoagent)
|
|
15
|
+
- [CustomAgent](#customagent)
|
|
16
|
+
3. [Execution Components](#execution-components)
|
|
17
|
+
- [CodeGenerator](#codegenerator)
|
|
18
|
+
- [SandboxExecutor](#sandboxexecutor)
|
|
19
|
+
- [AutoRepair](#autorepair)
|
|
20
|
+
4. [Storage Components](#storage-components)
|
|
21
|
+
- [ResultHandler](#resulthandler)
|
|
22
|
+
- [CodeRegistry](#coderegistry)
|
|
23
|
+
5. [Orchestration](#orchestration)
|
|
24
|
+
- [WorkflowEngine](#workflowengine)
|
|
25
|
+
6. [Utilities](#utilities)
|
|
26
|
+
- [InternetSearch](#internetsearch)
|
|
27
|
+
- [UnifiedLLMClient](#unifiedllmclient)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Core Components
|
|
32
|
+
|
|
33
|
+
### Mesh
|
|
34
|
+
|
|
35
|
+
The central orchestrator for managing agents and workflows.
|
|
36
|
+
|
|
37
|
+
#### Class: `Mesh`
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from jarviscore import Mesh
|
|
41
|
+
|
|
42
|
+
mesh = Mesh(mode="autonomous") # or "distributed"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Parameters:**
|
|
46
|
+
- `mode` (str): Execution mode - "autonomous" (single-node) or "distributed" (P2P mesh)
|
|
47
|
+
- `config` (dict, optional): Configuration dictionary
|
|
48
|
+
|
|
49
|
+
**Methods:**
|
|
50
|
+
|
|
51
|
+
#### `add_agent(profile_class, role, capabilities, **kwargs)`
|
|
52
|
+
|
|
53
|
+
Register an agent in the mesh.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from jarviscore.profiles import AutoAgent
|
|
57
|
+
|
|
58
|
+
mesh.add_agent(
|
|
59
|
+
AutoAgent,
|
|
60
|
+
role="calculator",
|
|
61
|
+
capabilities=["math", "calculation"],
|
|
62
|
+
system_prompt="You are a math expert"
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Parameters:**
|
|
67
|
+
- `profile_class`: Agent profile class (AutoAgent or CustomAgent)
|
|
68
|
+
- `role` (str): Unique agent role identifier
|
|
69
|
+
- `capabilities` (list): List of capability strings
|
|
70
|
+
- `**kwargs`: Additional agent-specific parameters
|
|
71
|
+
|
|
72
|
+
**Returns:** Agent instance
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
#### `async start()`
|
|
77
|
+
|
|
78
|
+
Start the mesh and initialize all agents.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
await mesh.start()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Raises:** `RuntimeError` if no agents registered or already started
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
#### `async stop()`
|
|
89
|
+
|
|
90
|
+
Stop the mesh and cleanup all agents.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
await mesh.stop()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
#### `async run_workflow(steps)`
|
|
99
|
+
|
|
100
|
+
Execute a multi-step workflow with dependency management.
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
results = await mesh.run_workflow([
|
|
104
|
+
{"agent": "scraper", "task": "Scrape data from URL"},
|
|
105
|
+
{"agent": "processor", "task": "Clean the data", "depends_on": [0]},
|
|
106
|
+
{"agent": "storage", "task": "Save to database", "depends_on": [1]}
|
|
107
|
+
])
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Parameters:**
|
|
111
|
+
- `steps` (list): List of step dictionaries with keys:
|
|
112
|
+
- `agent` (str): Role or capability of target agent
|
|
113
|
+
- `task` (str): Task description
|
|
114
|
+
- `depends_on` (list, optional): List of step indices/IDs this step depends on
|
|
115
|
+
- `id` (str, optional): Custom step identifier
|
|
116
|
+
|
|
117
|
+
**Returns:** List of result dictionaries
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Agent
|
|
122
|
+
|
|
123
|
+
Base class for all agents. Inherit from this to create custom agents.
|
|
124
|
+
|
|
125
|
+
#### Class: `Agent`
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from jarviscore.core import Agent
|
|
129
|
+
|
|
130
|
+
class MyAgent(Agent):
|
|
131
|
+
async def execute_task(self, task):
|
|
132
|
+
# Your implementation
|
|
133
|
+
return {"status": "success", "output": result}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Attributes:**
|
|
137
|
+
- `agent_id` (str): Unique agent identifier
|
|
138
|
+
- `role` (str): Agent role
|
|
139
|
+
- `capabilities` (list): List of capabilities
|
|
140
|
+
- `mesh`: Reference to parent mesh (set automatically)
|
|
141
|
+
|
|
142
|
+
**Methods:**
|
|
143
|
+
|
|
144
|
+
#### `can_handle(task)`
|
|
145
|
+
|
|
146
|
+
Check if agent can handle a task.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
if agent.can_handle({"agent": "calculator"}):
|
|
150
|
+
result = await agent.execute_task(task)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Parameters:**
|
|
154
|
+
- `task` (dict): Task dictionary with `agent` or `capability` key
|
|
155
|
+
|
|
156
|
+
**Returns:** bool
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
#### `async execute_task(task)`
|
|
161
|
+
|
|
162
|
+
Execute a task (must be implemented by subclasses).
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
async def execute_task(self, task):
|
|
166
|
+
task_desc = task.get('task', '')
|
|
167
|
+
# Process task
|
|
168
|
+
return {
|
|
169
|
+
"status": "success",
|
|
170
|
+
"output": result,
|
|
171
|
+
"agent": self.agent_id
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Parameters:**
|
|
176
|
+
- `task` (dict): Task dictionary with `task` key
|
|
177
|
+
|
|
178
|
+
**Returns:** Result dictionary with `status`, `output`, `agent` keys
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### Profile
|
|
183
|
+
|
|
184
|
+
Base class for agent profiles (AutoAgent, CustomAgent).
|
|
185
|
+
|
|
186
|
+
#### Class: `Profile(Agent)`
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from jarviscore.core import Profile
|
|
190
|
+
|
|
191
|
+
class MyProfile(Profile):
|
|
192
|
+
async def setup(self):
|
|
193
|
+
# Initialize components
|
|
194
|
+
pass
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Methods:**
|
|
198
|
+
|
|
199
|
+
#### `async setup()`
|
|
200
|
+
|
|
201
|
+
Initialize agent components (called during mesh.start()).
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
async def setup(self):
|
|
205
|
+
self.llm_client = create_llm_client()
|
|
206
|
+
self.my_tool = MyTool()
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
#### `async teardown()`
|
|
212
|
+
|
|
213
|
+
Cleanup agent resources (called during mesh.stop()).
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
async def teardown(self):
|
|
217
|
+
await self.llm_client.close()
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Agent Profiles
|
|
223
|
+
|
|
224
|
+
### AutoAgent
|
|
225
|
+
|
|
226
|
+
Zero-config autonomous agent with LLM-powered code generation.
|
|
227
|
+
|
|
228
|
+
#### Class: `AutoAgent(Profile)`
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from jarviscore.profiles import AutoAgent
|
|
232
|
+
|
|
233
|
+
agent = AutoAgent(
|
|
234
|
+
role="researcher",
|
|
235
|
+
capabilities=["research", "web_search"],
|
|
236
|
+
system_prompt="You are a research expert",
|
|
237
|
+
enable_search=True
|
|
238
|
+
)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Parameters:**
|
|
242
|
+
- `role` (str): Agent role identifier
|
|
243
|
+
- `capabilities` (list): List of capability strings
|
|
244
|
+
- `system_prompt` (str): LLM system prompt defining agent expertise
|
|
245
|
+
- `enable_search` (bool, optional): Enable internet search (default: False)
|
|
246
|
+
- `max_repair_attempts` (int, optional): Max code repair attempts (default: 3)
|
|
247
|
+
|
|
248
|
+
**Features:**
|
|
249
|
+
- Automatic LLM-based code generation
|
|
250
|
+
- Autonomous code repair (up to 3 attempts)
|
|
251
|
+
- Internet search integration (DuckDuckGo)
|
|
252
|
+
- Result storage with file-based persistence
|
|
253
|
+
- Code registry for function reuse
|
|
254
|
+
- Local and remote sandbox execution
|
|
255
|
+
|
|
256
|
+
**Example:**
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
from jarviscore import Mesh
|
|
260
|
+
from jarviscore.profiles import AutoAgent
|
|
261
|
+
|
|
262
|
+
mesh = Mesh(mode="autonomous")
|
|
263
|
+
|
|
264
|
+
# Add research agent with internet access
|
|
265
|
+
mesh.add_agent(
|
|
266
|
+
AutoAgent,
|
|
267
|
+
role="researcher",
|
|
268
|
+
capabilities=["research", "web_search"],
|
|
269
|
+
system_prompt="You are an expert researcher",
|
|
270
|
+
enable_search=True
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
await mesh.start()
|
|
274
|
+
|
|
275
|
+
# Execute task
|
|
276
|
+
results = await mesh.run_workflow([
|
|
277
|
+
{"agent": "researcher", "task": "Search for Python async tutorials"}
|
|
278
|
+
])
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**AutoAgent Components:**
|
|
282
|
+
- `codegen`: CodeGenerator instance
|
|
283
|
+
- `sandbox`: SandboxExecutor instance
|
|
284
|
+
- `repair`: AutoRepair instance
|
|
285
|
+
- `result_handler`: ResultHandler instance
|
|
286
|
+
- `code_registry`: CodeRegistry instance
|
|
287
|
+
- `search`: InternetSearch instance (if enabled)
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### CustomAgent
|
|
292
|
+
|
|
293
|
+
Flexible agent profile for integrating external frameworks.
|
|
294
|
+
|
|
295
|
+
#### Class: `CustomAgent(Profile)`
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
from jarviscore.profiles import CustomAgent
|
|
299
|
+
|
|
300
|
+
class LangChainAgent(CustomAgent):
|
|
301
|
+
async def setup(self):
|
|
302
|
+
from langchain import LLMChain
|
|
303
|
+
self.chain = LLMChain(...)
|
|
304
|
+
|
|
305
|
+
async def execute_task(self, task):
|
|
306
|
+
result = await self.chain.arun(task['task'])
|
|
307
|
+
return {
|
|
308
|
+
"status": "success",
|
|
309
|
+
"output": result,
|
|
310
|
+
"agent": self.agent_id
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Features:**
|
|
315
|
+
- Integrate LangChain, LlamaIndex, Haystack, CrewAI, etc.
|
|
316
|
+
- Manual control over execution logic
|
|
317
|
+
- Optional cost tracking with `track_cost()`
|
|
318
|
+
- Full access to mesh and workflow context
|
|
319
|
+
|
|
320
|
+
**Example:**
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
class APIAgent(CustomAgent):
|
|
324
|
+
async def setup(self):
|
|
325
|
+
self.api_client = MyAPIClient()
|
|
326
|
+
|
|
327
|
+
async def execute_task(self, task):
|
|
328
|
+
# Manual implementation
|
|
329
|
+
response = await self.api_client.call(task['task'])
|
|
330
|
+
|
|
331
|
+
# Optional cost tracking
|
|
332
|
+
self.track_cost(
|
|
333
|
+
input_tokens=100,
|
|
334
|
+
output_tokens=50,
|
|
335
|
+
cost_usd=0.01
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
return {
|
|
339
|
+
"status": "success",
|
|
340
|
+
"output": response,
|
|
341
|
+
"agent": self.agent_id
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Execution Components
|
|
348
|
+
|
|
349
|
+
### CodeGenerator
|
|
350
|
+
|
|
351
|
+
LLM-based Python code generation from natural language.
|
|
352
|
+
|
|
353
|
+
#### Class: `CodeGenerator`
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
from jarviscore.execution import create_code_generator
|
|
357
|
+
|
|
358
|
+
codegen = create_code_generator(llm_client, search_client)
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Parameters:**
|
|
362
|
+
- `llm_client`: UnifiedLLMClient instance
|
|
363
|
+
- `search_client` (optional): InternetSearch instance
|
|
364
|
+
|
|
365
|
+
**Methods:**
|
|
366
|
+
|
|
367
|
+
#### `async generate(task, system_prompt, context=None, enable_search=True)`
|
|
368
|
+
|
|
369
|
+
Generate Python code for a task.
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
code = await codegen.generate(
|
|
373
|
+
task={"task": "Calculate factorial of 10"},
|
|
374
|
+
system_prompt="You are a math expert",
|
|
375
|
+
enable_search=False
|
|
376
|
+
)
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Parameters:**
|
|
380
|
+
- `task` (dict): Task dictionary with `task` key
|
|
381
|
+
- `system_prompt` (str): Agent's system prompt
|
|
382
|
+
- `context` (dict, optional): Context from previous steps
|
|
383
|
+
- `enable_search` (bool): Auto-inject search tools if available
|
|
384
|
+
|
|
385
|
+
**Returns:** Python code string
|
|
386
|
+
|
|
387
|
+
**Features:**
|
|
388
|
+
- Automatic syntax validation
|
|
389
|
+
- Code cleaning (removes markdown, comments)
|
|
390
|
+
- Search tool auto-injection for research tasks
|
|
391
|
+
- Context-aware code generation
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
### SandboxExecutor
|
|
396
|
+
|
|
397
|
+
Safe code execution with resource limits and remote execution support.
|
|
398
|
+
|
|
399
|
+
#### Class: `SandboxExecutor`
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
from jarviscore.execution import create_sandbox_executor
|
|
403
|
+
|
|
404
|
+
executor = create_sandbox_executor(
|
|
405
|
+
timeout=300,
|
|
406
|
+
search_client=None,
|
|
407
|
+
config={
|
|
408
|
+
'sandbox_mode': 'remote',
|
|
409
|
+
'sandbox_service_url': 'https://...'
|
|
410
|
+
}
|
|
411
|
+
)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Parameters:**
|
|
415
|
+
- `timeout` (int): Max execution time in seconds (default: 300)
|
|
416
|
+
- `search_client` (optional): InternetSearch for web access
|
|
417
|
+
- `config` (dict, optional): Configuration with:
|
|
418
|
+
- `sandbox_mode`: "local" or "remote"
|
|
419
|
+
- `sandbox_service_url`: URL for remote sandbox
|
|
420
|
+
|
|
421
|
+
**Methods:**
|
|
422
|
+
|
|
423
|
+
#### `async execute(code, timeout=None, context=None)`
|
|
424
|
+
|
|
425
|
+
Execute Python code in isolated sandbox.
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
result = await executor.execute(
|
|
429
|
+
code="result = 2 + 2",
|
|
430
|
+
timeout=10,
|
|
431
|
+
context={"previous_result": 42}
|
|
432
|
+
)
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**Parameters:**
|
|
436
|
+
- `code` (str): Python code to execute
|
|
437
|
+
- `timeout` (int, optional): Override default timeout
|
|
438
|
+
- `context` (dict, optional): Variables to inject into namespace
|
|
439
|
+
|
|
440
|
+
**Returns:**
|
|
441
|
+
```python
|
|
442
|
+
{
|
|
443
|
+
"status": "success" | "failure",
|
|
444
|
+
"output": Any, # Value of 'result' variable
|
|
445
|
+
"error": str, # Error message if failed
|
|
446
|
+
"error_type": str, # Exception type
|
|
447
|
+
"execution_time": float, # Seconds
|
|
448
|
+
"mode": "local" | "remote"
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Execution Modes:**
|
|
453
|
+
|
|
454
|
+
**Local Mode** (default):
|
|
455
|
+
- In-process execution with isolated namespace
|
|
456
|
+
- Fast, no network latency
|
|
457
|
+
- Perfect for development
|
|
458
|
+
|
|
459
|
+
**Remote Mode** (production):
|
|
460
|
+
- Azure Container Apps sandbox
|
|
461
|
+
- Full isolation, better security
|
|
462
|
+
- Automatic fallback to local on failure
|
|
463
|
+
|
|
464
|
+
**Example:**
|
|
465
|
+
```python
|
|
466
|
+
# Async code execution
|
|
467
|
+
code = """
|
|
468
|
+
async def main():
|
|
469
|
+
results = await search.search("Python tutorials")
|
|
470
|
+
return results
|
|
471
|
+
"""
|
|
472
|
+
|
|
473
|
+
result = await executor.execute(code, timeout=30)
|
|
474
|
+
print(result['output']) # Search results
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### AutoRepair
|
|
480
|
+
|
|
481
|
+
Autonomous code repair with LLM-guided error fixing.
|
|
482
|
+
|
|
483
|
+
#### Class: `AutoRepair`
|
|
484
|
+
|
|
485
|
+
```python
|
|
486
|
+
from jarviscore.execution import create_auto_repair
|
|
487
|
+
|
|
488
|
+
repair = create_auto_repair(llm_client, max_attempts=3)
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**Parameters:**
|
|
492
|
+
- `llm_client`: UnifiedLLMClient instance
|
|
493
|
+
- `max_attempts` (int): Maximum repair attempts (default: 3)
|
|
494
|
+
|
|
495
|
+
**Methods:**
|
|
496
|
+
|
|
497
|
+
#### `async repair(code, error_msg, error_type, task, system_prompt)`
|
|
498
|
+
|
|
499
|
+
Attempt to fix broken code.
|
|
500
|
+
|
|
501
|
+
```python
|
|
502
|
+
fixed_code = await repair.repair(
|
|
503
|
+
code=broken_code,
|
|
504
|
+
error_msg="NameError: name 'x' is not defined",
|
|
505
|
+
error_type="NameError",
|
|
506
|
+
task="Calculate sum of numbers",
|
|
507
|
+
system_prompt="You are a Python expert"
|
|
508
|
+
)
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
**Parameters:**
|
|
512
|
+
- `code` (str): Broken code
|
|
513
|
+
- `error_msg` (str): Error message from execution
|
|
514
|
+
- `error_type` (str): Exception type
|
|
515
|
+
- `task` (str): Original task description
|
|
516
|
+
- `system_prompt` (str): Agent's system prompt
|
|
517
|
+
|
|
518
|
+
**Returns:** Fixed code string or raises exception
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## Storage Components
|
|
523
|
+
|
|
524
|
+
### ResultHandler
|
|
525
|
+
|
|
526
|
+
File-based storage for execution results with in-memory caching.
|
|
527
|
+
|
|
528
|
+
#### Class: `ResultHandler`
|
|
529
|
+
|
|
530
|
+
```python
|
|
531
|
+
from jarviscore.execution import create_result_handler
|
|
532
|
+
|
|
533
|
+
handler = create_result_handler(log_directory="./logs")
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**Parameters:**
|
|
537
|
+
- `log_directory` (str): Base directory for result storage (default: "./logs")
|
|
538
|
+
- `cache_size` (int): Max results in memory cache (default: 1000)
|
|
539
|
+
|
|
540
|
+
**Methods:**
|
|
541
|
+
|
|
542
|
+
#### `process_result(...)`
|
|
543
|
+
|
|
544
|
+
Store execution result.
|
|
545
|
+
|
|
546
|
+
```python
|
|
547
|
+
stored = handler.process_result(
|
|
548
|
+
agent_id="calculator-abc123",
|
|
549
|
+
task="Calculate factorial",
|
|
550
|
+
code="result = math.factorial(10)",
|
|
551
|
+
output=3628800,
|
|
552
|
+
status="success",
|
|
553
|
+
execution_time=0.001,
|
|
554
|
+
repairs=0
|
|
555
|
+
)
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**Parameters:**
|
|
559
|
+
- `agent_id` (str): Agent identifier
|
|
560
|
+
- `task` (str): Task description
|
|
561
|
+
- `code` (str): Executed code
|
|
562
|
+
- `output` (Any): Execution output
|
|
563
|
+
- `status` (str): "success" or "failure"
|
|
564
|
+
- `error` (str, optional): Error message
|
|
565
|
+
- `execution_time` (float, optional): Execution time in seconds
|
|
566
|
+
- `tokens` (dict, optional): Token usage `{input, output, total}`
|
|
567
|
+
- `cost_usd` (float, optional): Cost in USD
|
|
568
|
+
- `repairs` (int, optional): Number of repair attempts
|
|
569
|
+
- `metadata` (dict, optional): Additional metadata
|
|
570
|
+
|
|
571
|
+
**Returns:**
|
|
572
|
+
```python
|
|
573
|
+
{
|
|
574
|
+
"result_id": "calculator-abc123_2026-01-12T12-00-00_123456",
|
|
575
|
+
"agent_id": "calculator-abc123",
|
|
576
|
+
"task": "Calculate factorial",
|
|
577
|
+
"output": 3628800,
|
|
578
|
+
"status": "success",
|
|
579
|
+
"timestamp": "2026-01-12T12:00:00.123456",
|
|
580
|
+
# ... more fields
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**Storage:**
|
|
585
|
+
- File: `./logs/{agent_id}/{result_id}.json`
|
|
586
|
+
- Cache: In-memory LRU cache (1000 results)
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
#### `get_result(result_id)`
|
|
591
|
+
|
|
592
|
+
Retrieve a specific result (checks cache first, then file).
|
|
593
|
+
|
|
594
|
+
```python
|
|
595
|
+
result = handler.get_result("calculator-abc123_2026-01-12T12-00-00_123456")
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
#### `get_agent_results(agent_id, limit=10)`
|
|
601
|
+
|
|
602
|
+
Get recent results for an agent.
|
|
603
|
+
|
|
604
|
+
```python
|
|
605
|
+
recent = handler.get_agent_results("calculator-abc123", limit=5)
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### CodeRegistry
|
|
611
|
+
|
|
612
|
+
Searchable storage for generated code functions.
|
|
613
|
+
|
|
614
|
+
#### Class: `CodeRegistry`
|
|
615
|
+
|
|
616
|
+
```python
|
|
617
|
+
from jarviscore.execution import create_code_registry
|
|
618
|
+
|
|
619
|
+
registry = create_code_registry(registry_directory="./logs/code_registry")
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
**Parameters:**
|
|
623
|
+
- `registry_directory` (str): Directory for registry storage
|
|
624
|
+
|
|
625
|
+
**Methods:**
|
|
626
|
+
|
|
627
|
+
#### `register(code, agent_id, task, capabilities, output, result_id=None)`
|
|
628
|
+
|
|
629
|
+
Register generated code in the registry.
|
|
630
|
+
|
|
631
|
+
```python
|
|
632
|
+
function_id = registry.register(
|
|
633
|
+
code="result = math.factorial(10)",
|
|
634
|
+
agent_id="calculator-abc123",
|
|
635
|
+
task="Calculate factorial of 10",
|
|
636
|
+
capabilities=["math", "calculation"],
|
|
637
|
+
output=3628800,
|
|
638
|
+
result_id="calculator-abc123_2026-01-12T12-00-00_123456"
|
|
639
|
+
)
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
**Parameters:**
|
|
643
|
+
- `code` (str): Python code
|
|
644
|
+
- `agent_id` (str): Agent identifier
|
|
645
|
+
- `task` (str): Task description
|
|
646
|
+
- `capabilities` (list): Agent capabilities
|
|
647
|
+
- `output` (Any): Sample output
|
|
648
|
+
- `result_id` (str, optional): Associated result ID
|
|
649
|
+
|
|
650
|
+
**Returns:** function_id string
|
|
651
|
+
|
|
652
|
+
**Storage:**
|
|
653
|
+
- Index: `./logs/code_registry/index.json`
|
|
654
|
+
- Code: `./logs/code_registry/functions/{function_id}.py`
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
#### `search(query, capabilities=None, limit=5)`
|
|
659
|
+
|
|
660
|
+
Search for registered functions.
|
|
661
|
+
|
|
662
|
+
```python
|
|
663
|
+
matches = registry.search(
|
|
664
|
+
query="factorial calculation",
|
|
665
|
+
capabilities=["math"],
|
|
666
|
+
limit=3
|
|
667
|
+
)
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
**Parameters:**
|
|
671
|
+
- `query` (str): Search keywords
|
|
672
|
+
- `capabilities` (list, optional): Filter by capabilities
|
|
673
|
+
- `limit` (int): Max results (default: 5)
|
|
674
|
+
|
|
675
|
+
**Returns:** List of matching function metadata
|
|
676
|
+
|
|
677
|
+
---
|
|
678
|
+
|
|
679
|
+
#### `get(function_id)`
|
|
680
|
+
|
|
681
|
+
Get function details including code.
|
|
682
|
+
|
|
683
|
+
```python
|
|
684
|
+
func = registry.get("calculator-abc123_3a5b2f76")
|
|
685
|
+
print(func['code']) # Print the code
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## Orchestration
|
|
691
|
+
|
|
692
|
+
### WorkflowEngine
|
|
693
|
+
|
|
694
|
+
Multi-step workflow execution with dependency management.
|
|
695
|
+
|
|
696
|
+
#### Class: `WorkflowEngine`
|
|
697
|
+
|
|
698
|
+
```python
|
|
699
|
+
from jarviscore.orchestration import WorkflowEngine
|
|
700
|
+
|
|
701
|
+
engine = WorkflowEngine(mesh, p2p_coordinator=None)
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Parameters:**
|
|
705
|
+
- `mesh`: Mesh instance
|
|
706
|
+
- `p2p_coordinator` (optional): P2P coordinator for distributed execution
|
|
707
|
+
- `config` (dict, optional): Configuration
|
|
708
|
+
|
|
709
|
+
**Methods:**
|
|
710
|
+
|
|
711
|
+
#### `async execute(workflow_id, steps)`
|
|
712
|
+
|
|
713
|
+
Execute workflow with dependency resolution.
|
|
714
|
+
|
|
715
|
+
```python
|
|
716
|
+
results = await engine.execute(
|
|
717
|
+
workflow_id="pipeline-1",
|
|
718
|
+
steps=[
|
|
719
|
+
{"id": "fetch", "agent": "scraper", "task": "Fetch data"},
|
|
720
|
+
{"id": "process", "agent": "processor", "task": "Process data", "depends_on": ["fetch"]},
|
|
721
|
+
{"id": "save", "agent": "storage", "task": "Save results", "depends_on": ["process"]}
|
|
722
|
+
]
|
|
723
|
+
)
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
**Parameters:**
|
|
727
|
+
- `workflow_id` (str): Unique workflow identifier
|
|
728
|
+
- `steps` (list): List of step dictionaries
|
|
729
|
+
|
|
730
|
+
**Step Format:**
|
|
731
|
+
```python
|
|
732
|
+
{
|
|
733
|
+
"id": "step_id", # Optional, auto-generated if missing
|
|
734
|
+
"agent": "role_or_capability",
|
|
735
|
+
"task": "Task description",
|
|
736
|
+
"depends_on": ["step1", "step2"] # Optional dependencies
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
**Dependency Injection:**
|
|
741
|
+
|
|
742
|
+
Dependent steps automatically receive context:
|
|
743
|
+
```python
|
|
744
|
+
task['context'] = {
|
|
745
|
+
'previous_step_results': {
|
|
746
|
+
'step1': <output from step1>,
|
|
747
|
+
'step2': <output from step2>
|
|
748
|
+
},
|
|
749
|
+
'workflow_id': 'pipeline-1',
|
|
750
|
+
'step_id': 'current_step'
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## Utilities
|
|
757
|
+
|
|
758
|
+
### InternetSearch
|
|
759
|
+
|
|
760
|
+
Web search integration using DuckDuckGo.
|
|
761
|
+
|
|
762
|
+
#### Class: `InternetSearch`
|
|
763
|
+
|
|
764
|
+
```python
|
|
765
|
+
from jarviscore.tools import create_internet_search
|
|
766
|
+
|
|
767
|
+
search = create_internet_search()
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
**Methods:**
|
|
771
|
+
|
|
772
|
+
#### `async search(query, max_results=5)`
|
|
773
|
+
|
|
774
|
+
Search the web.
|
|
775
|
+
|
|
776
|
+
```python
|
|
777
|
+
results = await search.search("Python asyncio tutorial", max_results=3)
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
**Returns:**
|
|
781
|
+
```python
|
|
782
|
+
[
|
|
783
|
+
{
|
|
784
|
+
"title": "Page title",
|
|
785
|
+
"snippet": "Description...",
|
|
786
|
+
"url": "https://..."
|
|
787
|
+
},
|
|
788
|
+
...
|
|
789
|
+
]
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
---
|
|
793
|
+
|
|
794
|
+
#### `async extract_content(url, max_length=10000)`
|
|
795
|
+
|
|
796
|
+
Extract text content from URL.
|
|
797
|
+
|
|
798
|
+
```python
|
|
799
|
+
content = await search.extract_content("https://example.com")
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
**Returns:**
|
|
803
|
+
```python
|
|
804
|
+
{
|
|
805
|
+
"title": "Page title",
|
|
806
|
+
"content": "Extracted text...",
|
|
807
|
+
"success": true
|
|
808
|
+
}
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
---
|
|
812
|
+
|
|
813
|
+
#### `async search_and_extract(query, num_results=3)`
|
|
814
|
+
|
|
815
|
+
Combined search and content extraction.
|
|
816
|
+
|
|
817
|
+
```python
|
|
818
|
+
results = await search.search_and_extract("Python tutorials", num_results=2)
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
---
|
|
822
|
+
|
|
823
|
+
### UnifiedLLMClient
|
|
824
|
+
|
|
825
|
+
Multi-provider LLM client with automatic fallback.
|
|
826
|
+
|
|
827
|
+
#### Class: `UnifiedLLMClient`
|
|
828
|
+
|
|
829
|
+
```python
|
|
830
|
+
from jarviscore.execution import create_llm_client
|
|
831
|
+
|
|
832
|
+
llm = create_llm_client(config)
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
**Supported Providers:**
|
|
836
|
+
1. Claude (Anthropic)
|
|
837
|
+
2. vLLM (self-hosted)
|
|
838
|
+
3. Azure OpenAI
|
|
839
|
+
4. Google Gemini
|
|
840
|
+
|
|
841
|
+
**Methods:**
|
|
842
|
+
|
|
843
|
+
#### `async generate(prompt, system_msg=None, temperature=0.7, max_tokens=4000)`
|
|
844
|
+
|
|
845
|
+
Generate text from prompt.
|
|
846
|
+
|
|
847
|
+
```python
|
|
848
|
+
response = await llm.generate(
|
|
849
|
+
prompt="Write Python code to calculate factorial",
|
|
850
|
+
system_msg="You are a Python expert",
|
|
851
|
+
temperature=0.3,
|
|
852
|
+
max_tokens=2000
|
|
853
|
+
)
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
**Returns:**
|
|
857
|
+
```python
|
|
858
|
+
{
|
|
859
|
+
"content": "Generated text",
|
|
860
|
+
"provider": "claude",
|
|
861
|
+
"model": "claude-sonnet-4",
|
|
862
|
+
"tokens": {"input": 100, "output": 50, "total": 150},
|
|
863
|
+
"cost_usd": 0.05
|
|
864
|
+
}
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
**Automatic Fallback:**
|
|
868
|
+
- Tries providers in order: Claude → vLLM → Azure → Gemini
|
|
869
|
+
- Switches on API errors or rate limits
|
|
870
|
+
- Logs provider switches
|
|
871
|
+
|
|
872
|
+
---
|
|
873
|
+
|
|
874
|
+
## Configuration
|
|
875
|
+
|
|
876
|
+
See [Configuration Guide](CONFIGURATION.md) for environment variable reference.
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
## Error Handling
|
|
881
|
+
|
|
882
|
+
All async methods may raise:
|
|
883
|
+
- `RuntimeError`: Component not initialized or configuration error
|
|
884
|
+
- `ValueError`: Invalid parameters or data
|
|
885
|
+
- `TimeoutError`: Operation exceeded timeout
|
|
886
|
+
- `ExecutionTimeout`: Code execution timeout (sandbox)
|
|
887
|
+
|
|
888
|
+
**Example:**
|
|
889
|
+
```python
|
|
890
|
+
try:
|
|
891
|
+
result = await agent.execute_task(task)
|
|
892
|
+
except TimeoutError:
|
|
893
|
+
print("Task timed out")
|
|
894
|
+
except RuntimeError as e:
|
|
895
|
+
print(f"Runtime error: {e}")
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
---
|
|
899
|
+
|
|
900
|
+
## Type Hints
|
|
901
|
+
|
|
902
|
+
JarvisCore uses Python type hints for better IDE support:
|
|
903
|
+
|
|
904
|
+
```python
|
|
905
|
+
from typing import Dict, List, Any, Optional
|
|
906
|
+
|
|
907
|
+
async def execute_task(self, task: Dict[str, Any]) -> Dict[str, Any]:
|
|
908
|
+
...
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
---
|
|
912
|
+
|
|
913
|
+
## Best Practices
|
|
914
|
+
|
|
915
|
+
1. **Always use async/await**: JarvisCore is fully async
|
|
916
|
+
2. **Call mesh.start() before execution**: Initializes all agents
|
|
917
|
+
3. **Call mesh.stop() on shutdown**: Cleanup resources
|
|
918
|
+
4. **Use context managers where possible**: Automatic cleanup
|
|
919
|
+
5. **Handle errors gracefully**: Operations may fail
|
|
920
|
+
6. **Set reasonable timeouts**: Prevent hanging operations
|
|
921
|
+
7. **Monitor costs**: Track LLM token usage and costs
|
|
922
|
+
8. **Use AutoAgent for quick prototypes**: Zero-config
|
|
923
|
+
9. **Use CustomAgent for production**: Full control
|
|
924
|
+
10. **Enable remote sandbox in production**: Better isolation
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
## Version
|
|
929
|
+
|
|
930
|
+
API Reference for JarvisCore v0.1.0
|
|
931
|
+
|
|
932
|
+
Last Updated: 2026-01-12
|