@agentica/core 0.43.2 → 0.44.0-dev.20260313

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 (205) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +218 -218
  3. package/lib/constants/AgenticaSystemPrompt.js +1 -1
  4. package/lib/constants/AgenticaSystemPrompt.js.map +1 -1
  5. package/lib/context/AgenticaOperation.d.ts +3 -2
  6. package/lib/context/internal/AgenticaOperationComposer.js.map +1 -1
  7. package/lib/context/internal/AgenticaTokenUsageAggregator.js.map +1 -1
  8. package/lib/context/internal/__IChatInitialApplication.d.ts +1 -1
  9. package/lib/errors/AgenticaJsonParseError.d.ts +5 -8
  10. package/lib/errors/AgenticaJsonParseError.js +11 -6
  11. package/lib/errors/AgenticaJsonParseError.js.map +1 -1
  12. package/lib/errors/AgenticaValidationError.d.ts +1 -1
  13. package/lib/events/AgenticaExecuteEvent.d.ts +1 -1
  14. package/lib/events/AgenticaJsonParseErrorEvent.d.ts +2 -2
  15. package/lib/factory/events.d.ts +2 -3
  16. package/lib/factory/events.js +1 -2
  17. package/lib/factory/events.js.map +1 -1
  18. package/lib/functional/assertHttpController.d.ts +2 -3
  19. package/lib/functional/assertHttpController.js +3939 -2656
  20. package/lib/functional/assertHttpController.js.map +1 -1
  21. package/lib/functional/assertHttpLlmApplication.d.ts +3 -3
  22. package/lib/functional/assertHttpLlmApplication.js +3939 -2656
  23. package/lib/functional/assertHttpLlmApplication.js.map +1 -1
  24. package/lib/functional/assertMcpController.d.ts +2 -2
  25. package/lib/functional/assertMcpController.js +202 -629
  26. package/lib/functional/assertMcpController.js.map +1 -1
  27. package/lib/functional/createMcpLlmApplication.d.ts +6 -0
  28. package/lib/functional/createMcpLlmApplication.js +56 -0
  29. package/lib/functional/createMcpLlmApplication.js.map +1 -0
  30. package/lib/functional/validateHttpController.d.ts +3 -3
  31. package/lib/functional/validateHttpController.js +3367 -2268
  32. package/lib/functional/validateHttpController.js.map +1 -1
  33. package/lib/functional/validateHttpLlmApplication.d.ts +3 -4
  34. package/lib/functional/validateHttpLlmApplication.js +3367 -2268
  35. package/lib/functional/validateHttpLlmApplication.js.map +1 -1
  36. package/lib/functional/validateMcpController.d.ts +2 -2
  37. package/lib/functional/validateMcpController.js +388 -1161
  38. package/lib/functional/validateMcpController.js.map +1 -1
  39. package/lib/histories/AgenticaExecuteHistory.d.ts +1 -1
  40. package/lib/index.mjs +21256 -18948
  41. package/lib/index.mjs.map +1 -1
  42. package/lib/orchestrate/call.js +43 -56
  43. package/lib/orchestrate/call.js.map +1 -1
  44. package/lib/orchestrate/cancel.js +9 -66
  45. package/lib/orchestrate/cancel.js.map +1 -1
  46. package/lib/orchestrate/initialize.js +4 -947
  47. package/lib/orchestrate/initialize.js.map +1 -1
  48. package/lib/orchestrate/select.js +11 -68
  49. package/lib/orchestrate/select.js.map +1 -1
  50. package/lib/structures/IAgenticaController.d.ts +143 -151
  51. package/lib/structures/IMcpTool.d.ts +52 -0
  52. package/lib/structures/IMcpTool.js +3 -0
  53. package/lib/structures/IMcpTool.js.map +1 -0
  54. package/lib/utils/ChatGptCompletionMessageUtil.js +16 -5
  55. package/lib/utils/ChatGptCompletionMessageUtil.js.map +1 -1
  56. package/lib/utils/ChatGptCompletionMessageUtil.spec.js +0 -5
  57. package/lib/utils/ChatGptCompletionMessageUtil.spec.js.map +1 -1
  58. package/package.json +7 -9
  59. package/prompts/cancel.md +5 -5
  60. package/prompts/common.md +3 -3
  61. package/prompts/describe.md +7 -7
  62. package/prompts/execute.md +122 -122
  63. package/prompts/initialize.md +3 -3
  64. package/prompts/json_parse_error.md +35 -33
  65. package/prompts/select.md +7 -7
  66. package/prompts/validate.md +123 -123
  67. package/prompts/validate_repeated.md +31 -31
  68. package/src/Agentica.ts +367 -367
  69. package/src/MicroAgentica.ts +357 -357
  70. package/src/constants/AgenticaConstant.ts +4 -4
  71. package/src/constants/AgenticaDefaultPrompt.ts +44 -44
  72. package/src/constants/AgenticaSystemPrompt.ts +1 -1
  73. package/src/constants/index.ts +2 -2
  74. package/src/context/AgenticaContext.ts +136 -136
  75. package/src/context/AgenticaContextRequestResult.ts +14 -14
  76. package/src/context/AgenticaOperation.ts +73 -72
  77. package/src/context/AgenticaOperationCollection.ts +49 -49
  78. package/src/context/AgenticaOperationSelection.ts +9 -9
  79. package/src/context/AgenticaTokenUsage.ts +186 -186
  80. package/src/context/MicroAgenticaContext.ts +99 -99
  81. package/src/context/index.ts +5 -5
  82. package/src/context/internal/AgenticaOperationComposer.ts +177 -177
  83. package/src/context/internal/AgenticaTokenUsageAggregator.ts +66 -66
  84. package/src/context/internal/__IChatCancelFunctionsApplication.ts +23 -23
  85. package/src/context/internal/__IChatFunctionReference.ts +21 -21
  86. package/src/context/internal/__IChatInitialApplication.ts +15 -15
  87. package/src/context/internal/__IChatSelectFunctionsApplication.ts +24 -24
  88. package/src/context/internal/isAgenticaContext.ts +11 -11
  89. package/src/errors/AgenticaJsonParseError.ts +52 -47
  90. package/src/errors/AgenticaValidationError.ts +49 -49
  91. package/src/errors/index.ts +2 -2
  92. package/src/events/AgenticaAssistantMessageEvent.ts +12 -12
  93. package/src/events/AgenticaCallEvent.ts +27 -27
  94. package/src/events/AgenticaCancelEvent.ts +9 -9
  95. package/src/events/AgenticaDescribeEvent.ts +14 -14
  96. package/src/events/AgenticaEvent.ts +59 -59
  97. package/src/events/AgenticaEvent.type.ts +19 -19
  98. package/src/events/AgenticaEventBase.ts +18 -18
  99. package/src/events/AgenticaEventSource.ts +6 -6
  100. package/src/events/AgenticaExecuteEvent.ts +45 -45
  101. package/src/events/AgenticaInitializeEvent.ts +7 -7
  102. package/src/events/AgenticaJsonParseErrorEvent.ts +16 -15
  103. package/src/events/AgenticaRequestEvent.ts +27 -27
  104. package/src/events/AgenticaResponseEvent.ts +32 -32
  105. package/src/events/AgenticaSelectEvent.ts +11 -11
  106. package/src/events/AgenticaUserMessageEvent.ts +12 -12
  107. package/src/events/AgenticaValidateEvent.ts +32 -32
  108. package/src/events/MicroAgenticaEvent.ts +45 -45
  109. package/src/events/index.ts +15 -15
  110. package/src/factory/events.ts +357 -359
  111. package/src/factory/histories.ts +348 -348
  112. package/src/factory/index.ts +3 -3
  113. package/src/factory/operations.ts +16 -16
  114. package/src/functional/assertHttpController.ts +106 -104
  115. package/src/functional/assertHttpLlmApplication.ts +52 -57
  116. package/src/functional/assertMcpController.ts +47 -44
  117. package/src/functional/createMcpLlmApplication.ts +72 -0
  118. package/src/functional/index.ts +7 -7
  119. package/src/functional/validateHttpController.ts +113 -110
  120. package/src/functional/validateHttpLlmApplication.ts +65 -70
  121. package/src/functional/validateMcpController.ts +53 -50
  122. package/src/histories/AgenticaAssistantMessageHistory.ts +10 -10
  123. package/src/histories/AgenticaCancelHistory.ts +8 -8
  124. package/src/histories/AgenticaDescribeHistory.ts +18 -18
  125. package/src/histories/AgenticaExecuteHistory.ts +64 -64
  126. package/src/histories/AgenticaHistory.ts +28 -28
  127. package/src/histories/AgenticaHistoryBase.ts +35 -35
  128. package/src/histories/AgenticaSelectHistory.ts +8 -8
  129. package/src/histories/AgenticaSystemMessageHistory.ts +10 -10
  130. package/src/histories/AgenticaUserMessageHistory.ts +11 -11
  131. package/src/histories/MicroAgenticaHistory.ts +19 -19
  132. package/src/histories/contents/AgenticaUserMessageAudioContent.ts +21 -21
  133. package/src/histories/contents/AgenticaUserMessageContent.ts +19 -19
  134. package/src/histories/contents/AgenticaUserMessageContentBase.ts +6 -6
  135. package/src/histories/contents/AgenticaUserMessageFileContent.ts +25 -25
  136. package/src/histories/contents/AgenticaUserMessageImageContent.ts +33 -33
  137. package/src/histories/contents/AgenticaUserMessageTextContent.ts +15 -15
  138. package/src/histories/contents/index.ts +5 -5
  139. package/src/histories/index.ts +10 -10
  140. package/src/index.ts +15 -15
  141. package/src/json/IAgenticaEventJson.ts +265 -265
  142. package/src/json/IAgenticaEventJson.type.ts +19 -19
  143. package/src/json/IAgenticaHistoryJson.ts +165 -165
  144. package/src/json/IAgenticaHistoryJson.type.ts +19 -19
  145. package/src/json/IAgenticaOperationJson.ts +36 -36
  146. package/src/json/IAgenticaOperationSelectionJson.ts +26 -26
  147. package/src/json/IAgenticaTokenUsageJson.ts +107 -107
  148. package/src/json/IMicroAgenticaEventJson.ts +22 -22
  149. package/src/json/IMicroAgenticaHistoryJson.ts +25 -25
  150. package/src/json/index.ts +7 -7
  151. package/src/orchestrate/call.ts +542 -558
  152. package/src/orchestrate/cancel.ts +265 -269
  153. package/src/orchestrate/describe.ts +66 -66
  154. package/src/orchestrate/execute.ts +61 -61
  155. package/src/orchestrate/index.ts +6 -6
  156. package/src/orchestrate/initialize.ts +102 -102
  157. package/src/orchestrate/internal/cancelFunctionFromContext.ts +33 -33
  158. package/src/orchestrate/internal/selectFunctionFromContext.ts +34 -34
  159. package/src/orchestrate/select.ts +320 -322
  160. package/src/structures/IAgenticaConfig.ts +83 -83
  161. package/src/structures/IAgenticaConfigBase.ts +87 -87
  162. package/src/structures/IAgenticaController.ts +143 -151
  163. package/src/structures/IAgenticaExecutor.ts +167 -167
  164. package/src/structures/IAgenticaProps.ts +78 -78
  165. package/src/structures/IAgenticaSystemPrompt.ts +236 -236
  166. package/src/structures/IAgenticaVendor.ts +54 -54
  167. package/src/structures/IMcpTool.ts +60 -0
  168. package/src/structures/IMicroAgenticaConfig.ts +56 -56
  169. package/src/structures/IMicroAgenticaExecutor.ts +67 -67
  170. package/src/structures/IMicroAgenticaProps.ts +77 -77
  171. package/src/structures/IMicroAgenticaSystemPrompt.ts +169 -169
  172. package/src/structures/index.ts +10 -10
  173. package/src/transformers/transformHistory.ts +172 -172
  174. package/src/utils/AssistantMessageEmptyError.ts +20 -20
  175. package/src/utils/AsyncQueue.spec.ts +355 -355
  176. package/src/utils/AsyncQueue.ts +95 -95
  177. package/src/utils/ByteArrayUtil.ts +5 -5
  178. package/src/utils/ChatGptCompletionMessageUtil.spec.ts +314 -320
  179. package/src/utils/ChatGptCompletionMessageUtil.ts +210 -195
  180. package/src/utils/ChatGptCompletionStreamingUtil.spec.ts +909 -909
  181. package/src/utils/ChatGptCompletionStreamingUtil.ts +91 -91
  182. package/src/utils/ChatGptTokenUsageAggregator.spec.ts +226 -226
  183. package/src/utils/ChatGptTokenUsageAggregator.ts +57 -57
  184. package/src/utils/MPSC.spec.ts +276 -276
  185. package/src/utils/MPSC.ts +42 -42
  186. package/src/utils/Singleton.spec.ts +138 -138
  187. package/src/utils/Singleton.ts +42 -42
  188. package/src/utils/StreamUtil.spec.ts +512 -512
  189. package/src/utils/StreamUtil.ts +87 -87
  190. package/src/utils/__map_take.spec.ts +140 -140
  191. package/src/utils/__map_take.ts +13 -13
  192. package/src/utils/__retry.spec.ts +198 -198
  193. package/src/utils/__retry.ts +18 -18
  194. package/src/utils/assertExecuteFailure.ts +16 -16
  195. package/src/utils/index.ts +4 -4
  196. package/src/utils/request.ts +140 -140
  197. package/src/utils/types.ts +50 -50
  198. package/lib/context/internal/AgenticaOperationComposer.spec.d.ts +0 -1
  199. package/lib/context/internal/AgenticaOperationComposer.spec.js +0 -353
  200. package/lib/context/internal/AgenticaOperationComposer.spec.js.map +0 -1
  201. package/lib/utils/JsonUtil.d.ts +0 -8
  202. package/lib/utils/JsonUtil.js +0 -350
  203. package/lib/utils/JsonUtil.js.map +0 -1
  204. package/src/context/internal/AgenticaOperationComposer.spec.ts +0 -401
  205. package/src/utils/JsonUtil.ts +0 -462
@@ -1,558 +1,542 @@
1
- import type {
2
- IHttpResponse,
3
- ILlmSchema,
4
- IValidation,
5
- } from "@samchon/openapi";
6
- import type OpenAI from "openai";
7
-
8
- import { HttpLlm } from "@samchon/openapi";
9
-
10
- import type { AgenticaContext } from "../context/AgenticaContext";
11
- import type { AgenticaOperation } from "../context/AgenticaOperation";
12
- import type { MicroAgenticaContext } from "../context/MicroAgenticaContext";
13
- import type { AgenticaAssistantMessageEvent, AgenticaValidateEvent } from "../events";
14
- import type { AgenticaCallEvent } from "../events/AgenticaCallEvent";
15
- import type { AgenticaExecuteEvent } from "../events/AgenticaExecuteEvent";
16
- import type { AgenticaJsonParseErrorEvent } from "../events/AgenticaJsonParseErrorEvent";
17
- import type { MicroAgenticaHistory } from "../histories/MicroAgenticaHistory";
18
-
19
- import { AgenticaConstant } from "../constants/AgenticaConstant";
20
- import { AgenticaDefaultPrompt } from "../constants/AgenticaDefaultPrompt";
21
- import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
22
- import { isAgenticaContext } from "../context/internal/isAgenticaContext";
23
- import { AgenticaJsonParseError } from "../errors/AgenticaJsonParseError";
24
- import { AgenticaValidationError } from "../errors/AgenticaValidationError";
25
- import { createAssistantMessageEvent, createCallEvent, createExecuteEvent, createJsonParseErrorEvent, createValidateEvent } from "../factory/events";
26
- import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
27
- import { __get_retry } from "../utils/__retry";
28
- import { AssistantMessageEmptyError, AssistantMessageEmptyWithReasoningError } from "../utils/AssistantMessageEmptyError";
29
- import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
30
- import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
31
- import { JsonUtil } from "../utils/JsonUtil";
32
- import { StreamUtil, toAsyncGenerator } from "../utils/StreamUtil";
33
-
34
- import { cancelFunctionFromContext } from "./internal/cancelFunctionFromContext";
35
-
36
- export async function call(
37
- ctx: AgenticaContext | MicroAgenticaContext,
38
- operations: AgenticaOperation[],
39
- ): Promise<AgenticaExecuteEvent[]> {
40
- const _retryFn = __get_retry(1);
41
- const retryFn = async (fn: (prevError?: unknown) => Promise<OpenAI.ChatCompletion>) => {
42
- return _retryFn(fn).catch((e) => {
43
- if (e instanceof AssistantMessageEmptyError) {
44
- return Symbol("emptyAssistantMessage");
45
- }
46
- throw e;
47
- });
48
- };
49
-
50
- const completion = await retryFn(async (prevError) => {
51
- const result = await ctx.request("call", {
52
- messages: [
53
- // PREVIOUS HISTORIES
54
- ...ctx.histories.map(decodeHistory).flat(),
55
- // USER INPUT
56
- {
57
- role: "user",
58
- content: ctx.prompt.contents.map(decodeUserMessageContent),
59
- },
60
- ...(prevError instanceof AssistantMessageEmptyWithReasoningError
61
- ? [
62
- {
63
- role: "assistant",
64
- content: prevError.reasoning,
65
- } satisfies OpenAI.ChatCompletionMessageParam,
66
- ]
67
- : []),
68
- // SYSTEM PROMPT
69
- ...(ctx.config?.systemPrompt?.execute === null
70
- ? []
71
- : [{
72
- role: "system",
73
- content: ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory[])
74
- ?? AgenticaSystemPrompt.EXECUTE,
75
- } satisfies OpenAI.ChatCompletionSystemMessageParam]),
76
- // COMMON SYSTEM PROMPT
77
- {
78
- role: "system",
79
- content: AgenticaDefaultPrompt.write(ctx.config),
80
- } satisfies OpenAI.ChatCompletionSystemMessageParam,
81
- ],
82
- // STACKED FUNCTIONS
83
- tools: operations.map(
84
- s =>
85
- ({
86
- type: "function",
87
- function: {
88
- name: s.name,
89
- description: s.function.description,
90
- parameters: (
91
- "separated" in s.function
92
- && s.function.separated !== undefined
93
- ? (s.function.separated.llm
94
- ?? ({
95
- type: "object",
96
- properties: {},
97
- required: [],
98
- additionalProperties: false,
99
- $defs: {},
100
- } satisfies ILlmSchema.IParameters))
101
- : s.function.parameters) as Record<string, any>,
102
- },
103
- }) as OpenAI.ChatCompletionTool,
104
- ),
105
- tool_choice: "auto",
106
- // parallel_tool_calls: false,
107
- });
108
-
109
- if (result.type === "none-stream") {
110
- return result.value;
111
- }
112
-
113
- const completion = await reduceStreamingWithDispatch(result.value, (props) => {
114
- const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent(props);
115
- void ctx.dispatch(event).catch(() => {});
116
- });
117
-
118
- const allAssistantMessagesEmpty: boolean = (completion.choices ?? []).every(
119
- v => v.message.tool_calls == null && v.message.content === "",
120
- );
121
- if (allAssistantMessagesEmpty) {
122
- const firstChoice: OpenAI.ChatCompletion.Choice | undefined = completion.choices?.[0];
123
- if ((firstChoice?.message as { reasoning?: string })?.reasoning != null) {
124
- throw new AssistantMessageEmptyWithReasoningError((firstChoice?.message as { reasoning?: string })?.reasoning ?? "");
125
- }
126
- throw new AssistantMessageEmptyError();
127
- }
128
- return completion;
129
- });
130
-
131
- if (typeof completion === "symbol") {
132
- const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
133
- stream: toAsyncGenerator(""),
134
- done: () => true,
135
- get: () => "",
136
- join: async () => {
137
- return "";
138
- },
139
- });
140
- void ctx.dispatch(event).catch(() => {});
141
- return [];
142
- }
143
-
144
- const executes: AgenticaExecuteEvent[] = [];
145
-
146
- const retry: number = ctx.config?.retry ?? AgenticaConstant.RETRY;
147
- for (const choice of (completion.choices ?? [])) {
148
- for (const tc of choice.message.tool_calls ?? []) {
149
- if (tc.type === "function") {
150
- const operation: AgenticaOperation | undefined = operations.find(
151
- s => s.name === tc.function.name,
152
- );
153
- if (operation === undefined) {
154
- continue; // Ignore unknown tool calls
155
- }
156
- const event: AgenticaExecuteEvent = await predicate(
157
- ctx,
158
- operation,
159
- tc,
160
- [],
161
- retry,
162
- );
163
- await ctx.dispatch(event);
164
- executes.push(event);
165
- if (isAgenticaContext(ctx)) {
166
- cancelFunctionFromContext(ctx as unknown as AgenticaContext, {
167
- name: event.operation.name,
168
- reason: "completed",
169
- });
170
- }
171
- }
172
- }
173
- }
174
- return executes;
175
- }
176
-
177
- async function predicate(
178
- ctx: AgenticaContext | MicroAgenticaContext,
179
- operation: AgenticaOperation,
180
- toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
181
- previousValidationErrors: AgenticaValidateEvent[],
182
- life: number,
183
- ): Promise<AgenticaExecuteEvent> {
184
- // CHECK INPUT ARGUMENT
185
- const call: AgenticaCallEvent | AgenticaJsonParseErrorEvent
186
- = parseArguments(
187
- operation,
188
- toolCall,
189
- life,
190
- );
191
- await ctx.dispatch(call);
192
- if (call.type === "jsonParseError") {
193
- return correctJsonError(ctx, toolCall, call, previousValidationErrors, life - 1);
194
- }
195
-
196
- // CHECK TYPE VALIDATION
197
- const check: IValidation<unknown> = operation.function.validate(call.arguments);
198
- if (check.success === false) {
199
- const event: AgenticaValidateEvent = createValidateEvent({
200
- call_id: toolCall.id,
201
- operation,
202
- result: check,
203
- life,
204
- });
205
- await ctx.dispatch(event);
206
- return correctTypeError(
207
- ctx,
208
- call,
209
- event,
210
- [...previousValidationErrors, event],
211
- life - 1,
212
- );
213
- }
214
-
215
- // EXECUTE OPERATION
216
- return executeFunction(call, operation);
217
- }
218
-
219
- /* -----------------------------------------------------------
220
- ERROR CORRECTORS
221
- ----------------------------------------------------------- */
222
- async function correctTypeError(
223
- ctx: AgenticaContext | MicroAgenticaContext,
224
- callEvent: AgenticaCallEvent,
225
- validateEvent: AgenticaValidateEvent,
226
- previousValidationErrors: AgenticaValidateEvent[],
227
- life: number,
228
- ): Promise<AgenticaExecuteEvent> {
229
- return correctError(ctx, {
230
- giveUp: () => createExecuteEvent({
231
- call_id: callEvent.id,
232
- operation: callEvent.operation,
233
- arguments: callEvent.arguments,
234
- value: new AgenticaValidationError({
235
- arguments: callEvent.arguments,
236
- errors: validateEvent.result.errors,
237
- }),
238
- success: false,
239
- }),
240
- operation: callEvent.operation,
241
- toolCall: {
242
- id: callEvent.id,
243
- arguments: JSON.stringify(callEvent.arguments),
244
- result: [
245
- "🚨 VALIDATION FAILURE: Your function arguments do not conform to the required schema.",
246
- "",
247
- "The validation errors below represent computed absolute truth from rigorous type validation.",
248
- "Each error is marked with ❌ comments showing the exact location, expected type, and actual value.",
249
- "",
250
- "You must fix ALL errors to achieve 100% schema compliance.",
251
- "",
252
- JsonUtil.stringifyValidationFailure(validateEvent.result),
253
- ].join("\n"),
254
- },
255
- systemPrompt: ctx.config?.systemPrompt?.validate?.(previousValidationErrors.slice(0, -1))
256
- ?? [
257
- AgenticaSystemPrompt.VALIDATE,
258
- ...(previousValidationErrors.length > 1
259
- ? [
260
- "",
261
- AgenticaSystemPrompt.VALIDATE_REPEATED.replace(
262
- "${{HISTORICAL_ERRORS}}",
263
- previousValidationErrors
264
- .slice(0, -1)
265
- .map((ve, i) => [
266
- `### ${i + 1}. Previous Validation Error`,
267
- "",
268
- JsonUtil.stringifyValidationFailure(ve.result),
269
- ].join("\n"))
270
- .join("\n\n"),
271
- // JSON.stringify(previousValidationErrors.slice(0, -1).map(e => e.result.errors)),
272
- ),
273
- ]
274
- : []),
275
- ].join("\n"),
276
- life,
277
- previousValidationErrors,
278
- });
279
- }
280
-
281
- async function correctJsonError(
282
- ctx: AgenticaContext | MicroAgenticaContext,
283
- toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
284
- parseErrorEvent: AgenticaJsonParseErrorEvent,
285
- previousValidationErrors: AgenticaValidateEvent[],
286
- life: number,
287
- ): Promise<AgenticaExecuteEvent> {
288
- return correctError(ctx, {
289
- giveUp: () => createExecuteEvent({
290
- call_id: toolCall.id,
291
- operation: parseErrorEvent.operation,
292
- arguments: {},
293
- value: new AgenticaJsonParseError({
294
- arguments: parseErrorEvent.arguments,
295
- reason: parseErrorEvent.errorMessage,
296
- }),
297
- success: false,
298
- }),
299
- operation: parseErrorEvent.operation,
300
- toolCall: {
301
- id: parseErrorEvent.id,
302
- arguments: parseErrorEvent.arguments,
303
- result: parseErrorEvent.errorMessage,
304
- },
305
- systemPrompt: ctx.config?.systemPrompt?.jsonParseError?.(parseErrorEvent)
306
- ?? AgenticaSystemPrompt.JSON_PARSE_ERROR.replace(
307
- "${{ERROR_MESSAGE}}",
308
- parseErrorEvent.errorMessage,
309
- ),
310
- life,
311
- previousValidationErrors,
312
- });
313
- }
314
-
315
- function parseArguments(
316
- operation: AgenticaOperation,
317
- toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
318
- life: number,
319
- ): AgenticaCallEvent | AgenticaJsonParseErrorEvent {
320
- try {
321
- const data: Record<string, unknown> = JsonUtil.parse(
322
- toolCall.function.arguments,
323
- operation.function.parameters,
324
- );
325
- return createCallEvent({
326
- id: toolCall.id,
327
- operation,
328
- arguments: data,
329
- });
330
- }
331
- catch (error) {
332
- return createJsonParseErrorEvent({
333
- call_id: toolCall.id,
334
- operation,
335
- arguments: toolCall.function.arguments,
336
- errorMessage: error instanceof Error ? error.message : String(error),
337
- life,
338
- });
339
- }
340
- }
341
-
342
- async function correctError(
343
- ctx: AgenticaContext | MicroAgenticaContext,
344
- props: {
345
- giveUp: () => AgenticaExecuteEvent;
346
- operation: AgenticaOperation;
347
- toolCall: {
348
- id: string;
349
- arguments: string;
350
- result: string;
351
- };
352
- systemPrompt: string;
353
- life: number;
354
- previousValidationErrors: AgenticaValidateEvent[];
355
- },
356
- ): Promise<AgenticaExecuteEvent> {
357
- if (props.life <= 0) {
358
- return props.giveUp();
359
- }
360
-
361
- const result = await ctx.request("call", {
362
- messages: [
363
- // PREVIOUS HISTORIES
364
- ...ctx.histories.map(decodeHistory).flat(),
365
- // USER INPUT
366
- {
367
- role: "user",
368
- content: ctx.prompt.contents.map(decodeUserMessageContent),
369
- },
370
- // TYPE CORRECTION
371
- {
372
- role: "system",
373
- content:
374
- ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory[])
375
- ?? AgenticaSystemPrompt.EXECUTE,
376
- },
377
- {
378
- role: "assistant",
379
- tool_calls: [
380
- {
381
- type: "function",
382
- id: props.toolCall.id,
383
- function: {
384
- name: props.operation.name,
385
- arguments: props.toolCall.arguments,
386
- },
387
- } satisfies OpenAI.ChatCompletionMessageFunctionToolCall,
388
- ],
389
- } satisfies OpenAI.ChatCompletionAssistantMessageParam,
390
- {
391
- role: "tool",
392
- content: props.toolCall.result,
393
- tool_call_id: props.toolCall.id,
394
- },
395
- {
396
- role: "system",
397
- content: props.systemPrompt,
398
- },
399
- // COMMON SYSTEM PROMPT
400
- {
401
- role: "system",
402
- content: AgenticaDefaultPrompt.write(ctx.config),
403
- } satisfies OpenAI.ChatCompletionSystemMessageParam,
404
- ],
405
- // STACK FUNCTIONS
406
- tools: [
407
- {
408
- type: "function",
409
- function: {
410
- name: props.operation.name,
411
- description: props.operation.function.description,
412
- /**
413
- * @TODO fix it
414
- * The property and value have a type mismatch, but it works.
415
- */
416
- parameters: (
417
- ("separated" in props.operation.function
418
- && props.operation.function.separated !== undefined)
419
- ? (props.operation.function.separated?.llm
420
- ?? ({
421
- $defs: {},
422
- type: "object",
423
- properties: {},
424
- additionalProperties: false,
425
- required: [],
426
- } satisfies ILlmSchema.IParameters))
427
-
428
- : props.operation.function.parameters) as unknown as Record<string, unknown>,
429
- },
430
- },
431
- ],
432
- tool_choice: "required",
433
- // parallel_tool_calls: false,
434
- });
435
-
436
- const completion = await (async () => {
437
- if (result.type === "none-stream") {
438
- return result.value;
439
- }
440
- return ChatGptCompletionMessageUtil.merge(await StreamUtil.readAll(result.value));
441
- })();
442
-
443
- const toolCall: OpenAI.ChatCompletionMessageFunctionToolCall | undefined = completion.choices?.[0]?.message.tool_calls?.filter(
444
- tc => tc.type === "function",
445
- ).find(
446
- s => s.function.name === props.operation.name,
447
- );
448
- if (toolCall === undefined) {
449
- // LLM did not return a valid tool call - retry if life remains
450
- return correctError(ctx, {
451
- ...props,
452
- life: props.life - 1,
453
- });
454
- }
455
- return predicate(
456
- ctx,
457
- props.operation,
458
- toolCall,
459
- props.previousValidationErrors,
460
- props.life,
461
- );
462
- }
463
-
464
- /* -----------------------------------------------------------
465
- FUNCTION EXECUTORS
466
- ----------------------------------------------------------- */
467
- async function executeFunction(
468
- call: AgenticaCallEvent,
469
- operation: AgenticaOperation,
470
- ): Promise<AgenticaExecuteEvent> {
471
- try {
472
- const value: unknown = await (async () => {
473
- switch (operation.protocol) {
474
- case "class":
475
- return executeClassFunction(call, operation);
476
- case "http":
477
- return executeHttpOperation(call, operation);
478
- case "mcp":
479
- return executeMcpOperation(call, operation);
480
- default:
481
- operation satisfies never; // Ensure all cases are handled
482
- throw new Error("Unknown protocol"); // never be happen
483
- }
484
- })();
485
- return createExecuteEvent({
486
- call_id: call.id,
487
- operation: call.operation,
488
- arguments: call.arguments,
489
- value,
490
- success: true,
491
- });
492
- }
493
- catch (error) {
494
- return createExecuteEvent({
495
- call_id: call.id,
496
- operation: call.operation,
497
- arguments: call.arguments,
498
- value: error instanceof Error
499
- ? {
500
- ...error,
501
- name: error.name,
502
- message: error.message,
503
- stack: error.stack,
504
- }
505
- : error,
506
- success: false,
507
- });
508
- }
509
- }
510
-
511
- async function executeClassFunction(
512
- call: AgenticaCallEvent,
513
- operation: AgenticaOperation.Class,
514
- ): Promise<unknown> {
515
- const execute = operation.controller.execute;
516
- const value: unknown = typeof execute === "function"
517
- ? await execute({
518
- application: operation.controller.application,
519
- function: operation.function,
520
- arguments: call.arguments,
521
- })
522
- : await (execute as Record<string, any>)[operation.function.name](
523
- call.arguments,
524
- );
525
- return value;
526
- }
527
-
528
- async function executeHttpOperation(
529
- call: AgenticaCallEvent,
530
- operation: AgenticaOperation.Http,
531
- ): Promise<unknown> {
532
- const execute = operation.controller.execute;
533
- const value: IHttpResponse = typeof execute === "function"
534
- ? await execute({
535
- connection: operation.controller.connection,
536
- application: operation.controller.application,
537
- function: operation.function,
538
- arguments: call.arguments,
539
- })
540
- : await HttpLlm.propagate({
541
- connection: operation.controller.connection,
542
- application: operation.controller.application,
543
- function: operation.function,
544
- input: call.arguments,
545
- });
546
- return value;
547
- }
548
-
549
- async function executeMcpOperation(
550
- call: AgenticaCallEvent,
551
- operation: AgenticaOperation.Mcp,
552
- ): Promise<unknown> {
553
- return operation.controller.client.callTool({
554
- method: operation.function.name,
555
- name: operation.function.name,
556
- arguments: call.arguments,
557
- }).then(v => v.content);
558
- }
1
+ import type {
2
+ IHttpResponse,
3
+ IJsonParseResult,
4
+ IValidation,
5
+ } from "@typia/interface";
6
+ import type OpenAI from "openai";
7
+
8
+ import { dedent, HttpLlm, LlmJson } from "@typia/utils";
9
+
10
+ import type { AgenticaContext } from "../context/AgenticaContext";
11
+ import type { AgenticaOperation } from "../context/AgenticaOperation";
12
+ import type { MicroAgenticaContext } from "../context/MicroAgenticaContext";
13
+ import type { AgenticaAssistantMessageEvent, AgenticaValidateEvent } from "../events";
14
+ import type { AgenticaCallEvent } from "../events/AgenticaCallEvent";
15
+ import type { AgenticaExecuteEvent } from "../events/AgenticaExecuteEvent";
16
+ import type { AgenticaJsonParseErrorEvent } from "../events/AgenticaJsonParseErrorEvent";
17
+ import type { MicroAgenticaHistory } from "../histories/MicroAgenticaHistory";
18
+
19
+ import { AgenticaConstant } from "../constants/AgenticaConstant";
20
+ import { AgenticaDefaultPrompt } from "../constants/AgenticaDefaultPrompt";
21
+ import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
22
+ import { isAgenticaContext } from "../context/internal/isAgenticaContext";
23
+ import { AgenticaJsonParseError } from "../errors/AgenticaJsonParseError";
24
+ import { AgenticaValidationError } from "../errors/AgenticaValidationError";
25
+ import { createAssistantMessageEvent, createCallEvent, createExecuteEvent, createJsonParseErrorEvent, createValidateEvent } from "../factory/events";
26
+ import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
27
+ import { __get_retry } from "../utils/__retry";
28
+ import { AssistantMessageEmptyError, AssistantMessageEmptyWithReasoningError } from "../utils/AssistantMessageEmptyError";
29
+ import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
30
+ import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
31
+ import { StreamUtil, toAsyncGenerator } from "../utils/StreamUtil";
32
+
33
+ import { cancelFunctionFromContext } from "./internal/cancelFunctionFromContext";
34
+
35
+ export async function call(
36
+ ctx: AgenticaContext | MicroAgenticaContext,
37
+ operations: AgenticaOperation[],
38
+ ): Promise<AgenticaExecuteEvent[]> {
39
+ const _retryFn = __get_retry(1);
40
+ const retryFn = async (fn: (prevError?: unknown) => Promise<OpenAI.ChatCompletion>) => {
41
+ return _retryFn(fn).catch((e) => {
42
+ if (e instanceof AssistantMessageEmptyError) {
43
+ return Symbol("emptyAssistantMessage");
44
+ }
45
+ throw e;
46
+ });
47
+ };
48
+
49
+ const completion = await retryFn(async (prevError) => {
50
+ const result = await ctx.request("call", {
51
+ messages: [
52
+ // PREVIOUS HISTORIES
53
+ ...ctx.histories.map(decodeHistory).flat(),
54
+ // USER INPUT
55
+ {
56
+ role: "user",
57
+ content: ctx.prompt.contents.map(decodeUserMessageContent),
58
+ },
59
+ ...(prevError instanceof AssistantMessageEmptyWithReasoningError
60
+ ? [
61
+ {
62
+ role: "assistant",
63
+ content: prevError.reasoning,
64
+ } satisfies OpenAI.ChatCompletionMessageParam,
65
+ ]
66
+ : []),
67
+ // SYSTEM PROMPT
68
+ ...(ctx.config?.systemPrompt?.execute === null
69
+ ? []
70
+ : [{
71
+ role: "system",
72
+ content: ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory[])
73
+ ?? AgenticaSystemPrompt.EXECUTE,
74
+ } satisfies OpenAI.ChatCompletionSystemMessageParam]),
75
+ // COMMON SYSTEM PROMPT
76
+ {
77
+ role: "system",
78
+ content: AgenticaDefaultPrompt.write(ctx.config),
79
+ } satisfies OpenAI.ChatCompletionSystemMessageParam,
80
+ ],
81
+ // STACKED FUNCTIONS
82
+ tools: operations.map(
83
+ s =>
84
+ ({
85
+ type: "function",
86
+ function: {
87
+ name: s.name,
88
+ description: s.function.description,
89
+ parameters: s.function.parameters as Record<string, any>,
90
+ },
91
+ }) as OpenAI.ChatCompletionTool,
92
+ ),
93
+ tool_choice: "auto",
94
+ // parallel_tool_calls: false,
95
+ });
96
+
97
+ if (result.type === "none-stream") {
98
+ return result.value;
99
+ }
100
+
101
+ const completion = await reduceStreamingWithDispatch(result.value, (props) => {
102
+ const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent(props);
103
+ void ctx.dispatch(event).catch(() => {});
104
+ });
105
+
106
+ const allAssistantMessagesEmpty: boolean = (completion.choices ?? []).every(
107
+ v => v.message.tool_calls == null && v.message.content === "",
108
+ );
109
+ if (allAssistantMessagesEmpty) {
110
+ const firstChoice: OpenAI.ChatCompletion.Choice | undefined = completion.choices?.[0];
111
+ if ((firstChoice?.message as { reasoning?: string })?.reasoning != null) {
112
+ throw new AssistantMessageEmptyWithReasoningError((firstChoice?.message as { reasoning?: string })?.reasoning ?? "");
113
+ }
114
+ throw new AssistantMessageEmptyError();
115
+ }
116
+ return completion;
117
+ });
118
+
119
+ if (typeof completion === "symbol") {
120
+ const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
121
+ stream: toAsyncGenerator(""),
122
+ done: () => true,
123
+ get: () => "",
124
+ join: async () => {
125
+ return "";
126
+ },
127
+ });
128
+ void ctx.dispatch(event).catch(() => {});
129
+ return [];
130
+ }
131
+
132
+ const executes: AgenticaExecuteEvent[] = [];
133
+
134
+ const retry: number = ctx.config?.retry ?? AgenticaConstant.RETRY;
135
+ for (const choice of (completion.choices ?? [])) {
136
+ for (const tc of choice.message.tool_calls ?? []) {
137
+ if (tc.type === "function") {
138
+ const operation: AgenticaOperation | undefined = operations.find(
139
+ s => s.name === tc.function.name,
140
+ );
141
+ if (operation === undefined) {
142
+ continue; // Ignore unknown tool calls
143
+ }
144
+ const event: AgenticaExecuteEvent = await predicate(
145
+ ctx,
146
+ operation,
147
+ tc,
148
+ [],
149
+ retry,
150
+ );
151
+ await ctx.dispatch(event);
152
+ executes.push(event);
153
+ if (isAgenticaContext(ctx)) {
154
+ cancelFunctionFromContext(ctx as unknown as AgenticaContext, {
155
+ name: event.operation.name,
156
+ reason: "completed",
157
+ });
158
+ }
159
+ }
160
+ }
161
+ }
162
+ return executes;
163
+ }
164
+
165
+ async function predicate(
166
+ ctx: AgenticaContext | MicroAgenticaContext,
167
+ operation: AgenticaOperation,
168
+ toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
169
+ previousValidationErrors: AgenticaValidateEvent[],
170
+ life: number,
171
+ ): Promise<AgenticaExecuteEvent> {
172
+ // CHECK INPUT ARGUMENT
173
+ const call: AgenticaCallEvent | AgenticaJsonParseErrorEvent
174
+ = parseArguments(
175
+ operation,
176
+ toolCall,
177
+ life,
178
+ );
179
+ await ctx.dispatch(call);
180
+ if (call.type === "jsonParseError") {
181
+ return correctJsonError(ctx, toolCall, call, previousValidationErrors, life - 1);
182
+ }
183
+
184
+ // CHECK TYPE VALIDATION
185
+ const check: IValidation<unknown> = operation.function.validate(call.arguments);
186
+ if (check.success === false) {
187
+ const event: AgenticaValidateEvent = createValidateEvent({
188
+ call_id: toolCall.id,
189
+ operation,
190
+ result: check,
191
+ life,
192
+ });
193
+ await ctx.dispatch(event);
194
+ return correctTypeError(
195
+ ctx,
196
+ call,
197
+ event,
198
+ [...previousValidationErrors, event],
199
+ life - 1,
200
+ );
201
+ }
202
+
203
+ // EXECUTE OPERATION
204
+ return executeFunction(call, operation);
205
+ }
206
+
207
+ /* -----------------------------------------------------------
208
+ ERROR CORRECTORS
209
+ ----------------------------------------------------------- */
210
+ async function correctTypeError(
211
+ ctx: AgenticaContext | MicroAgenticaContext,
212
+ callEvent: AgenticaCallEvent,
213
+ validateEvent: AgenticaValidateEvent,
214
+ previousValidationErrors: AgenticaValidateEvent[],
215
+ life: number,
216
+ ): Promise<AgenticaExecuteEvent> {
217
+ return correctError(ctx, {
218
+ giveUp: () => createExecuteEvent({
219
+ call_id: callEvent.id,
220
+ operation: callEvent.operation,
221
+ arguments: callEvent.arguments,
222
+ value: new AgenticaValidationError({
223
+ arguments: callEvent.arguments,
224
+ errors: validateEvent.result.errors,
225
+ }),
226
+ success: false,
227
+ }),
228
+ operation: callEvent.operation,
229
+ toolCall: {
230
+ id: callEvent.id,
231
+ arguments: JSON.stringify(callEvent.arguments),
232
+ result: [
233
+ "🚨 VALIDATION FAILURE: Your function arguments do not conform to the required schema.",
234
+ "",
235
+ "The validation errors below represent computed absolute truth from rigorous type validation.",
236
+ "Each error is marked with ❌ comments showing the exact location, expected type, and actual value.",
237
+ "",
238
+ "You must fix ALL errors to achieve 100% schema compliance.",
239
+ "",
240
+ LlmJson.stringify(validateEvent.result),
241
+ ].join("\n"),
242
+ },
243
+ systemPrompt: ctx.config?.systemPrompt?.validate?.(previousValidationErrors.slice(0, -1))
244
+ ?? [
245
+ AgenticaSystemPrompt.VALIDATE,
246
+ ...(previousValidationErrors.length > 1
247
+ ? [
248
+ "",
249
+ AgenticaSystemPrompt.VALIDATE_REPEATED.replace(
250
+ "${{HISTORICAL_ERRORS}}",
251
+ previousValidationErrors
252
+ .slice(0, -1)
253
+ .map((ve, i) => [
254
+ `### ${i + 1}. Previous Validation Error`,
255
+ "",
256
+ LlmJson.stringify(ve.result),
257
+ ].join("\n"))
258
+ .join("\n\n"),
259
+ // JSON.stringify(previousValidationErrors.slice(0, -1).map(e => e.result.errors)),
260
+ ),
261
+ ]
262
+ : []),
263
+ ].join("\n"),
264
+ life,
265
+ previousValidationErrors,
266
+ });
267
+ }
268
+
269
+ async function correctJsonError(
270
+ ctx: AgenticaContext | MicroAgenticaContext,
271
+ toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
272
+ parseErrorEvent: AgenticaJsonParseErrorEvent,
273
+ previousValidationErrors: AgenticaValidateEvent[],
274
+ life: number,
275
+ ): Promise<AgenticaExecuteEvent> {
276
+ return correctError(ctx, {
277
+ giveUp: () => createExecuteEvent({
278
+ call_id: toolCall.id,
279
+ operation: parseErrorEvent.operation,
280
+ arguments: {},
281
+ value: new AgenticaJsonParseError(parseErrorEvent.failure),
282
+ success: false,
283
+ }),
284
+ operation: parseErrorEvent.operation,
285
+ toolCall: {
286
+ id: parseErrorEvent.id,
287
+ arguments: parseErrorEvent.failure.input,
288
+ result: dedent`
289
+ Invalid JSON format.
290
+
291
+ Here is the detailed parsing failure information,
292
+ including error messages and their locations within the input:
293
+
294
+ \`\`\`json
295
+ ${JSON.stringify(parseErrorEvent.failure.errors)}
296
+ \`\`\`
297
+
298
+ And here is the partially parsed data that was successfully
299
+ extracted before the error occurred:
300
+
301
+ \`\`\`json
302
+ ${JSON.stringify(parseErrorEvent.failure.data)}
303
+ \`\`\`
304
+ `,
305
+ },
306
+ systemPrompt: ctx.config?.systemPrompt?.jsonParseError?.(parseErrorEvent)
307
+ ?? AgenticaSystemPrompt.JSON_PARSE_ERROR.replace(
308
+ "${{FAILURE}}",
309
+ JSON.stringify(parseErrorEvent.failure),
310
+ ),
311
+ life,
312
+ previousValidationErrors,
313
+ });
314
+ }
315
+
316
+ function parseArguments(
317
+ operation: AgenticaOperation,
318
+ toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
319
+ life: number,
320
+ ): AgenticaCallEvent | AgenticaJsonParseErrorEvent {
321
+ const result: IJsonParseResult<Record<string, unknown>> = operation.function.parse(
322
+ toolCall.function.arguments,
323
+ ) satisfies IJsonParseResult<unknown> as IJsonParseResult<Record<string, unknown>>;
324
+ if (result.success === false) {
325
+ return createJsonParseErrorEvent({
326
+ call_id: toolCall.id,
327
+ operation,
328
+ failure: result,
329
+ life,
330
+ });
331
+ }
332
+ return createCallEvent({
333
+ id: toolCall.id,
334
+ operation,
335
+ arguments: result.data,
336
+ });
337
+ }
338
+
339
+ async function correctError(
340
+ ctx: AgenticaContext | MicroAgenticaContext,
341
+ props: {
342
+ giveUp: () => AgenticaExecuteEvent;
343
+ operation: AgenticaOperation;
344
+ toolCall: {
345
+ id: string;
346
+ arguments: string;
347
+ result: string;
348
+ };
349
+ systemPrompt: string;
350
+ life: number;
351
+ previousValidationErrors: AgenticaValidateEvent[];
352
+ },
353
+ ): Promise<AgenticaExecuteEvent> {
354
+ if (props.life <= 0) {
355
+ return props.giveUp();
356
+ }
357
+
358
+ const result = await ctx.request("call", {
359
+ messages: [
360
+ // PREVIOUS HISTORIES
361
+ ...ctx.histories.map(decodeHistory).flat(),
362
+ // USER INPUT
363
+ {
364
+ role: "user",
365
+ content: ctx.prompt.contents.map(decodeUserMessageContent),
366
+ },
367
+ // TYPE CORRECTION
368
+ {
369
+ role: "system",
370
+ content:
371
+ ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory[])
372
+ ?? AgenticaSystemPrompt.EXECUTE,
373
+ },
374
+ {
375
+ role: "assistant",
376
+ tool_calls: [
377
+ {
378
+ type: "function",
379
+ id: props.toolCall.id,
380
+ function: {
381
+ name: props.operation.name,
382
+ arguments: props.toolCall.arguments,
383
+ },
384
+ } satisfies OpenAI.ChatCompletionMessageFunctionToolCall,
385
+ ],
386
+ } satisfies OpenAI.ChatCompletionAssistantMessageParam,
387
+ {
388
+ role: "tool",
389
+ content: props.toolCall.result,
390
+ tool_call_id: props.toolCall.id,
391
+ },
392
+ {
393
+ role: "system",
394
+ content: props.systemPrompt,
395
+ },
396
+ // COMMON SYSTEM PROMPT
397
+ {
398
+ role: "system",
399
+ content: AgenticaDefaultPrompt.write(ctx.config),
400
+ } satisfies OpenAI.ChatCompletionSystemMessageParam,
401
+ ],
402
+ // STACK FUNCTIONS
403
+ tools: [
404
+ {
405
+ type: "function",
406
+ function: {
407
+ name: props.operation.name,
408
+ description: props.operation.function.description,
409
+ /**
410
+ * @TODO fix it
411
+ * The property and value have a type mismatch, but it works.
412
+ */
413
+ parameters: props.operation.function.parameters as unknown as Record<string, unknown>,
414
+ },
415
+ },
416
+ ],
417
+ tool_choice: "required",
418
+ // parallel_tool_calls: false,
419
+ });
420
+
421
+ const completion = await (async () => {
422
+ if (result.type === "none-stream") {
423
+ return result.value;
424
+ }
425
+ return ChatGptCompletionMessageUtil.merge(await StreamUtil.readAll(result.value));
426
+ })();
427
+
428
+ const toolCall: OpenAI.ChatCompletionMessageFunctionToolCall | undefined = completion.choices?.[0]?.message.tool_calls?.filter(
429
+ tc => tc.type === "function",
430
+ ).find(
431
+ s => s.function.name === props.operation.name,
432
+ );
433
+ if (toolCall === undefined) {
434
+ // LLM did not return a valid tool call - retry if life remains
435
+ return correctError(ctx, {
436
+ ...props,
437
+ life: props.life - 1,
438
+ });
439
+ }
440
+ return predicate(
441
+ ctx,
442
+ props.operation,
443
+ toolCall,
444
+ props.previousValidationErrors,
445
+ props.life,
446
+ );
447
+ }
448
+
449
+ /* -----------------------------------------------------------
450
+ FUNCTION EXECUTORS
451
+ ----------------------------------------------------------- */
452
+ async function executeFunction(
453
+ call: AgenticaCallEvent,
454
+ operation: AgenticaOperation,
455
+ ): Promise<AgenticaExecuteEvent> {
456
+ try {
457
+ const value: unknown = await (async () => {
458
+ switch (operation.protocol) {
459
+ case "class":
460
+ return executeClassFunction(call, operation);
461
+ case "http":
462
+ return executeHttpOperation(call, operation);
463
+ case "mcp":
464
+ return executeMcpOperation(call, operation);
465
+ default:
466
+ operation satisfies never; // Ensure all cases are handled
467
+ throw new Error("Unknown protocol"); // never be happen
468
+ }
469
+ })();
470
+ return createExecuteEvent({
471
+ call_id: call.id,
472
+ operation: call.operation,
473
+ arguments: call.arguments,
474
+ value,
475
+ success: true,
476
+ });
477
+ }
478
+ catch (error) {
479
+ return createExecuteEvent({
480
+ call_id: call.id,
481
+ operation: call.operation,
482
+ arguments: call.arguments,
483
+ value: error instanceof Error
484
+ ? {
485
+ ...error,
486
+ name: error.name,
487
+ message: error.message,
488
+ stack: error.stack,
489
+ }
490
+ : error,
491
+ success: false,
492
+ });
493
+ }
494
+ }
495
+
496
+ async function executeClassFunction(
497
+ call: AgenticaCallEvent,
498
+ operation: AgenticaOperation.Class,
499
+ ): Promise<unknown> {
500
+ const execute = operation.controller.execute;
501
+ const value: unknown = typeof execute === "function"
502
+ ? await execute({
503
+ application: operation.controller.application,
504
+ function: operation.function,
505
+ arguments: call.arguments,
506
+ })
507
+ : await (execute as Record<string, any>)[operation.function.name](
508
+ call.arguments,
509
+ );
510
+ return value;
511
+ }
512
+
513
+ async function executeHttpOperation(
514
+ call: AgenticaCallEvent,
515
+ operation: AgenticaOperation.Http,
516
+ ): Promise<unknown> {
517
+ const execute = operation.controller.execute;
518
+ const value: IHttpResponse = typeof execute === "function"
519
+ ? await execute({
520
+ connection: operation.controller.connection,
521
+ application: operation.controller.application,
522
+ function: operation.function,
523
+ arguments: call.arguments,
524
+ })
525
+ : await HttpLlm.propagate({
526
+ connection: operation.controller.connection,
527
+ application: operation.controller.application,
528
+ function: operation.function,
529
+ input: call.arguments,
530
+ });
531
+ return value;
532
+ }
533
+
534
+ async function executeMcpOperation(
535
+ call: AgenticaCallEvent,
536
+ operation: AgenticaOperation.Mcp,
537
+ ): Promise<unknown> {
538
+ return operation.controller.client.callTool({
539
+ name: operation.function.name,
540
+ arguments: call.arguments,
541
+ }).then(v => v.content);
542
+ }