@openserv-labs/sdk 2.3.0 → 2.4.1
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/README.md +110 -22
- package/dist/agent.d.ts +94 -41
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +155 -36
- package/dist/capability.d.ts +5 -2
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +8 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/run.d.ts +1 -1
- package/dist/run.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -232,7 +232,7 @@ npm install @openserv-labs/sdk
|
|
|
232
232
|
agent.addCapability({
|
|
233
233
|
name: 'greet',
|
|
234
234
|
description: 'Greet a user by name',
|
|
235
|
-
|
|
235
|
+
inputSchema: z.object({
|
|
236
236
|
name: z.string().describe('The name of the user to greet')
|
|
237
237
|
}),
|
|
238
238
|
async run({ args }) {
|
|
@@ -273,7 +273,7 @@ const agent = new Agent({
|
|
|
273
273
|
agent.addCapability({
|
|
274
274
|
name: 'greet',
|
|
275
275
|
description: 'Greet a user by name',
|
|
276
|
-
|
|
276
|
+
inputSchema: z.object({
|
|
277
277
|
name: z.string().describe('The name of the user to greet')
|
|
278
278
|
}),
|
|
279
279
|
async run({ args }) {
|
|
@@ -286,7 +286,7 @@ agent.addCapabilities([
|
|
|
286
286
|
{
|
|
287
287
|
name: 'farewell',
|
|
288
288
|
description: 'Say goodbye to a user',
|
|
289
|
-
|
|
289
|
+
inputSchema: z.object({
|
|
290
290
|
name: z.string().describe('The name of the user to bid farewell')
|
|
291
291
|
}),
|
|
292
292
|
async run({ args }) {
|
|
@@ -296,7 +296,7 @@ agent.addCapabilities([
|
|
|
296
296
|
{
|
|
297
297
|
name: 'help',
|
|
298
298
|
description: 'Show available commands',
|
|
299
|
-
|
|
299
|
+
inputSchema: z.object({}),
|
|
300
300
|
async run() {
|
|
301
301
|
return 'Available commands: greet, farewell, help'
|
|
302
302
|
}
|
|
@@ -316,13 +316,13 @@ agent.start()
|
|
|
316
316
|
| Variable | Description | Required | Default |
|
|
317
317
|
| --------------------- | ------------------------------------------ | -------- | ---------------------------------- |
|
|
318
318
|
| `OPENSERV_API_KEY` | Your OpenServ API key | Yes | - |
|
|
319
|
-
| `OPENAI_API_KEY` | OpenAI API key (for process() method)
|
|
319
|
+
| `OPENAI_API_KEY` | OpenAI API key (only for process() method) | No | - |
|
|
320
320
|
| `PORT` | Server port | No | 7378 |
|
|
321
321
|
| `OPENSERV_AUTH_TOKEN` | Token for authenticating incoming requests | No | - |
|
|
322
322
|
| `OPENSERV_PROXY_URL` | Custom proxy URL for tunnel connections | No | `https://agents-proxy.openserv.ai` |
|
|
323
323
|
| `DISABLE_TUNNEL` | Skip tunnel and run HTTP server only | No | - |
|
|
324
324
|
|
|
325
|
-
|
|
325
|
+
**Note:** `OPENAI_API_KEY` is only needed if you use the `process()` method for direct OpenAI calls. Most agents don't need it -- use run-less capabilities or `generate()` instead.
|
|
326
326
|
|
|
327
327
|
## Core Concepts
|
|
328
328
|
|
|
@@ -334,8 +334,10 @@ Each capability must include:
|
|
|
334
334
|
|
|
335
335
|
- `name`: Unique identifier for the capability
|
|
336
336
|
- `description`: What the capability does
|
|
337
|
-
- `
|
|
338
|
-
- `run`: Function that executes the capability
|
|
337
|
+
- `inputSchema`: Zod schema defining the input parameters (optional for run-less capabilities, defaults to `z.object({ input: z.string() })`)
|
|
338
|
+
- `run`: Function that executes the capability (optional -- omit for run-less capabilities handled by the runtime)
|
|
339
|
+
- `outputSchema`: Zod schema for structured LLM output (only for run-less capabilities)
|
|
340
|
+
- `schema`: **Deprecated** -- use `inputSchema` instead (kept for backwards compatibility)
|
|
339
341
|
|
|
340
342
|
```typescript
|
|
341
343
|
import { Agent } from '@openserv-labs/sdk'
|
|
@@ -349,7 +351,7 @@ const agent = new Agent({
|
|
|
349
351
|
agent.addCapability({
|
|
350
352
|
name: 'summarize',
|
|
351
353
|
description: 'Summarize a piece of text',
|
|
352
|
-
|
|
354
|
+
inputSchema: z.object({
|
|
353
355
|
text: z.string().describe('Text content to summarize'),
|
|
354
356
|
maxLength: z.number().optional().describe('Maximum length of summary')
|
|
355
357
|
}),
|
|
@@ -377,7 +379,7 @@ agent.addCapabilities([
|
|
|
377
379
|
{
|
|
378
380
|
name: 'analyze',
|
|
379
381
|
description: 'Analyze text for sentiment and keywords',
|
|
380
|
-
|
|
382
|
+
inputSchema: z.object({
|
|
381
383
|
text: z.string().describe('Text to analyze')
|
|
382
384
|
}),
|
|
383
385
|
async run({ args, action }) {
|
|
@@ -388,7 +390,7 @@ agent.addCapabilities([
|
|
|
388
390
|
{
|
|
389
391
|
name: 'help',
|
|
390
392
|
description: 'Show available commands',
|
|
391
|
-
|
|
393
|
+
inputSchema: z.object({}),
|
|
392
394
|
async run({ args, action }) {
|
|
393
395
|
return 'Available commands: summarize, analyze, help'
|
|
394
396
|
}
|
|
@@ -399,8 +401,8 @@ agent.addCapabilities([
|
|
|
399
401
|
Each capability's run function receives:
|
|
400
402
|
|
|
401
403
|
- `params`: Object containing:
|
|
402
|
-
- `args`: The validated arguments matching the capability's
|
|
403
|
-
- `action`: The action context containing:
|
|
404
|
+
- `args`: The validated arguments matching the capability's inputSchema
|
|
405
|
+
- `action`: The action context provided by the runtime, containing:
|
|
404
406
|
- `task`: The current task context (if running as part of a task)
|
|
405
407
|
- `workspace`: The current workspace context
|
|
406
408
|
- `me`: Information about the current agent
|
|
@@ -408,6 +410,92 @@ Each capability's run function receives:
|
|
|
408
410
|
|
|
409
411
|
The run function must return a string or Promise<string>.
|
|
410
412
|
|
|
413
|
+
### Run-less Capabilities
|
|
414
|
+
|
|
415
|
+
Run-less capabilities let you define tools without a `run` function. The OpenServ runtime handles execution via its own LLM, using the capability's `description` as instructions. This means you don't need your own OpenAI key.
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
import { Agent, run } from '@openserv-labs/sdk'
|
|
419
|
+
import { z } from 'zod'
|
|
420
|
+
|
|
421
|
+
const agent = new Agent({
|
|
422
|
+
systemPrompt: 'You are a creative writing assistant.'
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
// Simplest form: just name + description (default inputSchema: { input: string })
|
|
426
|
+
agent.addCapability({
|
|
427
|
+
name: 'generate_haiku',
|
|
428
|
+
description:
|
|
429
|
+
'Generate a haiku poem (5-7-5 syllables) about the given input. Only output the haiku.'
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
// With custom inputSchema
|
|
433
|
+
agent.addCapability({
|
|
434
|
+
name: 'translate',
|
|
435
|
+
description: 'Translate the given text to the target language. Return only the translated text.',
|
|
436
|
+
inputSchema: z.object({
|
|
437
|
+
text: z.string().describe('The text to translate'),
|
|
438
|
+
targetLanguage: z.string().describe('The target language')
|
|
439
|
+
})
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
// With structured output via outputSchema
|
|
443
|
+
agent.addCapability({
|
|
444
|
+
name: 'analyze_sentiment',
|
|
445
|
+
description: 'Analyze the sentiment of the given input text.',
|
|
446
|
+
outputSchema: z.object({
|
|
447
|
+
sentiment: z.enum(['positive', 'negative', 'neutral']),
|
|
448
|
+
confidence: z.number().min(0).max(1)
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
run(agent)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### The `generate()` Method
|
|
456
|
+
|
|
457
|
+
Inside custom `run` functions, use `this.generate()` to delegate LLM calls to the OpenServ runtime without needing your own OpenAI key. The `action` parameter is required for billing. You can optionally pass `messages` for conversation context.
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
agent.addCapability({
|
|
461
|
+
name: 'write_and_save_poem',
|
|
462
|
+
description: 'Write a poem and save it to the workspace',
|
|
463
|
+
inputSchema: z.object({ topic: z.string() }),
|
|
464
|
+
async run({ args, action }, messages) {
|
|
465
|
+
// Text generation
|
|
466
|
+
const poem = await this.generate({
|
|
467
|
+
prompt: `Write a short poem about ${args.topic}`,
|
|
468
|
+
action
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
// Structured output generation
|
|
472
|
+
const metadata = await this.generate({
|
|
473
|
+
prompt: `Suggest a title and 3 tags for this poem: ${poem}`,
|
|
474
|
+
outputSchema: z.object({
|
|
475
|
+
title: z.string(),
|
|
476
|
+
tags: z.array(z.string()).length(3)
|
|
477
|
+
}),
|
|
478
|
+
action
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
// With conversation history for context
|
|
482
|
+
const followUp = await this.generate({
|
|
483
|
+
prompt: 'Based on our conversation, suggest a related topic.',
|
|
484
|
+
messages, // pass conversation history from the run function
|
|
485
|
+
action
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
await this.uploadFile({
|
|
489
|
+
workspaceId: action.workspace.id,
|
|
490
|
+
path: `poems/${metadata.title}.txt`,
|
|
491
|
+
file: poem
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
return `Saved "${metadata.title}" with tags: ${metadata.tags.join(', ')}`
|
|
495
|
+
}
|
|
496
|
+
})
|
|
497
|
+
```
|
|
498
|
+
|
|
411
499
|
### Tasks
|
|
412
500
|
|
|
413
501
|
Tasks are units of work that agents can execute. They can have dependencies, require human assistance, and maintain state:
|
|
@@ -451,7 +539,7 @@ const customerSupportAgent = new Agent({
|
|
|
451
539
|
{
|
|
452
540
|
name: 'respondToCustomer',
|
|
453
541
|
description: 'Generate a response to a customer inquiry',
|
|
454
|
-
|
|
542
|
+
inputSchema: z.object({
|
|
455
543
|
query: z.string(),
|
|
456
544
|
context: z.string().optional()
|
|
457
545
|
}),
|
|
@@ -771,7 +859,7 @@ const agent = new Agent({
|
|
|
771
859
|
agent.addCapability({
|
|
772
860
|
name: 'greet',
|
|
773
861
|
description: 'Greet someone',
|
|
774
|
-
|
|
862
|
+
inputSchema: z.object({ name: z.string() }),
|
|
775
863
|
async run({ args }) {
|
|
776
864
|
return `Hello, ${args.name}!`
|
|
777
865
|
}
|
|
@@ -795,13 +883,13 @@ The `run()` function automatically:
|
|
|
795
883
|
|
|
796
884
|
#### Tunnel vs. Deployed Endpoint
|
|
797
885
|
|
|
798
|
-
| Aspect | Tunnel (Local Development) | Deployed Endpoint (Production)
|
|
799
|
-
| ----------------- | -------------------------- |
|
|
800
|
-
| Setup | Just run your code | Deploy to cloud/server
|
|
801
|
-
| URL Configuration | Not needed | Set Agent Endpoint in platform
|
|
802
|
-
| Connection | WebSocket via proxy | Direct HTTP
|
|
803
|
-
| Tunnel | Enabled (default) | Disabled (`DISABLE_TUNNEL=true`)
|
|
804
|
-
| Use case | Development & testing | Production
|
|
886
|
+
| Aspect | Tunnel (Local Development) | Deployed Endpoint (Production) |
|
|
887
|
+
| ----------------- | -------------------------- | -------------------------------- |
|
|
888
|
+
| Setup | Just run your code | Deploy to cloud/server |
|
|
889
|
+
| URL Configuration | Not needed | Set Agent Endpoint in platform |
|
|
890
|
+
| Connection | WebSocket via proxy | Direct HTTP |
|
|
891
|
+
| Tunnel | Enabled (default) | Disabled (`DISABLE_TUNNEL=true`) |
|
|
892
|
+
| Use case | Development & testing | Production |
|
|
805
893
|
|
|
806
894
|
When deploying to a hosting provider like Cloud Run, set `DISABLE_TUNNEL=true` as an environment variable. This makes `run()` start only the HTTP server without opening a WebSocket tunnel to the proxy — the platform reaches your agent directly at its public URL.
|
|
807
895
|
|
package/dist/agent.d.ts
CHANGED
|
@@ -2,9 +2,47 @@ import { type AxiosInstance } from 'axios';
|
|
|
2
2
|
import type { GetFilesParams, GetSecretsParams, GetSecretValueParams, UploadFileParams, DeleteFileParams, MarkTaskAsErroredParams, CompleteTaskParams, SendChatMessageParams, GetTaskDetailParams, GetAgentsParams, GetTasksParams, CreateTaskParams, AddLogToTaskParams, RequestHumanAssistanceParams, UpdateTaskStatusParams, ProcessParams, IntegrationCallRequest, GetChatMessagesParams, AgentChatMessagesResponse, GetFilesResponse, GetSecretsResponse, UploadFileResponse, DeleteFileResponse, GetTaskDetailResponse, GetAgentsResponse, GetTasksResponse, CreateTaskResponse, ActionSchema, DoTaskActionSchema, RespondChatMessageActionSchema } from './types';
|
|
3
3
|
import type { ChatCompletionMessageParam, ChatCompletion } from 'openai/resources/chat/completions';
|
|
4
4
|
import OpenAI from 'openai';
|
|
5
|
-
import
|
|
5
|
+
import { z } from 'zod';
|
|
6
6
|
import { Capability } from './capability';
|
|
7
7
|
import { type MCPServerConfig, MCPClient } from './mcp';
|
|
8
|
+
/** Accept inputSchema (preferred) or schema (deprecated), never both */
|
|
9
|
+
type WithInputSchema<S extends z.ZodTypeAny> = {
|
|
10
|
+
inputSchema: S;
|
|
11
|
+
schema?: never;
|
|
12
|
+
} | {
|
|
13
|
+
schema: S;
|
|
14
|
+
inputSchema?: never;
|
|
15
|
+
};
|
|
16
|
+
/** Optional inputSchema for run-less caps -- can omit entirely (uses default) */
|
|
17
|
+
type WithOptionalInputSchema<S extends z.ZodTypeAny> = {
|
|
18
|
+
inputSchema: S;
|
|
19
|
+
schema?: never;
|
|
20
|
+
} | {
|
|
21
|
+
schema: S;
|
|
22
|
+
inputSchema?: never;
|
|
23
|
+
} | {
|
|
24
|
+
inputSchema?: never;
|
|
25
|
+
schema?: never;
|
|
26
|
+
};
|
|
27
|
+
/** Capability with a run function -- inputSchema required, outputSchema not allowed */
|
|
28
|
+
type RunnableCapabilityConfig<M extends string, S extends z.ZodTypeAny> = {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
run(this: Agent<M>, params: {
|
|
32
|
+
args: z.infer<S>;
|
|
33
|
+
action: ActionSchema;
|
|
34
|
+
}, messages: ChatCompletionMessageParam[]): string | Promise<string>;
|
|
35
|
+
outputSchema?: never;
|
|
36
|
+
} & WithInputSchema<S>;
|
|
37
|
+
/** Capability without run -- inputSchema optional, outputSchema optional */
|
|
38
|
+
type RunlessCapabilityConfig<S extends z.ZodTypeAny = z.ZodTypeAny> = {
|
|
39
|
+
name: string;
|
|
40
|
+
description: string;
|
|
41
|
+
run?: never;
|
|
42
|
+
outputSchema?: z.ZodTypeAny;
|
|
43
|
+
} & WithOptionalInputSchema<S>;
|
|
44
|
+
/** Union of all valid capability forms */
|
|
45
|
+
export type CapabilityConfig<M extends string, S extends z.ZodTypeAny> = RunnableCapabilityConfig<M, S> | RunlessCapabilityConfig<S>;
|
|
8
46
|
/**
|
|
9
47
|
* Configuration options for creating a new Agent instance.
|
|
10
48
|
*/
|
|
@@ -31,9 +69,9 @@ export interface AgentOptions<T extends string> {
|
|
|
31
69
|
*/
|
|
32
70
|
systemPrompt: string;
|
|
33
71
|
/**
|
|
34
|
-
*
|
|
72
|
+
* Optional OpenAI API key for direct LLM access via process().
|
|
73
|
+
* NOT required for platform-deployed agents -- use generate() or run-less capabilities instead.
|
|
35
74
|
* Can also be provided via OPENAI_API_KEY environment variable.
|
|
36
|
-
* Required when using the process() method.
|
|
37
75
|
*/
|
|
38
76
|
openaiApiKey?: string;
|
|
39
77
|
/**
|
|
@@ -82,7 +120,8 @@ export declare class Agent<M extends string = string> {
|
|
|
82
120
|
protected systemPrompt: string;
|
|
83
121
|
/**
|
|
84
122
|
* Array of capabilities (tools) available to the agent.
|
|
85
|
-
* Each capability is an instance of the Capability class with a name, description,
|
|
123
|
+
* Each capability is an instance of the Capability class with a name, description, inputSchema,
|
|
124
|
+
* and optionally a run function and/or outputSchema.
|
|
86
125
|
* @protected
|
|
87
126
|
*/
|
|
88
127
|
protected tools: Array<Capability<M, z.ZodTypeAny>>;
|
|
@@ -167,53 +206,32 @@ export declare class Agent<M extends string = string> {
|
|
|
167
206
|
private initializeMCPClients;
|
|
168
207
|
/**
|
|
169
208
|
* Adds a single capability (tool) to the agent.
|
|
170
|
-
* Each capability must have a unique name
|
|
209
|
+
* Each capability must have a unique name. Capabilities can be:
|
|
210
|
+
* - **Runnable**: has a `run` function and requires `inputSchema` (or deprecated `schema`)
|
|
211
|
+
* - **Run-less**: no `run` function -- the runtime handles execution via LLM.
|
|
212
|
+
* `inputSchema` is optional (defaults to `{ input: z.string() }`), `outputSchema` is optional.
|
|
171
213
|
*
|
|
172
214
|
* @template S - The Zod schema type for the capability's parameters
|
|
173
|
-
* @param
|
|
174
|
-
* @
|
|
175
|
-
* @param {string} capability.description - Description of what the capability does
|
|
176
|
-
* @param {S} capability.schema - Zod schema defining the capability's parameters
|
|
177
|
-
* @param {Function} capability.run - Function that implements the capability's behavior
|
|
178
|
-
* @param {Object} capability.run.params - Parameters for the run function
|
|
179
|
-
* @param {z.infer<S>} capability.run.params.args - Validated arguments matching the schema
|
|
180
|
-
* @param {ActionSchema} [capability.run.params.action] - Optional action context
|
|
181
|
-
* @param {ChatCompletionMessageParam[]} capability.run.messages - Chat message history
|
|
182
|
-
* @returns {this} The agent instance for method chaining
|
|
215
|
+
* @param capability - The capability configuration
|
|
216
|
+
* @returns The agent instance for method chaining
|
|
183
217
|
* @throws {Error} If a capability with the same name already exists
|
|
218
|
+
* @throws {Error} If both `inputSchema` and `schema` are provided
|
|
219
|
+
* @throws {Error} If both `run` and `outputSchema` are provided
|
|
220
|
+
* @throws {Error} If a runnable capability omits `inputSchema`/`schema`
|
|
184
221
|
*/
|
|
185
|
-
addCapability<S extends z.ZodTypeAny>(
|
|
186
|
-
name: string;
|
|
187
|
-
description: string;
|
|
188
|
-
schema: S;
|
|
189
|
-
run(this: Agent<M>, params: {
|
|
190
|
-
args: z.infer<S>;
|
|
191
|
-
action?: ActionSchema;
|
|
192
|
-
}, messages: ChatCompletionMessageParam[]): string | Promise<string>;
|
|
193
|
-
}): this;
|
|
222
|
+
addCapability<S extends z.ZodTypeAny>(capability: CapabilityConfig<M, S>): this;
|
|
194
223
|
/**
|
|
195
224
|
* Adds multiple capabilities (tools) to the agent at once.
|
|
196
225
|
* Each capability must have a unique name and not conflict with existing capabilities.
|
|
226
|
+
* Each element can be runnable or run-less independently.
|
|
197
227
|
*
|
|
198
228
|
* @template T - Tuple of Zod schema types for the capabilities' parameters
|
|
199
|
-
* @param
|
|
200
|
-
* @
|
|
201
|
-
* @param {string} capabilities[].description - Description of what each capability does
|
|
202
|
-
* @param {T[number]} capabilities[].schema - Zod schema defining each capability's parameters
|
|
203
|
-
* @param {Function} capabilities[].run - Function that implements each capability's behavior
|
|
204
|
-
* @returns {this} The agent instance for method chaining
|
|
229
|
+
* @param capabilities - Array of capability configurations
|
|
230
|
+
* @returns The agent instance for method chaining
|
|
205
231
|
* @throws {Error} If any capability has a name that already exists
|
|
206
232
|
*/
|
|
207
233
|
addCapabilities<T extends readonly [z.ZodTypeAny, ...z.ZodTypeAny[]]>(capabilities: {
|
|
208
|
-
[K in keyof T]:
|
|
209
|
-
name: string;
|
|
210
|
-
description: string;
|
|
211
|
-
schema: T[K];
|
|
212
|
-
run(this: Agent<M>, params: {
|
|
213
|
-
args: z.infer<T[K]>;
|
|
214
|
-
action?: ActionSchema;
|
|
215
|
-
}, messages: ChatCompletionMessageParam[]): string | Promise<string>;
|
|
216
|
-
};
|
|
234
|
+
[K in keyof T]: CapabilityConfig<M, T[K]>;
|
|
217
235
|
}): this;
|
|
218
236
|
/**
|
|
219
237
|
* Gets files in a workspace.
|
|
@@ -370,6 +388,37 @@ export declare class Agent<M extends string = string> {
|
|
|
370
388
|
* @returns {Promise<UpdateTaskStatusResponse>} The updated task details
|
|
371
389
|
*/
|
|
372
390
|
updateTaskStatus(params: UpdateTaskStatusParams): Promise<undefined>;
|
|
391
|
+
/**
|
|
392
|
+
* Generate text via the OpenServ runtime.
|
|
393
|
+
* Billed to the workspace/task in the action.
|
|
394
|
+
* Use this inside custom `run` functions when you need LLM generation without your own OpenAI key.
|
|
395
|
+
*
|
|
396
|
+
* @param params.prompt - The prompt for the LLM
|
|
397
|
+
* @param params.messages - Optional conversation history for context
|
|
398
|
+
* @param params.action - Action context (required for billing)
|
|
399
|
+
* @returns The generated text
|
|
400
|
+
*/
|
|
401
|
+
generate(params: {
|
|
402
|
+
prompt: string;
|
|
403
|
+
messages?: ChatCompletionMessageParam[];
|
|
404
|
+
action: ActionSchema;
|
|
405
|
+
}): Promise<string>;
|
|
406
|
+
/**
|
|
407
|
+
* Generate a structured object via the OpenServ runtime.
|
|
408
|
+
* Billed to the workspace/task in the action.
|
|
409
|
+
*
|
|
410
|
+
* @param params.prompt - The prompt for the LLM
|
|
411
|
+
* @param params.messages - Optional conversation history for context
|
|
412
|
+
* @param params.outputSchema - Zod schema for structured output
|
|
413
|
+
* @param params.action - Action context (required for billing)
|
|
414
|
+
* @returns The generated object, validated against the schema
|
|
415
|
+
*/
|
|
416
|
+
generate<T extends z.ZodTypeAny>(params: {
|
|
417
|
+
prompt: string;
|
|
418
|
+
messages?: ChatCompletionMessageParam[];
|
|
419
|
+
outputSchema: T;
|
|
420
|
+
action: ActionSchema;
|
|
421
|
+
}): Promise<z.infer<T>>;
|
|
373
422
|
/**
|
|
374
423
|
* Processes a conversation with OpenAI, handling tool calls iteratively until completion.
|
|
375
424
|
*
|
|
@@ -394,15 +443,18 @@ export declare class Agent<M extends string = string> {
|
|
|
394
443
|
/**
|
|
395
444
|
* Handles execution of a specific tool/capability.
|
|
396
445
|
*
|
|
446
|
+
* The runtime calls this for both task execution (do-task) and chat (respond-chat-message),
|
|
447
|
+
* always providing the action context in the request body.
|
|
448
|
+
*
|
|
397
449
|
* @param {Object} req - The request object
|
|
398
450
|
* @param {Object} req.params - Request parameters
|
|
399
451
|
* @param {string} req.params.toolName - Name of the tool to execute
|
|
400
452
|
* @param {Object} req.body - Request body
|
|
401
453
|
* @param {z.infer<z.ZodTypeAny>} [req.body.args] - Arguments for the tool
|
|
402
|
-
* @param {ActionSchema}
|
|
454
|
+
* @param {ActionSchema} req.body.action - Action context (required)
|
|
403
455
|
* @param {ChatCompletionMessageParam[]} [req.body.messages] - Message history
|
|
404
456
|
* @returns {Promise<{result: string}>} The result of the tool execution
|
|
405
|
-
* @throws {BadRequest} If tool name is missing
|
|
457
|
+
* @throws {BadRequest} If tool name is missing, tool is not found, or action is missing
|
|
406
458
|
* @throws {Error} If tool execution fails
|
|
407
459
|
*/
|
|
408
460
|
handleToolRoute(req: {
|
|
@@ -479,4 +531,5 @@ export declare class Agent<M extends string = string> {
|
|
|
479
531
|
*/
|
|
480
532
|
private addMCPToolsAsCapabilities;
|
|
481
533
|
}
|
|
534
|
+
export {};
|
|
482
535
|
//# sourceMappingURL=agent.d.ts.map
|
package/dist/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAUjD,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,EAEhB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAOlB,YAAY,EACZ,kBAAkB,EAClB,8BAA8B,EAC/B,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EACV,0BAA0B,EAE1B,cAAc,EACf,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/agent.js
CHANGED
|
@@ -13,14 +13,61 @@ const helmet_1 = __importDefault(require("helmet"));
|
|
|
13
13
|
const hpp_1 = __importDefault(require("hpp"));
|
|
14
14
|
const logger_1 = require("./logger");
|
|
15
15
|
const http_errors_1 = require("http-errors");
|
|
16
|
+
const openai_1 = __importDefault(require("openai"));
|
|
17
|
+
const zod_1 = require("zod");
|
|
16
18
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
17
19
|
const json_schema_to_zod_1 = require("@n8n/json-schema-to-zod");
|
|
18
|
-
|
|
20
|
+
// Zod v4 has native toJSONSchema/fromJSONSchema. For v3 we use third-party libs.
|
|
21
|
+
function zodToJsonSchema(schema, opts) {
|
|
22
|
+
if (typeof zod_1.z.toJSONSchema === 'function') {
|
|
23
|
+
return zod_1.z.toJSONSchema(schema);
|
|
24
|
+
}
|
|
25
|
+
return (0, zod_to_json_schema_1.zodToJsonSchema)(schema, opts);
|
|
26
|
+
}
|
|
27
|
+
function jsonSchemaToZodSchema(jsonSchema) {
|
|
28
|
+
if (typeof zod_1.z.fromJSONSchema === 'function') {
|
|
29
|
+
return zod_1.z.fromJSONSchema(jsonSchema);
|
|
30
|
+
}
|
|
31
|
+
return (0, json_schema_to_zod_1.jsonSchemaToZod)(jsonSchema);
|
|
32
|
+
}
|
|
19
33
|
const capability_1 = require("./capability");
|
|
20
34
|
const mcp_1 = require("./mcp");
|
|
21
35
|
const PLATFORM_URL = process.env.OPENSERV_API_URL || 'https://api.openserv.ai';
|
|
22
36
|
const RUNTIME_URL = process.env.OPENSERV_RUNTIME_URL || 'https://agents.openserv.ai';
|
|
23
37
|
const DEFAULT_PORT = Number.parseInt(process.env.PORT || '') || 7378;
|
|
38
|
+
/** Default input schema for run-less capabilities that omit inputSchema */
|
|
39
|
+
const DEFAULT_INPUT_SCHEMA = zod_1.z.object({ input: zod_1.z.string() });
|
|
40
|
+
/** Runtime validation schema for capability configs */
|
|
41
|
+
const capabilityConfigSchema = zod_1.z
|
|
42
|
+
.object({
|
|
43
|
+
name: zod_1.z.string().min(1),
|
|
44
|
+
description: zod_1.z.string().min(1),
|
|
45
|
+
inputSchema: zod_1.z.any().optional(),
|
|
46
|
+
schema: zod_1.z.any().optional(),
|
|
47
|
+
run: zod_1.z.any().optional(),
|
|
48
|
+
outputSchema: zod_1.z.any().optional()
|
|
49
|
+
})
|
|
50
|
+
.superRefine((data, ctx) => {
|
|
51
|
+
if (data.inputSchema && data.schema) {
|
|
52
|
+
ctx.addIssue({
|
|
53
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
54
|
+
message: 'Cannot provide both "inputSchema" and "schema". Use "inputSchema" ("schema" is deprecated).'
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (data.run && data.outputSchema) {
|
|
58
|
+
ctx.addIssue({
|
|
59
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
60
|
+
message: 'Cannot provide both "run" and "outputSchema". "outputSchema" is only for run-less capabilities.'
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (!data.inputSchema && !data.schema && data.run) {
|
|
64
|
+
ctx.addIssue({
|
|
65
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
66
|
+
message: 'Runnable capabilities require "inputSchema" (or deprecated "schema"). ' +
|
|
67
|
+
'Only run-less capabilities can omit it.'
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
24
71
|
class Agent {
|
|
25
72
|
options;
|
|
26
73
|
/**
|
|
@@ -55,7 +102,8 @@ class Agent {
|
|
|
55
102
|
systemPrompt;
|
|
56
103
|
/**
|
|
57
104
|
* Array of capabilities (tools) available to the agent.
|
|
58
|
-
* Each capability is an instance of the Capability class with a name, description,
|
|
105
|
+
* Each capability is an instance of the Capability class with a name, description, inputSchema,
|
|
106
|
+
* and optionally a run function and/or outputSchema.
|
|
59
107
|
* @protected
|
|
60
108
|
*/
|
|
61
109
|
tools = [];
|
|
@@ -127,7 +175,7 @@ class Agent {
|
|
|
127
175
|
function: {
|
|
128
176
|
name: tool.name,
|
|
129
177
|
description: tool.description,
|
|
130
|
-
parameters:
|
|
178
|
+
parameters: zodToJsonSchema(tool.inputSchema)
|
|
131
179
|
}
|
|
132
180
|
}));
|
|
133
181
|
}
|
|
@@ -142,7 +190,8 @@ class Agent {
|
|
|
142
190
|
if (!this._openai) {
|
|
143
191
|
const apiKey = this.options.openaiApiKey || process.env.OPENAI_API_KEY;
|
|
144
192
|
if (!apiKey) {
|
|
145
|
-
throw new Error('OpenAI API key is required for process().
|
|
193
|
+
throw new Error('OpenAI API key is required for process(). Provide it via options or OPENAI_API_KEY env var. ' +
|
|
194
|
+
'Alternatively, use generate() for runtime-delegated LLM calls, or run-less capabilities.');
|
|
146
195
|
}
|
|
147
196
|
this._openai = new openai_1.default({ apiKey });
|
|
148
197
|
}
|
|
@@ -180,41 +229,42 @@ class Agent {
|
|
|
180
229
|
}
|
|
181
230
|
/**
|
|
182
231
|
* Adds a single capability (tool) to the agent.
|
|
183
|
-
* Each capability must have a unique name
|
|
232
|
+
* Each capability must have a unique name. Capabilities can be:
|
|
233
|
+
* - **Runnable**: has a `run` function and requires `inputSchema` (or deprecated `schema`)
|
|
234
|
+
* - **Run-less**: no `run` function -- the runtime handles execution via LLM.
|
|
235
|
+
* `inputSchema` is optional (defaults to `{ input: z.string() }`), `outputSchema` is optional.
|
|
184
236
|
*
|
|
185
237
|
* @template S - The Zod schema type for the capability's parameters
|
|
186
|
-
* @param
|
|
187
|
-
* @
|
|
188
|
-
* @param {string} capability.description - Description of what the capability does
|
|
189
|
-
* @param {S} capability.schema - Zod schema defining the capability's parameters
|
|
190
|
-
* @param {Function} capability.run - Function that implements the capability's behavior
|
|
191
|
-
* @param {Object} capability.run.params - Parameters for the run function
|
|
192
|
-
* @param {z.infer<S>} capability.run.params.args - Validated arguments matching the schema
|
|
193
|
-
* @param {ActionSchema} [capability.run.params.action] - Optional action context
|
|
194
|
-
* @param {ChatCompletionMessageParam[]} capability.run.messages - Chat message history
|
|
195
|
-
* @returns {this} The agent instance for method chaining
|
|
238
|
+
* @param capability - The capability configuration
|
|
239
|
+
* @returns The agent instance for method chaining
|
|
196
240
|
* @throws {Error} If a capability with the same name already exists
|
|
241
|
+
* @throws {Error} If both `inputSchema` and `schema` are provided
|
|
242
|
+
* @throws {Error} If both `run` and `outputSchema` are provided
|
|
243
|
+
* @throws {Error} If a runnable capability omits `inputSchema`/`schema`
|
|
197
244
|
*/
|
|
198
|
-
addCapability(
|
|
199
|
-
|
|
245
|
+
addCapability(capability) {
|
|
246
|
+
const result = capabilityConfigSchema.safeParse(capability);
|
|
247
|
+
if (!result.success) {
|
|
248
|
+
throw new Error(result.error.issues[0]?.message ?? 'Invalid capability configuration');
|
|
249
|
+
}
|
|
250
|
+
const { name, description, run, outputSchema } = result.data;
|
|
251
|
+
const resolvedSchema = (result.data.inputSchema ??
|
|
252
|
+
result.data.schema ??
|
|
253
|
+
DEFAULT_INPUT_SCHEMA);
|
|
200
254
|
if (this.tools.some(tool => tool.name === name)) {
|
|
201
255
|
throw new Error(`Tool with name "${name}" already exists`);
|
|
202
256
|
}
|
|
203
|
-
|
|
204
|
-
this.tools.push(new capability_1.Capability(name, description, schema, run));
|
|
257
|
+
this.tools.push(new capability_1.Capability(name, description, resolvedSchema, typeof run === 'function' ? run : undefined, outputSchema));
|
|
205
258
|
return this;
|
|
206
259
|
}
|
|
207
260
|
/**
|
|
208
261
|
* Adds multiple capabilities (tools) to the agent at once.
|
|
209
262
|
* Each capability must have a unique name and not conflict with existing capabilities.
|
|
263
|
+
* Each element can be runnable or run-less independently.
|
|
210
264
|
*
|
|
211
265
|
* @template T - Tuple of Zod schema types for the capabilities' parameters
|
|
212
|
-
* @param
|
|
213
|
-
* @
|
|
214
|
-
* @param {string} capabilities[].description - Description of what each capability does
|
|
215
|
-
* @param {T[number]} capabilities[].schema - Zod schema defining each capability's parameters
|
|
216
|
-
* @param {Function} capabilities[].run - Function that implements each capability's behavior
|
|
217
|
-
* @returns {this} The agent instance for method chaining
|
|
266
|
+
* @param capabilities - Array of capability configurations
|
|
267
|
+
* @returns The agent instance for method chaining
|
|
218
268
|
* @throws {Error} If any capability has a name that already exists
|
|
219
269
|
*/
|
|
220
270
|
addCapabilities(capabilities) {
|
|
@@ -479,6 +529,24 @@ class Agent {
|
|
|
479
529
|
});
|
|
480
530
|
return response.data;
|
|
481
531
|
}
|
|
532
|
+
async generate(params) {
|
|
533
|
+
const response = await this.runtimeClient.post('/generate', {
|
|
534
|
+
prompt: params.prompt,
|
|
535
|
+
...(params.messages ? { messages: params.messages } : {}),
|
|
536
|
+
...(params.outputSchema ? { outputSchema: zodToJsonSchema(params.outputSchema) } : {}),
|
|
537
|
+
action: params.action
|
|
538
|
+
});
|
|
539
|
+
if (params.outputSchema) {
|
|
540
|
+
if (response.data.object === undefined || response.data.object === null) {
|
|
541
|
+
throw new Error('Runtime returned no structured output for generate() with outputSchema');
|
|
542
|
+
}
|
|
543
|
+
return params.outputSchema.parse(response.data.object);
|
|
544
|
+
}
|
|
545
|
+
if (typeof response.data.text !== 'string') {
|
|
546
|
+
throw new Error('Runtime returned no text for generate()');
|
|
547
|
+
}
|
|
548
|
+
return response.data.text;
|
|
549
|
+
}
|
|
482
550
|
/**
|
|
483
551
|
* Processes a conversation with OpenAI, handling tool calls iteratively until completion.
|
|
484
552
|
*
|
|
@@ -491,7 +559,8 @@ class Agent {
|
|
|
491
559
|
try {
|
|
492
560
|
const apiKey = this.options.openaiApiKey || process.env.OPENAI_API_KEY;
|
|
493
561
|
if (!apiKey) {
|
|
494
|
-
throw new Error('OpenAI API key is required for process().
|
|
562
|
+
throw new Error('OpenAI API key is required for process(). Provide it via options or OPENAI_API_KEY env var. ' +
|
|
563
|
+
'Alternatively, use generate() for runtime-delegated LLM calls, or run-less capabilities.');
|
|
495
564
|
}
|
|
496
565
|
const currentMessages = [...messages];
|
|
497
566
|
if (!currentMessages.find(m => m.content === this.systemPrompt)) {
|
|
@@ -530,8 +599,35 @@ class Agent {
|
|
|
530
599
|
if (!tool) {
|
|
531
600
|
throw new Error(`Tool "${name}" not found`);
|
|
532
601
|
}
|
|
533
|
-
|
|
534
|
-
|
|
602
|
+
let result;
|
|
603
|
+
if (tool.run) {
|
|
604
|
+
// Call the tool's run method with the parsed arguments and bind this
|
|
605
|
+
result = await tool.run.bind(this)({ args: parsedArgs }, currentMessages);
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
// Shim: use OpenAI with conversation history + description for run-less capabilities
|
|
609
|
+
const shimCompletion = await this.openai.chat.completions.create({
|
|
610
|
+
model: 'gpt-4o',
|
|
611
|
+
messages: [
|
|
612
|
+
...currentMessages,
|
|
613
|
+
{ role: 'system', content: tool.description },
|
|
614
|
+
{ role: 'user', content: JSON.stringify(parsedArgs) }
|
|
615
|
+
],
|
|
616
|
+
...(tool.outputSchema
|
|
617
|
+
? {
|
|
618
|
+
response_format: {
|
|
619
|
+
type: 'json_schema',
|
|
620
|
+
json_schema: {
|
|
621
|
+
name: tool.name,
|
|
622
|
+
schema: zodToJsonSchema(tool.outputSchema),
|
|
623
|
+
strict: true
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
: {})
|
|
628
|
+
});
|
|
629
|
+
result = shimCompletion.choices[0]?.message?.content || '';
|
|
630
|
+
}
|
|
535
631
|
return {
|
|
536
632
|
role: 'tool',
|
|
537
633
|
content: JSON.stringify(result),
|
|
@@ -582,9 +678,12 @@ class Agent {
|
|
|
582
678
|
content: action.task.description
|
|
583
679
|
});
|
|
584
680
|
}
|
|
681
|
+
const proxyTools = this.tools.filter(t => t.run);
|
|
682
|
+
const runtimeTools = this.tools.filter(t => !t.run);
|
|
585
683
|
try {
|
|
586
684
|
await this.runtimeClient.post('/execute', {
|
|
587
|
-
tools:
|
|
685
|
+
tools: proxyTools.map(convertProxyToolToJsonSchema),
|
|
686
|
+
runtimeTools: runtimeTools.map(convertRuntimeToolToJsonSchema),
|
|
588
687
|
messages,
|
|
589
688
|
action
|
|
590
689
|
});
|
|
@@ -616,9 +715,12 @@ class Agent {
|
|
|
616
715
|
});
|
|
617
716
|
}
|
|
618
717
|
}
|
|
718
|
+
const proxyTools = this.tools.filter(t => t.run);
|
|
719
|
+
const runtimeTools = this.tools.filter(t => !t.run);
|
|
619
720
|
try {
|
|
620
721
|
await this.runtimeClient.post('/chat', {
|
|
621
|
-
tools:
|
|
722
|
+
tools: proxyTools.map(convertProxyToolToJsonSchema),
|
|
723
|
+
runtimeTools: runtimeTools.map(convertRuntimeToolToJsonSchema),
|
|
622
724
|
messages,
|
|
623
725
|
action
|
|
624
726
|
});
|
|
@@ -633,15 +735,18 @@ class Agent {
|
|
|
633
735
|
/**
|
|
634
736
|
* Handles execution of a specific tool/capability.
|
|
635
737
|
*
|
|
738
|
+
* The runtime calls this for both task execution (do-task) and chat (respond-chat-message),
|
|
739
|
+
* always providing the action context in the request body.
|
|
740
|
+
*
|
|
636
741
|
* @param {Object} req - The request object
|
|
637
742
|
* @param {Object} req.params - Request parameters
|
|
638
743
|
* @param {string} req.params.toolName - Name of the tool to execute
|
|
639
744
|
* @param {Object} req.body - Request body
|
|
640
745
|
* @param {z.infer<z.ZodTypeAny>} [req.body.args] - Arguments for the tool
|
|
641
|
-
* @param {ActionSchema}
|
|
746
|
+
* @param {ActionSchema} req.body.action - Action context (required)
|
|
642
747
|
* @param {ChatCompletionMessageParam[]} [req.body.messages] - Message history
|
|
643
748
|
* @returns {Promise<{result: string}>} The result of the tool execution
|
|
644
|
-
* @throws {BadRequest} If tool name is missing
|
|
749
|
+
* @throws {BadRequest} If tool name is missing, tool is not found, or action is missing
|
|
645
750
|
* @throws {Error} If tool execution fails
|
|
646
751
|
*/
|
|
647
752
|
async handleToolRoute(req) {
|
|
@@ -653,7 +758,13 @@ class Agent {
|
|
|
653
758
|
if (!tool) {
|
|
654
759
|
throw new http_errors_1.BadRequest(`Tool "${req.params.toolName}" not found`);
|
|
655
760
|
}
|
|
656
|
-
|
|
761
|
+
if (!tool.run) {
|
|
762
|
+
throw new http_errors_1.BadRequest(`Tool "${req.params.toolName}" is a run-less capability handled by the runtime, not by this agent.`);
|
|
763
|
+
}
|
|
764
|
+
if (!req.body?.action) {
|
|
765
|
+
throw new http_errors_1.BadRequest('Action context is required for tool execution');
|
|
766
|
+
}
|
|
767
|
+
const args = await tool.inputSchema.parseAsync(req.body?.args);
|
|
657
768
|
const messages = req.body.messages || [];
|
|
658
769
|
const result = await tool.run.call(this, { args, action: req.body.action }, messages);
|
|
659
770
|
return { result };
|
|
@@ -905,7 +1016,7 @@ class Agent {
|
|
|
905
1016
|
this.addCapability({
|
|
906
1017
|
name: capabilityName,
|
|
907
1018
|
description: tool.description || `Tool from MCP server ${serverId}`,
|
|
908
|
-
|
|
1019
|
+
inputSchema: jsonSchemaToZodSchema(inputSchema),
|
|
909
1020
|
async run({ args }) {
|
|
910
1021
|
const mcpClient = this.mcpClients[serverId];
|
|
911
1022
|
if (!mcpClient) {
|
|
@@ -930,10 +1041,18 @@ class Agent {
|
|
|
930
1041
|
}
|
|
931
1042
|
}
|
|
932
1043
|
exports.Agent = Agent;
|
|
933
|
-
function
|
|
1044
|
+
function convertProxyToolToJsonSchema(tool) {
|
|
1045
|
+
return {
|
|
1046
|
+
name: tool.name,
|
|
1047
|
+
description: tool.description,
|
|
1048
|
+
schema: zodToJsonSchema(tool.inputSchema)
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
function convertRuntimeToolToJsonSchema(tool) {
|
|
934
1052
|
return {
|
|
935
1053
|
name: tool.name,
|
|
936
1054
|
description: tool.description,
|
|
937
|
-
schema:
|
|
1055
|
+
schema: zodToJsonSchema(tool.inputSchema),
|
|
1056
|
+
...(tool.outputSchema ? { outputSchema: zodToJsonSchema(tool.outputSchema) } : {})
|
|
938
1057
|
};
|
|
939
1058
|
}
|
package/dist/capability.d.ts
CHANGED
|
@@ -5,8 +5,11 @@ import type { Agent } from './agent';
|
|
|
5
5
|
export declare class Capability<M extends string, Schema extends z.ZodTypeAny> {
|
|
6
6
|
readonly name: string;
|
|
7
7
|
readonly description: string;
|
|
8
|
+
readonly run?: ((this: Agent<M>, params: CapabilityFuncParams<Schema>, messages: ChatCompletionMessageParam[]) => string | Promise<string>) | undefined;
|
|
9
|
+
readonly outputSchema?: z.ZodTypeAny | undefined;
|
|
10
|
+
readonly inputSchema: Schema;
|
|
11
|
+
/** @deprecated Use `inputSchema` instead */
|
|
8
12
|
readonly schema: Schema;
|
|
9
|
-
|
|
10
|
-
constructor(name: string, description: string, schema: Schema, run: (this: Agent<M>, params: CapabilityFuncParams<Schema>, messages: ChatCompletionMessageParam[]) => string | Promise<string>);
|
|
13
|
+
constructor(name: string, description: string, inputSchema: Schema, run?: ((this: Agent<M>, params: CapabilityFuncParams<Schema>, messages: ChatCompletionMessageParam[]) => string | Promise<string>) | undefined, outputSchema?: z.ZodTypeAny | undefined);
|
|
11
14
|
}
|
|
12
15
|
//# sourceMappingURL=capability.d.ts.map
|
package/dist/capability.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAA;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,qBAAa,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,SAAS,CAAC,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAA;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,qBAAa,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,SAAS,CAAC,CAAC,UAAU;aAMjD,IAAI,EAAE,MAAM;aACZ,WAAW,EAAE,MAAM;aAEnB,GAAG,CAAC,GAAE,CACpB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,EACpC,QAAQ,EAAE,0BAA0B,EAAE,KACnC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;aACb,YAAY,CAAC,EAAE,CAAC,CAAC,UAAU;IAb7C,SAAgB,WAAW,EAAE,MAAM,CAAA;IACnC,4CAA4C;IAC5C,SAAgB,MAAM,EAAE,MAAM,CAAA;gBAGZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnC,WAAW,EAAE,MAAM,EACH,GAAG,CAAC,GAAE,CACpB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,EACpC,QAAQ,EAAE,0BAA0B,EAAE,KACnC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,aAAA,EACb,YAAY,CAAC,EAAE,CAAC,CAAC,UAAU,YAAA;CAK9C"}
|
package/dist/capability.js
CHANGED
|
@@ -4,13 +4,18 @@ exports.Capability = void 0;
|
|
|
4
4
|
class Capability {
|
|
5
5
|
name;
|
|
6
6
|
description;
|
|
7
|
-
schema;
|
|
8
7
|
run;
|
|
9
|
-
|
|
8
|
+
outputSchema;
|
|
9
|
+
inputSchema;
|
|
10
|
+
/** @deprecated Use `inputSchema` instead */
|
|
11
|
+
schema;
|
|
12
|
+
constructor(name, description, inputSchema, run, outputSchema) {
|
|
10
13
|
this.name = name;
|
|
11
14
|
this.description = description;
|
|
12
|
-
this.schema = schema;
|
|
13
15
|
this.run = run;
|
|
16
|
+
this.outputSchema = outputSchema;
|
|
17
|
+
this.inputSchema = inputSchema;
|
|
18
|
+
this.schema = inputSchema;
|
|
14
19
|
}
|
|
15
20
|
}
|
|
16
21
|
exports.Capability = Capability;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Agent } from './agent';
|
|
2
|
-
export type { AgentOptions } from './agent';
|
|
2
|
+
export type { AgentOptions, CapabilityConfig } from './agent';
|
|
3
3
|
export { Capability } from './capability';
|
|
4
4
|
export { OpenServTunnel } from './tunnel';
|
|
5
5
|
export type { OpenServTunnelOptions, RequestData, ResponseData, TunnelState, TunnelEvent } from './tunnel';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,YAAY,EACV,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAElD,YAAY,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,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,EACpB,qBAAqB,EACtB,MAAM,SAAS,CAAA"}
|
package/dist/run.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export interface RunResult {
|
|
|
45
45
|
* agent.addCapability({
|
|
46
46
|
* name: 'greet',
|
|
47
47
|
* description: 'Greet someone',
|
|
48
|
-
*
|
|
48
|
+
* inputSchema: z.object({ name: z.string() }),
|
|
49
49
|
* run: async ({ args }) => `Hello, ${args.name}!`
|
|
50
50
|
* })
|
|
51
51
|
*
|
package/dist/run.js
CHANGED
|
@@ -28,7 +28,7 @@ const tunnel_1 = require("./tunnel");
|
|
|
28
28
|
* agent.addCapability({
|
|
29
29
|
* name: 'greet',
|
|
30
30
|
* description: 'Greet someone',
|
|
31
|
-
*
|
|
31
|
+
* inputSchema: z.object({ name: z.string() }),
|
|
32
32
|
* run: async ({ args }) => `Hello, ${args.name}!`
|
|
33
33
|
* })
|
|
34
34
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openserv-labs/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "OpenServ Agent SDK - Create AI agents easily",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@asteasolutions/zod-to-openapi": "^7.3.0",
|
|
46
46
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
|
47
|
-
"@n8n/json-schema-to-zod": "^1.1.0",
|
|
48
47
|
"axios": "^1.6.8",
|
|
49
48
|
"axios-retry": "^4.1.0",
|
|
50
49
|
"bcryptjs": "^3.0.2",
|
|
@@ -57,8 +56,8 @@
|
|
|
57
56
|
"pino": "^9.6.0",
|
|
58
57
|
"pino-pretty": "^13.1.3",
|
|
59
58
|
"ws": "^8.18.0",
|
|
60
|
-
"zod": "^3.
|
|
61
|
-
"
|
|
59
|
+
"zod-to-json-schema": "^3.25.0",
|
|
60
|
+
"@n8n/json-schema-to-zod": "^1.1.0"
|
|
62
61
|
},
|
|
63
62
|
"devDependencies": {
|
|
64
63
|
"@tsconfig/strictest": "^2.0.3",
|
|
@@ -92,6 +91,7 @@
|
|
|
92
91
|
"node": ">=18.0.0"
|
|
93
92
|
},
|
|
94
93
|
"peerDependencies": {
|
|
95
|
-
"openai": "^5.0.1"
|
|
94
|
+
"openai": "^5.0.1",
|
|
95
|
+
"zod": "^3.22.4 || ^4.0.0"
|
|
96
96
|
}
|
|
97
97
|
}
|