@agentica/core 0.16.7 → 0.16.9

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 (61) hide show
  1. package/lib/Agentica.js +2 -2
  2. package/lib/Agentica.js.map +1 -1
  3. package/lib/MicroAgentica.js +2 -2
  4. package/lib/MicroAgentica.js.map +1 -1
  5. package/lib/context/AgenticaOperation.d.ts +4 -2
  6. package/lib/context/internal/AgenticaOperationComposer.d.ts +0 -9
  7. package/lib/context/internal/AgenticaOperationComposer.js +105 -35
  8. package/lib/context/internal/AgenticaOperationComposer.js.map +1 -1
  9. package/lib/context/internal/AgenticaOperationComposer.spec.d.ts +1 -0
  10. package/lib/context/internal/AgenticaOperationComposer.spec.js +266 -0
  11. package/lib/context/internal/AgenticaOperationComposer.spec.js.map +1 -0
  12. package/lib/functional/assertHttpLlmApplication.js +31 -31
  13. package/lib/functional/assertMcpLlmApplication.d.ts +15 -0
  14. package/lib/functional/assertMcpLlmApplication.js +59 -0
  15. package/lib/functional/assertMcpLlmApplication.js.map +1 -0
  16. package/lib/functional/validateHttpLlmApplication.js +27 -27
  17. package/lib/index.d.ts +1 -0
  18. package/lib/index.js +2 -0
  19. package/lib/index.js.map +1 -1
  20. package/lib/index.mjs +416 -215
  21. package/lib/index.mjs.map +1 -1
  22. package/lib/json/IAgenticaOperationJson.d.ts +1 -1
  23. package/lib/orchestrate/call.js +206 -96
  24. package/lib/orchestrate/call.js.map +1 -1
  25. package/lib/orchestrate/cancel.js +0 -1
  26. package/lib/orchestrate/cancel.js.map +1 -1
  27. package/lib/orchestrate/initialize.js +63 -62
  28. package/lib/orchestrate/initialize.js.map +1 -1
  29. package/lib/orchestrate/select.js +4 -3
  30. package/lib/orchestrate/select.js.map +1 -1
  31. package/lib/structures/IAgenticaController.d.ts +9 -2
  32. package/lib/structures/mcp/IMcpLlmApplication.d.ts +15 -0
  33. package/lib/structures/mcp/IMcpLlmApplication.js +3 -0
  34. package/lib/structures/mcp/IMcpLlmApplication.js.map +1 -0
  35. package/lib/structures/mcp/IMcpLlmFunction.d.ts +17 -0
  36. package/lib/structures/mcp/IMcpLlmFunction.js +3 -0
  37. package/lib/structures/mcp/IMcpLlmFunction.js.map +1 -0
  38. package/lib/structures/mcp/IMcpLlmTransportProps.d.ts +11 -0
  39. package/lib/structures/mcp/IMcpLlmTransportProps.js +3 -0
  40. package/lib/structures/mcp/IMcpLlmTransportProps.js.map +1 -0
  41. package/lib/structures/mcp/index.d.ts +3 -0
  42. package/lib/structures/mcp/index.js +20 -0
  43. package/lib/structures/mcp/index.js.map +1 -0
  44. package/package.json +11 -6
  45. package/src/Agentica.ts +2 -2
  46. package/src/MicroAgentica.ts +2 -2
  47. package/src/context/AgenticaOperation.ts +9 -2
  48. package/src/context/internal/AgenticaOperationComposer.spec.ts +314 -0
  49. package/src/context/internal/AgenticaOperationComposer.ts +119 -49
  50. package/src/functional/assertMcpLlmApplication.ts +48 -0
  51. package/src/index.ts +6 -2
  52. package/src/json/IAgenticaOperationJson.ts +1 -1
  53. package/src/orchestrate/call.ts +239 -137
  54. package/src/orchestrate/cancel.ts +0 -1
  55. package/src/orchestrate/initialize.ts +2 -1
  56. package/src/orchestrate/select.ts +3 -2
  57. package/src/structures/IAgenticaController.ts +12 -2
  58. package/src/structures/mcp/IMcpLlmApplication.ts +17 -0
  59. package/src/structures/mcp/IMcpLlmFunction.ts +19 -0
  60. package/src/structures/mcp/IMcpLlmTransportProps.ts +13 -0
  61. package/src/structures/mcp/index.ts +3 -0
@@ -73,16 +73,18 @@ export async function call<Model extends ILlmSchema.Model>(
73
73
  function: {
74
74
  name: s.name,
75
75
  description: s.function.description,
76
- parameters: (s.function.separated !== undefined
77
- ? (s.function.separated.llm
78
- ?? ({
79
- type: "object",
80
- properties: {},
81
- required: [],
82
- additionalProperties: false,
83
- $defs: {},
84
- } satisfies IChatGptSchema.IParameters))
85
- : s.function.parameters) as Record<string, any>,
76
+ parameters: (
77
+ "separated" in s.function
78
+ && s.function.separated !== undefined
79
+ ? (s.function.separated.llm
80
+ ?? ({
81
+ type: "object",
82
+ properties: {},
83
+ required: [],
84
+ additionalProperties: false,
85
+ $defs: {},
86
+ } satisfies IChatGptSchema.IParameters))
87
+ : s.function.parameters) as Record<string, any>,
86
88
  },
87
89
  }) as OpenAI.ChatCompletionTool,
88
90
  ),
@@ -171,8 +173,8 @@ export async function call<Model extends ILlmSchema.Model>(
171
173
  }
172
174
  if (
173
175
  choice.message.role === "assistant"
174
- && choice.message.content !== null
175
- && choice.message.content.length > 0
176
+ && choice.message.content != null
177
+ && choice.message.content.length !== 0
176
178
  ) {
177
179
  closures.push(async () => {
178
180
  const value: AgenticaTextHistory = createTextHistory({
@@ -200,126 +202,93 @@ async function propagate<Model extends ILlmSchema.Model>(
200
202
  call: AgenticaCallEvent<Model>,
201
203
  retry: number,
202
204
  ): Promise<AgenticaExecuteHistory<Model>> {
203
- if (call.operation.protocol === "http") {
204
- // ----
205
- // HTTP PROTOCOL
206
- // ----
207
- // NESTED VALIDATOR
208
- const check: IValidation<unknown> = call.operation.function.validate(
209
- call.arguments,
210
- );
211
- if (check.success === false) {
212
- ctx.dispatch(
213
- createValidateEvent({
214
- id: call.id,
215
- operation: call.operation,
216
- result: check,
217
- }),
218
- ).catch(() => {});
219
- if (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)) {
220
- const trial: AgenticaExecuteHistory<Model> | null = await correct(
221
- ctx,
222
- call,
223
- retry,
224
- check.errors,
225
- );
226
- if (trial !== null) {
227
- return trial;
228
- }
205
+ switch (call.operation.protocol) {
206
+ case "http": {
207
+ return propagateHttp({ ctx, operation: call.operation, call, retry });
208
+ }
209
+ case "class": {
210
+ return propagateClass({ ctx, operation: call.operation, call, retry });
211
+ }
212
+ case "mcp": {
213
+ return propagateMcp({ ctx, operation: call.operation, call, retry });
214
+ }
215
+ default: {
216
+ call.operation satisfies never;
217
+ throw new Error("Unsupported protocol");
218
+ }
219
+ }
220
+ }
221
+
222
+ async function propagateHttp<Model extends ILlmSchema.Model>(
223
+ props: {
224
+ ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
225
+ operation: AgenticaOperation.Http<Model>;
226
+ call: AgenticaCallEvent<Model>;
227
+ retry: number;
228
+ },
229
+ ): Promise<AgenticaExecuteHistory<Model>> {
230
+ // ----
231
+ // HTTP PROTOCOL
232
+ // ----
233
+ // NESTED VALIDATOR
234
+ const check: IValidation<unknown> = props.operation.function.validate(
235
+ props.call.arguments,
236
+ );
237
+ if (check.success === false) {
238
+ props.ctx.dispatch(
239
+ createValidateEvent({
240
+ id: props.call.id,
241
+ operation: props.operation,
242
+ result: check,
243
+ }),
244
+ ).catch(() => {});
245
+
246
+ if (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)) {
247
+ const trial: AgenticaExecuteHistory<Model> | null = await correct(
248
+ props.ctx,
249
+ props.call,
250
+ props.retry,
251
+ check.errors,
252
+ );
253
+ if (trial !== null) {
254
+ return trial;
229
255
  }
230
256
  }
231
- try {
232
- // CALL HTTP API
233
- const response: IHttpResponse = await executeHttpOperation(call.operation, call.arguments);
234
- // CHECK STATUS
235
- const success: boolean
257
+ }
258
+
259
+ try {
260
+ // CALL HTTP API
261
+ const response: IHttpResponse = await executeHttpOperation(props.operation, props.call.arguments);
262
+ // CHECK STATUS
263
+ const success: boolean
236
264
  = ((response.status === 400
237
265
  || response.status === 404
238
266
  || response.status === 422)
239
- && retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)
267
+ && props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
240
268
  && typeof response.body) === false;
241
- // DISPATCH EVENT
242
- return (
243
- (success === false
244
- ? await correct(ctx, call, retry, response.body)
245
- : null)
246
- ?? createExecuteHistory({
247
- operation: call.operation,
248
- id: call.id,
249
- arguments: call.arguments,
250
- value: response,
251
- })
252
- );
253
- }
254
- catch (error) {
255
- // DISPATCH ERROR
256
- return createExecuteHistory({
257
- operation: call.operation,
258
- id: call.id,
259
- arguments: call.arguments,
260
- value: {
261
- status: 500,
262
- headers: {},
263
- body:
264
- error instanceof Error
265
- ? {
266
- ...error,
267
- name: error.name,
268
- message: error.message,
269
- }
270
- : error,
271
- },
272
- });
273
- }
274
- }
275
- else {
276
- // ----
277
- // CLASS FUNCTION
278
- // ----
279
- // VALIDATE FIRST
280
- const check: IValidation<unknown> = call.operation.function.validate(
281
- call.arguments,
269
+ // DISPATCH EVENT
270
+ return (
271
+ (success === false
272
+ ? await correct(props.ctx, props.call, props.retry, response.body)
273
+ : null)
274
+ ?? createExecuteHistory({
275
+ operation: props.call.operation,
276
+ id: props.call.id,
277
+ arguments: props.call.arguments,
278
+ value: response,
279
+ })
282
280
  );
283
- if (check.success === false) {
284
- ctx.dispatch(
285
- createValidateEvent({
286
- id: call.id,
287
- operation: call.operation,
288
- result: check,
289
- }),
290
- ).catch(() => {});
291
- return (
292
- (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)
293
- ? await correct(ctx, call, retry, check.errors)
294
- : null)
295
- ?? createExecuteHistory({
296
- id: call.id,
297
- operation: call.operation,
298
- arguments: call.arguments,
299
- value: {
300
- name: "TypeGuardError",
301
- message: "Invalid arguments.",
302
- errors: check.errors,
303
- },
304
- })
305
- );
306
- }
307
- // EXECUTE FUNCTION
308
- try {
309
- const value = await executeClassOperation(call.operation, call.arguments);
310
- return createExecuteHistory({
311
- id: call.id,
312
- operation: call.operation,
313
- arguments: call.arguments,
314
- value,
315
- });
316
- }
317
- catch (error) {
318
- return createExecuteHistory({
319
- id: call.id,
320
- operation: call.operation,
321
- arguments: call.arguments,
322
- value:
281
+ }
282
+ catch (error) {
283
+ // DISPATCH ERROR
284
+ return createExecuteHistory({
285
+ operation: props.call.operation,
286
+ id: props.call.id,
287
+ arguments: props.call.arguments,
288
+ value: {
289
+ status: 500,
290
+ headers: {},
291
+ body:
323
292
  error instanceof Error
324
293
  ? {
325
294
  ...error,
@@ -327,8 +296,109 @@ async function propagate<Model extends ILlmSchema.Model>(
327
296
  message: error.message,
328
297
  }
329
298
  : error,
330
- });
331
- }
299
+ },
300
+ });
301
+ }
302
+ }
303
+
304
+ async function propagateClass<Model extends ILlmSchema.Model>(props: {
305
+ ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
306
+ operation: AgenticaOperation.Class<Model>;
307
+ call: AgenticaCallEvent<Model>;
308
+ retry: number;
309
+ }): Promise<AgenticaExecuteHistory<Model>> {
310
+ // ----
311
+ // CLASS FUNCTION
312
+ // ----
313
+ // VALIDATE FIRST
314
+ const check: IValidation<unknown> = props.operation.function.validate(
315
+ props.call.arguments,
316
+ );
317
+
318
+ if (check.success === false) {
319
+ props.ctx.dispatch(
320
+ createValidateEvent({
321
+ id: props.call.id,
322
+ operation: props.call.operation,
323
+ result: check,
324
+ }),
325
+ ).catch(() => {});
326
+ return (
327
+ (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
328
+ ? await correct(props.ctx, props.call, props.retry, check.errors)
329
+ : null)
330
+ ?? createExecuteHistory({
331
+ id: props.call.id,
332
+ operation: props.call.operation,
333
+ arguments: props.call.arguments,
334
+ value: {
335
+ name: "TypeGuardError",
336
+ message: "Invalid arguments.",
337
+ errors: check.errors,
338
+ },
339
+ })
340
+ );
341
+ }
342
+ // EXECUTE FUNCTION
343
+ try {
344
+ const value = await executeClassOperation(props.operation, props.call.arguments);
345
+ return createExecuteHistory({
346
+ id: props.call.id,
347
+ operation: props.call.operation,
348
+ arguments: props.call.arguments,
349
+ value,
350
+ });
351
+ }
352
+ catch (error) {
353
+ return createExecuteHistory({
354
+ id: props.call.id,
355
+ operation: props.call.operation,
356
+ arguments: props.call.arguments,
357
+ value:
358
+ error instanceof Error
359
+ ? {
360
+ ...error,
361
+ name: error.name,
362
+ message: error.message,
363
+ }
364
+ : error,
365
+ });
366
+ }
367
+ }
368
+
369
+ async function propagateMcp<Model extends ILlmSchema.Model>(props: {
370
+ ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
371
+ operation: AgenticaOperation.Mcp;
372
+ call: AgenticaCallEvent<Model>;
373
+ retry: number;
374
+ }): Promise<AgenticaExecuteHistory<Model>> {
375
+ // ----
376
+ // MCP PROTOCOL
377
+ // ----
378
+ // @TODO: implement argument validation logic
379
+ try {
380
+ const value = await executeMcpOperation(props.operation, props.call.arguments);
381
+ return createExecuteHistory({
382
+ id: props.call.id,
383
+ operation: props.call.operation,
384
+ arguments: props.call.arguments,
385
+ value,
386
+ });
387
+ }
388
+ catch (error) {
389
+ return createExecuteHistory({
390
+ id: props.call.id,
391
+ operation: props.call.operation,
392
+ arguments: props.call.arguments,
393
+ value:
394
+ error instanceof Error
395
+ ? {
396
+ ...error,
397
+ name: error.name,
398
+ message: error.message,
399
+ }
400
+ : error,
401
+ });
332
402
  }
333
403
  }
334
404
 
@@ -365,6 +435,36 @@ async function executeClassOperation<Model extends ILlmSchema.Model>(operation:
365
435
  return ((execute as Record<string, unknown>)[operation.function.name] as (...args: unknown[]) => Promise<unknown>)(operationArguments);
366
436
  }
367
437
 
438
+ async function executeMcpOperation(operation: AgenticaOperation.Mcp, operationArguments: Record<string, unknown>): Promise<unknown> {
439
+ // for peerDependencies
440
+ const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
441
+ const { SSEClientTransport } = await import("@modelcontextprotocol/sdk/client/sse.js");
442
+ const { StdioClientTransport } = await import("@modelcontextprotocol/sdk/client/stdio.js");
443
+
444
+ const client = new Client({
445
+ name: operation.name,
446
+ version: "1.0.0",
447
+ });
448
+
449
+ const transport = (() => {
450
+ switch (operation.controller.application.transport.type) {
451
+ case "sse":
452
+ return new SSEClientTransport(operation.controller.application.transport.url);
453
+ case "stdio":
454
+ // @TODO: implement StdioClientTransport cache
455
+ // StdioClientTransport and connects a new child process every time it is initialized and connected.
456
+ // This results in significant latency and resource waste.
457
+ return new StdioClientTransport(operation.controller.application.transport);
458
+ default:
459
+ operation.controller.application.transport satisfies never;
460
+ throw new Error("Unsupported transport type");
461
+ }
462
+ })();
463
+ await client.connect(transport);
464
+ const result = await client.callTool({ method: operation.function.name, name: operation.function.name, arguments: operationArguments });
465
+ return result.content;
466
+ }
467
+
368
468
  async function correct<Model extends ILlmSchema.Model>(
369
469
  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
370
470
  call: AgenticaCallEvent<Model>,
@@ -436,16 +536,18 @@ async function correct<Model extends ILlmSchema.Model>(
436
536
  * @TODO fix it
437
537
  * The property and value have a type mismatch, but it works.
438
538
  */
439
- parameters: (call.operation.function.separated !== undefined
440
- ? (call.operation.function.separated?.llm
441
- ?? ({
442
- $defs: {},
443
- type: "object",
444
- properties: {},
445
- additionalProperties: false,
446
- required: [],
447
- } satisfies IChatGptSchema.IParameters))
448
- : call.operation.function.parameters) as unknown as Record<string, unknown>,
539
+ parameters: (
540
+ "separated" in call.operation.function
541
+ && call.operation.function.separated !== undefined
542
+ ? (call.operation.function.separated?.llm
543
+ ?? ({
544
+ $defs: {},
545
+ type: "object",
546
+ properties: {},
547
+ additionalProperties: false,
548
+ required: [],
549
+ } satisfies IChatGptSchema.IParameters))
550
+ : call.operation.function.parameters) as unknown as Record<string, unknown>,
449
551
  },
450
552
  },
451
553
  ],
@@ -34,7 +34,6 @@ interface IFailure {
34
34
  }
35
35
 
36
36
  export async function cancel<Model extends ILlmSchema.Model>(ctx: AgenticaContext<Model>): Promise<AgenticaCancelHistory<Model>[]> {
37
- console.error("orchestrate.cancel");
38
37
  if (ctx.operations.divided === undefined) {
39
38
  return step(ctx, ctx.operations.array, 0);
40
39
  }
@@ -88,7 +88,7 @@ export async function initialize<Model extends ILlmSchema.Model>(ctx: AgenticaCo
88
88
  continue;
89
89
  }
90
90
 
91
- if (choice.delta.content == null) {
91
+ if (choice.delta.content == null || choice.delta.content.length === 0) {
92
92
  continue;
93
93
  }
94
94
 
@@ -142,6 +142,7 @@ export async function initialize<Model extends ILlmSchema.Model>(ctx: AgenticaCo
142
142
  if (
143
143
  choice.message.role === "assistant"
144
144
  && choice.message.content != null
145
+ && choice.message.content.length !== 0
145
146
  ) {
146
147
  prompts.push(
147
148
  createTextHistory({
@@ -258,6 +258,7 @@ async function step<Model extends ILlmSchema.Model>(ctx: AgenticaContext<Model>,
258
258
  if (
259
259
  choice.message.role === "assistant"
260
260
  && choice.message.content != null
261
+ && choice.message.content.length !== 0
261
262
  ) {
262
263
  const text: AgenticaTextHistory = createTextHistory({
263
264
  role: "assistant",
@@ -265,7 +266,7 @@ async function step<Model extends ILlmSchema.Model>(ctx: AgenticaContext<Model>,
265
266
  });
266
267
  prompts.push(text);
267
268
 
268
- await ctx.dispatch(
269
+ ctx.dispatch(
269
270
  createTextEvent({
270
271
  role: "assistant",
271
272
  stream: StreamUtil.to(text.text),
@@ -273,7 +274,7 @@ async function step<Model extends ILlmSchema.Model>(ctx: AgenticaContext<Model>,
273
274
  done: () => true,
274
275
  get: () => text.text,
275
276
  }),
276
- );
277
+ ).catch(() => {});
277
278
  }
278
279
  }
279
280
 
@@ -8,6 +8,8 @@ import type {
8
8
  ILlmSchema,
9
9
  } from "@samchon/openapi";
10
10
 
11
+ import type { IMcpLlmApplication } from "./mcp/IMcpLlmApplication";
12
+
11
13
  /**
12
14
  * Controller of the Agentica Agent.
13
15
  *
@@ -18,14 +20,17 @@ import type {
18
20
  * Also, `IAgenticaController` is an union type which can specify
19
21
  * a subtype by checking the {@link protocol} property.
20
22
  *
21
- * - HTTP server: {@link IAgenticaController..IHttp}
23
+ * - HTTP server: {@link IAgenticaController.IHttp}
22
24
  * - TypeScript class: {@link IAgenticaController.IClass}
25
+ * - MCP Server: {@link IAgenticaController.IMcp}
23
26
  *
24
27
  * @author Samchon
25
28
  */
26
29
  export type IAgenticaController<Model extends ILlmSchema.Model> =
27
30
  | IAgenticaController.IHttp<Model>
28
- | IAgenticaController.IClass<Model>;
31
+ | IAgenticaController.IClass<Model>
32
+ | IAgenticaController.IMcp;
33
+
29
34
  export namespace IAgenticaController {
30
35
  /**
31
36
  * HTTP controller.
@@ -114,6 +119,11 @@ export namespace IAgenticaController {
114
119
  }) => Promise<unknown>);
115
120
  }
116
121
 
122
+ /**
123
+ * MCP Server controller.
124
+ */
125
+ export interface IMcp extends IBase<"mcp", IMcpLlmApplication> { }
126
+
117
127
  interface IBase<Protocol, Application> {
118
128
  /**
119
129
  * Protocol discrminator.
@@ -0,0 +1,17 @@
1
+ import type { IMcpLlmFunction } from "./IMcpLlmFunction";
2
+ import type { IMcpLlmTransportProps } from "./IMcpLlmTransportProps";
3
+
4
+ /**
5
+ * MCP LLM application.
6
+ */
7
+ export interface IMcpLlmApplication {
8
+ /**
9
+ * Functions of the MCP server.
10
+ */
11
+ functions: IMcpLlmFunction[];
12
+
13
+ /**
14
+ * Transport properties of the MCP server.
15
+ */
16
+ transport: IMcpLlmTransportProps;
17
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * MCP LLM function.
3
+ */
4
+ export interface IMcpLlmFunction {
5
+ /**
6
+ * Name of the function.
7
+ */
8
+ name: string;
9
+
10
+ /**
11
+ * Description of the function.
12
+ */
13
+ description?: string;
14
+
15
+ /**
16
+ * Parameters of the function.
17
+ */
18
+ parameters: object;
19
+ }
@@ -0,0 +1,13 @@
1
+ import type { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.d.ts";
2
+ import type { StdioServerParameters } from "@modelcontextprotocol/sdk/client/stdio.d.ts";
3
+
4
+ export type IMcpLlmTransportProps = IMcpLlmTransportPropsHttp | IMcpLlmTransportPropsStdio;
5
+
6
+ export interface IMcpLlmTransportPropsHttp extends IMcpLlmTransportPropsBase<"sse">, SSEClientTransportOptions {
7
+ url: URL;
8
+ }
9
+ export interface IMcpLlmTransportPropsStdio extends IMcpLlmTransportPropsBase<"stdio">, StdioServerParameters {}
10
+
11
+ export interface IMcpLlmTransportPropsBase<T extends string> {
12
+ type: T;
13
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./IMcpLlmApplication";
2
+ export * from "./IMcpLlmFunction";
3
+ export * from "./IMcpLlmTransportProps";