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.
Files changed (94) hide show
  1. package/.env.example +18 -0
  2. package/.fluen/cache/state.json +7 -0
  3. package/README.md +350 -0
  4. package/actions/action_registry.py +75 -0
  5. package/actions/python_coder.py +470 -0
  6. package/api/main.py +269 -0
  7. package/dist/core/agent.d.ts +69 -0
  8. package/dist/core/agent.d.ts.map +1 -0
  9. package/dist/core/agent.js +214 -0
  10. package/dist/core/agent.js.map +1 -0
  11. package/dist/core/config.d.ts +222 -0
  12. package/dist/core/config.d.ts.map +1 -0
  13. package/dist/core/config.js +138 -0
  14. package/dist/core/config.js.map +1 -0
  15. package/dist/core/workspace.d.ts +53 -0
  16. package/dist/core/workspace.d.ts.map +1 -0
  17. package/dist/core/workspace.js +164 -0
  18. package/dist/core/workspace.js.map +1 -0
  19. package/dist/index.d.ts +17 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +17 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/interfaces/cli/index.d.ts +6 -0
  24. package/dist/interfaces/cli/index.d.ts.map +1 -0
  25. package/dist/interfaces/cli/index.js +257 -0
  26. package/dist/interfaces/cli/index.js.map +1 -0
  27. package/dist/interfaces/cli/repl.d.ts +9 -0
  28. package/dist/interfaces/cli/repl.d.ts.map +1 -0
  29. package/dist/interfaces/cli/repl.js +139 -0
  30. package/dist/interfaces/cli/repl.js.map +1 -0
  31. package/dist/interfaces/cli/setup-wizard.d.ts +9 -0
  32. package/dist/interfaces/cli/setup-wizard.d.ts.map +1 -0
  33. package/dist/interfaces/cli/setup-wizard.js +321 -0
  34. package/dist/interfaces/cli/setup-wizard.js.map +1 -0
  35. package/dist/mcp/client.d.ts +58 -0
  36. package/dist/mcp/client.d.ts.map +1 -0
  37. package/dist/mcp/client.js +178 -0
  38. package/dist/mcp/client.js.map +1 -0
  39. package/dist/mcp/server-manager.d.ts +58 -0
  40. package/dist/mcp/server-manager.d.ts.map +1 -0
  41. package/dist/mcp/server-manager.js +135 -0
  42. package/dist/mcp/server-manager.js.map +1 -0
  43. package/dist/models/base.d.ts +57 -0
  44. package/dist/models/base.d.ts.map +1 -0
  45. package/dist/models/base.js +5 -0
  46. package/dist/models/base.js.map +1 -0
  47. package/dist/models/harmony.d.ts +78 -0
  48. package/dist/models/harmony.d.ts.map +1 -0
  49. package/dist/models/harmony.js +226 -0
  50. package/dist/models/harmony.js.map +1 -0
  51. package/dist/models/krutrim.d.ts +30 -0
  52. package/dist/models/krutrim.d.ts.map +1 -0
  53. package/dist/models/krutrim.js +185 -0
  54. package/dist/models/krutrim.js.map +1 -0
  55. package/dist/models/orchestrator.d.ts +49 -0
  56. package/dist/models/orchestrator.d.ts.map +1 -0
  57. package/dist/models/orchestrator.js +140 -0
  58. package/dist/models/orchestrator.js.map +1 -0
  59. package/dist/utils/errors.d.ts +23 -0
  60. package/dist/utils/errors.d.ts.map +1 -0
  61. package/dist/utils/errors.js +45 -0
  62. package/dist/utils/errors.js.map +1 -0
  63. package/dist/utils/logger.d.ts +24 -0
  64. package/dist/utils/logger.d.ts.map +1 -0
  65. package/dist/utils/logger.js +74 -0
  66. package/dist/utils/logger.js.map +1 -0
  67. package/docs/BUILD.md +317 -0
  68. package/docs/DEV_WORKFLOW.md +197 -0
  69. package/docs/FILESYSTEM_ACCESS.md +244 -0
  70. package/docs/IMPLEMENTATION_SUMMARY.md +459 -0
  71. package/docs/QUICKSTART.md +162 -0
  72. package/docs/TROUBLESHOOTING.md +393 -0
  73. package/examples/code-review-directive.md +26 -0
  74. package/examples/data-analysis-directive.md +26 -0
  75. package/examples/programmatic-usage.ts +120 -0
  76. package/jiva-directive.md +24 -0
  77. package/package.json +46 -0
  78. package/setup.sh +65 -0
  79. package/src/core/agent.ts +275 -0
  80. package/src/core/config.ts +177 -0
  81. package/src/core/workspace.ts +205 -0
  82. package/src/index.ts +21 -0
  83. package/src/interfaces/cli/index.ts +290 -0
  84. package/src/interfaces/cli/repl.ts +182 -0
  85. package/src/interfaces/cli/setup-wizard.ts +355 -0
  86. package/src/mcp/client.ts +231 -0
  87. package/src/mcp/server-manager.ts +168 -0
  88. package/src/models/base.ts +63 -0
  89. package/src/models/harmony.ts +301 -0
  90. package/src/models/krutrim.ts +236 -0
  91. package/src/models/orchestrator.ts +180 -0
  92. package/src/utils/errors.ts +41 -0
  93. package/src/utils/logger.ts +87 -0
  94. 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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"}