@agentica/core 0.29.6 → 0.30.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.
Files changed (44) hide show
  1. package/lib/constants/AgenticaSystemPrompt.d.ts +1 -0
  2. package/lib/constants/AgenticaSystemPrompt.js +1 -0
  3. package/lib/constants/AgenticaSystemPrompt.js.map +1 -1
  4. package/lib/events/AgenticaEvent.d.ts +3 -1
  5. package/lib/events/AgenticaJsonParseErrorEvent.d.ts +8 -0
  6. package/lib/events/AgenticaJsonParseErrorEvent.js +3 -0
  7. package/lib/events/AgenticaJsonParseErrorEvent.js.map +1 -0
  8. package/lib/events/MicroAgenticaEvent.d.ts +3 -1
  9. package/lib/events/index.d.ts +1 -0
  10. package/lib/events/index.js +1 -0
  11. package/lib/events/index.js.map +1 -1
  12. package/lib/factory/events.d.ts +8 -1
  13. package/lib/factory/events.js +14 -2
  14. package/lib/factory/events.js.map +1 -1
  15. package/lib/functional/assertHttpController.js +14 -14
  16. package/lib/functional/assertHttpLlmApplication.js +14 -14
  17. package/lib/functional/validateHttpController.js +14 -14
  18. package/lib/functional/validateHttpLlmApplication.js +14 -14
  19. package/lib/index.mjs +231 -285
  20. package/lib/index.mjs.map +1 -1
  21. package/lib/json/IAgenticaEventJson.d.ts +18 -5
  22. package/lib/orchestrate/call.d.ts +1 -1
  23. package/lib/orchestrate/call.js +198 -285
  24. package/lib/orchestrate/call.js.map +1 -1
  25. package/lib/orchestrate/initialize.js +1 -1
  26. package/lib/orchestrate/initialize.js.map +1 -1
  27. package/lib/orchestrate/select.js +1 -1
  28. package/lib/orchestrate/select.js.map +1 -1
  29. package/lib/structures/IAgenticaSystemPrompt.d.ts +31 -0
  30. package/lib/structures/IMicroAgenticaSystemPrompt.d.ts +31 -0
  31. package/package.json +1 -1
  32. package/prompts/json_parse_error.md +32 -0
  33. package/src/constants/AgenticaSystemPrompt.ts +2 -0
  34. package/src/events/AgenticaEvent.ts +3 -0
  35. package/src/events/AgenticaJsonParseErrorEvent.ts +12 -0
  36. package/src/events/MicroAgenticaEvent.ts +4 -1
  37. package/src/events/index.ts +1 -0
  38. package/src/factory/events.ts +19 -1
  39. package/src/json/IAgenticaEventJson.ts +20 -4
  40. package/src/orchestrate/call.ts +272 -389
  41. package/src/orchestrate/initialize.ts +2 -2
  42. package/src/orchestrate/select.ts +2 -2
  43. package/src/structures/IAgenticaSystemPrompt.ts +32 -0
  44. package/src/structures/IMicroAgenticaSystemPrompt.ts +32 -0
@@ -1,30 +1,28 @@
1
1
  import type {
2
2
  IChatGptSchema,
3
- IHttpMigrateRoute,
4
3
  IHttpResponse,
5
4
  ILlmSchema,
5
+ IValidation,
6
6
  } from "@samchon/openapi";
7
7
  import type OpenAI from "openai";
8
- import type { IValidation } from "typia";
9
8
 
10
- import {
11
- ChatGptTypeChecker,
12
- HttpLlm,
13
- LlmTypeCheckerV3_1,
14
- } from "@samchon/openapi";
9
+ import { HttpLlm } from "@samchon/openapi";
10
+ import { v4 } from "uuid";
15
11
 
16
12
  import type { AgenticaContext } from "../context/AgenticaContext";
17
13
  import type { AgenticaOperation } from "../context/AgenticaOperation";
18
14
  import type { MicroAgenticaContext } from "../context/MicroAgenticaContext";
19
- import type { AgenticaAssistantMessageEvent, AgenticaExecuteEvent, AgenticaValidateEvent } from "../events";
15
+ import type { AgenticaAssistantMessageEvent, AgenticaValidateEvent } from "../events";
20
16
  import type { AgenticaCallEvent } from "../events/AgenticaCallEvent";
17
+ import type { AgenticaExecuteEvent } from "../events/AgenticaExecuteEvent";
18
+ import type { AgenticaJsonParseErrorEvent } from "../events/AgenticaJsonParseErrorEvent";
21
19
  import type { MicroAgenticaHistory } from "../histories/MicroAgenticaHistory";
22
20
 
23
21
  import { AgenticaConstant } from "../constants/AgenticaConstant";
24
22
  import { AgenticaDefaultPrompt } from "../constants/AgenticaDefaultPrompt";
25
23
  import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
26
24
  import { isAgenticaContext } from "../context/internal/isAgenticaContext";
27
- import { creatAssistantMessageEvent, createCallEvent, createExecuteEvent, createValidateEvent } from "../factory/events";
25
+ import { createAssistantMessageEvent, createCallEvent, createExecuteEvent, createJsonParseErrorEvent, createValidateEvent } from "../factory/events";
28
26
  import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
29
27
  import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
30
28
  import { StreamUtil, toAsyncGenerator } from "../utils/StreamUtil";
@@ -35,18 +33,7 @@ export async function call<Model extends ILlmSchema.Model>(
35
33
  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
36
34
  operations: AgenticaOperation<Model>[],
37
35
  ): Promise<AgenticaExecuteEvent<Model>[]> {
38
- return station(ctx, operations, []);
39
- }
40
-
41
- async function station<Model extends ILlmSchema.Model>(
42
- ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
43
- operations: AgenticaOperation<Model>[],
44
- validateEvents: AgenticaValidateEvent<Model>[],
45
- ): Promise<AgenticaExecuteEvent<Model>[]> {
46
- // ----
47
- // EXECUTE CHATGPT API
48
- // ----
49
- const completionStream = await ctx.request("call", {
36
+ const stream: ReadableStream<OpenAI.ChatCompletionChunk> = await ctx.request("call", {
50
37
  messages: [
51
38
  // COMMON SYSTEM PROMPT
52
39
  {
@@ -99,48 +86,31 @@ async function station<Model extends ILlmSchema.Model>(
99
86
  tool_choice: "auto",
100
87
  // parallel_tool_calls: false,
101
88
  });
102
-
103
- // ----
104
- // PROCESS COMPLETION
105
- // ----
106
- const chunks = await StreamUtil.readAll(completionStream);
107
- const completion = ChatGptCompletionMessageUtil.merge(chunks);
89
+ const chunks: OpenAI.ChatCompletionChunk[] = await StreamUtil.readAll(stream);
90
+ const completion: OpenAI.ChatCompletion = ChatGptCompletionMessageUtil.merge(chunks);
108
91
  const executes: AgenticaExecuteEvent<Model>[] = [];
109
92
 
110
93
  for (const choice of completion.choices) {
111
94
  for (const tc of choice.message.tool_calls ?? []) {
112
95
  if (tc.type === "function") {
113
- const operation: AgenticaOperation<Model> | undefined
114
- = ctx.operations.flat.get(tc.function.name);
96
+ const operation: AgenticaOperation<Model> | undefined = operations.find(
97
+ s => s.name === tc.function.name,
98
+ );
115
99
  if (operation === undefined) {
116
- continue;
117
- }
118
- const call: AgenticaCallEvent<Model> = createCallEvent({
119
- id: tc.id,
120
- operation,
121
- // @TODO add type assertion!
122
- arguments: JSON.parse(tc.function.arguments) as Record<string, unknown>,
123
- });
124
- if (call.operation.protocol === "http") {
125
- fillHttpArguments({
126
- operation: call.operation,
127
- arguments: call.arguments,
128
- });
100
+ continue; // Ignore unknown tool calls
129
101
  }
130
- ctx.dispatch(call);
131
-
132
- const exec: AgenticaExecuteEvent<Model> = await propagate(
102
+ const event: AgenticaExecuteEvent<Model> = await predicate(
133
103
  ctx,
134
- call,
135
- 0,
136
- validateEvents,
104
+ operation,
105
+ tc,
106
+ [],
107
+ ctx.config?.retry ?? AgenticaConstant.RETRY,
137
108
  );
138
- ctx.dispatch(exec);
139
- executes.push(exec);
140
-
109
+ ctx.dispatch(event);
110
+ executes.push(event);
141
111
  if (isAgenticaContext(ctx)) {
142
112
  cancelFunctionFromContext(ctx, {
143
- name: call.operation.name,
113
+ name: event.operation.name,
144
114
  reason: "completed",
145
115
  });
146
116
  }
@@ -152,7 +122,7 @@ async function station<Model extends ILlmSchema.Model>(
152
122
  && choice.message.content.length !== 0
153
123
  ) {
154
124
  const text: string = choice.message.content;
155
- const event: AgenticaAssistantMessageEvent = creatAssistantMessageEvent({
125
+ const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
156
126
  get: () => text,
157
127
  done: () => true,
158
128
  stream: toAsyncGenerator(text),
@@ -164,275 +134,162 @@ async function station<Model extends ILlmSchema.Model>(
164
134
  return executes;
165
135
  }
166
136
 
167
- async function propagate<Model extends ILlmSchema.Model>(
137
+ async function predicate<Model extends ILlmSchema.Model>(
168
138
  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
169
- call: AgenticaCallEvent<Model>,
170
- retry: number,
171
- validateEvents: AgenticaValidateEvent<Model>[],
139
+ operation: AgenticaOperation<Model>,
140
+ toolCall: OpenAI.ChatCompletionMessageToolCall,
141
+ previousValidationErrors: AgenticaValidateEvent<Model>[],
142
+ life: number,
172
143
  ): Promise<AgenticaExecuteEvent<Model>> {
173
- switch (call.operation.protocol) {
174
- case "http": {
175
- return propagateHttp({
176
- ctx,
177
- operation: call.operation,
178
- call,
179
- retry,
180
- validateEvents,
181
- });
182
- }
183
- case "class": {
184
- return propagateClass({ ctx, operation: call.operation, call, retry, validateEvents });
185
- }
186
- case "mcp": {
187
- return propagateMcp({ ctx, operation: call.operation, call, retry, validateEvents });
188
- }
189
- default: {
190
- call.operation satisfies never;
191
- throw new Error("Unsupported protocol");
192
- }
144
+ // CHECK INPUT ARGUMENT
145
+ const call: AgenticaCallEvent<Model> | AgenticaJsonParseErrorEvent<Model>
146
+ = parseArguments(
147
+ operation,
148
+ toolCall,
149
+ );
150
+ ctx.dispatch(call);
151
+ if (call.type === "jsonParseError") {
152
+ return correctJsonError(ctx, call, previousValidationErrors, life - 1);
193
153
  }
194
- }
195
154
 
196
- async function propagateHttp<Model extends ILlmSchema.Model>(
197
- props: {
198
- ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
199
- operation: AgenticaOperation.Http<Model>;
200
- call: AgenticaCallEvent<Model>;
201
- validateEvents: AgenticaValidateEvent<Model>[];
202
- retry: number;
203
- },
204
- ): Promise<AgenticaExecuteEvent<Model>> {
205
- // ----
206
- // HTTP PROTOCOL
207
- // ----
208
- // NESTED VALIDATOR
209
- const check: IValidation<unknown> = props.operation.function.validate(
210
- props.call.arguments,
211
- );
155
+ // CHECK TYPE VALIDATION
156
+ const check: IValidation<unknown> = operation.function.validate(call.arguments);
212
157
  if (check.success === false) {
213
- const ve: AgenticaValidateEvent<Model> = createValidateEvent({
214
- id: props.call.id,
215
- operation: props.call.operation,
158
+ const event: AgenticaValidateEvent<Model> = createValidateEvent({
159
+ id: toolCall.id,
160
+ operation,
216
161
  result: check,
217
162
  });
218
- props.ctx.dispatch(ve);
219
- props.validateEvents.push(ve);
220
-
221
- if (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)) {
222
- const trial: AgenticaExecuteEvent<Model> | null = await correct(
223
- props.ctx,
224
- props.call,
225
- props.retry,
226
- check.errors,
227
- props.validateEvents,
228
- );
229
- if (trial !== null) {
230
- return trial;
231
- }
232
- }
233
- }
234
-
235
- try {
236
- // CALL HTTP API
237
- const response: IHttpResponse = await executeHttpOperation(props.operation, props.call.arguments);
238
- // CHECK STATUS
239
- const success: boolean
240
- = ((response.status === 400
241
- || response.status === 404
242
- || response.status === 422)
243
- && props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
244
- && typeof response.body) === false;
245
- // DISPATCH EVENT
246
- return (
247
- (success === false
248
- ? await correct(
249
- props.ctx,
250
- props.call,
251
- props.retry,
252
- response.body,
253
- props.validateEvents,
254
- )
255
- : null)
256
- ?? createExecuteEvent({
257
- operation: props.call.operation,
258
- arguments: props.call.arguments,
259
- value: response,
260
- })
163
+ ctx.dispatch(event);
164
+ return correctTypeError(
165
+ ctx,
166
+ call,
167
+ event,
168
+ [...previousValidationErrors, event],
169
+ life - 1,
261
170
  );
262
171
  }
263
- catch (error) {
264
- // DISPATCH ERROR
265
- return createExecuteEvent({
266
- operation: props.call.operation,
267
- arguments: props.call.arguments,
172
+
173
+ // EXECUTE OPERATION
174
+ const execute: AgenticaExecuteEvent<Model> = await executeFunction(call, operation);
175
+ ctx.dispatch(execute);
176
+ return execute;
177
+ }
178
+
179
+ /* -----------------------------------------------------------
180
+ ERROR CORRECTORS
181
+ ----------------------------------------------------------- */
182
+ async function correctTypeError<Model extends ILlmSchema.Model>(
183
+ ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
184
+ callEvent: AgenticaCallEvent<Model>,
185
+ validateEvent: AgenticaValidateEvent<Model>,
186
+ previousValidationErrors: AgenticaValidateEvent<Model>[],
187
+ life: number,
188
+ ): Promise<AgenticaExecuteEvent<Model>> {
189
+ return correctError<Model>(ctx, {
190
+ giveUp: () => createExecuteEvent({
191
+ operation: callEvent.operation,
192
+ arguments: callEvent.arguments,
268
193
  value: {
269
- status: 500,
270
- headers: {},
271
- body:
272
- error instanceof Error
273
- ? {
274
- ...error,
275
- name: error.name,
276
- message: error.message,
277
- }
278
- : error,
194
+ name: "ValidationError",
195
+ message: `Invalid arguments. The validation failed after ${AgenticaConstant.RETRY} retries.`,
196
+ errors: validateEvent.result.errors,
279
197
  },
280
- });
281
- }
198
+ }),
199
+ operation: callEvent.operation,
200
+ messageArguments: JSON.stringify(callEvent.arguments),
201
+ messageToolParam: {
202
+ role: "tool",
203
+ content: JSON.stringify(validateEvent.result.errors),
204
+ tool_call_id: callEvent.id,
205
+ } satisfies OpenAI.ChatCompletionToolMessageParam,
206
+ systemPrompt: ctx.config?.systemPrompt?.validate?.(previousValidationErrors.slice(0, -1))
207
+ ?? [
208
+ AgenticaSystemPrompt.VALIDATE,
209
+ ...(previousValidationErrors.length > 1
210
+ ? [
211
+ "",
212
+ AgenticaSystemPrompt.VALIDATE_REPEATED.replace(
213
+ "${{HISTORICAL_ERRORS}}",
214
+ JSON.stringify(previousValidationErrors.slice(0, -1).map(e => e.result.errors)),
215
+ ),
216
+ ]
217
+ : []),
218
+ ].join("\n"),
219
+ life,
220
+ previousValidationErrors,
221
+ });
282
222
  }
283
223
 
284
- async function propagateClass<Model extends ILlmSchema.Model>(props: {
285
- ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
286
- operation: AgenticaOperation.Class<Model>;
287
- call: AgenticaCallEvent<Model>;
288
- validateEvents: AgenticaValidateEvent<Model>[];
289
- retry: number;
290
- }): Promise<AgenticaExecuteEvent<Model>> {
291
- // ----
292
- // CLASS FUNCTION
293
- // ----
294
- // VALIDATE FIRST
295
- const check: IValidation<unknown> = props.operation.function.validate(
296
- props.call.arguments,
297
- );
298
- if (check.success === false) {
299
- const ve: AgenticaValidateEvent<Model> = createValidateEvent({
300
- id: props.call.id,
301
- operation: props.call.operation,
302
- result: check,
303
- });
304
- props.ctx.dispatch(ve);
305
- props.validateEvents.push(ve);
306
- return (
307
- (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
308
- ? await correct(props.ctx, props.call, props.retry, check.errors, props.validateEvents)
309
- : null)
310
- ?? createExecuteEvent({
311
- operation: props.call.operation,
312
- arguments: props.call.arguments,
313
- value: {
314
- name: "TypeGuardError",
315
- message: "Invalid arguments.",
316
- errors: check.errors,
317
- },
318
- })
319
- );
320
- }
321
- // EXECUTE FUNCTION
322
- try {
323
- const value = await executeClassOperation(props.operation, props.call.arguments);
324
- return createExecuteEvent({
325
- operation: props.call.operation,
326
- arguments: props.call.arguments,
327
- value,
328
- });
329
- }
330
- catch (error) {
331
- return createExecuteEvent({
332
- operation: props.call.operation,
333
- arguments: props.call.arguments,
334
- value:
335
- error instanceof Error
336
- ? {
337
- ...error,
338
- name: error.name,
339
- message: error.message,
340
- }
341
- : error,
342
- });
343
- }
224
+ async function correctJsonError<Model extends ILlmSchema.Model>(
225
+ ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
226
+ parseErrorEvent: AgenticaJsonParseErrorEvent<Model>,
227
+ previousValidationErrors: AgenticaValidateEvent<Model>[],
228
+ life: number,
229
+ ): Promise<AgenticaExecuteEvent<Model>> {
230
+ return correctError<Model>(ctx, {
231
+ giveUp: () => createExecuteEvent({
232
+ operation: parseErrorEvent.operation,
233
+ arguments: {},
234
+ value: {
235
+ name: "JsonParseError",
236
+ message: `Invalid JSON format. The parsing failed after ${AgenticaConstant.RETRY} retries.`,
237
+ arguments: parseErrorEvent.arguments,
238
+ errorMessage: parseErrorEvent.errorMessage,
239
+ },
240
+ }),
241
+ operation: parseErrorEvent.operation,
242
+ messageArguments: parseErrorEvent.arguments,
243
+ messageToolParam: null,
244
+ systemPrompt: ctx.config?.systemPrompt?.jsonParseError?.(parseErrorEvent)
245
+ ?? AgenticaSystemPrompt.JSON_PARSE_ERROR.replace(
246
+ "${{ERROR_MESSAGE}}",
247
+ parseErrorEvent.errorMessage,
248
+ ),
249
+ life,
250
+ previousValidationErrors,
251
+ });
344
252
  }
345
253
 
346
- async function propagateMcp<Model extends ILlmSchema.Model>(props: {
347
- ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
348
- operation: AgenticaOperation.Mcp<Model>;
349
- call: AgenticaCallEvent<Model>;
350
- validateEvents: AgenticaValidateEvent<Model>[];
351
- retry: number;
352
- }): Promise<AgenticaExecuteEvent<Model>> {
353
- // ----
354
- // MCP PROTOCOL
355
- // ----
356
- // @TODO: implement argument validation logic
254
+ function parseArguments<Model extends ILlmSchema.Model>(
255
+ operation: AgenticaOperation<Model>,
256
+ toolCall: OpenAI.ChatCompletionMessageToolCall,
257
+ ): AgenticaCallEvent<Model> | AgenticaJsonParseErrorEvent<Model> {
357
258
  try {
358
- const value = await executeMcpOperation(props.operation, props.call.arguments);
359
- return createExecuteEvent({
360
- operation: props.call.operation,
361
- arguments: props.call.arguments,
362
- value,
259
+ const data: Record<string, unknown> = JSON.parse(toolCall.function.arguments);
260
+ return createCallEvent({
261
+ id: toolCall.id,
262
+ operation,
263
+ arguments: data,
363
264
  });
364
265
  }
365
266
  catch (error) {
366
- return createExecuteEvent({
367
- operation: props.call.operation,
368
- arguments: props.call.arguments,
369
- value:
370
- error instanceof Error
371
- ? {
372
- ...error,
373
- name: error.name,
374
- message: error.message,
375
- }
376
- : error,
267
+ return createJsonParseErrorEvent({
268
+ id: toolCall.id,
269
+ operation,
270
+ arguments: toolCall.function.arguments,
271
+ errorMessage: error instanceof Error ? error.message : String(error),
377
272
  });
378
273
  }
379
274
  }
380
275
 
381
- async function executeHttpOperation<Model extends ILlmSchema.Model>(operation: AgenticaOperation.Http<Model>, operationArguments: Record<string, unknown>): Promise<IHttpResponse> {
382
- const controllerBaseArguments = {
383
- connection: operation.controller.connection,
384
- application: operation.controller.application,
385
- function: operation.function,
386
- };
387
- return operation.controller.execute !== undefined
388
- ? operation.controller.execute({ ...controllerBaseArguments, arguments: operationArguments })
389
- : HttpLlm.propagate({ ...controllerBaseArguments, input: operationArguments });
390
- }
391
-
392
- /**
393
- * @throws {TypeError}
394
- */
395
- async function executeClassOperation<Model extends ILlmSchema.Model>(operation: AgenticaOperation.Class<Model>, operationArguments: Record<string, unknown>): Promise<unknown> {
396
- const execute = operation.controller.execute;
397
- if (typeof execute === "function") {
398
- return await execute({
399
- application: operation.controller.application,
400
- function: operation.function,
401
- arguments: operationArguments,
402
- });
276
+ async function correctError<Model extends ILlmSchema.Model>(
277
+ ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
278
+ props: {
279
+ giveUp: () => AgenticaExecuteEvent<Model>;
280
+ operation: AgenticaOperation<Model>;
281
+ messageArguments: string;
282
+ messageToolParam: null | OpenAI.ChatCompletionToolMessageParam;
283
+ systemPrompt: string;
284
+ life: number;
285
+ previousValidationErrors: AgenticaValidateEvent<Model>[];
286
+ },
287
+ ): Promise<AgenticaExecuteEvent<Model>> {
288
+ if (props.life <= 0) {
289
+ return props.giveUp();
403
290
  }
404
291
 
405
- // As you know, it's very unstable logic.
406
- // But this is an intended error.
407
- // There are two types of errors that can occur here.
408
- // One is a TypeError caused by referencing an undefined value, and the other is a TypeError caused by calling something that isn't a function.
409
- // These errors are intentional, and any call to this function must be wrapped in a try-catch block.
410
- // Unless there is an overall structural improvement, this function will remain as-is.
411
- return ((execute as Record<string, unknown>)[operation.function.name] as (...args: unknown[]) => Promise<unknown>)(operationArguments);
412
- }
413
-
414
- async function executeMcpOperation<Model extends ILlmSchema.Model>(
415
- operation: AgenticaOperation.Mcp<Model>,
416
- operationArguments: Record<string, unknown>,
417
- ): Promise<unknown> {
418
- return operation.controller.client.callTool({
419
- method: operation.function.name,
420
- name: operation.function.name,
421
- arguments: operationArguments,
422
- }).then(v => v.content);
423
- }
424
-
425
- async function correct<Model extends ILlmSchema.Model>(
426
- ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
427
- call: AgenticaCallEvent<Model>,
428
- retry: number,
429
- error: unknown,
430
- validateEvents: AgenticaValidateEvent<Model>[],
431
- ): Promise<AgenticaExecuteEvent<Model> | null> {
432
- // ----
433
- // EXECUTE CHATGPT API
434
- // ----
435
- const completionStream = await ctx.request("call", {
292
+ const stream: ReadableStream<OpenAI.ChatCompletionChunk> = await ctx.request("call", {
436
293
  messages: [
437
294
  // COMMON SYSTEM PROMPT
438
295
  {
@@ -447,48 +304,31 @@ async function correct<Model extends ILlmSchema.Model>(
447
304
  content: ctx.prompt.contents.map(decodeUserMessageContent),
448
305
  },
449
306
  // TYPE CORRECTION
450
- ...(ctx.config?.systemPrompt?.execute === null
451
- ? []
452
- : [{
453
- role: "system",
454
- content:
455
- ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory<Model>[])
456
- ?? AgenticaSystemPrompt.EXECUTE,
457
- } satisfies OpenAI.ChatCompletionSystemMessageParam]
458
- ),
307
+ {
308
+ role: "system",
309
+ content:
310
+ ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory<Model>[])
311
+ ?? AgenticaSystemPrompt.EXECUTE,
312
+ },
459
313
  {
460
314
  role: "assistant",
461
315
  tool_calls: [
462
316
  {
463
317
  type: "function",
464
- id: call.id,
318
+ id: v4(),
465
319
  function: {
466
- name: call.operation.name,
467
- arguments: JSON.stringify(call.arguments),
320
+ name: props.operation.name,
321
+ arguments: props.messageArguments,
468
322
  },
469
323
  } satisfies OpenAI.ChatCompletionMessageToolCall,
470
324
  ],
471
325
  } satisfies OpenAI.ChatCompletionAssistantMessageParam,
472
- {
473
- role: "tool",
474
- content: typeof error === "string" ? error : JSON.stringify(error),
475
- tool_call_id: call.id,
476
- } satisfies OpenAI.ChatCompletionToolMessageParam,
326
+ ...(props.messageToolParam !== null
327
+ ? [props.messageToolParam]
328
+ : []),
477
329
  {
478
330
  role: "system",
479
- content: ctx.config?.systemPrompt?.validate?.(validateEvents.slice(0, -1))
480
- ?? [
481
- AgenticaSystemPrompt.VALIDATE,
482
- ...(validateEvents.length > 1
483
- ? [
484
- "",
485
- AgenticaSystemPrompt.VALIDATE_REPEATED.replace(
486
- "${{HISTORICAL_ERRORS}}",
487
- JSON.stringify(validateEvents.slice(0, -1).map(e => e.result.errors)),
488
- ),
489
- ]
490
- : []),
491
- ].join("\n"),
331
+ content: props.systemPrompt,
492
332
  },
493
333
  ],
494
334
  // STACK FUNCTIONS
@@ -496,16 +336,16 @@ async function correct<Model extends ILlmSchema.Model>(
496
336
  {
497
337
  type: "function",
498
338
  function: {
499
- name: call.operation.name,
500
- description: call.operation.function.description,
339
+ name: props.operation.name,
340
+ description: props.operation.function.description,
501
341
  /**
502
342
  * @TODO fix it
503
343
  * The property and value have a type mismatch, but it works.
504
344
  */
505
345
  parameters: (
506
- ("separated" in call.operation.function
507
- && call.operation.function.separated !== undefined)
508
- ? (call.operation.function.separated?.llm
346
+ ("separated" in props.operation.function
347
+ && props.operation.function.separated !== undefined)
348
+ ? (props.operation.function.separated?.llm
509
349
  ?? ({
510
350
  $defs: {},
511
351
  type: "object",
@@ -514,79 +354,122 @@ async function correct<Model extends ILlmSchema.Model>(
514
354
  required: [],
515
355
  } satisfies IChatGptSchema.IParameters))
516
356
 
517
- : call.operation.function.parameters) as unknown as Record<string, unknown>,
357
+ : props.operation.function.parameters) as unknown as Record<string, unknown>,
518
358
  },
519
359
  },
520
360
  ],
521
361
  tool_choice: {
522
362
  type: "function",
523
363
  function: {
524
- name: call.operation.name,
364
+ name: props.operation.name,
525
365
  },
526
366
  },
527
367
  // parallel_tool_calls: false,
528
368
  });
369
+ const chunks: OpenAI.ChatCompletionChunk[] = await StreamUtil.readAll(stream);
370
+ const completion: OpenAI.ChatCompletion = ChatGptCompletionMessageUtil.merge(chunks);
529
371
 
530
- const chunks = await StreamUtil.readAll(completionStream);
531
- const completion = ChatGptCompletionMessageUtil.merge(chunks);
532
-
533
- // ----
534
- // PROCESS COMPLETION
535
- // ----
536
- const toolCall: OpenAI.ChatCompletionMessageToolCall | undefined = (
537
- completion.choices[0]?.message.tool_calls ?? []
538
- ).find(
539
- tc =>
540
- tc.type === "function" && tc.function.name === call.operation.name,
541
- );
542
- if (toolCall === undefined) {
543
- return null;
544
- }
545
- return propagate(
546
- ctx,
547
- createCallEvent({
548
- id: toolCall.id,
549
- operation: call.operation,
550
- arguments: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,
551
- }),
552
- retry,
553
- validateEvents,
372
+ const toolCall: OpenAI.ChatCompletionMessageToolCall | undefined = completion.choices[0]?.message.tool_calls?.find(
373
+ s => s.function.name === props.operation.name,
554
374
  );
375
+ return toolCall === undefined
376
+ ? props.giveUp()
377
+ : predicate<Model>(
378
+ ctx,
379
+ props.operation,
380
+ toolCall,
381
+ props.previousValidationErrors,
382
+ props.life,
383
+ );
555
384
  }
556
385
 
557
- function fillHttpArguments<Model extends ILlmSchema.Model>(props: {
558
- operation: AgenticaOperation<Model>;
559
- arguments: Record<string, unknown>;
560
- }): void {
561
- if (props.operation.protocol !== "http") {
562
- return;
386
+ /* -----------------------------------------------------------
387
+ FUNCTION EXECUTORS
388
+ ----------------------------------------------------------- */
389
+ async function executeFunction<Model extends ILlmSchema.Model>(
390
+ call: AgenticaCallEvent<Model>,
391
+ operation: AgenticaOperation<Model>,
392
+ ): Promise<AgenticaExecuteEvent<Model>> {
393
+ try {
394
+ const value: unknown = await (async () => {
395
+ switch (operation.protocol) {
396
+ case "class":
397
+ return executeClassFunction(call, operation);
398
+ case "http":
399
+ return executeHttpOperation(call, operation);
400
+ case "mcp":
401
+ return executeMcpOperation(call, operation);
402
+ default:
403
+ operation satisfies never; // Ensure all cases are handled
404
+ throw new Error("Unknown protocol"); // never be happen
405
+ }
406
+ })();
407
+ return createExecuteEvent({
408
+ operation: call.operation,
409
+ arguments: call.arguments,
410
+ value,
411
+ });
563
412
  }
564
- const route: IHttpMigrateRoute = props.operation.function.route();
565
- if (
566
- route.body !== null
567
- && route.operation().requestBody?.required === true
568
- && "body" in props.arguments
569
- && isObject(
570
- (props.operation.function.parameters as IChatGptSchema.IParameters)
571
- .$defs,
572
- (props.operation.function.parameters as IChatGptSchema.IParameters)
573
- .properties
574
- .body!,
575
- )
576
- ) { props.arguments.body = {}; }
577
- if (route.query !== null && "query" in props.arguments && props.arguments.query === undefined) {
578
- props.arguments.query = {};
413
+ catch (error) {
414
+ return createExecuteEvent({
415
+ operation: call.operation,
416
+ arguments: call.arguments,
417
+ value: error instanceof Error
418
+ ? {
419
+ ...error,
420
+ name: error.name,
421
+ message: error.message,
422
+ }
423
+ : error,
424
+ });
579
425
  }
580
426
  }
581
427
 
582
- function isObject($defs: Record<string, IChatGptSchema>, schema: IChatGptSchema): boolean {
583
- return (
584
- ChatGptTypeChecker.isObject(schema)
585
- || (ChatGptTypeChecker.isReference(schema)
586
- && isObject($defs, $defs[schema.$ref.split("/").at(-1)!]!))
587
- || (ChatGptTypeChecker.isAnyOf(schema)
588
- && schema.anyOf.every(schema => isObject($defs, schema)))
589
- || (LlmTypeCheckerV3_1.isOneOf(schema)
590
- && schema.oneOf.every(schema => isObject($defs, schema)))
591
- );
428
+ async function executeClassFunction<Model extends ILlmSchema.Model>(
429
+ call: AgenticaCallEvent<Model>,
430
+ operation: AgenticaOperation.Class<Model>,
431
+ ): Promise<unknown> {
432
+ const execute = operation.controller.execute;
433
+ const value: unknown = typeof execute === "function"
434
+ ? await execute({
435
+ application: operation.controller.application,
436
+ function: operation.function,
437
+ arguments: call.arguments,
438
+ })
439
+ : await (execute as Record<string, any>)[operation.function.name](
440
+ call.arguments,
441
+ );
442
+ return value;
443
+ }
444
+
445
+ async function executeHttpOperation<Model extends ILlmSchema.Model>(
446
+ call: AgenticaCallEvent<Model>,
447
+ operation: AgenticaOperation.Http<Model>,
448
+ ): Promise<unknown> {
449
+ const execute = operation.controller.execute;
450
+ const value: IHttpResponse = typeof execute === "function"
451
+ ? await execute({
452
+ connection: operation.controller.connection,
453
+ application: operation.controller.application,
454
+ function: operation.function,
455
+ arguments: call.arguments,
456
+ })
457
+ : await HttpLlm.propagate({
458
+ connection: operation.controller.connection,
459
+ application: operation.controller.application,
460
+ function: operation.function,
461
+ input: call.arguments,
462
+ });
463
+ return value;
464
+ }
465
+
466
+ async function executeMcpOperation<Model extends ILlmSchema.Model>(
467
+ call: AgenticaCallEvent<Model>,
468
+ operation: AgenticaOperation.Mcp<Model>,
469
+ ): Promise<unknown> {
470
+ return operation.controller.client.callTool({
471
+ method: operation.function.name,
472
+ name: operation.function.name,
473
+ arguments: call.arguments,
474
+ }).then(v => v.content);
592
475
  }