@n8n/agents 0.1.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 (231) hide show
  1. package/LICENSE.md +88 -0
  2. package/dist/build.tsbuildinfo +1 -0
  3. package/dist/evals/categorization.d.ts +2 -0
  4. package/dist/evals/categorization.js +23 -0
  5. package/dist/evals/categorization.js.map +1 -0
  6. package/dist/evals/contains-keywords.d.ts +2 -0
  7. package/dist/evals/contains-keywords.js +29 -0
  8. package/dist/evals/contains-keywords.js.map +1 -0
  9. package/dist/evals/correctness.d.ts +2 -0
  10. package/dist/evals/correctness.js +28 -0
  11. package/dist/evals/correctness.js.map +1 -0
  12. package/dist/evals/helpfulness.d.ts +2 -0
  13. package/dist/evals/helpfulness.js +26 -0
  14. package/dist/evals/helpfulness.js.map +1 -0
  15. package/dist/evals/index.d.ts +7 -0
  16. package/dist/evals/index.js +18 -0
  17. package/dist/evals/index.js.map +1 -0
  18. package/dist/evals/json-validity.d.ts +2 -0
  19. package/dist/evals/json-validity.js +21 -0
  20. package/dist/evals/json-validity.js.map +1 -0
  21. package/dist/evals/parse-judge-response.d.ts +2 -0
  22. package/dist/evals/parse-judge-response.js +25 -0
  23. package/dist/evals/parse-judge-response.js.map +1 -0
  24. package/dist/evals/string-similarity.d.ts +2 -0
  25. package/dist/evals/string-similarity.js +42 -0
  26. package/dist/evals/string-similarity.js.map +1 -0
  27. package/dist/evals/tool-call-accuracy.d.ts +2 -0
  28. package/dist/evals/tool-call-accuracy.js +29 -0
  29. package/dist/evals/tool-call-accuracy.js.map +1 -0
  30. package/dist/index.d.ts +34 -0
  31. package/dist/index.js +85 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/integrations/langsmith.d.ts +13 -0
  34. package/dist/integrations/langsmith.js +77 -0
  35. package/dist/integrations/langsmith.js.map +1 -0
  36. package/dist/runtime/agent-runtime.d.ts +80 -0
  37. package/dist/runtime/agent-runtime.js +1246 -0
  38. package/dist/runtime/agent-runtime.js.map +1 -0
  39. package/dist/runtime/event-bus.d.ts +14 -0
  40. package/dist/runtime/event-bus.js +53 -0
  41. package/dist/runtime/event-bus.js.map +1 -0
  42. package/dist/runtime/logger.d.ts +22 -0
  43. package/dist/runtime/logger.js +40 -0
  44. package/dist/runtime/logger.js.map +1 -0
  45. package/dist/runtime/mcp-connection.d.ts +23 -0
  46. package/dist/runtime/mcp-connection.js +135 -0
  47. package/dist/runtime/mcp-connection.js.map +1 -0
  48. package/dist/runtime/mcp-tool-resolver.d.ts +7 -0
  49. package/dist/runtime/mcp-tool-resolver.js +64 -0
  50. package/dist/runtime/mcp-tool-resolver.js.map +1 -0
  51. package/dist/runtime/memory-store.d.ts +29 -0
  52. package/dist/runtime/memory-store.js +68 -0
  53. package/dist/runtime/memory-store.js.map +1 -0
  54. package/dist/runtime/message-list.d.ts +25 -0
  55. package/dist/runtime/message-list.js +79 -0
  56. package/dist/runtime/message-list.js.map +1 -0
  57. package/dist/runtime/messages.d.ts +8 -0
  58. package/dist/runtime/messages.js +239 -0
  59. package/dist/runtime/messages.js.map +1 -0
  60. package/dist/runtime/model-factory.d.ts +33 -0
  61. package/dist/runtime/model-factory.js +68 -0
  62. package/dist/runtime/model-factory.js.map +1 -0
  63. package/dist/runtime/run-state.d.ts +9 -0
  64. package/dist/runtime/run-state.js +49 -0
  65. package/dist/runtime/run-state.js.map +1 -0
  66. package/dist/runtime/runtime-helpers.d.ts +21 -0
  67. package/dist/runtime/runtime-helpers.js +96 -0
  68. package/dist/runtime/runtime-helpers.js.map +1 -0
  69. package/dist/runtime/stream.d.ts +15 -0
  70. package/dist/runtime/stream.js +94 -0
  71. package/dist/runtime/stream.js.map +1 -0
  72. package/dist/runtime/strip-orphaned-tool-messages.d.ts +2 -0
  73. package/dist/runtime/strip-orphaned-tool-messages.js +48 -0
  74. package/dist/runtime/strip-orphaned-tool-messages.js.map +1 -0
  75. package/dist/runtime/title-generation.d.ts +11 -0
  76. package/dist/runtime/title-generation.js +56 -0
  77. package/dist/runtime/title-generation.js.map +1 -0
  78. package/dist/runtime/tool-adapter.d.ts +23 -0
  79. package/dist/runtime/tool-adapter.js +104 -0
  80. package/dist/runtime/tool-adapter.js.map +1 -0
  81. package/dist/runtime/working-memory.d.ts +21 -0
  82. package/dist/runtime/working-memory.js +138 -0
  83. package/dist/runtime/working-memory.js.map +1 -0
  84. package/dist/sdk/agent.d.ts +88 -0
  85. package/dist/sdk/agent.js +327 -0
  86. package/dist/sdk/agent.js.map +1 -0
  87. package/dist/sdk/catalog.d.ts +31 -0
  88. package/dist/sdk/catalog.js +80 -0
  89. package/dist/sdk/catalog.js.map +1 -0
  90. package/dist/sdk/eval.d.ts +23 -0
  91. package/dist/sdk/eval.js +99 -0
  92. package/dist/sdk/eval.js.map +1 -0
  93. package/dist/sdk/evaluate.d.ts +13 -0
  94. package/dist/sdk/evaluate.js +84 -0
  95. package/dist/sdk/evaluate.js.map +1 -0
  96. package/dist/sdk/guardrail.d.ts +14 -0
  97. package/dist/sdk/guardrail.js +41 -0
  98. package/dist/sdk/guardrail.js.map +1 -0
  99. package/dist/sdk/mcp-client.d.ts +16 -0
  100. package/dist/sdk/mcp-client.js +128 -0
  101. package/dist/sdk/mcp-client.js.map +1 -0
  102. package/dist/sdk/memory.d.ts +22 -0
  103. package/dist/sdk/memory.js +101 -0
  104. package/dist/sdk/memory.js.map +1 -0
  105. package/dist/sdk/message.d.ts +4 -0
  106. package/dist/sdk/message.js +18 -0
  107. package/dist/sdk/message.js.map +1 -0
  108. package/dist/sdk/network.d.ts +20 -0
  109. package/dist/sdk/network.js +46 -0
  110. package/dist/sdk/network.js.map +1 -0
  111. package/dist/sdk/provider-tools.d.ts +18 -0
  112. package/dist/sdk/provider-tools.js +31 -0
  113. package/dist/sdk/provider-tools.js.map +1 -0
  114. package/dist/sdk/telemetry.d.ts +31 -0
  115. package/dist/sdk/telemetry.js +186 -0
  116. package/dist/sdk/telemetry.js.map +1 -0
  117. package/dist/sdk/tool.d.ts +38 -0
  118. package/dist/sdk/tool.js +143 -0
  119. package/dist/sdk/tool.js.map +1 -0
  120. package/dist/sdk/verify.d.ts +5 -0
  121. package/dist/sdk/verify.js +37 -0
  122. package/dist/sdk/verify.js.map +1 -0
  123. package/dist/storage/postgres-memory.d.ts +79 -0
  124. package/dist/storage/postgres-memory.js +411 -0
  125. package/dist/storage/postgres-memory.js.map +1 -0
  126. package/dist/storage/sqlite-memory.d.ts +60 -0
  127. package/dist/storage/sqlite-memory.js +349 -0
  128. package/dist/storage/sqlite-memory.js.map +1 -0
  129. package/dist/types/index.d.ts +13 -0
  130. package/dist/types/index.js +6 -0
  131. package/dist/types/index.js.map +1 -0
  132. package/dist/types/runtime/event.d.ts +41 -0
  133. package/dist/types/runtime/event.js +14 -0
  134. package/dist/types/runtime/event.js.map +1 -0
  135. package/dist/types/runtime/message-list.d.ts +7 -0
  136. package/dist/types/runtime/message-list.js +3 -0
  137. package/dist/types/runtime/message-list.js.map +1 -0
  138. package/dist/types/sdk/agent.d.ts +174 -0
  139. package/dist/types/sdk/agent.js +3 -0
  140. package/dist/types/sdk/agent.js.map +1 -0
  141. package/dist/types/sdk/eval.d.ts +41 -0
  142. package/dist/types/sdk/eval.js +3 -0
  143. package/dist/types/sdk/eval.js.map +1 -0
  144. package/dist/types/sdk/guardrail.d.ts +9 -0
  145. package/dist/types/sdk/guardrail.js +3 -0
  146. package/dist/types/sdk/guardrail.js.map +1 -0
  147. package/dist/types/sdk/mcp.d.ts +24 -0
  148. package/dist/types/sdk/mcp.js +3 -0
  149. package/dist/types/sdk/mcp.js.map +1 -0
  150. package/dist/types/sdk/memory.d.ts +99 -0
  151. package/dist/types/sdk/memory.js +3 -0
  152. package/dist/types/sdk/memory.js.map +1 -0
  153. package/dist/types/sdk/message.d.ts +79 -0
  154. package/dist/types/sdk/message.js +3 -0
  155. package/dist/types/sdk/message.js.map +1 -0
  156. package/dist/types/sdk/provider.d.ts +16 -0
  157. package/dist/types/sdk/provider.js +3 -0
  158. package/dist/types/sdk/provider.js.map +1 -0
  159. package/dist/types/sdk/tool.d.ts +32 -0
  160. package/dist/types/sdk/tool.js +3 -0
  161. package/dist/types/sdk/tool.js.map +1 -0
  162. package/dist/types/telemetry.d.ts +18 -0
  163. package/dist/types/telemetry.js +3 -0
  164. package/dist/types/telemetry.js.map +1 -0
  165. package/dist/types/utils/json.d.ts +5 -0
  166. package/dist/types/utils/json.js +3 -0
  167. package/dist/types/utils/json.js.map +1 -0
  168. package/dist/utils/zod.d.ts +3 -0
  169. package/dist/utils/zod.js +7 -0
  170. package/dist/utils/zod.js.map +1 -0
  171. package/dist/workspace/filesystem/base-filesystem.d.ts +40 -0
  172. package/dist/workspace/filesystem/base-filesystem.js +99 -0
  173. package/dist/workspace/filesystem/base-filesystem.js.map +1 -0
  174. package/dist/workspace/index.d.ts +8 -0
  175. package/dist/workspace/index.js +17 -0
  176. package/dist/workspace/index.js.map +1 -0
  177. package/dist/workspace/lifecycle.d.ts +13 -0
  178. package/dist/workspace/lifecycle.js +11 -0
  179. package/dist/workspace/lifecycle.js.map +1 -0
  180. package/dist/workspace/process.d.ts +36 -0
  181. package/dist/workspace/process.js +76 -0
  182. package/dist/workspace/process.js.map +1 -0
  183. package/dist/workspace/sandbox/base-sandbox.d.ts +28 -0
  184. package/dist/workspace/sandbox/base-sandbox.js +163 -0
  185. package/dist/workspace/sandbox/base-sandbox.js.map +1 -0
  186. package/dist/workspace/tools/append-file.d.ts +3 -0
  187. package/dist/workspace/tools/append-file.js +22 -0
  188. package/dist/workspace/tools/append-file.js.map +1 -0
  189. package/dist/workspace/tools/copy-file.d.ts +3 -0
  190. package/dist/workspace/tools/copy-file.js +26 -0
  191. package/dist/workspace/tools/copy-file.js.map +1 -0
  192. package/dist/workspace/tools/delete-file.d.ts +3 -0
  193. package/dist/workspace/tools/delete-file.js +26 -0
  194. package/dist/workspace/tools/delete-file.js.map +1 -0
  195. package/dist/workspace/tools/execute-command.d.ts +3 -0
  196. package/dist/workspace/tools/execute-command.js +39 -0
  197. package/dist/workspace/tools/execute-command.js.map +1 -0
  198. package/dist/workspace/tools/file-stat.d.ts +3 -0
  199. package/dist/workspace/tools/file-stat.js +33 -0
  200. package/dist/workspace/tools/file-stat.js.map +1 -0
  201. package/dist/workspace/tools/list-files.d.ts +3 -0
  202. package/dist/workspace/tools/list-files.js +28 -0
  203. package/dist/workspace/tools/list-files.js.map +1 -0
  204. package/dist/workspace/tools/mkdir.d.ts +3 -0
  205. package/dist/workspace/tools/mkdir.js +22 -0
  206. package/dist/workspace/tools/mkdir.js.map +1 -0
  207. package/dist/workspace/tools/move-file.d.ts +3 -0
  208. package/dist/workspace/tools/move-file.js +26 -0
  209. package/dist/workspace/tools/move-file.js.map +1 -0
  210. package/dist/workspace/tools/process-tools.d.ts +4 -0
  211. package/dist/workspace/tools/process-tools.js +37 -0
  212. package/dist/workspace/tools/process-tools.js.map +1 -0
  213. package/dist/workspace/tools/read-file.d.ts +3 -0
  214. package/dist/workspace/tools/read-file.js +24 -0
  215. package/dist/workspace/tools/read-file.js.map +1 -0
  216. package/dist/workspace/tools/rmdir.d.ts +3 -0
  217. package/dist/workspace/tools/rmdir.js +26 -0
  218. package/dist/workspace/tools/rmdir.js.map +1 -0
  219. package/dist/workspace/tools/workspace-tools.d.ts +8 -0
  220. package/dist/workspace/tools/workspace-tools.js +39 -0
  221. package/dist/workspace/tools/workspace-tools.js.map +1 -0
  222. package/dist/workspace/tools/write-file.d.ts +3 -0
  223. package/dist/workspace/tools/write-file.js +26 -0
  224. package/dist/workspace/tools/write-file.js.map +1 -0
  225. package/dist/workspace/types.d.ts +178 -0
  226. package/dist/workspace/types.js +7 -0
  227. package/dist/workspace/types.js.map +1 -0
  228. package/dist/workspace/workspace.d.ts +21 -0
  229. package/dist/workspace/workspace.js +131 -0
  230. package/dist/workspace/workspace.js.map +1 -0
  231. package/package.json +65 -0
@@ -0,0 +1,1246 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.AgentRuntime = void 0;
40
+ const ai_1 = require("ai");
41
+ const ajv_1 = __importDefault(require("ajv"));
42
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
43
+ const catalog_1 = require("../sdk/catalog");
44
+ const message_1 = require("../sdk/message");
45
+ const event_bus_1 = require("./event-bus");
46
+ const logger_1 = require("./logger");
47
+ const memory_store_1 = require("./memory-store");
48
+ const message_list_1 = require("./message-list");
49
+ const messages_1 = require("./messages");
50
+ const model_factory_1 = require("./model-factory");
51
+ const run_state_1 = require("./run-state");
52
+ const runtime_helpers_1 = require("./runtime-helpers");
53
+ const stream_1 = require("./stream");
54
+ const strip_orphaned_tool_messages_1 = require("./strip-orphaned-tool-messages");
55
+ const title_generation_1 = require("./title-generation");
56
+ const tool_adapter_1 = require("./tool-adapter");
57
+ const working_memory_1 = require("./working-memory");
58
+ const zod_1 = require("../utils/zod");
59
+ const logger = (0, logger_1.createFilteredLogger)();
60
+ function isTextPart(part) {
61
+ return (typeof part === 'object' &&
62
+ part !== null &&
63
+ 'type' in part &&
64
+ part.type === 'text' &&
65
+ 'text' in part);
66
+ }
67
+ const MAX_LOOP_ITERATIONS = 20;
68
+ const ajv = new ajv_1.default({ strict: false });
69
+ const EMPTY_MESSAGE_LIST = {
70
+ messages: [],
71
+ historyIds: [],
72
+ inputIds: [],
73
+ responseIds: [],
74
+ };
75
+ class AgentRuntime {
76
+ constructor(config) {
77
+ this.config = config;
78
+ this.runState = new run_state_1.RunStateManager(config.checkpointStorage);
79
+ this.eventBus = config.eventBus ?? new event_bus_1.AgentEventBus();
80
+ this.currentState = {
81
+ persistence: undefined,
82
+ status: 'idle',
83
+ messageList: EMPTY_MESSAGE_LIST,
84
+ pendingToolCalls: {},
85
+ };
86
+ }
87
+ getState() {
88
+ return { ...this.currentState };
89
+ }
90
+ abort() {
91
+ this.eventBus.abort();
92
+ }
93
+ async generate(input, options) {
94
+ const runId = (0, run_state_1.generateRunId)();
95
+ let list = undefined;
96
+ try {
97
+ list = await this.initRun(input, options);
98
+ const rawResult = await this.runGenerateLoop(list, options, undefined, runId);
99
+ return this.finalizeGenerate(rawResult, list, runId);
100
+ }
101
+ catch (error) {
102
+ await this.flushTelemetry(options);
103
+ const isAbort = this.eventBus.isAborted;
104
+ this.updateState({ status: isAbort ? 'cancelled' : 'failed' });
105
+ if (!isAbort) {
106
+ this.eventBus.emit({ type: "error", message: String(error), error });
107
+ }
108
+ return { runId, messages: list?.responseDelta() ?? [], finishReason: 'error', error };
109
+ }
110
+ }
111
+ async stream(input, options) {
112
+ const runId = (0, run_state_1.generateRunId)();
113
+ let list;
114
+ try {
115
+ list = await this.initRun(input, options);
116
+ }
117
+ catch (error) {
118
+ const isAbort = this.eventBus.isAborted;
119
+ this.updateState({ status: isAbort ? 'cancelled' : 'failed' });
120
+ if (!isAbort) {
121
+ this.eventBus.emit({ type: "error", message: String(error), error });
122
+ }
123
+ return { runId, stream: (0, runtime_helpers_1.makeErrorStream)(error) };
124
+ }
125
+ return { runId, stream: this.startStreamLoop(list, options, undefined, runId) };
126
+ }
127
+ async resume(method, data, options) {
128
+ const state = await this.runState.resume(options.runId);
129
+ if (!state)
130
+ throw new Error(`No suspended run found for runId: ${options.runId}`);
131
+ const toolCall = state.pendingToolCalls[options.toolCallId];
132
+ if (!toolCall)
133
+ throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`);
134
+ const tool = this.config.tools?.find((t) => t.name === toolCall.toolName);
135
+ if (!tool)
136
+ throw new Error(`Tool ${toolCall.toolName} not found`);
137
+ let resumeData = data;
138
+ if (tool.resumeSchema) {
139
+ const parseResult = await tool.resumeSchema.safeParseAsync(data);
140
+ if (!parseResult.success) {
141
+ throw new Error(`Invalid resume payload: ${parseResult.error.message}`);
142
+ }
143
+ resumeData = parseResult.data;
144
+ }
145
+ try {
146
+ const list = message_list_1.AgentMessageList.deserialize(state.messageList);
147
+ const { runId: _rid, toolCallId: _tcid, ...callerExecOptions } = options;
148
+ const persisted = state.executionOptions ?? {};
149
+ const mergedExecOptions = {
150
+ ...persisted,
151
+ ...callerExecOptions,
152
+ };
153
+ const resumeOptions = {
154
+ persistence: state.persistence,
155
+ ...mergedExecOptions,
156
+ };
157
+ this.eventBus.resetAbort(resumeOptions.abortSignal);
158
+ const pendingResume = {
159
+ pendingToolCalls: state.pendingToolCalls,
160
+ resumeToolCallId: options.toolCallId,
161
+ resumeData,
162
+ messages: state.messageList.messages,
163
+ };
164
+ await this.ensureModelCost();
165
+ await this.setListWorkingMemoryConfig(list, state.persistence);
166
+ if (method === 'generate') {
167
+ const rawResult = await this.runGenerateLoop(list, resumeOptions, pendingResume, options.runId);
168
+ if (!rawResult.pendingSuspend) {
169
+ await this.cleanupRun(options.runId);
170
+ }
171
+ return this.finalizeGenerate(rawResult, list, options.runId);
172
+ }
173
+ return {
174
+ runId: options.runId,
175
+ stream: this.startStreamLoop(list, resumeOptions, pendingResume, options.runId),
176
+ };
177
+ }
178
+ catch (error) {
179
+ const isAbort = this.eventBus.isAborted;
180
+ this.updateState({ status: isAbort ? 'cancelled' : 'failed' });
181
+ if (!isAbort) {
182
+ this.eventBus.emit({ type: "error", message: String(error), error });
183
+ }
184
+ if (method === 'generate') {
185
+ return {
186
+ runId: options.runId,
187
+ messages: [],
188
+ finishReason: 'error',
189
+ error,
190
+ };
191
+ }
192
+ return { runId: options.runId, stream: (0, runtime_helpers_1.makeErrorStream)(error) };
193
+ }
194
+ }
195
+ async buildMessageList(input, options) {
196
+ const list = new message_list_1.AgentMessageList();
197
+ if (this.config.memory && options?.persistence?.threadId) {
198
+ const memMessages = await this.config.memory.getMessages(options.persistence.threadId, {
199
+ limit: this.config.lastMessages ?? 10,
200
+ });
201
+ if (memMessages.length > 0) {
202
+ list.addHistory((0, strip_orphaned_tool_messages_1.stripOrphanedToolMessages)(memMessages.map(message_1.toDbMessage)));
203
+ }
204
+ }
205
+ if (this.config.semanticRecall && options?.persistence?.threadId) {
206
+ await this.performSemanticRecall(list, input, options.persistence.threadId, options.persistence.resourceId);
207
+ }
208
+ await this.setListWorkingMemoryConfig(list, options?.persistence);
209
+ list.addInput(input);
210
+ return list;
211
+ }
212
+ async performSemanticRecall(list, input, threadId, resourceId) {
213
+ if (!this.config.semanticRecall || !this.config.memory)
214
+ return;
215
+ const userText = input
216
+ .filter((m) => (0, message_1.isLlmMessage)(m) && m.role === 'user')
217
+ .flatMap((m) => ((0, message_1.isLlmMessage)(m) ? m.content : []))
218
+ .filter((c) => c.type === 'text')
219
+ .map((c) => c.text)
220
+ .join(' ');
221
+ if (!userText)
222
+ return;
223
+ let recalled = [];
224
+ if (this.config.memory.queryEmbeddings && this.config.semanticRecall.embedder) {
225
+ const { embed } = await Promise.resolve().then(() => __importStar(require('ai')));
226
+ const embeddingModel = (0, model_factory_1.createEmbeddingModel)(this.config.semanticRecall.embedder, this.config.semanticRecall.apiKey);
227
+ const { embedding } = await embed({ model: embeddingModel, value: userText });
228
+ const hits = await this.config.memory.queryEmbeddings({
229
+ scope: this.config.semanticRecall.scope ?? 'resource',
230
+ threadId,
231
+ resourceId,
232
+ vector: embedding,
233
+ topK: this.config.semanticRecall.topK,
234
+ });
235
+ if (hits.length > 0) {
236
+ const hitIds = new Set(hits.map((h) => h.id));
237
+ const allMsgs = await this.config.memory.getMessages(threadId);
238
+ if (this.config.semanticRecall.messageRange) {
239
+ recalled = this.expandMessageRange(allMsgs, hitIds, this.config.semanticRecall.messageRange);
240
+ }
241
+ else {
242
+ recalled = allMsgs.filter((m) => {
243
+ const id = 'id' in m && typeof m.id === 'string' ? m.id : undefined;
244
+ return id !== undefined && hitIds.has(id);
245
+ });
246
+ }
247
+ }
248
+ }
249
+ else if (this.config.memory.search) {
250
+ recalled = await this.config.memory.search(userText, {
251
+ threadId,
252
+ resourceId,
253
+ topK: this.config.semanticRecall.topK,
254
+ messageRange: this.config.semanticRecall.messageRange,
255
+ });
256
+ }
257
+ if (recalled.length === 0)
258
+ return;
259
+ const { historyIds } = list.serialize();
260
+ const historyIdSet = new Set(historyIds);
261
+ const newRecalled = recalled
262
+ .filter((m) => {
263
+ const id = 'id' in m && typeof m.id === 'string' ? m.id : undefined;
264
+ return !id || !historyIdSet.has(id);
265
+ })
266
+ .map(message_1.toDbMessage);
267
+ if (newRecalled.length > 0) {
268
+ list.addHistory(newRecalled);
269
+ }
270
+ }
271
+ expandMessageRange(allMsgs, hitIds, range) {
272
+ const expandedIds = new Set();
273
+ for (const msg of allMsgs) {
274
+ const id = 'id' in msg && typeof msg.id === 'string' ? msg.id : undefined;
275
+ if (!id || !hitIds.has(id))
276
+ continue;
277
+ const idx = allMsgs.indexOf(msg);
278
+ const start = Math.max(0, idx - (range.before ?? 0));
279
+ const end = Math.min(allMsgs.length - 1, idx + (range.after ?? 0));
280
+ for (let i = start; i <= end; i++) {
281
+ const el = allMsgs[i];
282
+ const mid = 'id' in el && typeof el.id === 'string' ? el.id : undefined;
283
+ if (mid)
284
+ expandedIds.add(mid);
285
+ }
286
+ }
287
+ return allMsgs.filter((m) => {
288
+ const mid = 'id' in m && typeof m.id === 'string' ? m.id : undefined;
289
+ return mid && expandedIds.has(mid);
290
+ });
291
+ }
292
+ async initRun(input, options) {
293
+ this.eventBus.resetAbort(options?.abortSignal);
294
+ this.updateState({
295
+ status: 'running',
296
+ persistence: options?.persistence,
297
+ });
298
+ this.eventBus.emit({ type: "agent_start" });
299
+ await this.ensureModelCost();
300
+ const normalizedInput = (0, runtime_helpers_1.normalizeInput)(input);
301
+ return await this.buildMessageList(normalizedInput, options);
302
+ }
303
+ finalizeGenerate(result, list, runId) {
304
+ result.runId = runId;
305
+ result.usage = this.applyCost(result.usage);
306
+ result.model = this.modelIdString;
307
+ const finalized = (0, runtime_helpers_1.applySubAgentUsage)(result);
308
+ this.updateState({ status: 'success', messageList: list.serialize() });
309
+ this.eventBus.emit({ type: "agent_end", messages: finalized.messages });
310
+ return finalized;
311
+ }
312
+ resolveTelemetry(options) {
313
+ if (this.config.telemetry)
314
+ return this.config.telemetry;
315
+ const inherited = options?.telemetry;
316
+ if (!inherited)
317
+ return undefined;
318
+ return { ...inherited, functionId: this.config.name };
319
+ }
320
+ async flushTelemetry(options) {
321
+ try {
322
+ const resolved = this.resolveTelemetry(options);
323
+ if (resolved?.provider) {
324
+ await resolved.provider.forceFlush();
325
+ }
326
+ }
327
+ catch {
328
+ }
329
+ }
330
+ buildTelemetryOptions(options) {
331
+ const t = this.resolveTelemetry(options);
332
+ if (!t?.enabled)
333
+ return {};
334
+ return {
335
+ experimental_telemetry: {
336
+ isEnabled: true,
337
+ functionId: t.functionId ?? this.config.name,
338
+ metadata: t.metadata,
339
+ recordInputs: t.recordInputs,
340
+ recordOutputs: t.recordOutputs,
341
+ tracer: t.tracer,
342
+ integrations: t.integrations.length > 0 ? t.integrations : undefined,
343
+ },
344
+ };
345
+ }
346
+ async runGenerateLoop(list, options, pendingResume, runId) {
347
+ const { model, toolMap, aiTools, providerOptions, hasTools, outputSpec } = this.buildLoopContext(options);
348
+ let totalUsage;
349
+ let lastFinishReason = 'stop';
350
+ let structuredOutput;
351
+ const toolCallSummary = [];
352
+ const collectedSubAgentUsage = [];
353
+ const runTelemetry = this.resolveTelemetry(options);
354
+ if (pendingResume) {
355
+ const batch = await this.iteratePendingToolCallsConcurrent(pendingResume, toolMap, list, runTelemetry);
356
+ for (const r of batch.results) {
357
+ toolCallSummary.push(r.toolEntry);
358
+ if (r.subAgentUsage)
359
+ collectedSubAgentUsage.push(...r.subAgentUsage);
360
+ }
361
+ if (Object.keys(batch.pending).length > 0) {
362
+ const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
363
+ return {
364
+ runId: suspendRunId,
365
+ messages: list.responseDelta(),
366
+ finishReason: 'tool-calls',
367
+ usage: totalUsage,
368
+ pendingSuspend: batch.suspensions.map((s) => ({
369
+ runId: suspendRunId,
370
+ toolCallId: s.toolCallId,
371
+ toolName: s.toolName,
372
+ input: s.input,
373
+ suspendPayload: s.payload,
374
+ resumeSchema: s.resumeSchema,
375
+ })),
376
+ };
377
+ }
378
+ }
379
+ const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS;
380
+ for (let i = 0; i < maxIterations; i++) {
381
+ if (this.eventBus.isAborted) {
382
+ this.updateState({ status: 'cancelled' });
383
+ throw new Error('Agent run was aborted');
384
+ }
385
+ this.eventBus.emit({ type: "turn_start" });
386
+ const result = await (0, ai_1.generateText)({
387
+ model,
388
+ messages: list.forLlm(this.config.instructions, this.config.instructionProviderOptions),
389
+ abortSignal: this.eventBus.signal,
390
+ ...(hasTools ? { tools: aiTools } : {}),
391
+ ...(providerOptions
392
+ ? { providerOptions: providerOptions }
393
+ : {}),
394
+ ...(outputSpec ? { output: outputSpec } : {}),
395
+ ...this.buildTelemetryOptions(options),
396
+ });
397
+ const aiFinishReason = result.finishReason;
398
+ lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
399
+ totalUsage = (0, runtime_helpers_1.accumulateUsage)(totalUsage, result.usage);
400
+ const responseMessages = result.response.messages;
401
+ const newMessages = (0, messages_1.fromAiMessages)(responseMessages);
402
+ list.addResponse(newMessages);
403
+ if (aiFinishReason !== 'tool-calls') {
404
+ if (outputSpec) {
405
+ structuredOutput = result.output;
406
+ }
407
+ this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractToolResults)(newMessages));
408
+ break;
409
+ }
410
+ const batch = await this.iterateToolCallsConcurrent(result.toolCalls, toolMap, list, runTelemetry);
411
+ for (const r of batch.results) {
412
+ toolCallSummary.push(r.toolEntry);
413
+ if (r.subAgentUsage)
414
+ collectedSubAgentUsage.push(...r.subAgentUsage);
415
+ }
416
+ if (Object.keys(batch.pending).length > 0) {
417
+ const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
418
+ return {
419
+ runId: suspendRunId,
420
+ messages: list.responseDelta(),
421
+ finishReason: 'tool-calls',
422
+ usage: totalUsage,
423
+ pendingSuspend: batch.suspensions.map((s) => ({
424
+ runId: suspendRunId,
425
+ toolCallId: s.toolCallId,
426
+ toolName: s.toolName,
427
+ input: s.input,
428
+ suspendPayload: s.payload,
429
+ resumeSchema: s.resumeSchema,
430
+ })),
431
+ };
432
+ }
433
+ this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractToolResults)(list.responseDelta()));
434
+ }
435
+ if (lastFinishReason === 'tool-calls') {
436
+ throw new Error(`Agent loop exceeded ${maxIterations} iterations without reaching a stop condition`);
437
+ }
438
+ if (this.config.workingMemory &&
439
+ this.config.memory?.saveWorkingMemory &&
440
+ options?.persistence) {
441
+ this.extractAndPersistWorkingMemory(list, {
442
+ threadId: options.persistence.threadId,
443
+ resourceId: options.persistence.resourceId,
444
+ scope: this.config.workingMemory?.scope ?? 'resource',
445
+ });
446
+ }
447
+ await this.saveToMemory(list, options);
448
+ await this.flushTelemetry(options);
449
+ if (this.config.titleGeneration && options?.persistence?.threadId && this.config.memory) {
450
+ void (0, title_generation_1.generateThreadTitle)({
451
+ memory: this.config.memory,
452
+ threadId: options.persistence.threadId,
453
+ resourceId: options.persistence.resourceId,
454
+ titleConfig: this.config.titleGeneration,
455
+ agentModel: this.config.model,
456
+ turnDelta: list.turnDelta(),
457
+ });
458
+ }
459
+ return {
460
+ runId: runId ?? '',
461
+ messages: list.responseDelta(),
462
+ finishReason: lastFinishReason,
463
+ usage: totalUsage,
464
+ ...(structuredOutput !== undefined && { structuredOutput }),
465
+ ...(toolCallSummary.length > 0 && { toolCalls: toolCallSummary }),
466
+ ...(collectedSubAgentUsage.length > 0 && { subAgentUsage: collectedSubAgentUsage }),
467
+ };
468
+ }
469
+ startStreamLoop(list, options, pendingResume, runId) {
470
+ const { readable, writable } = new TransformStream();
471
+ const writer = writable.getWriter();
472
+ this.runStreamLoop(list, options, writer, pendingResume, runId).catch(async (error) => {
473
+ await this.flushTelemetry(options);
474
+ await this.cleanupRun(runId);
475
+ try {
476
+ await writer.write({ type: 'error', error });
477
+ await writer.write({ type: 'finish', finishReason: 'error' });
478
+ await writer.close();
479
+ }
480
+ catch {
481
+ writer.abort(error).catch(() => { });
482
+ }
483
+ });
484
+ return readable;
485
+ }
486
+ async runStreamLoop(list, options, writer, pendingResume, runId) {
487
+ const { model, toolMap, aiTools, providerOptions, hasTools, outputSpec } = this.buildLoopContext(options);
488
+ const wmParamsStream = this.resolveWorkingMemoryParams(options?.persistence);
489
+ const wmFilter = wmParamsStream?.persistFn
490
+ ? new working_memory_1.WorkingMemoryStreamFilter(writer, async (content) => {
491
+ await wmParamsStream.persistFn(content);
492
+ })
493
+ : undefined;
494
+ const writeChunk = async (chunk) => {
495
+ if (wmFilter) {
496
+ await wmFilter.write(chunk);
497
+ }
498
+ else {
499
+ await writer.write(chunk);
500
+ }
501
+ };
502
+ let totalUsage;
503
+ let lastFinishReason = 'stop';
504
+ let structuredOutput;
505
+ const collectedSubAgentUsage = [];
506
+ const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS;
507
+ const closeStreamWithError = async (error, status) => {
508
+ await this.cleanupRun(runId);
509
+ this.updateState({ status });
510
+ if (wmFilter)
511
+ await wmFilter.flush();
512
+ await writer.write({ type: 'error', error });
513
+ await writer.write({ type: 'finish', finishReason: 'error' });
514
+ await writer.close();
515
+ };
516
+ const handleAbort = async () => {
517
+ if (!this.eventBus.isAborted)
518
+ return false;
519
+ await closeStreamWithError(new Error('Agent run was aborted'), 'cancelled');
520
+ return true;
521
+ };
522
+ const runTelemetry = this.resolveTelemetry(options);
523
+ if (pendingResume) {
524
+ try {
525
+ const batch = await this.iteratePendingToolCallsConcurrent(pendingResume, toolMap, list, runTelemetry);
526
+ for (const r of batch.results) {
527
+ if (r.subAgentUsage)
528
+ collectedSubAgentUsage.push(...r.subAgentUsage);
529
+ await writer.write({
530
+ type: 'message',
531
+ message: r.message,
532
+ });
533
+ if (r.customMessage) {
534
+ await writer.write({ type: 'message', message: r.customMessage });
535
+ }
536
+ }
537
+ for (const e of batch.errors) {
538
+ await writer.write({
539
+ type: 'message',
540
+ message: e.message,
541
+ });
542
+ }
543
+ if (Object.keys(batch.pending).length > 0) {
544
+ const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
545
+ for (const s of batch.suspensions) {
546
+ await writer.write({
547
+ type: 'tool-call-suspended',
548
+ runId: suspendRunId,
549
+ toolCallId: s.toolCallId,
550
+ toolName: s.toolName,
551
+ input: s.input,
552
+ suspendPayload: s.payload,
553
+ resumeSchema: s.resumeSchema,
554
+ });
555
+ }
556
+ await writer.write({ type: 'finish', finishReason: 'tool-calls' });
557
+ await writer.close();
558
+ return;
559
+ }
560
+ }
561
+ catch (error) {
562
+ this.eventBus.emit({ type: "error", message: String(error), error });
563
+ await closeStreamWithError(error, 'failed');
564
+ return;
565
+ }
566
+ }
567
+ for (let i = 0; i < maxIterations; i++) {
568
+ if (await handleAbort())
569
+ return;
570
+ this.eventBus.emit({ type: "turn_start" });
571
+ const result = (0, ai_1.streamText)({
572
+ model,
573
+ messages: list.forLlm(this.config.instructions, this.config.instructionProviderOptions),
574
+ abortSignal: this.eventBus.signal,
575
+ ...(hasTools ? { tools: aiTools } : {}),
576
+ ...(providerOptions
577
+ ? { providerOptions: providerOptions }
578
+ : {}),
579
+ ...(outputSpec ? { output: outputSpec } : {}),
580
+ ...this.buildTelemetryOptions(options),
581
+ });
582
+ try {
583
+ for await (const chunk of result.fullStream) {
584
+ if (chunk.type === 'finish' || chunk.type === 'finish-step')
585
+ continue;
586
+ const converted = (0, stream_1.convertChunk)(chunk);
587
+ if (converted)
588
+ await writeChunk(converted);
589
+ }
590
+ }
591
+ catch (streamError) {
592
+ if (await handleAbort())
593
+ return;
594
+ this.eventBus.emit({
595
+ type: "error",
596
+ message: String(streamError),
597
+ error: streamError,
598
+ });
599
+ await closeStreamWithError(streamError, 'failed');
600
+ return;
601
+ }
602
+ if (await handleAbort())
603
+ return;
604
+ const aiFinishReason = await result.finishReason;
605
+ const usage = await result.usage;
606
+ const response = await result.response;
607
+ lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
608
+ totalUsage = (0, runtime_helpers_1.accumulateUsage)(totalUsage, usage);
609
+ const responseMessages = response.messages;
610
+ const newMessages = (0, messages_1.fromAiMessages)(responseMessages);
611
+ list.addResponse(newMessages);
612
+ if (aiFinishReason !== 'tool-calls') {
613
+ if (outputSpec) {
614
+ structuredOutput = await result.output;
615
+ }
616
+ this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractToolResults)(newMessages));
617
+ break;
618
+ }
619
+ const toolCalls = await result.toolCalls;
620
+ try {
621
+ const batch = await this.iterateToolCallsConcurrent(toolCalls, toolMap, list, runTelemetry);
622
+ if (await handleAbort())
623
+ return;
624
+ for (const r of batch.results) {
625
+ if (r.subAgentUsage)
626
+ collectedSubAgentUsage.push(...r.subAgentUsage);
627
+ await writer.write({
628
+ type: 'message',
629
+ message: r.message,
630
+ });
631
+ if (r.customMessage) {
632
+ await writer.write({ type: 'message', message: r.customMessage });
633
+ }
634
+ }
635
+ for (const e of batch.errors) {
636
+ await writer.write({
637
+ type: 'message',
638
+ message: e.message,
639
+ });
640
+ }
641
+ if (Object.keys(batch.pending).length > 0) {
642
+ const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
643
+ for (const s of batch.suspensions) {
644
+ await writer.write({
645
+ type: 'tool-call-suspended',
646
+ runId: suspendRunId,
647
+ toolCallId: s.toolCallId,
648
+ toolName: s.toolName,
649
+ input: s.input,
650
+ suspendPayload: s.payload,
651
+ resumeSchema: s.resumeSchema,
652
+ });
653
+ }
654
+ await writer.write({ type: 'finish', finishReason: 'tool-calls' });
655
+ await writer.close();
656
+ return;
657
+ }
658
+ }
659
+ catch (error) {
660
+ this.eventBus.emit({ type: "error", message: String(error), error });
661
+ await closeStreamWithError(error, 'failed');
662
+ return;
663
+ }
664
+ this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractToolResults)(list.responseDelta()));
665
+ }
666
+ if (wmFilter)
667
+ await wmFilter.flush();
668
+ const costUsage = this.applyCost(totalUsage);
669
+ const parentCost = costUsage?.cost ?? 0;
670
+ const subCost = collectedSubAgentUsage.reduce((sum, s) => sum + (s.usage.cost ?? 0), 0);
671
+ await writer.write({
672
+ type: 'finish',
673
+ finishReason: lastFinishReason,
674
+ ...(costUsage && { usage: costUsage }),
675
+ model: this.modelIdString,
676
+ ...(structuredOutput !== undefined && { structuredOutput }),
677
+ ...(collectedSubAgentUsage.length > 0 && {
678
+ subAgentUsage: collectedSubAgentUsage,
679
+ totalCost: parentCost + subCost,
680
+ }),
681
+ });
682
+ try {
683
+ if (this.config.workingMemory &&
684
+ this.config.memory?.saveWorkingMemory &&
685
+ options?.persistence) {
686
+ this.extractAndPersistWorkingMemory(list, {
687
+ threadId: options.persistence.threadId,
688
+ resourceId: options.persistence.resourceId,
689
+ scope: this.config.workingMemory?.scope ?? 'resource',
690
+ });
691
+ }
692
+ await this.saveToMemory(list, options);
693
+ if (this.config.titleGeneration && options?.persistence && this.config.memory) {
694
+ void (0, title_generation_1.generateThreadTitle)({
695
+ memory: this.config.memory,
696
+ threadId: options.persistence.threadId,
697
+ resourceId: options.persistence.resourceId,
698
+ titleConfig: this.config.titleGeneration,
699
+ agentModel: this.config.model,
700
+ turnDelta: list.turnDelta(),
701
+ });
702
+ }
703
+ await this.cleanupRun(runId);
704
+ await this.flushTelemetry(options);
705
+ this.updateState({ status: 'success', messageList: list.serialize() });
706
+ this.eventBus.emit({ type: "agent_end", messages: list.responseDelta() });
707
+ }
708
+ finally {
709
+ await writer.close();
710
+ }
711
+ }
712
+ async saveToMemory(list, options) {
713
+ if (!this.config.memory || !options?.persistence)
714
+ return;
715
+ const delta = list.turnDelta();
716
+ if (delta.length === 0)
717
+ return;
718
+ await (0, memory_store_1.saveMessagesToThread)(this.config.memory, options.persistence.threadId, options.persistence.resourceId, delta);
719
+ if (this.config.semanticRecall?.embedder && this.config.memory.saveEmbeddings) {
720
+ await this.saveEmbeddingsForMessages(options.persistence.threadId, options.persistence.resourceId, delta);
721
+ }
722
+ }
723
+ async saveEmbeddingsForMessages(threadId, resourceId, messages) {
724
+ const embeddable = [];
725
+ for (const msg of messages) {
726
+ if (!(0, message_1.isLlmMessage)(msg) || (msg.role !== 'user' && msg.role !== 'assistant'))
727
+ continue;
728
+ const text = msg.content
729
+ .filter((c) => c.type === 'text')
730
+ .map((c) => c.text)
731
+ .join('\n');
732
+ if (!text)
733
+ continue;
734
+ embeddable.push({ id: msg.id, text });
735
+ }
736
+ if (embeddable.length === 0)
737
+ return;
738
+ const embedder = this.config.semanticRecall?.embedder;
739
+ if (!embedder)
740
+ return;
741
+ const { embedMany } = await Promise.resolve().then(() => __importStar(require('ai')));
742
+ const embeddingModel = (0, model_factory_1.createEmbeddingModel)(embedder, this.config.semanticRecall?.apiKey);
743
+ const { embeddings } = await embedMany({
744
+ model: embeddingModel,
745
+ values: embeddable.map((e) => e.text),
746
+ });
747
+ await this.config.memory.saveEmbeddings({
748
+ scope: this.config.semanticRecall?.scope ?? 'resource',
749
+ threadId,
750
+ resourceId,
751
+ entries: embeddable.map((e, i) => ({
752
+ id: e.id,
753
+ vector: embeddings[i],
754
+ text: e.text,
755
+ model: embedder,
756
+ })),
757
+ });
758
+ }
759
+ extractAndPersistWorkingMemory(list, params) {
760
+ const delta = list.responseDelta();
761
+ for (let i = delta.length - 1; i >= 0; i--) {
762
+ const msg = delta[i];
763
+ if (!(0, message_1.isLlmMessage)(msg) || msg.role !== 'assistant')
764
+ continue;
765
+ for (const part of msg.content) {
766
+ if (!isTextPart(part))
767
+ continue;
768
+ const { cleanText, workingMemory } = (0, working_memory_1.parseWorkingMemory)(part.text);
769
+ if (workingMemory !== null) {
770
+ if (this.config.workingMemory?.structured && this.config.workingMemory.schema) {
771
+ try {
772
+ this.config.workingMemory.schema.parse(JSON.parse(workingMemory));
773
+ }
774
+ catch {
775
+ part.text = cleanText;
776
+ return;
777
+ }
778
+ }
779
+ part.text = cleanText;
780
+ this.config.memory.saveWorkingMemory(params, workingMemory).catch((error) => {
781
+ logger.warn('Failed to persist working memory', { error });
782
+ });
783
+ }
784
+ return;
785
+ }
786
+ }
787
+ }
788
+ buildThinkingProviderOptions() {
789
+ if (!this.config.thinking)
790
+ return undefined;
791
+ const provider = this.modelIdString.split('/')[0];
792
+ const thinking = this.config.thinking;
793
+ switch (provider) {
794
+ case 'anthropic': {
795
+ const cfg = thinking;
796
+ return {
797
+ anthropic: {
798
+ thinking: {
799
+ type: 'enabled',
800
+ budgetTokens: cfg.budgetTokens ?? 10000,
801
+ },
802
+ },
803
+ };
804
+ }
805
+ case 'openai': {
806
+ const cfg = thinking;
807
+ return { openai: { reasoningEffort: cfg.reasoningEffort ?? 'medium' } };
808
+ }
809
+ case 'google': {
810
+ const cfg = thinking;
811
+ return {
812
+ google: {
813
+ thinkingConfig: {
814
+ ...(cfg.thinkingBudget !== undefined && { thinkingBudget: cfg.thinkingBudget }),
815
+ ...(cfg.thinkingLevel !== undefined && { thinkingLevel: cfg.thinkingLevel }),
816
+ },
817
+ },
818
+ };
819
+ }
820
+ case 'xai': {
821
+ const cfg = thinking;
822
+ return { xai: { reasoningEffort: cfg.reasoningEffort ?? 'high' } };
823
+ }
824
+ default:
825
+ return undefined;
826
+ }
827
+ }
828
+ buildCallProviderOptions(runProviderOptions) {
829
+ const thinkingOpts = this.buildThinkingProviderOptions();
830
+ if (!thinkingOpts && !runProviderOptions)
831
+ return undefined;
832
+ if (!thinkingOpts)
833
+ return runProviderOptions;
834
+ if (!runProviderOptions)
835
+ return thinkingOpts;
836
+ const merged = { ...thinkingOpts };
837
+ for (const [provider, opts] of Object.entries(runProviderOptions)) {
838
+ if (provider in merged) {
839
+ merged[provider] = { ...merged[provider], ...opts };
840
+ }
841
+ else {
842
+ merged[provider] = opts;
843
+ }
844
+ }
845
+ return merged;
846
+ }
847
+ async iterateToolCallsConcurrent(toolCalls, toolMap, list, resolvedTelemetry) {
848
+ const executableCalls = toolCalls.filter((tc) => !tc.providerExecuted);
849
+ const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc]));
850
+ const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId));
851
+ const batchSize = this.concurrency;
852
+ const results = [];
853
+ const suspensions = [];
854
+ const errors = [];
855
+ const pending = {};
856
+ for (let batchStart = 0; batchStart < executableCalls.length; batchStart += batchSize) {
857
+ if (this.eventBus.isAborted) {
858
+ this.updateState({ status: 'cancelled' });
859
+ throw new Error('Agent run was aborted');
860
+ }
861
+ const batch = executableCalls.slice(batchStart, batchStart + batchSize);
862
+ const settledResults = await Promise.allSettled(batch.map(async (tc) => await this.processToolCall(tc.toolCallId, tc.toolName, tc.input, toolMap, list, undefined, resolvedTelemetry)));
863
+ for (const tc of batch) {
864
+ unexecutedIds.delete(tc.toolCallId);
865
+ }
866
+ let hasSuspension = false;
867
+ for (let i = 0; i < settledResults.length; i++) {
868
+ const result = settledResults[i];
869
+ const tc = batch[i];
870
+ const toolInput = tc.input;
871
+ if (result.status === 'rejected') {
872
+ errors.push({
873
+ toolCallId: tc.toolCallId,
874
+ toolName: tc.toolName,
875
+ input: toolInput,
876
+ error: result.reason,
877
+ message: (0, runtime_helpers_1.makeErrorToolResultMessage)(tc.toolCallId, tc.toolName, result.reason),
878
+ });
879
+ }
880
+ else if (result.value.outcome === 'suspended') {
881
+ hasSuspension = true;
882
+ suspensions.push({
883
+ toolCallId: tc.toolCallId,
884
+ toolName: tc.toolName,
885
+ input: toolInput,
886
+ payload: result.value.payload,
887
+ resumeSchema: result.value.resumeSchema,
888
+ });
889
+ pending[tc.toolCallId] = {
890
+ suspended: true,
891
+ toolCallId: tc.toolCallId,
892
+ toolName: tc.toolName,
893
+ input: toolInput,
894
+ suspendPayload: result.value.payload,
895
+ resumeSchema: result.value.resumeSchema,
896
+ };
897
+ }
898
+ else if (result.value.outcome === 'success') {
899
+ results.push({
900
+ toolCallId: tc.toolCallId,
901
+ toolName: tc.toolName,
902
+ input: toolInput,
903
+ toolEntry: result.value.toolEntry,
904
+ subAgentUsage: result.value.subAgentUsage,
905
+ customMessage: result.value.customMessage,
906
+ message: result.value.message,
907
+ });
908
+ }
909
+ else if (result.value.outcome === 'error') {
910
+ errors.push({
911
+ toolCallId: tc.toolCallId,
912
+ toolName: tc.toolName,
913
+ input: toolInput,
914
+ error: result.value.error,
915
+ message: result.value.message,
916
+ });
917
+ }
918
+ else if (result.value.outcome === 'noop') {
919
+ }
920
+ }
921
+ if (hasSuspension) {
922
+ for (const id of unexecutedIds) {
923
+ const tc = executableCallsById.get(id);
924
+ pending[tc.toolCallId] = {
925
+ suspended: false,
926
+ toolCallId: tc.toolCallId,
927
+ toolName: tc.toolName,
928
+ input: tc.input,
929
+ };
930
+ }
931
+ break;
932
+ }
933
+ }
934
+ return { results, suspensions, errors, pending };
935
+ }
936
+ async iteratePendingToolCallsConcurrent(pendingResume, toolMap, list, resolvedTelemetry) {
937
+ const resumedId = pendingResume.resumeToolCallId;
938
+ const resumedEntry = pendingResume.pendingToolCalls[resumedId];
939
+ if (!resumedEntry) {
940
+ throw new Error(`No pending tool call found for toolCallId: ${resumedId}`);
941
+ }
942
+ const resumedToolName = resumedEntry.toolName;
943
+ const results = [];
944
+ const suspensions = [];
945
+ const errors = [];
946
+ const pending = {};
947
+ const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, pendingResume.resumeData, resolvedTelemetry);
948
+ if (processResult.outcome === 'suspended') {
949
+ pending[resumedId] = {
950
+ ...resumedEntry,
951
+ suspended: true,
952
+ suspendPayload: processResult.payload,
953
+ resumeSchema: processResult.resumeSchema,
954
+ };
955
+ suspensions.push({
956
+ toolCallId: resumedId,
957
+ toolName: resumedToolName,
958
+ input: resumedEntry.input,
959
+ payload: processResult.payload,
960
+ resumeSchema: processResult.resumeSchema,
961
+ });
962
+ }
963
+ else if (processResult.outcome === 'success') {
964
+ results.push({
965
+ toolCallId: resumedEntry.toolCallId,
966
+ toolName: resumedToolName,
967
+ input: resumedEntry.input,
968
+ toolEntry: processResult.toolEntry,
969
+ subAgentUsage: processResult.subAgentUsage,
970
+ customMessage: processResult.customMessage,
971
+ message: processResult.message,
972
+ });
973
+ }
974
+ else if (processResult.outcome === 'error') {
975
+ errors.push({
976
+ toolCallId: resumedEntry.toolCallId,
977
+ toolName: resumedToolName,
978
+ input: resumedEntry.input,
979
+ error: processResult.error,
980
+ message: processResult.message,
981
+ });
982
+ }
983
+ else if (processResult.outcome === 'noop') {
984
+ }
985
+ const unexecuted = [];
986
+ for (const [id, entry] of Object.entries(pendingResume.pendingToolCalls)) {
987
+ if (id === resumedId)
988
+ continue;
989
+ const entryToolName = entry.toolName;
990
+ if (entry.suspended) {
991
+ pending[id] = entry;
992
+ suspensions.push({
993
+ toolCallId: id,
994
+ toolName: entryToolName,
995
+ input: entry.input,
996
+ payload: entry.suspendPayload,
997
+ resumeSchema: entry.resumeSchema,
998
+ });
999
+ }
1000
+ else {
1001
+ unexecuted.push({
1002
+ toolCallId: id,
1003
+ toolName: entryToolName,
1004
+ input: entry.input,
1005
+ });
1006
+ }
1007
+ }
1008
+ if (unexecuted.length > 0) {
1009
+ const batch = await this.iterateToolCallsConcurrent(unexecuted, toolMap, list, resolvedTelemetry);
1010
+ results.push(...batch.results);
1011
+ suspensions.push(...batch.suspensions);
1012
+ errors.push(...batch.errors);
1013
+ Object.assign(pending, batch.pending);
1014
+ }
1015
+ return { results, suspensions, errors, pending };
1016
+ }
1017
+ async processToolCall(toolCallId, toolName, toolInput, toolMap, list, resumeData, resolvedTelemetry) {
1018
+ const builtTool = toolMap.get(toolName);
1019
+ this.eventBus.emit({
1020
+ type: "tool_execution_start",
1021
+ toolCallId,
1022
+ toolName,
1023
+ args: toolInput,
1024
+ });
1025
+ const makeToolError = (error) => {
1026
+ this.eventBus.emit({
1027
+ type: "tool_execution_end",
1028
+ toolCallId,
1029
+ toolName,
1030
+ result: error,
1031
+ isError: true,
1032
+ });
1033
+ const errorMsg = (0, runtime_helpers_1.makeErrorToolResultMessage)(toolCallId, toolName, error);
1034
+ list.addResponse([errorMsg]);
1035
+ return { outcome: 'error', error, message: errorMsg };
1036
+ };
1037
+ if (!builtTool) {
1038
+ return makeToolError(new Error(`Tool ${toolName} not found`));
1039
+ }
1040
+ const existingToolResults = list
1041
+ .responseDelta()
1042
+ .filter((m) => (0, message_1.isLlmMessage)(m) && m.role === 'tool')
1043
+ .flatMap((m) => m.content.filter((content) => content.type === 'tool-result'));
1044
+ const existingToolResult = existingToolResults.find((r) => r.toolCallId === toolCallId);
1045
+ if (existingToolResult) {
1046
+ this.eventBus.emit({
1047
+ type: "tool_execution_end",
1048
+ toolCallId,
1049
+ toolName,
1050
+ result: existingToolResult.result,
1051
+ isError: !!existingToolResult.isError,
1052
+ });
1053
+ return { outcome: 'noop' };
1054
+ }
1055
+ if (builtTool.inputSchema) {
1056
+ if ((0, zod_1.isZodSchema)(builtTool.inputSchema)) {
1057
+ const result = await builtTool.inputSchema.safeParseAsync(toolInput);
1058
+ if (!result.success) {
1059
+ return makeToolError(new Error(`Invalid tool input: ${result.error.message}`));
1060
+ }
1061
+ toolInput = result.data;
1062
+ }
1063
+ else {
1064
+ const validate = ajv.compile(builtTool.inputSchema);
1065
+ const valid = validate(toolInput);
1066
+ if (!valid) {
1067
+ const message = ajv.errorsText(validate.errors);
1068
+ return makeToolError(new Error(`Invalid tool input: ${message}`));
1069
+ }
1070
+ }
1071
+ }
1072
+ let toolResult;
1073
+ try {
1074
+ toolResult = await (0, tool_adapter_1.executeTool)(toolInput, builtTool, resumeData, resolvedTelemetry);
1075
+ }
1076
+ catch (error) {
1077
+ return makeToolError(error);
1078
+ }
1079
+ if ((0, tool_adapter_1.isSuspendedToolResult)(toolResult)) {
1080
+ if (builtTool?.suspendSchema) {
1081
+ const parseResult = await builtTool.suspendSchema.safeParseAsync(toolResult.payload);
1082
+ if (!parseResult.success) {
1083
+ return makeToolError(new Error(`Invalid suspend payload: ${parseResult.error.message}`));
1084
+ }
1085
+ toolResult.payload = parseResult.data;
1086
+ }
1087
+ if (!builtTool?.resumeSchema) {
1088
+ const error = new Error(`Tool ${toolName} has no resume schema`);
1089
+ return makeToolError(error);
1090
+ }
1091
+ const resumeSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(builtTool.resumeSchema);
1092
+ return { outcome: 'suspended', payload: toolResult.payload, resumeSchema };
1093
+ }
1094
+ let actualResult = toolResult;
1095
+ let extractedSubAgentUsage;
1096
+ if ((0, tool_adapter_1.isAgentToolResult)(toolResult)) {
1097
+ actualResult = toolResult.output;
1098
+ extractedSubAgentUsage = toolResult.subAgentUsage;
1099
+ }
1100
+ this.eventBus.emit({
1101
+ type: "tool_execution_end",
1102
+ toolCallId,
1103
+ toolName,
1104
+ result: actualResult,
1105
+ isError: false,
1106
+ });
1107
+ const modelResult = builtTool.toModelOutput
1108
+ ? builtTool.toModelOutput(actualResult)
1109
+ : actualResult;
1110
+ const toolResultMsg = (0, runtime_helpers_1.makeToolResultMessage)(toolCallId, toolName, modelResult);
1111
+ list.addResponse([toolResultMsg]);
1112
+ const customToolMessage = builtTool?.toMessage?.(actualResult);
1113
+ let customMessage;
1114
+ if (customToolMessage) {
1115
+ customMessage = (0, message_1.toDbMessage)(customToolMessage);
1116
+ list.addResponse([customMessage]);
1117
+ }
1118
+ return {
1119
+ outcome: 'success',
1120
+ toolEntry: {
1121
+ tool: toolName,
1122
+ input: toolInput,
1123
+ output: actualResult,
1124
+ transformed: !!builtTool.toModelOutput,
1125
+ },
1126
+ subAgentUsage: extractedSubAgentUsage,
1127
+ customMessage,
1128
+ message: toolResultMsg,
1129
+ };
1130
+ }
1131
+ buildLoopContext(execOptions) {
1132
+ const aiTools = (0, tool_adapter_1.toAiSdkTools)(this.config.tools);
1133
+ const aiProviderTools = (0, tool_adapter_1.toAiSdkProviderTools)(this.config.providerTools);
1134
+ const allTools = { ...aiTools, ...aiProviderTools };
1135
+ return {
1136
+ model: (0, model_factory_1.createModel)(this.config.model),
1137
+ toolMap: (0, tool_adapter_1.buildToolMap)(this.config.tools),
1138
+ aiTools: allTools,
1139
+ providerOptions: this.buildCallProviderOptions(execOptions?.providerOptions),
1140
+ hasTools: Object.keys(allTools).length > 0,
1141
+ outputSpec: this.config.structuredOutput
1142
+ ? ai_1.Output.object({ schema: this.config.structuredOutput })
1143
+ : undefined,
1144
+ };
1145
+ }
1146
+ async persistSuspension(pendingToolCalls, options, list, totalUsage, existingRunId) {
1147
+ const runId = existingRunId ?? (0, run_state_1.generateRunId)();
1148
+ const executionOptions = options?.maxIterations !== undefined ? { maxIterations: options.maxIterations } : undefined;
1149
+ const state = {
1150
+ persistence: options?.persistence,
1151
+ status: 'suspended',
1152
+ messageList: list.serialize(),
1153
+ pendingToolCalls,
1154
+ usage: totalUsage,
1155
+ executionOptions,
1156
+ };
1157
+ await this.runState.suspend(runId, state);
1158
+ this.updateState({ status: 'suspended', pendingToolCalls, messageList: list.serialize() });
1159
+ return runId;
1160
+ }
1161
+ async cleanupRun(runId) {
1162
+ if (runId) {
1163
+ await this.runState.complete(runId);
1164
+ }
1165
+ }
1166
+ emitTurnEnd(newMessages, toolResults) {
1167
+ const assistantMsg = newMessages.find((m) => 'role' in m && m.role === 'assistant');
1168
+ if (assistantMsg) {
1169
+ this.eventBus.emit({ type: "turn_end", message: assistantMsg, toolResults });
1170
+ }
1171
+ }
1172
+ updateState(patch) {
1173
+ this.currentState = { ...this.currentState, ...patch };
1174
+ }
1175
+ get modelIdString() {
1176
+ const m = this.config.model;
1177
+ if (typeof m === 'string')
1178
+ return m;
1179
+ if ('id' in m && typeof m.id === 'string')
1180
+ return m.id;
1181
+ if ('modelId' in m && typeof m.modelId === 'string') {
1182
+ const provider = 'provider' in m ? String(m.provider) : 'unknown';
1183
+ return `${provider}/${m.modelId}`;
1184
+ }
1185
+ return 'unknown';
1186
+ }
1187
+ get concurrency() {
1188
+ return this.config.toolCallConcurrency ?? 1;
1189
+ }
1190
+ async ensureModelCost() {
1191
+ if (this.modelCost)
1192
+ return this.modelCost;
1193
+ try {
1194
+ this.modelCost = await (0, catalog_1.getModelCost)(this.modelIdString);
1195
+ }
1196
+ catch {
1197
+ }
1198
+ return this.modelCost;
1199
+ }
1200
+ applyCost(usage) {
1201
+ if (!usage || !this.modelCost)
1202
+ return usage;
1203
+ return { ...usage, cost: (0, catalog_1.computeCost)(usage, this.modelCost) };
1204
+ }
1205
+ async setListWorkingMemoryConfig(list, options) {
1206
+ const wmParams = this.resolveWorkingMemoryParams(options);
1207
+ if (!wmParams || !this.config.memory?.getWorkingMemory)
1208
+ return;
1209
+ const wmState = await this.config.memory.getWorkingMemory(wmParams.memoryParams);
1210
+ list.workingMemory = {
1211
+ template: wmParams.template,
1212
+ structured: wmParams.structured,
1213
+ state: wmState,
1214
+ };
1215
+ }
1216
+ resolveWorkingMemoryParams(options) {
1217
+ if (!options)
1218
+ return null;
1219
+ if (!this.config.workingMemory)
1220
+ return null;
1221
+ const scope = this.config.workingMemory?.scope ?? 'resource';
1222
+ if (scope === 'resource' && !options.resourceId) {
1223
+ throw new Error('Working memory scope is "resource" but no resourceId was provided. ' +
1224
+ 'Pass a resourceId in RunOptions or change the scope to "thread".');
1225
+ }
1226
+ if (!options)
1227
+ return null;
1228
+ const memoryParams = { ...options, scope };
1229
+ const persistFn = this.config.workingMemory && this.config.memory?.saveWorkingMemory && options
1230
+ ? async (content) => {
1231
+ await this.config.memory.saveWorkingMemory(memoryParams, content);
1232
+ }
1233
+ : undefined;
1234
+ if (!persistFn)
1235
+ return null;
1236
+ return {
1237
+ persistFn,
1238
+ memoryParams,
1239
+ template: this.config.workingMemory.template,
1240
+ structured: this.config.workingMemory.structured,
1241
+ schema: this.config.workingMemory.schema,
1242
+ };
1243
+ }
1244
+ }
1245
+ exports.AgentRuntime = AgentRuntime;
1246
+ //# sourceMappingURL=agent-runtime.js.map