jiva-core 0.1.0
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.
- package/.env.example +18 -0
- package/.fluen/cache/state.json +7 -0
- package/README.md +350 -0
- package/actions/action_registry.py +75 -0
- package/actions/python_coder.py +470 -0
- package/api/main.py +269 -0
- package/dist/core/agent.d.ts +69 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +214 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/config.d.ts +222 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +138 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/workspace.d.ts +53 -0
- package/dist/core/workspace.d.ts.map +1 -0
- package/dist/core/workspace.js +164 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/cli/index.d.ts +6 -0
- package/dist/interfaces/cli/index.d.ts.map +1 -0
- package/dist/interfaces/cli/index.js +257 -0
- package/dist/interfaces/cli/index.js.map +1 -0
- package/dist/interfaces/cli/repl.d.ts +9 -0
- package/dist/interfaces/cli/repl.d.ts.map +1 -0
- package/dist/interfaces/cli/repl.js +139 -0
- package/dist/interfaces/cli/repl.js.map +1 -0
- package/dist/interfaces/cli/setup-wizard.d.ts +9 -0
- package/dist/interfaces/cli/setup-wizard.d.ts.map +1 -0
- package/dist/interfaces/cli/setup-wizard.js +321 -0
- package/dist/interfaces/cli/setup-wizard.js.map +1 -0
- package/dist/mcp/client.d.ts +58 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +178 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/server-manager.d.ts +58 -0
- package/dist/mcp/server-manager.d.ts.map +1 -0
- package/dist/mcp/server-manager.js +135 -0
- package/dist/mcp/server-manager.js.map +1 -0
- package/dist/models/base.d.ts +57 -0
- package/dist/models/base.d.ts.map +1 -0
- package/dist/models/base.js +5 -0
- package/dist/models/base.js.map +1 -0
- package/dist/models/harmony.d.ts +78 -0
- package/dist/models/harmony.d.ts.map +1 -0
- package/dist/models/harmony.js +226 -0
- package/dist/models/harmony.js.map +1 -0
- package/dist/models/krutrim.d.ts +30 -0
- package/dist/models/krutrim.d.ts.map +1 -0
- package/dist/models/krutrim.js +185 -0
- package/dist/models/krutrim.js.map +1 -0
- package/dist/models/orchestrator.d.ts +49 -0
- package/dist/models/orchestrator.d.ts.map +1 -0
- package/dist/models/orchestrator.js +140 -0
- package/dist/models/orchestrator.js.map +1 -0
- package/dist/utils/errors.d.ts +23 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +45 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +74 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/BUILD.md +317 -0
- package/docs/DEV_WORKFLOW.md +197 -0
- package/docs/FILESYSTEM_ACCESS.md +244 -0
- package/docs/IMPLEMENTATION_SUMMARY.md +459 -0
- package/docs/QUICKSTART.md +162 -0
- package/docs/TROUBLESHOOTING.md +393 -0
- package/examples/code-review-directive.md +26 -0
- package/examples/data-analysis-directive.md +26 -0
- package/examples/programmatic-usage.ts +120 -0
- package/jiva-directive.md +24 -0
- package/package.json +46 -0
- package/setup.sh +65 -0
- package/src/core/agent.ts +275 -0
- package/src/core/config.ts +177 -0
- package/src/core/workspace.ts +205 -0
- package/src/index.ts +21 -0
- package/src/interfaces/cli/index.ts +290 -0
- package/src/interfaces/cli/repl.ts +182 -0
- package/src/interfaces/cli/setup-wizard.ts +355 -0
- package/src/mcp/client.ts +231 -0
- package/src/mcp/server-manager.ts +168 -0
- package/src/models/base.ts +63 -0
- package/src/models/harmony.ts +301 -0
- package/src/models/krutrim.ts +236 -0
- package/src/models/orchestrator.ts +180 -0
- package/src/utils/errors.ts +41 -0
- package/src/utils/logger.ts +87 -0
- package/tsconfig.json +22 -0
package/api/main.py
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# api/main.py
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from fastapi import FastAPI, Depends, HTTPException
|
|
5
|
+
from fastapi.responses import JSONResponse
|
|
6
|
+
from typing import Dict, Any, List, Optional
|
|
7
|
+
import logging
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
# Initialize FastAPI app
|
|
11
|
+
app = FastAPI(
|
|
12
|
+
title="Jiva Agent API",
|
|
13
|
+
description="REST API for interacting with Jiva agents",
|
|
14
|
+
version="1.0.0"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger("Jiva.API")
|
|
18
|
+
|
|
19
|
+
def get_agent():
|
|
20
|
+
"""Dependency to get the agent instance from app state."""
|
|
21
|
+
if not hasattr(app.state, 'agent'):
|
|
22
|
+
raise HTTPException(status_code=503, detail="Agent not initialized")
|
|
23
|
+
return app.state.agent
|
|
24
|
+
|
|
25
|
+
@app.get("/status", response_model=Dict[str, Any])
|
|
26
|
+
async def get_status(agent = Depends(get_agent)) -> Dict[str, Any]:
|
|
27
|
+
"""Get the current status of the Jiva agent."""
|
|
28
|
+
try:
|
|
29
|
+
return {
|
|
30
|
+
"status": "Working" if agent.task_manager.has_pending_tasks() else "Idle",
|
|
31
|
+
"current_goal": agent.current_goal,
|
|
32
|
+
"pending_tasks": [
|
|
33
|
+
{
|
|
34
|
+
"id": task.id,
|
|
35
|
+
"description": task.description,
|
|
36
|
+
"status": task.status,
|
|
37
|
+
"created_at": task.created_at.isoformat()
|
|
38
|
+
} for task in agent.task_manager.task_queue.queue
|
|
39
|
+
] if agent.task_manager.has_pending_tasks() else []
|
|
40
|
+
}
|
|
41
|
+
except Exception as e:
|
|
42
|
+
logger.error(f"Error getting agent status: {str(e)}")
|
|
43
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
44
|
+
|
|
45
|
+
@app.get("/goals", response_model=List[Dict[str, Any]])
|
|
46
|
+
async def get_goals(agent = Depends(get_agent)) -> List[Dict[str, Any]]:
|
|
47
|
+
"""Get list of all goals, ordered by latest first."""
|
|
48
|
+
try:
|
|
49
|
+
# Get tasks from memory that have goal information
|
|
50
|
+
goal_tasks = []
|
|
51
|
+
for task_id, task in agent.task_manager.all_tasks.items():
|
|
52
|
+
if task.goal and not any(g["goal"] == task.goal for g in goal_tasks):
|
|
53
|
+
goal_tasks.append({
|
|
54
|
+
"goal": task.goal,
|
|
55
|
+
"created_at": task.created_at.isoformat(),
|
|
56
|
+
"status": "completed" if all(t.status == "completed"
|
|
57
|
+
for t in agent.task_manager.all_tasks.values()
|
|
58
|
+
if t.goal == task.goal) else "in_progress",
|
|
59
|
+
"first_task_id": task_id
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
# Sort by creation time, latest first
|
|
63
|
+
return sorted(goal_tasks, key=lambda x: x["created_at"], reverse=True)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
logger.error(f"Error getting goals: {str(e)}")
|
|
66
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
67
|
+
|
|
68
|
+
@app.get("/tasks", response_model=List[Dict[str, Any]])
|
|
69
|
+
async def get_tasks(goal: Optional[str] = None, agent = Depends(get_agent)) -> List[Dict[str, Any]]:
|
|
70
|
+
"""Get list of tasks, optionally filtered by goal."""
|
|
71
|
+
try:
|
|
72
|
+
tasks = []
|
|
73
|
+
for task_id, task in agent.task_manager.all_tasks.items():
|
|
74
|
+
if goal is None or task.goal == goal:
|
|
75
|
+
tasks.append({
|
|
76
|
+
"id": task_id,
|
|
77
|
+
"description": task.description,
|
|
78
|
+
"status": task.status,
|
|
79
|
+
"created_at": task.created_at.isoformat(),
|
|
80
|
+
"completed_at": task.completed_at.isoformat() if task.completed_at else None,
|
|
81
|
+
"goal": task.goal,
|
|
82
|
+
"action": task.action,
|
|
83
|
+
"result": str(task.result) if task.result else None
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
# Sort by creation time, latest first
|
|
87
|
+
return sorted(tasks, key=lambda x: x["created_at"], reverse=True)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.error(f"Error getting tasks: {str(e)}")
|
|
90
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
91
|
+
|
|
92
|
+
@app.post("/goal", response_model=Dict[str, Any])
|
|
93
|
+
async def create_goal(goal: Dict[str, str], agent = Depends(get_agent)) -> Dict[str, Any]:
|
|
94
|
+
"""Create a new goal for the agent."""
|
|
95
|
+
try:
|
|
96
|
+
if 'description' not in goal:
|
|
97
|
+
raise HTTPException(status_code=400, detail="Goal description is required")
|
|
98
|
+
|
|
99
|
+
# Process the goal like a regular input
|
|
100
|
+
input_data = [{
|
|
101
|
+
"type": "goal",
|
|
102
|
+
"content": goal['description'],
|
|
103
|
+
"timestamp": datetime.now().isoformat()
|
|
104
|
+
}]
|
|
105
|
+
|
|
106
|
+
await agent.process_input(input_data)
|
|
107
|
+
|
|
108
|
+
# Wait a short time to allow initial task generation
|
|
109
|
+
await asyncio.sleep(0.5)
|
|
110
|
+
|
|
111
|
+
# Get the initial set of tasks
|
|
112
|
+
initial_tasks = [
|
|
113
|
+
{
|
|
114
|
+
"id": task.id,
|
|
115
|
+
"description": task.description,
|
|
116
|
+
"status": task.status
|
|
117
|
+
}
|
|
118
|
+
for task in agent.task_manager.task_queue.queue
|
|
119
|
+
] if agent.task_manager.has_pending_tasks() else []
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
"status": "success",
|
|
123
|
+
"message": "Goal created successfully",
|
|
124
|
+
"goal": goal['description'],
|
|
125
|
+
"initial_tasks": initial_tasks
|
|
126
|
+
}
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.error(f"Error creating goal: {str(e)}")
|
|
129
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
130
|
+
|
|
131
|
+
@app.get("/about", response_model=Dict[str, Any])
|
|
132
|
+
async def get_about(agent = Depends(get_agent)) -> Dict[str, Any]:
|
|
133
|
+
"""Get information about the agent and its configuration."""
|
|
134
|
+
try:
|
|
135
|
+
# Get config without sensitive information
|
|
136
|
+
config = agent.config.copy()
|
|
137
|
+
# Remove sensitive fields
|
|
138
|
+
for provider in ['llm', 'mistral-llm']:
|
|
139
|
+
if provider in config:
|
|
140
|
+
if 'api_key' in config[provider]:
|
|
141
|
+
config[provider]['api_key'] = '***'
|
|
142
|
+
|
|
143
|
+
# Get available actions
|
|
144
|
+
actions = agent.action_manager.get_available_actions()
|
|
145
|
+
# Clean up action info for API response
|
|
146
|
+
clean_actions = {}
|
|
147
|
+
for action_name, action_info in actions.items():
|
|
148
|
+
clean_actions[action_name] = {
|
|
149
|
+
"description": action_info["description"],
|
|
150
|
+
"parameters": action_info["parameters"]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
"config": config,
|
|
155
|
+
"available_actions": clean_actions,
|
|
156
|
+
"sensors": list(agent.sensor_manager.get_available_sensors())
|
|
157
|
+
}
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logger.error(f"Error getting agent information: {str(e)}")
|
|
160
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
161
|
+
|
|
162
|
+
# Error handling
|
|
163
|
+
@app.exception_handler(Exception)
|
|
164
|
+
async def generic_exception_handler(request, exc):
|
|
165
|
+
logger.error(f"Unhandled exception: {str(exc)}")
|
|
166
|
+
return JSONResponse(
|
|
167
|
+
status_code=500,
|
|
168
|
+
content={"detail": "Internal server error"}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
@app.post("/trigger", response_model=Dict[str, Any])
|
|
172
|
+
async def trigger_agent(agent = Depends(get_agent)) -> Dict[str, Any]:
|
|
173
|
+
"""Trigger the agent to check and execute pending tasks if it's idle."""
|
|
174
|
+
try:
|
|
175
|
+
if not agent.is_awake:
|
|
176
|
+
raise HTTPException(
|
|
177
|
+
status_code=400,
|
|
178
|
+
detail="Agent is sleeping and cannot be triggered"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# First get all pending tasks
|
|
182
|
+
pending_tasks = agent.task_manager.get_pending_tasks()
|
|
183
|
+
|
|
184
|
+
if not pending_tasks:
|
|
185
|
+
return {
|
|
186
|
+
"status": "no_action",
|
|
187
|
+
"message": "No pending tasks to execute",
|
|
188
|
+
"debug": {
|
|
189
|
+
"queue_size": 0,
|
|
190
|
+
"queue_tasks": [],
|
|
191
|
+
"all_pending_count": 0,
|
|
192
|
+
"all_pending": [],
|
|
193
|
+
"has_pending_tasks": False
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# Requeue the pending tasks
|
|
198
|
+
agent.task_manager.requeue_pending_tasks()
|
|
199
|
+
|
|
200
|
+
# Signal the agent to check for tasks
|
|
201
|
+
agent._task_trigger.set()
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
"status": "triggered",
|
|
205
|
+
"message": f"Agent triggered to execute {len(pending_tasks)} pending tasks",
|
|
206
|
+
"debug": {
|
|
207
|
+
"queue_size": len(pending_tasks),
|
|
208
|
+
"queue_tasks": [
|
|
209
|
+
{
|
|
210
|
+
"id": task.id,
|
|
211
|
+
"description": task.description,
|
|
212
|
+
"status": task.status,
|
|
213
|
+
"created_at": task.created_at.isoformat()
|
|
214
|
+
} for task in pending_tasks
|
|
215
|
+
],
|
|
216
|
+
"all_pending_count": len(pending_tasks),
|
|
217
|
+
"all_pending": [
|
|
218
|
+
{
|
|
219
|
+
"id": task.id,
|
|
220
|
+
"description": task.description
|
|
221
|
+
} for task in pending_tasks
|
|
222
|
+
],
|
|
223
|
+
"has_pending_tasks": True
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
except Exception as e:
|
|
228
|
+
logger.error(f"Error triggering agent: {str(e)}")
|
|
229
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
230
|
+
|
|
231
|
+
@app.get("/about", response_model=Dict[str, Any])
|
|
232
|
+
async def get_about(agent = Depends(get_agent)) -> Dict[str, Any]:
|
|
233
|
+
"""Get information about the agent and its configuration."""
|
|
234
|
+
try:
|
|
235
|
+
# Get config without sensitive information
|
|
236
|
+
config = agent.config.copy()
|
|
237
|
+
# Remove sensitive fields
|
|
238
|
+
for provider in ['llm', 'mistral-llm']:
|
|
239
|
+
if provider in config:
|
|
240
|
+
if 'api_key' in config[provider]:
|
|
241
|
+
config[provider]['api_key'] = '***'
|
|
242
|
+
|
|
243
|
+
# Get available actions
|
|
244
|
+
actions = agent.action_manager.get_available_actions()
|
|
245
|
+
clean_actions = {}
|
|
246
|
+
for action_name, action_info in actions.items():
|
|
247
|
+
clean_actions[action_name] = {
|
|
248
|
+
"description": action_info["description"],
|
|
249
|
+
"parameters": action_info["parameters"]
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
# Add sleep cycle status
|
|
253
|
+
status = {
|
|
254
|
+
"sleep_cycle": {
|
|
255
|
+
"enabled": agent.sleep_config.get('enabled', False),
|
|
256
|
+
"is_awake": agent.is_awake,
|
|
257
|
+
"last_sleep_time": agent.last_sleep_time.isoformat() if agent.last_sleep_time else None
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
"config": config,
|
|
263
|
+
"available_actions": clean_actions,
|
|
264
|
+
"sensors": list(agent.sensor_manager.get_available_sensors()),
|
|
265
|
+
"status": status
|
|
266
|
+
}
|
|
267
|
+
except Exception as e:
|
|
268
|
+
logger.error(f"Error getting agent information: {str(e)}")
|
|
269
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jiva Agent - Main Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Coordinates between models, MCP servers, and workspace to provide
|
|
5
|
+
* autonomous agent capabilities.
|
|
6
|
+
*/
|
|
7
|
+
import { ModelOrchestrator } from '../models/orchestrator.js';
|
|
8
|
+
import { MCPServerManager } from '../mcp/server-manager.js';
|
|
9
|
+
import { WorkspaceManager } from './workspace.js';
|
|
10
|
+
import { Message } from '../models/base.js';
|
|
11
|
+
export interface AgentConfig {
|
|
12
|
+
orchestrator: ModelOrchestrator;
|
|
13
|
+
mcpManager: MCPServerManager;
|
|
14
|
+
workspace: WorkspaceManager;
|
|
15
|
+
maxIterations?: number;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface AgentResponse {
|
|
19
|
+
content: string;
|
|
20
|
+
iterations: number;
|
|
21
|
+
toolsUsed: string[];
|
|
22
|
+
}
|
|
23
|
+
export declare class JivaAgent {
|
|
24
|
+
private orchestrator;
|
|
25
|
+
private mcpManager;
|
|
26
|
+
private workspace;
|
|
27
|
+
private maxIterations;
|
|
28
|
+
private temperature;
|
|
29
|
+
private conversationHistory;
|
|
30
|
+
constructor(config: AgentConfig);
|
|
31
|
+
/**
|
|
32
|
+
* Initialize system prompt with directive if available
|
|
33
|
+
*/
|
|
34
|
+
private initializeSystemPrompt;
|
|
35
|
+
/**
|
|
36
|
+
* Trim conversation history to prevent WAF blocking and reduce token usage
|
|
37
|
+
* Keeps system + developer messages + last N message pairs
|
|
38
|
+
*/
|
|
39
|
+
private trimConversationHistory;
|
|
40
|
+
/**
|
|
41
|
+
* Process a user message and return agent response
|
|
42
|
+
*/
|
|
43
|
+
chat(userMessage: string): Promise<AgentResponse>;
|
|
44
|
+
/**
|
|
45
|
+
* Reset conversation history
|
|
46
|
+
*/
|
|
47
|
+
resetConversation(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Get conversation history
|
|
50
|
+
*/
|
|
51
|
+
getConversationHistory(): Message[];
|
|
52
|
+
/**
|
|
53
|
+
* Get workspace manager
|
|
54
|
+
*/
|
|
55
|
+
getWorkspace(): WorkspaceManager;
|
|
56
|
+
/**
|
|
57
|
+
* Get MCP server manager
|
|
58
|
+
*/
|
|
59
|
+
getMCPManager(): MCPServerManager;
|
|
60
|
+
/**
|
|
61
|
+
* Get model orchestrator
|
|
62
|
+
*/
|
|
63
|
+
getOrchestrator(): ModelOrchestrator;
|
|
64
|
+
/**
|
|
65
|
+
* Cleanup resources
|
|
66
|
+
*/
|
|
67
|
+
cleanup(): Promise<void>;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAiB,MAAM,mBAAmB,CAAC;AAK3D,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,iBAAiB,CAAC;IAChC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,mBAAmB,CAAiB;gBAEhC,MAAM,EAAE,WAAW;IAU/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAgD9B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAe/B;;OAEG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA8GvD;;OAEG;IACH,iBAAiB;IAMjB;;OAEG;IACH,sBAAsB,IAAI,OAAO,EAAE;IAInC;;OAEG;IACH,YAAY,IAAI,gBAAgB;IAIhC;;OAEG;IACH,aAAa,IAAI,gBAAgB;IAIjC;;OAEG;IACH,eAAe,IAAI,iBAAiB;IAIpC;;OAEG;IACG,OAAO;CAId"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jiva Agent - Main Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Coordinates between models, MCP servers, and workspace to provide
|
|
5
|
+
* autonomous agent capabilities.
|
|
6
|
+
*/
|
|
7
|
+
import { formatToolResult } from '../models/harmony.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { JivaError } from '../utils/errors.js';
|
|
10
|
+
export class JivaAgent {
|
|
11
|
+
orchestrator;
|
|
12
|
+
mcpManager;
|
|
13
|
+
workspace;
|
|
14
|
+
maxIterations;
|
|
15
|
+
temperature;
|
|
16
|
+
conversationHistory = [];
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.orchestrator = config.orchestrator;
|
|
19
|
+
this.mcpManager = config.mcpManager;
|
|
20
|
+
this.workspace = config.workspace;
|
|
21
|
+
this.maxIterations = config.maxIterations || 10;
|
|
22
|
+
this.temperature = config.temperature || 0.7;
|
|
23
|
+
this.initializeSystemPrompt();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Initialize system prompt with directive if available
|
|
27
|
+
*/
|
|
28
|
+
initializeSystemPrompt() {
|
|
29
|
+
// System message - high-level behavior
|
|
30
|
+
const systemParts = [
|
|
31
|
+
'You are Jiva, an autonomous AI agent designed to help users accomplish tasks efficiently.',
|
|
32
|
+
'',
|
|
33
|
+
`Default workspace directory: ${this.workspace.getWorkspaceDir()}`,
|
|
34
|
+
'',
|
|
35
|
+
'You have broad filesystem access to user directories (subject to OS permissions).',
|
|
36
|
+
'The workspace is your default working area, but you can access files in other user directories as requested.',
|
|
37
|
+
];
|
|
38
|
+
this.conversationHistory.push({
|
|
39
|
+
role: 'system',
|
|
40
|
+
content: systemParts.join('\n'),
|
|
41
|
+
});
|
|
42
|
+
// Developer message - tool usage instructions and constraints
|
|
43
|
+
const developerParts = [
|
|
44
|
+
'CRITICAL INSTRUCTIONS:',
|
|
45
|
+
'',
|
|
46
|
+
'1. When you need to perform file operations or system tasks, you MUST use the available tools',
|
|
47
|
+
'2. Use tools by outputting: <|call|>tool_name({"param": "value"})<|return|>',
|
|
48
|
+
'3. Do NOT output markdown code blocks or JSON - use the exact format above',
|
|
49
|
+
'4. Tool names are prefixed with the server name (e.g., filesystem__read_file)',
|
|
50
|
+
'5. After calling a tool, wait for the result before responding to the user',
|
|
51
|
+
'6. You can access ANY files/directories - not just the workspace (use absolute paths when needed)',
|
|
52
|
+
'',
|
|
53
|
+
'Guidelines:',
|
|
54
|
+
'- Break down complex tasks into smaller steps',
|
|
55
|
+
'- Use available tools to gather information and perform actions',
|
|
56
|
+
'- Use absolute paths when accessing files outside the workspace',
|
|
57
|
+
'- Provide clear explanations of your reasoning',
|
|
58
|
+
'- Ask for clarification when requirements are ambiguous',
|
|
59
|
+
'',
|
|
60
|
+
];
|
|
61
|
+
const directivePrompt = this.workspace.getDirectivePrompt();
|
|
62
|
+
if (directivePrompt) {
|
|
63
|
+
developerParts.push(directivePrompt);
|
|
64
|
+
developerParts.push('');
|
|
65
|
+
}
|
|
66
|
+
this.conversationHistory.push({
|
|
67
|
+
role: 'developer',
|
|
68
|
+
content: developerParts.join('\n'),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Trim conversation history to prevent WAF blocking and reduce token usage
|
|
73
|
+
* Keeps system + developer messages + last N message pairs
|
|
74
|
+
*/
|
|
75
|
+
trimConversationHistory(maxMessages = 10) {
|
|
76
|
+
// Always keep system and developer messages (first 2 messages)
|
|
77
|
+
const systemMessage = this.conversationHistory[0]; // system
|
|
78
|
+
const developerMessage = this.conversationHistory[1]; // developer
|
|
79
|
+
if (this.conversationHistory.length <= maxMessages + 2) {
|
|
80
|
+
return this.conversationHistory;
|
|
81
|
+
}
|
|
82
|
+
// Keep only the last N messages (after system and developer)
|
|
83
|
+
const recentMessages = this.conversationHistory.slice(-maxMessages);
|
|
84
|
+
return [systemMessage, developerMessage, ...recentMessages];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Process a user message and return agent response
|
|
88
|
+
*/
|
|
89
|
+
async chat(userMessage) {
|
|
90
|
+
logger.info('Processing user message...');
|
|
91
|
+
// Add user message to history
|
|
92
|
+
this.conversationHistory.push({
|
|
93
|
+
role: 'user',
|
|
94
|
+
content: userMessage,
|
|
95
|
+
});
|
|
96
|
+
const toolsUsed = [];
|
|
97
|
+
let iterations = 0;
|
|
98
|
+
let finalResponse = '';
|
|
99
|
+
// Agent loop: iterate until completion or max iterations
|
|
100
|
+
while (iterations < this.maxIterations) {
|
|
101
|
+
iterations++;
|
|
102
|
+
logger.debug(`Agent iteration ${iterations}/${this.maxIterations}`);
|
|
103
|
+
// Get available tools from MCP servers
|
|
104
|
+
const tools = this.mcpManager.getClient().getAllTools();
|
|
105
|
+
// Trim conversation history to prevent WAF blocking
|
|
106
|
+
const messagesToSend = this.trimConversationHistory(20);
|
|
107
|
+
if (messagesToSend.length < this.conversationHistory.length) {
|
|
108
|
+
logger.debug(`Trimmed conversation: ${this.conversationHistory.length} → ${messagesToSend.length} messages`);
|
|
109
|
+
}
|
|
110
|
+
// Call model
|
|
111
|
+
let response;
|
|
112
|
+
try {
|
|
113
|
+
response = await this.orchestrator.chat({
|
|
114
|
+
model: 'gpt-oss-120b',
|
|
115
|
+
messages: messagesToSend,
|
|
116
|
+
tools: tools.length > 0 ? tools : undefined,
|
|
117
|
+
temperature: this.temperature,
|
|
118
|
+
maxTokens: 4096,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
logger.error('Model call failed', error);
|
|
123
|
+
throw new JivaError(`Failed to get response from model: ${error instanceof Error ? error.message : String(error)}`);
|
|
124
|
+
}
|
|
125
|
+
// Add assistant response to history
|
|
126
|
+
this.conversationHistory.push({
|
|
127
|
+
role: 'assistant',
|
|
128
|
+
content: response.content,
|
|
129
|
+
});
|
|
130
|
+
// Check if there are tool calls
|
|
131
|
+
if (response.toolCalls && response.toolCalls.length > 0) {
|
|
132
|
+
logger.info(`Model requested ${response.toolCalls.length} tool call(s)`);
|
|
133
|
+
// Execute tool calls
|
|
134
|
+
for (const toolCall of response.toolCalls) {
|
|
135
|
+
const toolName = toolCall.function.name;
|
|
136
|
+
logger.info(`Executing tool: ${toolName}`);
|
|
137
|
+
try {
|
|
138
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
139
|
+
const result = await this.mcpManager.getClient().executeTool(toolName, args);
|
|
140
|
+
toolsUsed.push(toolName);
|
|
141
|
+
// Add tool result to history
|
|
142
|
+
const toolMessage = formatToolResult(toolCall.id, toolName, result);
|
|
143
|
+
this.conversationHistory.push(toolMessage);
|
|
144
|
+
logger.success(`Tool ${toolName} executed successfully`);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
logger.error(`Tool ${toolName} execution failed`, error);
|
|
148
|
+
// Add error as tool result
|
|
149
|
+
this.conversationHistory.push({
|
|
150
|
+
role: 'tool',
|
|
151
|
+
name: toolName,
|
|
152
|
+
tool_call_id: toolCall.id,
|
|
153
|
+
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Continue loop to process tool results
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
// No tool calls, this is the final response
|
|
161
|
+
finalResponse = response.content;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
if (iterations >= this.maxIterations) {
|
|
165
|
+
logger.warn('Max iterations reached');
|
|
166
|
+
finalResponse = finalResponse || 'Maximum iterations reached. Task may be incomplete.';
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
content: finalResponse,
|
|
170
|
+
iterations,
|
|
171
|
+
toolsUsed,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Reset conversation history
|
|
176
|
+
*/
|
|
177
|
+
resetConversation() {
|
|
178
|
+
this.conversationHistory = [];
|
|
179
|
+
this.initializeSystemPrompt();
|
|
180
|
+
logger.info('Conversation history reset');
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get conversation history
|
|
184
|
+
*/
|
|
185
|
+
getConversationHistory() {
|
|
186
|
+
return [...this.conversationHistory];
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get workspace manager
|
|
190
|
+
*/
|
|
191
|
+
getWorkspace() {
|
|
192
|
+
return this.workspace;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get MCP server manager
|
|
196
|
+
*/
|
|
197
|
+
getMCPManager() {
|
|
198
|
+
return this.mcpManager;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get model orchestrator
|
|
202
|
+
*/
|
|
203
|
+
getOrchestrator() {
|
|
204
|
+
return this.orchestrator;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Cleanup resources
|
|
208
|
+
*/
|
|
209
|
+
async cleanup() {
|
|
210
|
+
logger.info('Cleaning up agent resources...');
|
|
211
|
+
await this.mcpManager.cleanup();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
|