@carlonicora/nestjs-neo4jsonapi 1.64.0 → 1.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/dist/agents/agents.modules.js +3 -3
  2. package/dist/agents/agents.modules.js.map +1 -1
  3. package/dist/agents/graph/graph.module.d.ts +3 -0
  4. package/dist/agents/graph/graph.module.d.ts.map +1 -0
  5. package/dist/agents/{chatbot/chatbot.module.js → graph/graph.module.js} +12 -16
  6. package/dist/agents/graph/graph.module.js.map +1 -0
  7. package/dist/agents/{chatbot → graph}/interfaces/graph.catalog.interface.d.ts +4 -0
  8. package/dist/agents/graph/interfaces/graph.catalog.interface.d.ts.map +1 -0
  9. package/dist/agents/graph/interfaces/graph.catalog.interface.js.map +1 -0
  10. package/dist/agents/graph/interfaces/graph.node.output.interface.d.ts +30 -0
  11. package/dist/agents/graph/interfaces/graph.node.output.interface.d.ts.map +1 -0
  12. package/dist/agents/graph/interfaces/graph.node.output.interface.js +3 -0
  13. package/dist/agents/graph/interfaces/graph.node.output.interface.js.map +1 -0
  14. package/dist/agents/graph/prompts/graph.node.system.prompt.d.ts +3 -0
  15. package/dist/agents/graph/prompts/graph.node.system.prompt.d.ts.map +1 -0
  16. package/dist/agents/graph/prompts/graph.node.system.prompt.js +66 -0
  17. package/dist/agents/graph/prompts/graph.node.system.prompt.js.map +1 -0
  18. package/dist/agents/graph/repositories/user-modules.repository.d.ts.map +1 -0
  19. package/dist/agents/graph/repositories/user-modules.repository.js.map +1 -0
  20. package/dist/agents/{chatbot → graph}/services/descriptor.source.d.ts +2 -0
  21. package/dist/agents/graph/services/descriptor.source.d.ts.map +1 -0
  22. package/dist/agents/{chatbot → graph}/services/descriptor.source.js +18 -3
  23. package/dist/agents/graph/services/descriptor.source.js.map +1 -0
  24. package/dist/agents/graph/services/field-formatting.d.ts.map +1 -0
  25. package/dist/agents/graph/services/field-formatting.js.map +1 -0
  26. package/dist/agents/{chatbot → graph}/services/graph.catalog.service.d.ts +16 -0
  27. package/dist/agents/graph/services/graph.catalog.service.d.ts.map +1 -0
  28. package/dist/agents/{chatbot → graph}/services/graph.catalog.service.js +63 -1
  29. package/dist/agents/graph/services/graph.catalog.service.js.map +1 -0
  30. package/dist/agents/{chatbot/services/chatbot.index.manager.d.ts → graph/services/graph.index.manager.d.ts} +2 -2
  31. package/dist/agents/graph/services/graph.index.manager.d.ts.map +1 -0
  32. package/dist/agents/{chatbot/services/chatbot.index.manager.js → graph/services/graph.index.manager.js} +9 -9
  33. package/dist/agents/graph/services/graph.index.manager.js.map +1 -0
  34. package/dist/agents/graph/services/graph.search.service.d.ts +69 -0
  35. package/dist/agents/graph/services/graph.search.service.d.ts.map +1 -0
  36. package/dist/agents/graph/services/graph.search.service.js +230 -0
  37. package/dist/agents/graph/services/graph.search.service.js.map +1 -0
  38. package/dist/agents/graph/services/humanize-tool.d.ts.map +1 -0
  39. package/dist/agents/graph/services/humanize-tool.js.map +1 -0
  40. package/dist/agents/graph/services/materialise-bridge.d.ts +36 -0
  41. package/dist/agents/graph/services/materialise-bridge.d.ts.map +1 -0
  42. package/dist/agents/graph/services/materialise-bridge.js +69 -0
  43. package/dist/agents/graph/services/materialise-bridge.js.map +1 -0
  44. package/dist/agents/graph/tools/describe-entity.tool.d.ts.map +1 -0
  45. package/dist/agents/{chatbot → graph}/tools/describe-entity.tool.js +1 -0
  46. package/dist/agents/graph/tools/describe-entity.tool.js.map +1 -0
  47. package/dist/agents/{chatbot → graph}/tools/read-entity.tool.d.ts +5 -1
  48. package/dist/agents/graph/tools/read-entity.tool.d.ts.map +1 -0
  49. package/dist/agents/{chatbot → graph}/tools/read-entity.tool.js +37 -8
  50. package/dist/agents/graph/tools/read-entity.tool.js.map +1 -0
  51. package/dist/agents/{chatbot → graph}/tools/resolve-entity.tool.d.ts +2 -2
  52. package/dist/agents/graph/tools/resolve-entity.tool.d.ts.map +1 -0
  53. package/dist/agents/{chatbot → graph}/tools/resolve-entity.tool.js +2 -2
  54. package/dist/agents/graph/tools/resolve-entity.tool.js.map +1 -0
  55. package/dist/agents/{chatbot → graph}/tools/search-entities.tool.d.ts +6 -2
  56. package/dist/agents/graph/tools/search-entities.tool.d.ts.map +1 -0
  57. package/dist/agents/{chatbot → graph}/tools/search-entities.tool.js +36 -12
  58. package/dist/agents/graph/tools/search-entities.tool.js.map +1 -0
  59. package/dist/agents/{chatbot → graph}/tools/tool.factory.d.ts +7 -0
  60. package/dist/agents/graph/tools/tool.factory.d.ts.map +1 -0
  61. package/dist/agents/{chatbot → graph}/tools/tool.factory.js +57 -3
  62. package/dist/agents/graph/tools/tool.factory.js.map +1 -0
  63. package/dist/agents/{chatbot → graph}/tools/traverse.tool.d.ts +5 -1
  64. package/dist/agents/graph/tools/traverse.tool.d.ts.map +1 -0
  65. package/dist/agents/{chatbot → graph}/tools/traverse.tool.js +38 -15
  66. package/dist/agents/graph/tools/traverse.tool.js.map +1 -0
  67. package/dist/agents/index.d.ts +6 -9
  68. package/dist/agents/index.d.ts.map +1 -1
  69. package/dist/agents/index.js +13 -15
  70. package/dist/agents/index.js.map +1 -1
  71. package/dist/agents/responder/contexts/responder.context.d.ts +75 -1
  72. package/dist/agents/responder/contexts/responder.context.d.ts.map +1 -1
  73. package/dist/agents/responder/contexts/responder.context.js +29 -4
  74. package/dist/agents/responder/contexts/responder.context.js.map +1 -1
  75. package/dist/agents/responder/factories/responder.context.factory.d.ts +4 -5
  76. package/dist/agents/responder/factories/responder.context.factory.d.ts.map +1 -1
  77. package/dist/agents/responder/factories/responder.context.factory.js +28 -8
  78. package/dist/agents/responder/factories/responder.context.factory.js.map +1 -1
  79. package/dist/agents/responder/interfaces/entity.reference.interface.d.ts +7 -0
  80. package/dist/agents/responder/interfaces/entity.reference.interface.d.ts.map +1 -0
  81. package/dist/agents/{chatbot/interfaces/chatbot.response.interface.js → responder/interfaces/entity.reference.interface.js} +1 -1
  82. package/dist/agents/responder/interfaces/entity.reference.interface.js.map +1 -0
  83. package/dist/agents/responder/interfaces/responder.response.interface.d.ts +12 -3
  84. package/dist/agents/responder/interfaces/responder.response.interface.d.ts.map +1 -1
  85. package/dist/agents/responder/interfaces/unified.trace.interface.d.ts +64 -0
  86. package/dist/agents/responder/interfaces/unified.trace.interface.d.ts.map +1 -0
  87. package/dist/agents/responder/interfaces/unified.trace.interface.js +3 -0
  88. package/dist/agents/responder/interfaces/unified.trace.interface.js.map +1 -0
  89. package/dist/agents/responder/nodes/graph.node.service.d.ts +31 -0
  90. package/dist/agents/responder/nodes/graph.node.service.d.ts.map +1 -0
  91. package/dist/agents/responder/nodes/graph.node.service.js +319 -0
  92. package/dist/agents/responder/nodes/graph.node.service.js.map +1 -0
  93. package/dist/agents/responder/nodes/planner.node.service.d.ts +14 -0
  94. package/dist/agents/responder/nodes/planner.node.service.d.ts.map +1 -0
  95. package/dist/agents/responder/nodes/planner.node.service.js +121 -0
  96. package/dist/agents/responder/nodes/planner.node.service.js.map +1 -0
  97. package/dist/agents/responder/nodes/responder.answer.node.service.d.ts +5 -23
  98. package/dist/agents/responder/nodes/responder.answer.node.service.d.ts.map +1 -1
  99. package/dist/agents/responder/nodes/responder.answer.node.service.js +257 -432
  100. package/dist/agents/responder/nodes/responder.answer.node.service.js.map +1 -1
  101. package/dist/agents/responder/responder.module.d.ts.map +1 -1
  102. package/dist/agents/responder/responder.module.js +12 -3
  103. package/dist/agents/responder/responder.module.js.map +1 -1
  104. package/dist/agents/responder/services/responder.service.d.ts +15 -22
  105. package/dist/agents/responder/services/responder.service.d.ts.map +1 -1
  106. package/dist/agents/responder/services/responder.service.js +116 -89
  107. package/dist/agents/responder/services/responder.service.js.map +1 -1
  108. package/dist/common/helpers/define-entity.d.ts.map +1 -1
  109. package/dist/common/helpers/define-entity.js +16 -1
  110. package/dist/common/helpers/define-entity.js.map +1 -1
  111. package/dist/common/interfaces/entity.schema.interface.d.ts +15 -0
  112. package/dist/common/interfaces/entity.schema.interface.d.ts.map +1 -1
  113. package/dist/core/llm/interfaces/llm-call-metadata.interface.d.ts +19 -0
  114. package/dist/core/llm/interfaces/llm-call-metadata.interface.d.ts.map +1 -0
  115. package/dist/core/llm/interfaces/llm-call-metadata.interface.js +3 -0
  116. package/dist/core/llm/interfaces/llm-call-metadata.interface.js.map +1 -0
  117. package/dist/core/llm/llm.module.d.ts +1 -0
  118. package/dist/core/llm/llm.module.d.ts.map +1 -1
  119. package/dist/core/llm/llm.module.js +3 -1
  120. package/dist/core/llm/llm.module.js.map +1 -1
  121. package/dist/core/llm/services/llm-call-dumper.service.d.ts +64 -0
  122. package/dist/core/llm/services/llm-call-dumper.service.d.ts.map +1 -0
  123. package/dist/core/llm/services/llm-call-dumper.service.js +204 -0
  124. package/dist/core/llm/services/llm-call-dumper.service.js.map +1 -0
  125. package/dist/core/llm/services/llm.service.d.ts +4 -1
  126. package/dist/core/llm/services/llm.service.d.ts.map +1 -1
  127. package/dist/core/llm/services/llm.service.js +304 -220
  128. package/dist/core/llm/services/llm.service.js.map +1 -1
  129. package/dist/foundations/assistant/assistant.module.d.ts.map +1 -1
  130. package/dist/foundations/assistant/assistant.module.js +3 -2
  131. package/dist/foundations/assistant/assistant.module.js.map +1 -1
  132. package/dist/foundations/assistant/entities/assistant.d.ts +15 -16
  133. package/dist/foundations/assistant/entities/assistant.d.ts.map +1 -1
  134. package/dist/foundations/assistant/entities/assistant.js +21 -9
  135. package/dist/foundations/assistant/entities/assistant.js.map +1 -1
  136. package/dist/foundations/assistant/repositories/assistant.repository.d.ts +13 -0
  137. package/dist/foundations/assistant/repositories/assistant.repository.d.ts.map +1 -1
  138. package/dist/foundations/assistant/services/assistant.service.d.ts +35 -10
  139. package/dist/foundations/assistant/services/assistant.service.d.ts.map +1 -1
  140. package/dist/foundations/assistant/services/assistant.service.js +132 -17
  141. package/dist/foundations/assistant/services/assistant.service.js.map +1 -1
  142. package/dist/foundations/assistant-message/entities/assistant-message.d.ts +30 -10
  143. package/dist/foundations/assistant-message/entities/assistant-message.d.ts.map +1 -1
  144. package/dist/foundations/assistant-message/entities/assistant-message.js +19 -4
  145. package/dist/foundations/assistant-message/entities/assistant-message.js.map +1 -1
  146. package/dist/foundations/assistant-message/repositories/assistant-message.repository.d.ts +53 -4
  147. package/dist/foundations/assistant-message/repositories/assistant-message.repository.d.ts.map +1 -1
  148. package/dist/foundations/assistant-message/repositories/assistant-message.repository.js +43 -3
  149. package/dist/foundations/assistant-message/repositories/assistant-message.repository.js.map +1 -1
  150. package/dist/foundations/assistant-message/services/assistant-message.service.d.ts +26 -0
  151. package/dist/foundations/assistant-message/services/assistant-message.service.d.ts.map +1 -1
  152. package/dist/foundations/chunk/chunk.module.d.ts.map +1 -1
  153. package/dist/foundations/chunk/chunk.module.js +4 -5
  154. package/dist/foundations/chunk/chunk.module.js.map +1 -1
  155. package/dist/foundations/chunk/entities/chunk.entity.d.ts +19 -4
  156. package/dist/foundations/chunk/entities/chunk.entity.d.ts.map +1 -1
  157. package/dist/foundations/chunk/entities/chunk.entity.js +48 -0
  158. package/dist/foundations/chunk/entities/chunk.entity.js.map +1 -1
  159. package/dist/foundations/chunk/index.d.ts +1 -2
  160. package/dist/foundations/chunk/index.d.ts.map +1 -1
  161. package/dist/foundations/chunk/index.js +3 -3
  162. package/dist/foundations/chunk/index.js.map +1 -1
  163. package/dist/foundations/chunk/repositories/chunk.repository.d.ts.map +1 -1
  164. package/dist/foundations/chunk/repositories/chunk.repository.js +8 -8
  165. package/dist/foundations/chunk/repositories/chunk.repository.js.map +1 -1
  166. package/dist/foundations/chunk/services/chunk.service.d.ts.map +1 -1
  167. package/dist/foundations/chunk/services/chunk.service.js +2 -2
  168. package/dist/foundations/chunk/services/chunk.service.js.map +1 -1
  169. package/package.json +1 -1
  170. package/dist/agents/chatbot/chatbot.module.d.ts +0 -3
  171. package/dist/agents/chatbot/chatbot.module.d.ts.map +0 -1
  172. package/dist/agents/chatbot/chatbot.module.js.map +0 -1
  173. package/dist/agents/chatbot/interfaces/chatbot.response.interface.d.ts +0 -25
  174. package/dist/agents/chatbot/interfaces/chatbot.response.interface.d.ts.map +0 -1
  175. package/dist/agents/chatbot/interfaces/chatbot.response.interface.js.map +0 -1
  176. package/dist/agents/chatbot/interfaces/graph.catalog.interface.d.ts.map +0 -1
  177. package/dist/agents/chatbot/interfaces/graph.catalog.interface.js.map +0 -1
  178. package/dist/agents/chatbot/prompts/chatbot.system.prompt.d.ts +0 -3
  179. package/dist/agents/chatbot/prompts/chatbot.system.prompt.d.ts.map +0 -1
  180. package/dist/agents/chatbot/prompts/chatbot.system.prompt.js +0 -60
  181. package/dist/agents/chatbot/prompts/chatbot.system.prompt.js.map +0 -1
  182. package/dist/agents/chatbot/repositories/user-modules.repository.d.ts.map +0 -1
  183. package/dist/agents/chatbot/repositories/user-modules.repository.js.map +0 -1
  184. package/dist/agents/chatbot/services/chatbot.index.manager.d.ts.map +0 -1
  185. package/dist/agents/chatbot/services/chatbot.index.manager.js.map +0 -1
  186. package/dist/agents/chatbot/services/chatbot.search.service.d.ts +0 -46
  187. package/dist/agents/chatbot/services/chatbot.search.service.d.ts.map +0 -1
  188. package/dist/agents/chatbot/services/chatbot.search.service.js +0 -148
  189. package/dist/agents/chatbot/services/chatbot.search.service.js.map +0 -1
  190. package/dist/agents/chatbot/services/chatbot.service.d.ts +0 -36
  191. package/dist/agents/chatbot/services/chatbot.service.d.ts.map +0 -1
  192. package/dist/agents/chatbot/services/chatbot.service.js +0 -220
  193. package/dist/agents/chatbot/services/chatbot.service.js.map +0 -1
  194. package/dist/agents/chatbot/services/descriptor.source.d.ts.map +0 -1
  195. package/dist/agents/chatbot/services/descriptor.source.js.map +0 -1
  196. package/dist/agents/chatbot/services/field-formatting.d.ts.map +0 -1
  197. package/dist/agents/chatbot/services/field-formatting.js.map +0 -1
  198. package/dist/agents/chatbot/services/graph.catalog.service.d.ts.map +0 -1
  199. package/dist/agents/chatbot/services/graph.catalog.service.js.map +0 -1
  200. package/dist/agents/chatbot/services/humanize-tool.d.ts.map +0 -1
  201. package/dist/agents/chatbot/services/humanize-tool.js.map +0 -1
  202. package/dist/agents/chatbot/tools/describe-entity.tool.d.ts.map +0 -1
  203. package/dist/agents/chatbot/tools/describe-entity.tool.js.map +0 -1
  204. package/dist/agents/chatbot/tools/read-entity.tool.d.ts.map +0 -1
  205. package/dist/agents/chatbot/tools/read-entity.tool.js.map +0 -1
  206. package/dist/agents/chatbot/tools/resolve-entity.tool.d.ts.map +0 -1
  207. package/dist/agents/chatbot/tools/resolve-entity.tool.js.map +0 -1
  208. package/dist/agents/chatbot/tools/search-entities.tool.d.ts.map +0 -1
  209. package/dist/agents/chatbot/tools/search-entities.tool.js.map +0 -1
  210. package/dist/agents/chatbot/tools/tool.factory.d.ts.map +0 -1
  211. package/dist/agents/chatbot/tools/tool.factory.js.map +0 -1
  212. package/dist/agents/chatbot/tools/traverse.tool.d.ts.map +0 -1
  213. package/dist/agents/chatbot/tools/traverse.tool.js.map +0 -1
  214. package/dist/foundations/chunk/entities/chunk.map.d.ts +0 -8
  215. package/dist/foundations/chunk/entities/chunk.map.d.ts.map +0 -1
  216. package/dist/foundations/chunk/entities/chunk.map.js +0 -31
  217. package/dist/foundations/chunk/entities/chunk.map.js.map +0 -1
  218. package/dist/foundations/chunk/entities/chunk.model.d.ts +0 -4
  219. package/dist/foundations/chunk/entities/chunk.model.d.ts.map +0 -1
  220. package/dist/foundations/chunk/entities/chunk.model.js +0 -13
  221. package/dist/foundations/chunk/entities/chunk.model.js.map +0 -1
  222. package/dist/foundations/chunk/serialisers/chunk.serialiser.d.ts +0 -14
  223. package/dist/foundations/chunk/serialisers/chunk.serialiser.d.ts.map +0 -1
  224. package/dist/foundations/chunk/serialisers/chunk.serialiser.js +0 -54
  225. package/dist/foundations/chunk/serialisers/chunk.serialiser.js.map +0 -1
  226. /package/dist/agents/{chatbot → graph}/interfaces/graph.catalog.interface.js +0 -0
  227. /package/dist/agents/{chatbot → graph}/repositories/user-modules.repository.d.ts +0 -0
  228. /package/dist/agents/{chatbot → graph}/repositories/user-modules.repository.js +0 -0
  229. /package/dist/agents/{chatbot → graph}/services/field-formatting.d.ts +0 -0
  230. /package/dist/agents/{chatbot → graph}/services/field-formatting.js +0 -0
  231. /package/dist/agents/{chatbot → graph}/services/humanize-tool.d.ts +0 -0
  232. /package/dist/agents/{chatbot → graph}/services/humanize-tool.js +0 -0
  233. /package/dist/agents/{chatbot → graph}/tools/describe-entity.tool.d.ts +0 -0
@@ -17,6 +17,7 @@ const config_1 = require("@nestjs/config");
17
17
  const agentmessage_type_1 = require("../../../common/enums/agentmessage.type");
18
18
  const model_service_1 = require("../../llm/services/model.service");
19
19
  const schema_utils_1 = require("../../llm/utils/schema.utils");
20
+ const llm_call_dumper_service_1 = require("./llm-call-dumper.service");
20
21
  /**
21
22
  * Type guard to validate raw response structure
22
23
  */
@@ -24,9 +25,10 @@ function isValidRaw(raw) {
24
25
  return typeof raw === "object" && raw !== null;
25
26
  }
26
27
  let LLMService = class LLMService {
27
- constructor(modelService, config) {
28
+ constructor(modelService, config, dumper) {
28
29
  this.modelService = modelService;
29
30
  this.config = config;
31
+ this.dumper = dumper;
30
32
  this._sessionTokens = {
31
33
  input: 0,
32
34
  output: 0,
@@ -268,244 +270,325 @@ let LLMService = class LLMService {
268
270
  * ```
269
271
  */
270
272
  async call(params) {
273
+ const aiConfig = this.config.get("ai").ai;
274
+ const session = this.dumper.startSession({
275
+ metadata: params.metadata,
276
+ model: aiConfig.model,
277
+ provider: aiConfig.provider,
278
+ temperature: params.temperature,
279
+ });
280
+ let totalInput = 0;
281
+ let totalOutput = 0;
282
+ const parseFallbacks = [];
283
+ const warnings = [];
271
284
  try {
272
- // Optional: Validate input parameters against schema
273
- if (params.inputSchema && params.validateInput) {
274
- try {
275
- params.inputParams = params.inputSchema.parse(params.inputParams);
276
- }
277
- catch (validationError) {
278
- console.error("[LLMService] Input validation failed:", validationError);
279
- throw new Error(`Invalid input parameters: ${validationError instanceof Error ? validationError.message : "Unknown validation error"}`);
280
- }
281
- }
282
- // Create messages with modern MessagesPlaceholder pattern (with schema-guided instructions)
283
- const { template, historyMessages } = this._createMessages({
284
- systemPrompts: params.systemPrompts,
285
- instructions: params.instructions,
286
- inputParams: params.inputParams,
287
- inputSchema: params.inputSchema,
288
- history: params.history,
289
- maxHistoryMessages: params.maxHistoryMessages,
285
+ const result = await this._invokeOriginal(params, session, (i, o) => {
286
+ totalInput += i;
287
+ totalOutput += o;
288
+ }, (kind) => parseFallbacks.push(kind), (w) => warnings.push(w));
289
+ session.close({
290
+ finalStatus: "success",
291
+ totalTokens: { input: totalInput, output: totalOutput },
292
+ warnings,
293
+ parseFallbacks,
290
294
  });
291
- const prompt = prompts_1.ChatPromptTemplate.fromMessages(template);
292
- // Get base model
293
- const baseModel = this.modelService.getLLM({
294
- temperature: params.temperature,
295
- });
296
- // Build config options for the invocation
297
- const configOptions = {};
298
- if (params.maxTokens)
299
- configOptions.maxTokens = params.maxTokens;
300
- if (params.stopSequences)
301
- configOptions.stop = params.stopSequences;
302
- if (params.metadata)
303
- configOptions.metadata = params.metadata;
304
- if (params.timeout)
305
- configOptions.timeout = params.timeout;
306
- // Track token usage across tool iterations
307
- let totalInputTokens = 0;
308
- let totalOutputTokens = 0;
309
- // Build initial messages for the conversation
310
- const conversationMessages = await prompt.formatMessages({
311
- ...params.inputParams,
312
- chat_history: historyMessages,
295
+ return result;
296
+ }
297
+ catch (error) {
298
+ const message = error instanceof Error ? error.message : String(error);
299
+ const stack = error instanceof Error ? (error.stack ?? "").split("\n").slice(0, 10).join("\n") : undefined;
300
+ session.close({
301
+ finalStatus: "error",
302
+ errorMessage: message,
303
+ errorStack: stack,
304
+ totalTokens: { input: totalInput, output: totalOutput },
305
+ warnings,
306
+ parseFallbacks,
313
307
  });
314
- // If tools are provided, handle tool calling loop
315
- if (params.tools && params.tools.length > 0) {
316
- const maxIterations = params.maxToolIterations ?? 5;
317
- // Build tool map for execution
318
- const toolMap = new Map();
319
- for (const tool of params.tools) {
320
- toolMap.set(tool.name, tool);
321
- }
322
- // Bind tools to model
323
- const modelWithTools = baseModel.bindTools(params.tools);
324
- // Tool calling loop
325
- for (let iteration = 0; iteration < maxIterations; iteration++) {
326
- // Call model with tools
327
- const toolResponse = Object.keys(configOptions).length > 0
328
- ? await modelWithTools.invoke(conversationMessages, configOptions)
329
- : await modelWithTools.invoke(conversationMessages);
330
- // Track token usage
331
- const responseUsage = toolResponse.usage_metadata;
332
- if (responseUsage) {
333
- totalInputTokens += responseUsage.input_tokens ?? 0;
334
- totalOutputTokens += responseUsage.output_tokens ?? 0;
335
- }
336
- // Check for tool calls
337
- const toolCalls = toolResponse.tool_calls ?? [];
338
- if (toolCalls.length === 0) {
339
- // No more tool calls - break to get final structured response
340
- break;
341
- }
342
- // Add AI message with tool calls to conversation
343
- conversationMessages.push(toolResponse);
344
- // Execute each tool call
345
- for (const toolCall of toolCalls) {
346
- const tool = toolMap.get(toolCall.name);
347
- if (!tool) {
348
- console.warn(`[LLMService] Tool not found: ${toolCall.name}`);
349
- conversationMessages.push(new messages_1.ToolMessage({
350
- content: `Tool "${toolCall.name}" not found`,
351
- tool_call_id: toolCall.id ?? "",
352
- }));
353
- continue;
354
- }
355
- try {
356
- const result = await tool.invoke(toolCall.args);
357
- const resultStr = typeof result === "string" ? result : JSON.stringify(result);
358
- conversationMessages.push(new messages_1.ToolMessage({
359
- content: resultStr,
360
- tool_call_id: toolCall.id ?? "",
361
- }));
362
- }
363
- catch (error) {
364
- console.error(`[LLMService] Tool error: ${toolCall.name}`, error);
365
- conversationMessages.push(new messages_1.ToolMessage({
366
- content: `Tool error: ${error instanceof Error ? error.message : "Unknown error"}`,
367
- tool_call_id: toolCall.id ?? "",
368
- }));
369
- }
370
- }
371
- }
372
- }
373
- // Nudge the model out of tool-use mode before asking for the final structured
374
- // answer. Without this, some models (notably gpt-oss) emit another tool_calls
375
- // response instead of producing the structured output, and parsing fails with
376
- // "No content" / finish_reason=tool_calls. The nudge is only appended when the
377
- // tool-calling loop ran at all.
378
- if (params.tools && params.tools.length > 0 && conversationMessages.length > 0) {
379
- conversationMessages.push(new messages_1.HumanMessage("You have gathered enough information from the tool calls above to answer the user's question. Produce your final answer now as the structured output the system expects. Do not request any further tool calls."));
380
- }
381
- // Get final structured response (unified path for both tool and non-tool flows)
382
- // For Requesty + Gemini: sanitize schema to remove $schema, $defs, etc. that Gemini rejects
383
- const aiConfig = this.config.get("ai").ai;
384
- // Check if model is Gemini (handles both "gemini-..." and "google/gemini-..." formats)
385
- const modelLower = aiConfig.model.toLowerCase();
386
- const isGeminiModel = modelLower.startsWith("gemini") || modelLower.includes("/gemini");
387
- const needsGeminiSanitization = aiConfig.provider === "requesty" && isGeminiModel;
388
- let structuredLlm;
389
- if (needsGeminiSanitization) {
390
- // Convert Zod to JSON Schema and remove Gemini-incompatible properties
391
- const jsonSchema = (0, schema_utils_1.convertZodToJsonSchema)(params.outputSchema);
392
- const sanitizedSchema = (0, schema_utils_1.sanitizeSchemaForGemini)(jsonSchema);
393
- structuredLlm = baseModel.withStructuredOutput(sanitizedSchema, {
394
- includeRaw: true,
395
- });
308
+ console.error("[LLMService] Error calling LLM:", error);
309
+ throw new Error(`LLM service error: ${message}`);
310
+ }
311
+ }
312
+ async _invokeOriginal(params, session, addTokens, addParseFallback, addWarning) {
313
+ // Optional: Validate input parameters against schema
314
+ if (params.inputSchema && params.validateInput) {
315
+ try {
316
+ params.inputParams = params.inputSchema.parse(params.inputParams);
396
317
  }
397
- else {
398
- // All other providers: use Zod schema directly
399
- structuredLlm = baseModel.withStructuredOutput(params.outputSchema, {
400
- includeRaw: true,
401
- });
318
+ catch (validationError) {
319
+ console.error("[LLMService] Input validation failed:", validationError);
320
+ throw new Error(`Invalid input parameters: ${validationError instanceof Error ? validationError.message : "Unknown validation error"}`);
402
321
  }
403
- const response = (await structuredLlm.invoke(conversationMessages, Object.keys(configOptions).length > 0 ? configOptions : undefined));
404
- // Extract token usage with type guard (includes tool iteration tokens)
405
- const raw = isValidRaw(response.raw) ? response.raw : undefined;
406
- const input = totalInputTokens + (raw?.usage_metadata?.input_tokens ?? 0);
407
- const output = totalOutputTokens + (raw?.usage_metadata?.output_tokens ?? 0);
408
- // Update session tracking
409
- this._sessionTokens.input += input;
410
- this._sessionTokens.output += output;
411
- this._sessionTokens.total += input + output;
412
- this._sessionTokens.callCount += 1;
413
- // Warn if high token usage
414
- const totalTokens = input + output;
415
- if (totalTokens > 8000) {
416
- console.warn(`[LLMService] High token usage detected: ${totalTokens} tokens in this call`);
322
+ }
323
+ // Create messages with modern MessagesPlaceholder pattern (with schema-guided instructions)
324
+ const { template, historyMessages } = this._createMessages({
325
+ systemPrompts: params.systemPrompts,
326
+ instructions: params.instructions,
327
+ inputParams: params.inputParams,
328
+ inputSchema: params.inputSchema,
329
+ history: params.history,
330
+ maxHistoryMessages: params.maxHistoryMessages,
331
+ });
332
+ const prompt = prompts_1.ChatPromptTemplate.fromMessages(template);
333
+ // Get base model
334
+ const baseModel = this.modelService.getLLM({
335
+ temperature: params.temperature,
336
+ });
337
+ // Build config options for the invocation
338
+ const configOptions = {};
339
+ if (params.maxTokens)
340
+ configOptions.maxTokens = params.maxTokens;
341
+ if (params.stopSequences)
342
+ configOptions.stop = params.stopSequences;
343
+ if (params.metadata)
344
+ configOptions.metadata = params.metadata;
345
+ if (params.timeout)
346
+ configOptions.timeout = params.timeout;
347
+ // Track token usage across tool iterations
348
+ let totalInputTokens = 0;
349
+ let totalOutputTokens = 0;
350
+ // Build initial messages for the conversation
351
+ const conversationMessages = await prompt.formatMessages({
352
+ ...params.inputParams,
353
+ chat_history: historyMessages,
354
+ });
355
+ session.recordInputs({
356
+ systemPrompts: params.systemPrompts,
357
+ instructions: params.instructions ?? this._generateSchemaGuidedInstructions(params.inputParams, params.inputSchema),
358
+ inputParams: params.inputParams,
359
+ history: (params.history ?? []).map((h) => ({ role: String(h.role), content: h.content })),
360
+ tools: (params.tools ?? []).map((t) => ({
361
+ name: t.name,
362
+ description: t.description,
363
+ schema: t.schema,
364
+ })),
365
+ outputSchemaName: params.outputSchema?.constructor?.name ?? "outputSchema",
366
+ });
367
+ // If tools are provided, handle tool calling loop
368
+ if (params.tools && params.tools.length > 0) {
369
+ const maxIterations = params.maxToolIterations ?? 5;
370
+ // Build tool map for execution
371
+ const toolMap = new Map();
372
+ for (const tool of params.tools) {
373
+ toolMap.set(tool.name, tool);
417
374
  }
418
- // Enhanced error handling with detailed diagnostics
419
- if (!response.parsed) {
420
- const rawContent = raw?.content || "No content";
421
- const finishReason = raw?.response_metadata?.finish_reason;
422
- console.error("[LLMService] Parsing failed:", {
423
- rawContentPreview: rawContent.substring(0, 500),
424
- finishReason,
425
- schemaName: params.outputSchema.constructor.name,
375
+ // Bind tools to model
376
+ const modelWithTools = baseModel.bindTools(params.tools);
377
+ // Tool calling loop
378
+ for (let iteration = 0; iteration < maxIterations; iteration++) {
379
+ session.startIteration("tool-loop", conversationMessages);
380
+ // Call model with tools
381
+ const toolResponse = Object.keys(configOptions).length > 0
382
+ ? await modelWithTools.invoke(conversationMessages, configOptions)
383
+ : await modelWithTools.invoke(conversationMessages);
384
+ session.recordResponse({
385
+ content: typeof toolResponse.content === "string" ? toolResponse.content : "",
386
+ toolCalls: (toolResponse.tool_calls ?? []).map((c) => ({
387
+ id: c.id ?? "",
388
+ name: c.name,
389
+ args: c.args,
390
+ })),
391
+ tokenUsage: {
392
+ input: toolResponse.usage_metadata?.input_tokens ?? 0,
393
+ output: toolResponse.usage_metadata?.output_tokens ?? 0,
394
+ },
395
+ finishReason: toolResponse.response_metadata?.finish_reason,
426
396
  });
427
- // Attempt fallback parsing from tool_calls first (Azure/OpenAI function calling puts structured data here)
428
- const rawAnyFallback = raw;
429
- const toolCallArgs = rawAnyFallback?.tool_calls?.[0]?.args;
430
- if (toolCallArgs && typeof toolCallArgs === "object") {
397
+ // Track token usage
398
+ const responseUsage = toolResponse.usage_metadata;
399
+ if (responseUsage) {
400
+ totalInputTokens += responseUsage.input_tokens ?? 0;
401
+ totalOutputTokens += responseUsage.output_tokens ?? 0;
402
+ }
403
+ // Check for tool calls
404
+ const toolCalls = toolResponse.tool_calls ?? [];
405
+ if (toolCalls.length === 0) {
406
+ // No more tool calls - break to get final structured response
407
+ break;
408
+ }
409
+ // Add AI message with tool calls to conversation
410
+ conversationMessages.push(toolResponse);
411
+ // Execute each tool call
412
+ for (const toolCall of toolCalls) {
413
+ const tool = toolMap.get(toolCall.name);
414
+ if (!tool) {
415
+ console.warn(`[LLMService] Tool not found: ${toolCall.name}`);
416
+ conversationMessages.push(new messages_1.ToolMessage({
417
+ content: `Tool "${toolCall.name}" not found`,
418
+ tool_call_id: toolCall.id ?? "",
419
+ }));
420
+ session.recordToolResult(toolCall.id ?? "", toolCall.name, `Tool "${toolCall.name}" not found`);
421
+ continue;
422
+ }
431
423
  try {
432
- console.warn("[LLMService] Attempting fallback parsing from tool_calls args");
433
- const validated = params.outputSchema.parse(toolCallArgs);
434
- console.warn("[LLMService] Fallback tool_calls parsing succeeded");
435
- return {
436
- ...validated,
437
- tokenUsage: { input, output },
438
- };
424
+ const result = await tool.invoke(toolCall.args);
425
+ const resultStr = typeof result === "string" ? result : JSON.stringify(result);
426
+ conversationMessages.push(new messages_1.ToolMessage({
427
+ content: resultStr,
428
+ tool_call_id: toolCall.id ?? "",
429
+ }));
430
+ session.recordToolResult(toolCall.id ?? "", toolCall.name, resultStr);
439
431
  }
440
- catch (_toolCallFallbackError) {
441
- // Lenient fallback: filter out malformed array entries from tool_calls args
442
- // This handles cases where the model returns mostly valid data with a few corrupt entries
443
- try {
444
- console.warn("[LLMService] Attempting lenient tool_calls parsing (filtering invalid array entries)");
445
- const cleanedArgs = { ...toolCallArgs };
446
- const shape = params.outputSchema?.shape;
447
- if (shape) {
448
- for (const [key, fieldSchema] of Object.entries(shape)) {
449
- if (Array.isArray(cleanedArgs[key])) {
450
- // In Zod v4, ZodArray exposes .element as the element schema with .safeParse()
451
- // Unwrap optional/default/nullable wrappers first if present
452
- let schema = fieldSchema;
453
- while (schema?.unwrap && !schema?.element) {
454
- schema = schema.unwrap();
455
- }
456
- const elementSchema = schema?.element;
457
- if (elementSchema && typeof elementSchema.safeParse === "function") {
458
- const original = cleanedArgs[key];
459
- cleanedArgs[key] = original.filter((entry) => elementSchema.safeParse(entry).success);
460
- if (cleanedArgs[key].length < original.length) {
461
- console.warn(`[LLMService] Filtered ${original.length - cleanedArgs[key].length}/${original.length} invalid entries from "${key}"`);
462
- }
463
- }
464
- }
465
- }
466
- }
467
- const validated = params.outputSchema.parse(cleanedArgs);
468
- console.warn("[LLMService] Lenient tool_calls parsing succeeded");
469
- return {
470
- ...validated,
471
- tokenUsage: { input, output },
472
- };
473
- }
474
- catch {
475
- // Fall through to raw content parsing
476
- }
432
+ catch (error) {
433
+ console.error(`[LLMService] Tool error: ${toolCall.name}`, error);
434
+ conversationMessages.push(new messages_1.ToolMessage({
435
+ content: `Tool error: ${error instanceof Error ? error.message : "Unknown error"}`,
436
+ tool_call_id: toolCall.id ?? "",
437
+ }));
438
+ session.recordToolResult(toolCall.id ?? "", toolCall.name, `Tool error: ${error instanceof Error ? error.message : "Unknown error"}`);
477
439
  }
478
440
  }
479
- // Attempt fallback parsing from raw content
441
+ }
442
+ }
443
+ // Nudge the model out of tool-use mode before asking for the final structured
444
+ // answer. Without this, some models (notably gpt-oss) emit another tool_calls
445
+ // response instead of producing the structured output, and parsing fails with
446
+ // "No content" / finish_reason=tool_calls. The nudge is only appended when the
447
+ // tool-calling loop ran at all.
448
+ if (params.tools && params.tools.length > 0 && conversationMessages.length > 0) {
449
+ conversationMessages.push(new messages_1.HumanMessage("You have gathered enough information from the tool calls above to answer the user's question. Produce your final answer now as the structured output the system expects. Do not request any further tool calls."));
450
+ }
451
+ // Get final structured response (unified path for both tool and non-tool flows)
452
+ // For Requesty + Gemini: sanitize schema to remove $schema, $defs, etc. that Gemini rejects
453
+ const aiConfig = this.config.get("ai").ai;
454
+ // Check if model is Gemini (handles both "gemini-..." and "google/gemini-..." formats)
455
+ const modelLower = aiConfig.model.toLowerCase();
456
+ const isGeminiModel = modelLower.startsWith("gemini") || modelLower.includes("/gemini");
457
+ const needsGeminiSanitization = aiConfig.provider === "requesty" && isGeminiModel;
458
+ let structuredLlm;
459
+ if (needsGeminiSanitization) {
460
+ // Convert Zod to JSON Schema and remove Gemini-incompatible properties
461
+ const jsonSchema = (0, schema_utils_1.convertZodToJsonSchema)(params.outputSchema);
462
+ const sanitizedSchema = (0, schema_utils_1.sanitizeSchemaForGemini)(jsonSchema);
463
+ structuredLlm = baseModel.withStructuredOutput(sanitizedSchema, {
464
+ includeRaw: true,
465
+ });
466
+ }
467
+ else {
468
+ // All other providers: use Zod schema directly
469
+ structuredLlm = baseModel.withStructuredOutput(params.outputSchema, {
470
+ includeRaw: true,
471
+ });
472
+ }
473
+ session.startIteration("final-structured", conversationMessages);
474
+ const response = (await structuredLlm.invoke(conversationMessages, Object.keys(configOptions).length > 0 ? configOptions : undefined));
475
+ // Extract token usage with type guard (includes tool iteration tokens)
476
+ const raw = isValidRaw(response.raw) ? response.raw : undefined;
477
+ session.recordResponse({
478
+ content: typeof raw?.content === "string" ? raw.content : "",
479
+ tokenUsage: {
480
+ input: raw?.usage_metadata?.input_tokens ?? 0,
481
+ output: raw?.usage_metadata?.output_tokens ?? 0,
482
+ },
483
+ finishReason: raw?.response_metadata?.finish_reason,
484
+ });
485
+ const input = totalInputTokens + (raw?.usage_metadata?.input_tokens ?? 0);
486
+ const output = totalOutputTokens + (raw?.usage_metadata?.output_tokens ?? 0);
487
+ // Update session tracking
488
+ this._sessionTokens.input += input;
489
+ this._sessionTokens.output += output;
490
+ this._sessionTokens.total += input + output;
491
+ this._sessionTokens.callCount += 1;
492
+ // Warn if high token usage
493
+ const totalTokens = input + output;
494
+ if (totalTokens > 8000) {
495
+ const msg = `High token usage detected: ${totalTokens} tokens in this call`;
496
+ console.warn(`[LLMService] ${msg}`);
497
+ addWarning(msg);
498
+ }
499
+ // Enhanced error handling with detailed diagnostics
500
+ if (!response.parsed) {
501
+ const rawContent = raw?.content || "No content";
502
+ const finishReason = raw?.response_metadata?.finish_reason;
503
+ console.error("[LLMService] Parsing failed:", {
504
+ rawContentPreview: rawContent.substring(0, 500),
505
+ finishReason,
506
+ schemaName: params.outputSchema.constructor.name,
507
+ });
508
+ // Attempt fallback parsing from tool_calls first (Azure/OpenAI function calling puts structured data here)
509
+ const rawAnyFallback = raw;
510
+ const toolCallArgs = rawAnyFallback?.tool_calls?.[0]?.args;
511
+ if (toolCallArgs && typeof toolCallArgs === "object") {
512
+ addParseFallback("tool_calls");
480
513
  try {
481
- console.warn("[LLMService] Attempting fallback JSON parsing");
482
- const manualParse = JSON.parse(rawContent);
483
- const validated = params.outputSchema.parse(manualParse);
484
- console.warn("[LLMService] Fallback parsing succeeded");
514
+ console.warn("[LLMService] Attempting fallback parsing from tool_calls args");
515
+ const validated = params.outputSchema.parse(toolCallArgs);
516
+ console.warn("[LLMService] Fallback tool_calls parsing succeeded");
517
+ addTokens(input, output);
485
518
  return {
486
519
  ...validated,
487
520
  tokenUsage: { input, output },
488
521
  };
489
522
  }
490
- catch (fallbackError) {
491
- throw new Error(`LLM failed to return structured output. ` +
492
- `Finish reason: ${finishReason}. ` +
493
- `Raw content preview: ${rawContent.substring(0, 200)}...` +
494
- `Fallback parsing error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`);
523
+ catch (_toolCallFallbackError) {
524
+ // Lenient fallback: filter out malformed array entries from tool_calls args
525
+ // This handles cases where the model returns mostly valid data with a few corrupt entries
526
+ addParseFallback("lenient");
527
+ try {
528
+ console.warn("[LLMService] Attempting lenient tool_calls parsing (filtering invalid array entries)");
529
+ const cleanedArgs = { ...toolCallArgs };
530
+ const shape = params.outputSchema?.shape;
531
+ if (shape) {
532
+ for (const [key, fieldSchema] of Object.entries(shape)) {
533
+ if (Array.isArray(cleanedArgs[key])) {
534
+ // In Zod v4, ZodArray exposes .element as the element schema with .safeParse()
535
+ // Unwrap optional/default/nullable wrappers first if present
536
+ let schema = fieldSchema;
537
+ while (schema?.unwrap && !schema?.element) {
538
+ schema = schema.unwrap();
539
+ }
540
+ const elementSchema = schema?.element;
541
+ if (elementSchema && typeof elementSchema.safeParse === "function") {
542
+ const original = cleanedArgs[key];
543
+ cleanedArgs[key] = original.filter((entry) => elementSchema.safeParse(entry).success);
544
+ if (cleanedArgs[key].length < original.length) {
545
+ console.warn(`[LLMService] Filtered ${original.length - cleanedArgs[key].length}/${original.length} invalid entries from "${key}"`);
546
+ }
547
+ }
548
+ }
549
+ }
550
+ }
551
+ const validated = params.outputSchema.parse(cleanedArgs);
552
+ console.warn("[LLMService] Lenient tool_calls parsing succeeded");
553
+ addTokens(input, output);
554
+ return {
555
+ ...validated,
556
+ tokenUsage: { input, output },
557
+ };
558
+ }
559
+ catch {
560
+ // Fall through to raw content parsing
561
+ }
495
562
  }
496
563
  }
497
- return {
498
- ...response.parsed,
499
- tokenUsage: {
500
- input,
501
- output,
502
- },
503
- };
504
- }
505
- catch (error) {
506
- console.error("[LLMService] Error calling LLM:", error);
507
- throw new Error(`LLM service error: ${error instanceof Error ? error.message : "Unknown error"}`);
564
+ // Attempt fallback parsing from raw content
565
+ addParseFallback("raw");
566
+ try {
567
+ console.warn("[LLMService] Attempting fallback JSON parsing");
568
+ const manualParse = JSON.parse(rawContent);
569
+ const validated = params.outputSchema.parse(manualParse);
570
+ console.warn("[LLMService] Fallback parsing succeeded");
571
+ addTokens(input, output);
572
+ return {
573
+ ...validated,
574
+ tokenUsage: { input, output },
575
+ };
576
+ }
577
+ catch (fallbackError) {
578
+ throw new Error(`LLM failed to return structured output. ` +
579
+ `Finish reason: ${finishReason}. ` +
580
+ `Raw content preview: ${rawContent.substring(0, 200)}...` +
581
+ `Fallback parsing error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`);
582
+ }
508
583
  }
584
+ addTokens(input, output);
585
+ return {
586
+ ...response.parsed,
587
+ tokenUsage: {
588
+ input,
589
+ output,
590
+ },
591
+ };
509
592
  }
510
593
  /**
511
594
  * Get session-level token usage statistics
@@ -533,6 +616,7 @@ exports.LLMService = LLMService;
533
616
  exports.LLMService = LLMService = __decorate([
534
617
  (0, common_1.Injectable)(),
535
618
  __metadata("design:paramtypes", [model_service_1.ModelService,
536
- config_1.ConfigService])
619
+ config_1.ConfigService,
620
+ llm_call_dumper_service_1.LLMCallDumper])
537
621
  ], LLMService);
538
622
  //# sourceMappingURL=llm.service.js.map