@openserv-labs/sdk 1.0.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/dist/agent.js ADDED
@@ -0,0 +1,643 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Agent = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const compression_1 = __importDefault(require("compression"));
9
+ const express_1 = __importDefault(require("express"));
10
+ const express_async_router_1 = require("express-async-router");
11
+ const helmet_1 = __importDefault(require("helmet"));
12
+ const hpp_1 = __importDefault(require("hpp"));
13
+ const logger_1 = require("./logger");
14
+ const types_1 = require("./types");
15
+ const http_errors_1 = require("http-errors");
16
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
17
+ const openai_1 = __importDefault(require("openai"));
18
+ const capability_1 = require("./capability");
19
+ const PLATFORM_URL = process.env.OPENSERV_API_URL || 'https://api.openserv.ai';
20
+ const RUNTIME_URL = process.env.OPENSERV_RUNTIME_URL || 'https://agents.openserv.ai';
21
+ const DEFAULT_PORT = Number.parseInt(process.env.PORT || '') || 7378;
22
+ class Agent {
23
+ options;
24
+ /**
25
+ * The Express application instance used to handle HTTP requests.
26
+ * This is initialized in the constructor and used to set up middleware and routes.
27
+ * @private
28
+ */
29
+ app;
30
+ /**
31
+ * The HTTP server instance created from the Express application.
32
+ * This is initialized when start() is called and used to listen for incoming requests.
33
+ * @private
34
+ */
35
+ server = null;
36
+ /**
37
+ * The Express router instance used to define API routes.
38
+ * This handles routing for health checks, tool execution, and action handling.
39
+ * @private
40
+ */
41
+ router;
42
+ /**
43
+ * The port number the server will listen on.
44
+ * Defaults to DEFAULT_PORT (7378) if not specified in options.
45
+ * @private
46
+ */
47
+ port;
48
+ /**
49
+ * The system prompt used for OpenAI chat completions.
50
+ * This defines the base behavior and context for the agent.
51
+ * @protected
52
+ */
53
+ systemPrompt;
54
+ /**
55
+ * Array of capabilities (tools) available to the agent.
56
+ * Each capability is an instance of the Capability class with a name, description, schema, and run function.
57
+ * @protected
58
+ */
59
+ tools = [];
60
+ /**
61
+ * The OpenServ API key used for authentication.
62
+ * Can be provided in options or via OPENSERV_API_KEY environment variable.
63
+ * @private
64
+ */
65
+ apiKey;
66
+ /**
67
+ * Axios instance for making requests to the OpenServ API.
68
+ * Pre-configured with base URL and authentication headers.
69
+ * @private
70
+ */
71
+ apiClient;
72
+ /**
73
+ * Axios instance for making requests to the OpenServ Runtime API.
74
+ * Pre-configured with base URL and authentication headers.
75
+ * @protected
76
+ */
77
+ runtimeClient;
78
+ /**
79
+ * OpenAI client instance.
80
+ * Lazily initialized when needed using the provided API key.
81
+ * @protected
82
+ */
83
+ _openai;
84
+ /**
85
+ * Getter that converts the agent's tools into OpenAI function calling format.
86
+ * Used when making chat completion requests to OpenAI.
87
+ * @private
88
+ * @returns Array of ChatCompletionTool objects
89
+ */
90
+ get openAiTools() {
91
+ return this.tools.map(tool => ({
92
+ type: 'function',
93
+ function: {
94
+ name: tool.name,
95
+ description: tool.description,
96
+ parameters: (0, zod_to_json_schema_1.zodToJsonSchema)(tool.schema)
97
+ }
98
+ }));
99
+ }
100
+ /**
101
+ * Getter that provides access to the OpenAI client instance.
102
+ * Lazily initializes the client with the API key from options or environment.
103
+ * @private
104
+ * @throws {Error} If no OpenAI API key is available
105
+ * @returns {OpenAI} The OpenAI client instance
106
+ */
107
+ get openai() {
108
+ if (!this._openai) {
109
+ const apiKey = this.options.openaiApiKey || process.env.OPENAI_API_KEY;
110
+ if (!apiKey) {
111
+ throw new Error('OpenAI API key is required for process(). Please provide it in options or set OPENAI_API_KEY environment variable.');
112
+ }
113
+ this._openai = new openai_1.default({ apiKey });
114
+ }
115
+ return this._openai;
116
+ }
117
+ /**
118
+ * Creates a new Agent instance.
119
+ * Sets up the Express application, middleware, and routes.
120
+ * Initializes API clients with appropriate authentication.
121
+ *
122
+ * @param {AgentOptions} options - Configuration options for the agent
123
+ * @throws {Error} If OpenServ API key is not provided in options or environment
124
+ */
125
+ constructor(options) {
126
+ this.options = options;
127
+ this.app = (0, express_1.default)();
128
+ this.router = (0, express_async_router_1.AsyncRouter)();
129
+ this.port = this.options.port || DEFAULT_PORT;
130
+ this.systemPrompt = this.options.systemPrompt;
131
+ this.apiKey = this.options.apiKey || process.env.OPENSERV_API_KEY || '';
132
+ if (!this.apiKey) {
133
+ throw new Error('OpenServ API key is required. Please provide it in options or set OPENSERV_API_KEY environment variable.');
134
+ }
135
+ // Initialize API client
136
+ this.apiClient = axios_1.default.create({
137
+ baseURL: PLATFORM_URL,
138
+ headers: {
139
+ 'Content-Type': 'application/json',
140
+ 'x-openserv-key': this.apiKey
141
+ }
142
+ });
143
+ // Initialize runtime client
144
+ this.runtimeClient = axios_1.default.create({
145
+ baseURL: `${RUNTIME_URL}/runtime`,
146
+ headers: {
147
+ 'Content-Type': 'application/json',
148
+ 'x-openserv-key': this.apiKey
149
+ }
150
+ });
151
+ this.app.use(express_1.default.json());
152
+ this.app.use(express_1.default.urlencoded({ extended: false }));
153
+ this.app.use((0, hpp_1.default)());
154
+ this.app.use((0, helmet_1.default)());
155
+ this.app.use((0, compression_1.default)());
156
+ this.setupRoutes();
157
+ }
158
+ /**
159
+ * Adds a single capability (tool) to the agent.
160
+ * Each capability must have a unique name and defines a function that can be called via the API.
161
+ *
162
+ * @template S - The Zod schema type for the capability's parameters
163
+ * @param {Object} capability - The capability configuration
164
+ * @param {string} capability.name - Unique name for the capability
165
+ * @param {string} capability.description - Description of what the capability does
166
+ * @param {S} capability.schema - Zod schema defining the capability's parameters
167
+ * @param {Function} capability.run - Function that implements the capability's behavior
168
+ * @param {Object} capability.run.params - Parameters for the run function
169
+ * @param {z.infer<S>} capability.run.params.args - Validated arguments matching the schema
170
+ * @param {z.infer<typeof actionSchema>} [capability.run.params.action] - Optional action context
171
+ * @param {ChatCompletionMessageParam[]} capability.run.messages - Chat message history
172
+ * @returns {this} The agent instance for method chaining
173
+ * @throws {Error} If a capability with the same name already exists
174
+ */
175
+ addCapability({ name, description, schema, run }) {
176
+ // Validate tool name uniqueness
177
+ if (this.tools.some(tool => tool.name === name)) {
178
+ throw new Error(`Tool with name "${name}" already exists`);
179
+ }
180
+ this.tools.push(new capability_1.Capability(name, description, schema, run));
181
+ return this;
182
+ }
183
+ /**
184
+ * Adds multiple capabilities (tools) to the agent at once.
185
+ * Each capability must have a unique name and not conflict with existing capabilities.
186
+ *
187
+ * @template T - Tuple of Zod schema types for the capabilities' parameters
188
+ * @param {Object} capabilities - Array of capability configurations
189
+ * @param {string} capabilities[].name - Unique name for each capability
190
+ * @param {string} capabilities[].description - Description of what each capability does
191
+ * @param {T[number]} capabilities[].schema - Zod schema defining each capability's parameters
192
+ * @param {Function} capabilities[].run - Function that implements each capability's behavior
193
+ * @returns {this} The agent instance for method chaining
194
+ * @throws {Error} If any capability has a name that already exists
195
+ */
196
+ addCapabilities(capabilities) {
197
+ capabilities.forEach(capability => {
198
+ this.addCapability(capability);
199
+ });
200
+ return this;
201
+ }
202
+ /**
203
+ * Gets files in a workspace.
204
+ *
205
+ * @param {GetFilesParams} params - Parameters for the file retrieval
206
+ * @param {number} params.workspaceId - ID of the workspace to get files from
207
+ * @returns {Promise<any>} The files in the workspace
208
+ */
209
+ async getFiles(params) {
210
+ const response = await this.apiClient.get(`/workspaces/${params.workspaceId}/files`);
211
+ return response.data;
212
+ }
213
+ /**
214
+ * Uploads a file to a workspace.
215
+ *
216
+ * @param {UploadFileParams} params - Parameters for the file upload
217
+ * @param {number} params.workspaceId - ID of the workspace to upload to
218
+ * @param {string} params.path - Path where the file should be stored
219
+ * @param {number[]|number|null} [params.taskIds] - Optional task IDs to associate with the file
220
+ * @param {boolean} [params.skipSummarizer] - Whether to skip file summarization
221
+ * @param {Buffer|string} params.file - The file content to upload
222
+ * @returns {Promise<any>} The uploaded file details
223
+ */
224
+ async uploadFile(params) {
225
+ const formData = new FormData();
226
+ formData.append('path', params.path);
227
+ if (params.taskIds) {
228
+ formData.append('taskIds', JSON.stringify(params.taskIds));
229
+ }
230
+ if (params.skipSummarizer !== undefined) {
231
+ formData.append('skipSummarizer', params.skipSummarizer.toString());
232
+ }
233
+ // Convert Buffer or string to Blob for FormData
234
+ const fileBlob = params.file instanceof Buffer
235
+ ? new Blob([params.file])
236
+ : new Blob([params.file], { type: 'text/plain' });
237
+ formData.append('file', fileBlob);
238
+ const response = await this.apiClient.post(`/workspaces/${params.workspaceId}/file`, formData, {
239
+ headers: {
240
+ 'Content-Type': 'multipart/form-data'
241
+ }
242
+ });
243
+ return response.data;
244
+ }
245
+ /**
246
+ * Marks a task as errored.
247
+ *
248
+ * @param {MarkTaskAsErroredParams} params - Parameters for marking the task as errored
249
+ * @param {number} params.workspaceId - ID of the workspace containing the task
250
+ * @param {number} params.taskId - ID of the task to mark as errored
251
+ * @param {string} params.error - Error message describing what went wrong
252
+ * @returns {Promise<any>} The updated task details
253
+ */
254
+ async markTaskAsErrored(params) {
255
+ const response = await this.apiClient.post(`/workspaces/${params.workspaceId}/tasks/${params.taskId}/error`, {
256
+ error: params.error
257
+ });
258
+ return response.data;
259
+ }
260
+ /**
261
+ * Completes a task with the specified output.
262
+ *
263
+ * @param {CompleteTaskParams} params - Parameters for completing the task
264
+ * @param {number} params.workspaceId - ID of the workspace containing the task
265
+ * @param {number} params.taskId - ID of the task to complete
266
+ * @param {string} params.output - Output or result of the completed task
267
+ * @returns {Promise<any>} The completed task details
268
+ */
269
+ async completeTask(params) {
270
+ const response = await this.apiClient.put(`/workspaces/${params.workspaceId}/tasks/${params.taskId}/complete`, {
271
+ output: params.output
272
+ });
273
+ return response.data;
274
+ }
275
+ /**
276
+ * Sends a chat message from the agent.
277
+ *
278
+ * @param {SendChatMessageParams} params - Parameters for sending the chat message
279
+ * @param {number} params.workspaceId - ID of the workspace where the chat is happening
280
+ * @param {number} params.agentId - ID of the agent sending the message
281
+ * @param {string} params.message - Content of the message to send
282
+ * @returns {Promise<any>} The sent message details
283
+ */
284
+ async sendChatMessage(params) {
285
+ const response = await this.apiClient.post(`/workspaces/${params.workspaceId}/agent-chat/${params.agentId}/message`, {
286
+ message: params.message
287
+ });
288
+ return response.data;
289
+ }
290
+ /**
291
+ * Gets detailed information about a specific task.
292
+ *
293
+ * @param {GetTaskDetailParams} params - Parameters for getting task details
294
+ * @param {number} params.workspaceId - ID of the workspace containing the task
295
+ * @param {number} params.taskId - ID of the task to get details for
296
+ * @returns {Promise<any>} The detailed task information
297
+ */
298
+ async getTaskDetail(params) {
299
+ const response = await this.apiClient.get(`/workspaces/${params.workspaceId}/tasks/${params.taskId}/detail`);
300
+ return response.data;
301
+ }
302
+ /**
303
+ * Gets a list of agents in a workspace.
304
+ *
305
+ * @param {GetAgentsParams} params - Parameters for getting agents
306
+ * @param {number} params.workspaceId - ID of the workspace to get agents from
307
+ * @returns {Promise<any>} List of agents in the workspace
308
+ */
309
+ async getAgents(params) {
310
+ const response = await this.apiClient.get(`/workspaces/${params.workspaceId}/agents`);
311
+ return response.data;
312
+ }
313
+ /**
314
+ * Gets a list of tasks in a workspace.
315
+ *
316
+ * @param {GetTasksParams} params - Parameters for getting tasks
317
+ * @param {number} params.workspaceId - ID of the workspace to get tasks from
318
+ * @returns {Promise<any>} List of tasks in the workspace
319
+ */
320
+ async getTasks(params) {
321
+ const response = await this.apiClient.get(`/workspaces/${params.workspaceId}/tasks`);
322
+ return response.data;
323
+ }
324
+ /**
325
+ * Creates a new task in a workspace.
326
+ *
327
+ * @param {CreateTaskParams} params - Parameters for creating the task
328
+ * @param {number} params.workspaceId - ID of the workspace to create the task in
329
+ * @param {number} params.assignee - ID of the agent to assign the task to
330
+ * @param {string} params.description - Short description of the task
331
+ * @param {string} params.body - Detailed body/content of the task
332
+ * @param {string} params.input - Input data for the task
333
+ * @param {string} params.expectedOutput - Expected output format or content
334
+ * @param {number[]} params.dependencies - IDs of tasks that this task depends on
335
+ * @returns {Promise<any>} The created task details
336
+ */
337
+ async createTask(params) {
338
+ const response = await this.apiClient.post(`/workspaces/${params.workspaceId}/task`, {
339
+ assignee: params.assignee,
340
+ description: params.description,
341
+ body: params.body,
342
+ input: params.input,
343
+ expectedOutput: params.expectedOutput,
344
+ dependencies: params.dependencies
345
+ });
346
+ return response.data;
347
+ }
348
+ /**
349
+ * Adds a log entry to a task.
350
+ *
351
+ * @param {AddLogToTaskParams} params - Parameters for adding the log
352
+ * @param {number} params.workspaceId - ID of the workspace containing the task
353
+ * @param {number} params.taskId - ID of the task to add the log to
354
+ * @param {'info'|'warning'|'error'} params.severity - Severity level of the log
355
+ * @param {'text'|'openai-message'} params.type - Type of log entry
356
+ * @param {string|object} params.body - Content of the log entry
357
+ * @returns {Promise<any>} The created log entry details
358
+ */
359
+ async addLogToTask(params) {
360
+ const response = await this.apiClient.post(`/workspaces/${params.workspaceId}/tasks/${params.taskId}/log`, {
361
+ severity: params.severity,
362
+ type: params.type,
363
+ body: params.body
364
+ });
365
+ return response.data;
366
+ }
367
+ /**
368
+ * Requests human assistance for a task.
369
+ *
370
+ * @param {RequestHumanAssistanceParams} params - Parameters for requesting assistance
371
+ * @param {number} params.workspaceId - ID of the workspace containing the task
372
+ * @param {number} params.taskId - ID of the task needing assistance
373
+ * @param {'text'|'project-manager-plan-review'} params.type - Type of assistance needed
374
+ * @param {string|object} params.question - Question or request for the human
375
+ * @param {object} [params.agentDump] - Optional agent state/context information
376
+ * @returns {Promise<any>} The created assistance request details
377
+ */
378
+ async requestHumanAssistance(params) {
379
+ const response = await this.apiClient.post(`/workspaces/${params.workspaceId}/tasks/${params.taskId}/human-assistance`, {
380
+ type: params.type,
381
+ question: params.question,
382
+ agentDump: params.agentDump
383
+ });
384
+ return response.data;
385
+ }
386
+ /**
387
+ * Updates the status of a task.
388
+ *
389
+ * @param {UpdateTaskStatusParams} params - Parameters for updating the status
390
+ * @param {number} params.workspaceId - ID of the workspace containing the task
391
+ * @param {number} params.taskId - ID of the task to update
392
+ * @param {TaskStatus} params.status - New status for the task
393
+ * @returns {Promise<any>} The updated task details
394
+ */
395
+ async updateTaskStatus(params) {
396
+ const response = await this.apiClient.put(`/workspaces/${params.workspaceId}/tasks/${params.taskId}/status`, {
397
+ status: params.status
398
+ });
399
+ return response.data;
400
+ }
401
+ /**
402
+ * Processes a conversation with OpenAI, handling tool calls iteratively until completion.
403
+ *
404
+ * @param {ProcessParams} params - Parameters for processing the conversation
405
+ * @param {ChatCompletionMessageParam[]} params.messages - The conversation history
406
+ * @returns {Promise<ChatCompletion>} The final response from OpenAI
407
+ * @throws {Error} If no response is received from OpenAI or max iterations are reached
408
+ */
409
+ async process({ messages }) {
410
+ const currentMessages = [...messages];
411
+ let completion = null;
412
+ let iterationCount = 0;
413
+ const MAX_ITERATIONS = 10;
414
+ while (iterationCount < MAX_ITERATIONS) {
415
+ completion = await this.openai.chat.completions.create({
416
+ model: 'gpt-4o',
417
+ messages: currentMessages,
418
+ tools: this.openAiTools
419
+ });
420
+ if (!completion.choices?.length || !completion.choices[0]?.message) {
421
+ throw new Error('No response from OpenAI');
422
+ }
423
+ const lastMessage = completion.choices[0].message;
424
+ // If there are no tool calls, we're done
425
+ if (!lastMessage.tool_calls?.length) {
426
+ return completion;
427
+ }
428
+ // Process each tool call
429
+ const toolResults = await Promise.all(lastMessage.tool_calls.map(async (toolCall) => {
430
+ // We know the function exists because we provided the tools
431
+ const { name, arguments: args } = toolCall.function;
432
+ const parsedArgs = JSON.parse(args);
433
+ try {
434
+ // Call the corresponding method on this class with named parameters
435
+ const result = await this[name](parsedArgs);
436
+ return {
437
+ tool_call_id: toolCall.id,
438
+ role: 'tool',
439
+ name,
440
+ content: JSON.stringify(result)
441
+ };
442
+ }
443
+ catch (error) {
444
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
445
+ logger_1.logger.error({ error, toolCall }, 'Error executing tool call');
446
+ return {
447
+ tool_call_id: toolCall.id,
448
+ role: 'tool',
449
+ name,
450
+ content: JSON.stringify({ error: errorMessage })
451
+ };
452
+ }
453
+ }));
454
+ // Add the assistant's message and tool results to the conversation
455
+ currentMessages.push(lastMessage, ...toolResults);
456
+ iterationCount++;
457
+ }
458
+ throw new Error('Max iterations reached without completion');
459
+ }
460
+ /**
461
+ * Handle a task execution request
462
+ * This method can be overridden by extending classes to customize task handling
463
+ * @protected
464
+ */
465
+ async doTask(action) {
466
+ const messages = [
467
+ {
468
+ role: 'system',
469
+ content: this.systemPrompt
470
+ }
471
+ ];
472
+ if (action.task?.description) {
473
+ messages.push({
474
+ role: 'user',
475
+ content: action.task.description
476
+ });
477
+ }
478
+ try {
479
+ await this.runtimeClient.post('/execute', {
480
+ tools: this.tools.map(convertToolToJsonSchema),
481
+ messages,
482
+ action
483
+ });
484
+ }
485
+ catch (error) {
486
+ if (action.task) {
487
+ await this.markTaskAsErrored({
488
+ workspaceId: action.workspace.id,
489
+ taskId: action.task.id,
490
+ error: error instanceof Error ? error.message : 'Unknown error occurred'
491
+ });
492
+ }
493
+ logger_1.logger.error({ error }, 'Failed to forward action to runtime agent');
494
+ throw error;
495
+ }
496
+ }
497
+ /**
498
+ * Handle a chat message response request
499
+ * This method can be overridden by extending classes to customize chat handling
500
+ * @protected
501
+ */
502
+ async respondToChat(action) {
503
+ const messages = [
504
+ {
505
+ role: 'system',
506
+ content: this.systemPrompt
507
+ }
508
+ ];
509
+ if (action.messages) {
510
+ action.messages.forEach((msg) => {
511
+ messages.push({
512
+ role: msg.author === 'user' ? 'user' : 'assistant',
513
+ content: msg.message
514
+ });
515
+ });
516
+ }
517
+ try {
518
+ await this.runtimeClient.post('/chat', {
519
+ tools: this.tools.map(convertToolToJsonSchema),
520
+ messages,
521
+ action
522
+ });
523
+ }
524
+ catch (error) {
525
+ await this.sendChatMessage({
526
+ workspaceId: action.workspace.id,
527
+ agentId: action.me.id,
528
+ message: error instanceof Error ? error.message : 'Unknown error occurred'
529
+ });
530
+ logger_1.logger.error({ error }, 'Failed to forward action to runtime agent');
531
+ throw error;
532
+ }
533
+ }
534
+ /**
535
+ * Handles execution of a specific tool/capability.
536
+ *
537
+ * @param {Object} req - The request object
538
+ * @param {Object} req.params - Request parameters
539
+ * @param {string} req.params.toolName - Name of the tool to execute
540
+ * @param {Object} req.body - Request body
541
+ * @param {z.infer<z.ZodTypeAny>} [req.body.args] - Arguments for the tool
542
+ * @param {z.infer<typeof actionSchema>} [req.body.action] - Action context
543
+ * @returns {Promise<{result: string}>} The result of the tool execution
544
+ * @throws {BadRequest} If tool name is missing or tool is not found
545
+ * @throws {Error} If tool execution fails
546
+ */
547
+ async handleToolRoute(req) {
548
+ if (!('toolName' in req.params)) {
549
+ throw new http_errors_1.BadRequest('Tool name is required');
550
+ }
551
+ const tool = this.tools.find(t => t.name === req.params.toolName);
552
+ if (!tool) {
553
+ throw new http_errors_1.BadRequest(`Tool "${req.params.toolName}" not found`);
554
+ }
555
+ try {
556
+ const args = await tool.schema.parseAsync(req.body?.args);
557
+ const result = await tool.run.call(this, { args, action: req.body.action }, []);
558
+ return { result };
559
+ }
560
+ catch (error) {
561
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
562
+ throw new Error(errorMessage);
563
+ }
564
+ }
565
+ /**
566
+ * Handles the root route for task execution and chat message responses.
567
+ *
568
+ * @param {Object} req - The request object
569
+ * @param {unknown} req.body - Request body to be parsed as an action
570
+ * @returns {Promise<void>}
571
+ * @throws {Error} If action type is invalid
572
+ */
573
+ async handleRootRoute(req) {
574
+ const action = await types_1.actionSchema.parseAsync(req.body);
575
+ if (action.type === 'do-task') {
576
+ this.doTask(action);
577
+ }
578
+ else if (action.type === 'respond-chat-message') {
579
+ this.respondToChat(action);
580
+ }
581
+ else
582
+ throw new Error('Invalid action type');
583
+ }
584
+ /**
585
+ * Sets up the Express routes for the agent's HTTP server.
586
+ * Configures health check endpoint and routes for tool execution.
587
+ * @private
588
+ */
589
+ setupRoutes() {
590
+ this.router.get('/health', async (_req, res) => {
591
+ res.status(200).json({ status: 'ok', uptime: process.uptime() });
592
+ });
593
+ this.router.post('/', async (req) => {
594
+ return this.handleRootRoute({ body: req.body });
595
+ });
596
+ this.router.post('/tools/:toolName', async (req) => {
597
+ const { toolName } = req.params;
598
+ if (!toolName) {
599
+ throw new http_errors_1.BadRequest('Tool name is required');
600
+ }
601
+ return this.handleToolRoute({
602
+ params: { toolName },
603
+ body: req.body
604
+ });
605
+ });
606
+ this.app.use('/', this.router);
607
+ }
608
+ /**
609
+ * Starts the agent's HTTP server.
610
+ *
611
+ * @returns {Promise<void>} Resolves when the server has started
612
+ * @throws {Error} If server fails to start
613
+ */
614
+ async start() {
615
+ return new Promise((resolve, reject) => {
616
+ this.server = this.app.listen(this.port, () => {
617
+ logger_1.logger.info(`Agent server started on port ${this.port}`);
618
+ resolve();
619
+ });
620
+ this.server.on('error', reject);
621
+ });
622
+ }
623
+ /**
624
+ * Stops the agent's HTTP server.
625
+ *
626
+ * @returns {Promise<void>} Resolves when the server has stopped
627
+ */
628
+ async stop() {
629
+ if (!this.server)
630
+ return;
631
+ return new Promise(resolve => {
632
+ this.server?.close(() => resolve());
633
+ });
634
+ }
635
+ }
636
+ exports.Agent = Agent;
637
+ function convertToolToJsonSchema(tool) {
638
+ return {
639
+ name: tool.name,
640
+ description: tool.description,
641
+ schema: (0, zod_to_json_schema_1.zodToJsonSchema)(tool.schema)
642
+ };
643
+ }
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
3
+ import type { CapabilityFuncParams } from './types';
4
+ export declare class Capability<Schema extends z.ZodTypeAny> {
5
+ readonly name: string;
6
+ readonly description: string;
7
+ readonly schema: Schema;
8
+ readonly run: (params: CapabilityFuncParams<Schema>, messages: ChatCompletionMessageParam[]) => string | Promise<string>;
9
+ constructor(name: string, description: string, schema: Schema, run: (params: CapabilityFuncParams<Schema>, messages: ChatCompletionMessageParam[]) => string | Promise<string>);
10
+ }
11
+ //# sourceMappingURL=capability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAA;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,qBAAa,UAAU,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU;aAE/B,IAAI,EAAE,MAAM;aACZ,WAAW,EAAE,MAAM;aACnB,MAAM,EAAE,MAAM;aACd,GAAG,EAAE,CACnB,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,EACpC,QAAQ,EAAE,0BAA0B,EAAE,KACnC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;gBANb,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,CACnB,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,EACpC,QAAQ,EAAE,0BAA0B,EAAE,KACnC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAEhC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Capability = void 0;
4
+ class Capability {
5
+ name;
6
+ description;
7
+ schema;
8
+ run;
9
+ constructor(name, description, schema, run) {
10
+ this.name = name;
11
+ this.description = description;
12
+ this.schema = schema;
13
+ this.run = run;
14
+ }
15
+ }
16
+ exports.Capability = Capability;
@@ -0,0 +1,6 @@
1
+ export { Agent } from './agent';
2
+ export type { AgentOptions } from './agent';
3
+ export { Capability } from './capability';
4
+ export type { TaskStatus, GetFilesParams, UploadFileParams, MarkTaskAsErroredParams, CompleteTaskParams, SendChatMessageParams, GetTaskDetailParams, GetAgentsParams, GetTasksParams, CreateTaskParams, AddLogToTaskParams, RequestHumanAssistanceParams, UpdateTaskStatusParams, ProcessParams, CapabilityFuncParams } from './types';
5
+ export { actionSchema, doTaskActionSchema, respondChatMessageActionSchema, taskStatusSchema, agentKind } from './types';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,YAAY,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,aAAa,EACb,oBAAoB,EACrB,MAAM,SAAS,CAAA;AAEhB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,8BAA8B,EAC9B,gBAAgB,EAChB,SAAS,EACV,MAAM,SAAS,CAAA"}