@aigne/core 1.15.0 → 1.17.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 (194) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +9 -7
  3. package/README.zh.md +9 -7
  4. package/lib/cjs/agents/agent.d.ts +168 -29
  5. package/lib/cjs/agents/agent.js +152 -56
  6. package/lib/cjs/agents/ai-agent.d.ts +7 -7
  7. package/lib/cjs/agents/ai-agent.js +19 -15
  8. package/lib/{esm/models → cjs/agents}/chat-model.d.ts +29 -19
  9. package/lib/cjs/{models → agents}/chat-model.js +56 -15
  10. package/lib/cjs/agents/guide-rail-agent.d.ts +62 -0
  11. package/lib/cjs/agents/guide-rail-agent.js +14 -0
  12. package/lib/cjs/agents/mcp-agent.d.ts +3 -4
  13. package/lib/cjs/agents/mcp-agent.js +11 -11
  14. package/lib/cjs/agents/team-agent.d.ts +7 -8
  15. package/lib/cjs/agents/team-agent.js +10 -10
  16. package/lib/cjs/agents/user-agent.d.ts +4 -4
  17. package/lib/cjs/agents/user-agent.js +10 -10
  18. package/lib/cjs/aigne/aigne.d.ts +13 -11
  19. package/lib/cjs/aigne/aigne.js +7 -6
  20. package/lib/cjs/aigne/context.d.ts +19 -8
  21. package/lib/cjs/aigne/context.js +27 -7
  22. package/lib/cjs/index.d.ts +2 -1
  23. package/lib/cjs/index.js +2 -1
  24. package/lib/cjs/loader/agent-yaml.d.ts +2 -2
  25. package/lib/cjs/loader/index.d.ts +18 -11
  26. package/lib/cjs/loader/index.js +8 -27
  27. package/lib/cjs/memory/default-memory/default-memory-storage/index.d.ts +30 -0
  28. package/lib/cjs/memory/default-memory/default-memory-storage/index.js +69 -0
  29. package/lib/cjs/memory/default-memory/default-memory-storage/migrate.d.ts +7 -0
  30. package/lib/cjs/memory/default-memory/default-memory-storage/migrate.js +53 -0
  31. package/lib/cjs/memory/default-memory/default-memory-storage/migrations/20250523165801-init.d.ts +7 -0
  32. package/lib/cjs/memory/default-memory/default-memory-storage/migrations/20250523165801-init.js +33 -0
  33. package/lib/cjs/memory/default-memory/default-memory-storage/models/memory.d.ts +10 -0
  34. package/lib/cjs/memory/default-memory/default-memory-storage/models/memory.js +32 -0
  35. package/lib/cjs/memory/default-memory/index.d.ts +10 -0
  36. package/lib/cjs/memory/{default-memory.js → default-memory/index.js} +16 -25
  37. package/lib/cjs/memory/default-memory/storage.d.ts +13 -0
  38. package/lib/cjs/memory/default-memory/storage.js +6 -0
  39. package/lib/cjs/memory/memory.d.ts +3 -2
  40. package/lib/cjs/memory/memory.js +1 -1
  41. package/lib/cjs/memory/retriever.d.ts +2 -2
  42. package/lib/cjs/prompt/prompt-builder.d.ts +10 -4
  43. package/lib/cjs/prompt/prompt-builder.js +4 -4
  44. package/lib/cjs/prompt/template.d.ts +3 -3
  45. package/lib/cjs/utils/json-schema.js +1 -1
  46. package/lib/cjs/utils/logger.d.ts +33 -8
  47. package/lib/cjs/utils/logger.js +63 -5
  48. package/lib/cjs/utils/model-utils.d.ts +1 -1
  49. package/lib/cjs/utils/stream-utils.d.ts +3 -1
  50. package/lib/cjs/utils/stream-utils.js +31 -1
  51. package/lib/cjs/utils/type-utils.d.ts +7 -2
  52. package/lib/dts/agents/agent.d.ts +168 -29
  53. package/lib/dts/agents/ai-agent.d.ts +7 -7
  54. package/lib/{cjs/models → dts/agents}/chat-model.d.ts +29 -19
  55. package/lib/dts/agents/guide-rail-agent.d.ts +62 -0
  56. package/lib/dts/agents/mcp-agent.d.ts +3 -4
  57. package/lib/dts/agents/team-agent.d.ts +7 -8
  58. package/lib/dts/agents/user-agent.d.ts +4 -4
  59. package/lib/dts/aigne/aigne.d.ts +13 -11
  60. package/lib/dts/aigne/context.d.ts +19 -8
  61. package/lib/dts/index.d.ts +2 -1
  62. package/lib/dts/loader/agent-yaml.d.ts +2 -2
  63. package/lib/dts/loader/index.d.ts +18 -11
  64. package/lib/dts/memory/default-memory/default-memory-storage/index.d.ts +30 -0
  65. package/lib/dts/memory/default-memory/default-memory-storage/migrate.d.ts +7 -0
  66. package/lib/dts/memory/default-memory/default-memory-storage/migrations/20250523165801-init.d.ts +7 -0
  67. package/lib/dts/memory/default-memory/default-memory-storage/models/memory.d.ts +10 -0
  68. package/lib/dts/memory/default-memory/index.d.ts +10 -0
  69. package/lib/dts/memory/default-memory/storage.d.ts +13 -0
  70. package/lib/dts/memory/memory.d.ts +3 -2
  71. package/lib/dts/memory/retriever.d.ts +2 -2
  72. package/lib/dts/prompt/prompt-builder.d.ts +10 -4
  73. package/lib/dts/prompt/template.d.ts +3 -3
  74. package/lib/dts/utils/logger.d.ts +33 -8
  75. package/lib/dts/utils/model-utils.d.ts +1 -1
  76. package/lib/dts/utils/stream-utils.d.ts +3 -1
  77. package/lib/dts/utils/type-utils.d.ts +7 -2
  78. package/lib/esm/agents/agent.d.ts +168 -29
  79. package/lib/esm/agents/agent.js +152 -56
  80. package/lib/esm/agents/ai-agent.d.ts +7 -7
  81. package/lib/esm/agents/ai-agent.js +18 -14
  82. package/lib/{dts/models → esm/agents}/chat-model.d.ts +29 -19
  83. package/lib/esm/{models → agents}/chat-model.js +56 -15
  84. package/lib/esm/agents/guide-rail-agent.d.ts +62 -0
  85. package/lib/esm/agents/guide-rail-agent.js +11 -0
  86. package/lib/esm/agents/mcp-agent.d.ts +3 -4
  87. package/lib/esm/agents/mcp-agent.js +11 -11
  88. package/lib/esm/agents/team-agent.d.ts +7 -8
  89. package/lib/esm/agents/team-agent.js +10 -10
  90. package/lib/esm/agents/user-agent.d.ts +4 -4
  91. package/lib/esm/agents/user-agent.js +10 -10
  92. package/lib/esm/aigne/aigne.d.ts +13 -11
  93. package/lib/esm/aigne/aigne.js +7 -6
  94. package/lib/esm/aigne/context.d.ts +19 -8
  95. package/lib/esm/aigne/context.js +28 -8
  96. package/lib/esm/index.d.ts +2 -1
  97. package/lib/esm/index.js +2 -1
  98. package/lib/esm/loader/agent-yaml.d.ts +2 -2
  99. package/lib/esm/loader/index.d.ts +18 -11
  100. package/lib/esm/loader/index.js +8 -27
  101. package/lib/esm/memory/default-memory/default-memory-storage/index.d.ts +30 -0
  102. package/lib/esm/memory/default-memory/default-memory-storage/index.js +64 -0
  103. package/lib/esm/memory/default-memory/default-memory-storage/migrate.d.ts +7 -0
  104. package/lib/esm/memory/default-memory/default-memory-storage/migrate.js +16 -0
  105. package/lib/esm/memory/default-memory/default-memory-storage/migrations/20250523165801-init.d.ts +7 -0
  106. package/lib/esm/memory/default-memory/default-memory-storage/migrations/20250523165801-init.js +28 -0
  107. package/lib/esm/memory/default-memory/default-memory-storage/models/memory.d.ts +10 -0
  108. package/lib/esm/memory/default-memory/default-memory-storage/models/memory.js +29 -0
  109. package/lib/esm/memory/default-memory/index.d.ts +10 -0
  110. package/lib/esm/memory/{default-memory.js → default-memory/index.js} +15 -24
  111. package/lib/esm/memory/default-memory/storage.d.ts +13 -0
  112. package/lib/esm/memory/default-memory/storage.js +2 -0
  113. package/lib/esm/memory/memory.d.ts +3 -2
  114. package/lib/esm/memory/memory.js +2 -2
  115. package/lib/esm/memory/retriever.d.ts +2 -2
  116. package/lib/esm/prompt/prompt-builder.d.ts +10 -4
  117. package/lib/esm/prompt/prompt-builder.js +4 -4
  118. package/lib/esm/prompt/template.d.ts +3 -3
  119. package/lib/esm/utils/json-schema.js +1 -1
  120. package/lib/esm/utils/logger.d.ts +33 -8
  121. package/lib/esm/utils/logger.js +61 -4
  122. package/lib/esm/utils/model-utils.d.ts +1 -1
  123. package/lib/esm/utils/stream-utils.d.ts +3 -1
  124. package/lib/esm/utils/stream-utils.js +29 -1
  125. package/lib/esm/utils/type-utils.d.ts +7 -2
  126. package/package.json +4 -20
  127. package/lib/cjs/client/client.d.ts +0 -97
  128. package/lib/cjs/client/client.js +0 -87
  129. package/lib/cjs/client/index.d.ts +0 -1
  130. package/lib/cjs/client/index.js +0 -17
  131. package/lib/cjs/memory/default-memory.d.ts +0 -16
  132. package/lib/cjs/models/bedrock-chat-model.d.ts +0 -79
  133. package/lib/cjs/models/bedrock-chat-model.js +0 -303
  134. package/lib/cjs/models/claude-chat-model.d.ts +0 -114
  135. package/lib/cjs/models/claude-chat-model.js +0 -317
  136. package/lib/cjs/models/deepseek-chat-model.d.ts +0 -23
  137. package/lib/cjs/models/deepseek-chat-model.js +0 -35
  138. package/lib/cjs/models/gemini-chat-model.d.ts +0 -23
  139. package/lib/cjs/models/gemini-chat-model.js +0 -35
  140. package/lib/cjs/models/ollama-chat-model.d.ts +0 -22
  141. package/lib/cjs/models/ollama-chat-model.js +0 -34
  142. package/lib/cjs/models/open-router-chat-model.d.ts +0 -22
  143. package/lib/cjs/models/open-router-chat-model.js +0 -34
  144. package/lib/cjs/models/openai-chat-model.d.ts +0 -166
  145. package/lib/cjs/models/openai-chat-model.js +0 -415
  146. package/lib/cjs/models/xai-chat-model.d.ts +0 -21
  147. package/lib/cjs/models/xai-chat-model.js +0 -33
  148. package/lib/cjs/server/error.d.ts +0 -15
  149. package/lib/cjs/server/error.js +0 -22
  150. package/lib/cjs/server/index.d.ts +0 -2
  151. package/lib/cjs/server/index.js +0 -18
  152. package/lib/cjs/server/server.d.ts +0 -135
  153. package/lib/cjs/server/server.js +0 -187
  154. package/lib/dts/client/client.d.ts +0 -97
  155. package/lib/dts/client/index.d.ts +0 -1
  156. package/lib/dts/memory/default-memory.d.ts +0 -16
  157. package/lib/dts/models/bedrock-chat-model.d.ts +0 -79
  158. package/lib/dts/models/claude-chat-model.d.ts +0 -114
  159. package/lib/dts/models/deepseek-chat-model.d.ts +0 -23
  160. package/lib/dts/models/gemini-chat-model.d.ts +0 -23
  161. package/lib/dts/models/ollama-chat-model.d.ts +0 -22
  162. package/lib/dts/models/open-router-chat-model.d.ts +0 -22
  163. package/lib/dts/models/openai-chat-model.d.ts +0 -166
  164. package/lib/dts/models/xai-chat-model.d.ts +0 -21
  165. package/lib/dts/server/error.d.ts +0 -15
  166. package/lib/dts/server/index.d.ts +0 -2
  167. package/lib/dts/server/server.d.ts +0 -135
  168. package/lib/esm/client/client.d.ts +0 -97
  169. package/lib/esm/client/client.js +0 -83
  170. package/lib/esm/client/index.d.ts +0 -1
  171. package/lib/esm/client/index.js +0 -1
  172. package/lib/esm/memory/default-memory.d.ts +0 -16
  173. package/lib/esm/models/bedrock-chat-model.d.ts +0 -79
  174. package/lib/esm/models/bedrock-chat-model.js +0 -298
  175. package/lib/esm/models/claude-chat-model.d.ts +0 -114
  176. package/lib/esm/models/claude-chat-model.js +0 -310
  177. package/lib/esm/models/deepseek-chat-model.d.ts +0 -23
  178. package/lib/esm/models/deepseek-chat-model.js +0 -31
  179. package/lib/esm/models/gemini-chat-model.d.ts +0 -23
  180. package/lib/esm/models/gemini-chat-model.js +0 -31
  181. package/lib/esm/models/ollama-chat-model.d.ts +0 -22
  182. package/lib/esm/models/ollama-chat-model.js +0 -30
  183. package/lib/esm/models/open-router-chat-model.d.ts +0 -22
  184. package/lib/esm/models/open-router-chat-model.js +0 -30
  185. package/lib/esm/models/openai-chat-model.d.ts +0 -166
  186. package/lib/esm/models/openai-chat-model.js +0 -405
  187. package/lib/esm/models/xai-chat-model.d.ts +0 -21
  188. package/lib/esm/models/xai-chat-model.js +0 -29
  189. package/lib/esm/server/error.d.ts +0 -15
  190. package/lib/esm/server/error.js +0 -18
  191. package/lib/esm/server/index.d.ts +0 -2
  192. package/lib/esm/server/index.js +0 -2
  193. package/lib/esm/server/server.d.ts +0 -135
  194. package/lib/esm/server/server.js +0 -180
@@ -61,6 +61,16 @@ exports.agentOptionsSchema = zod_1.z.object({
61
61
  skills: zod_1.z.array(zod_1.z.union([zod_1.z.custom(), zod_1.z.custom()])).optional(),
62
62
  disableEvents: zod_1.z.boolean().optional(),
63
63
  memory: zod_1.z.union([zod_1.z.custom(), zod_1.z.array(zod_1.z.custom())]).optional(),
64
+ hooks: zod_1.z
65
+ .object({
66
+ onStart: zod_1.z.custom().optional(),
67
+ onEnd: zod_1.z.custom().optional(),
68
+ onSkillStart: zod_1.z.custom().optional(),
69
+ onSkillEnd: zod_1.z.custom().optional(),
70
+ onHandoff: zod_1.z.custom().optional(),
71
+ })
72
+ .optional(),
73
+ guideRails: zod_1.z.array(zod_1.z.custom()).optional(),
64
74
  });
65
75
  /**
66
76
  * Agent is the base class for all agents.
@@ -107,11 +117,42 @@ class Agent {
107
117
  else if (options.memory) {
108
118
  this.memories.push(options.memory);
109
119
  }
120
+ this.hooks = options.hooks ?? {};
121
+ this.guideRails = options.guideRails;
110
122
  }
111
123
  /**
112
124
  * List of memories this agent can use
113
125
  */
114
126
  memories = [];
127
+ /**
128
+ * Lifecycle hooks for agent processing.
129
+ *
130
+ * Hooks enable tracing, logging, monitoring, and custom behavior
131
+ * without modifying the core agent implementation
132
+ *
133
+ * @example
134
+ * Here's an example of using hooks:
135
+ * {@includeCode ../../test/agents/agent.test.ts#example-agent-hooks}
136
+ */
137
+ hooks;
138
+ /**
139
+ * List of GuideRail agents applied to this agent
140
+ *
141
+ * GuideRail agents validate, transform, or control the message flow by:
142
+ * - Enforcing rules and safety policies
143
+ * - Validating inputs/outputs against specific criteria
144
+ * - Implementing business logic validations
145
+ * - Monitoring and auditing agent behavior
146
+ *
147
+ * Each GuideRail agent can examine both input and expected output,
148
+ * and has the ability to abort the process with an explanation
149
+ *
150
+ * @example
151
+ * Here's an example of using GuideRail agents:
152
+ *
153
+ * {@includeCode ../../test/agents/agent.test.ts#example-agent-guide-rails}
154
+ */
155
+ guideRails;
115
156
  /**
116
157
  * Name of the agent, used for identification and logging
117
158
  *
@@ -251,61 +292,71 @@ class Agent {
251
292
  /**
252
293
  * Check context status to ensure it hasn't timed out
253
294
  *
254
- * @param context The context to check
295
+ * @param options Invocation options containing context
255
296
  * @throws Error if the context has timed out
256
297
  */
257
- checkContextStatus(context) {
258
- if (context) {
259
- const { status } = context;
260
- if (status === "timeout") {
261
- throw new Error(`AIGNE for agent ${this.name} has timed out`);
262
- }
298
+ checkContextStatus(options) {
299
+ const { status } = options.context;
300
+ if (status === "timeout") {
301
+ throw new Error(`AIGNE for agent ${this.name} has timed out`);
263
302
  }
264
303
  }
265
304
  async newDefaultContext() {
266
305
  return Promise.resolve().then(() => __importStar(require("../aigne/context.js"))).then((m) => new m.AIGNEContext());
267
306
  }
268
- async invoke(input, context, options) {
269
- const ctx = context ?? (await this.newDefaultContext());
307
+ async invoke(input, options = {}) {
308
+ const opts = {
309
+ ...options,
310
+ context: options.context ?? (await this.newDefaultContext()),
311
+ };
270
312
  const message = typeof input === "string" ? (0, prompt_builder_js_1.createMessage)(input) : input;
271
- logger_js_1.logger.core("Invoke agent %s started with input: %O", this.name, input);
313
+ logger_js_1.logger.debug("Invoke agent %s started with input: %O", this.name, input);
272
314
  if (!this.disableEvents)
273
- ctx.emit("agentStarted", { agent: this, input: message });
315
+ opts.context.emit("agentStarted", { agent: this, input: message });
274
316
  try {
317
+ await this.hooks.onStart?.({ context: opts.context, input: message });
275
318
  const parsedInput = (0, type_utils_js_1.checkArguments)(`Agent ${this.name} input`, this.inputSchema, message);
276
- this.preprocess(parsedInput, ctx);
277
- this.checkContextStatus(ctx);
278
- let response = await this.process(parsedInput, ctx);
319
+ await this.preprocess(parsedInput, opts);
320
+ this.checkContextStatus(opts);
321
+ let response = await this.process(parsedInput, opts);
279
322
  if (response instanceof Agent) {
280
323
  response = (0, types_js_1.transferToAgentOutput)(response);
281
324
  }
282
- if (options?.streaming) {
325
+ if (opts.streaming) {
283
326
  const stream = response instanceof ReadableStream
284
327
  ? response
285
328
  : (0, stream_utils_js_1.isAsyncGenerator)(response)
286
329
  ? (0, stream_utils_js_1.asyncGeneratorToReadableStream)(response)
287
330
  : (0, stream_utils_js_1.objectToAgentResponseStream)(response);
288
- return (0, stream_utils_js_1.onAgentResponseStreamEnd)(stream, async (result) => {
289
- return await this.processAgentOutput(parsedInput, result, ctx);
331
+ return this.checkResponseByGuideRails(message, (0, stream_utils_js_1.onAgentResponseStreamEnd)(stream, async (result) => {
332
+ return await this.processAgentOutput(parsedInput, result, opts);
290
333
  }, {
291
- errorCallback: (error) => {
292
- try {
293
- this.processAgentError(error, ctx);
294
- }
295
- catch (error) {
296
- return error;
297
- }
334
+ errorCallback: async (error) => {
335
+ return await this.processAgentError(message, error, opts);
298
336
  },
299
- });
337
+ }), opts);
300
338
  }
301
- return await this.processAgentOutput(parsedInput, response instanceof ReadableStream
339
+ return await this.checkResponseByGuideRails(message, this.processAgentOutput(parsedInput, response instanceof ReadableStream
302
340
  ? await (0, stream_utils_js_1.agentResponseStreamToObject)(response)
303
341
  : (0, stream_utils_js_1.isAsyncGenerator)(response)
304
342
  ? await (0, stream_utils_js_1.agentResponseStreamToObject)(response)
305
- : response, ctx);
343
+ : response, opts), opts);
306
344
  }
307
345
  catch (error) {
308
- this.processAgentError(error, ctx);
346
+ throw await this.processAgentError(message, error, opts);
347
+ }
348
+ }
349
+ async invokeSkill(skill, input, options) {
350
+ const { context } = options;
351
+ await this.hooks.onSkillStart?.({ context, skill, input });
352
+ try {
353
+ const output = await context.invoke(skill, input);
354
+ await this.hooks.onSkillEnd?.({ context, skill, input, output });
355
+ return output;
356
+ }
357
+ catch (error) {
358
+ await this.hooks.onSkillEnd?.({ context, skill, input, error });
359
+ throw error;
309
360
  }
310
361
  }
311
362
  /**
@@ -315,16 +366,18 @@ class Agent {
315
366
  *
316
367
  * @param input Original input message
317
368
  * @param output Raw output produced by the agent
318
- * @param context Execution context
369
+ * @param options Invocation options
319
370
  * @returns Final processed output
320
371
  */
321
- async processAgentOutput(input, output, context) {
372
+ async processAgentOutput(input, output, options) {
373
+ const { context } = options;
322
374
  const parsedOutput = (0, type_utils_js_1.checkArguments)(`Agent ${this.name} output`, this.outputSchema, output);
323
375
  const finalOutput = this.includeInputInOutput ? { ...input, ...parsedOutput } : parsedOutput;
324
- this.postprocess(input, finalOutput, context);
325
- logger_js_1.logger.core("Invoke agent %s succeed with output: %O", this.name, finalOutput);
376
+ await this.postprocess(input, finalOutput, options);
377
+ logger_js_1.logger.debug("Invoke agent %s succeed with output: %O", this.name, finalOutput);
326
378
  if (!this.disableEvents)
327
379
  context.emit("agentSucceed", { agent: this, output: finalOutput });
380
+ await this.hooks.onEnd?.({ context, input, output: finalOutput });
328
381
  return finalOutput;
329
382
  }
330
383
  /**
@@ -333,14 +386,15 @@ class Agent {
333
386
  * Logs error information, triggers failure events, and re-throws the error
334
387
  *
335
388
  * @param error Caught error
336
- * @param context Execution context
337
- * @throws Always throws the received error
389
+ * @param options Invocation options
338
390
  */
339
- processAgentError(error, context) {
340
- logger_js_1.logger.core("Invoke agent %s failed with error: %O", this.name, error);
391
+ async processAgentError(input, error, options) {
392
+ logger_js_1.logger.error("Invoke agent %s failed with error: %O", this.name, error);
341
393
  if (!this.disableEvents)
342
- context.emit("agentFailed", { agent: this, error });
343
- throw error;
394
+ options.context.emit("agentFailed", { agent: this, error });
395
+ const { context } = options;
396
+ await this.hooks.onEnd?.({ context, input, error });
397
+ return error;
344
398
  }
345
399
  /**
346
400
  * Check agent invocation usage to prevent exceeding limits
@@ -348,11 +402,11 @@ class Agent {
348
402
  * If the context has a maximum invocation limit set, checks if the limit
349
403
  * has been exceeded and increments the invocation counter
350
404
  *
351
- * @param context Execution context
405
+ * @param options Invocation options containing context and limits
352
406
  * @throws Error if maximum invocation limit is exceeded
353
407
  */
354
- checkAgentInvokesUsage(context) {
355
- const { limits, usage } = context;
408
+ checkAgentInvokesUsage(options) {
409
+ const { limits, usage } = options.context;
356
410
  if (limits?.maxAgentInvokes && usage.agentCalls >= limits.maxAgentInvokes) {
357
411
  throw new Error(`Exceeded max agent invokes ${usage.agentCalls}/${limits.maxAgentInvokes}`);
358
412
  }
@@ -366,11 +420,53 @@ class Agent {
366
420
  * - Verifying invocation limits
367
421
  *
368
422
  * @param _ Input message (unused)
369
- * @param context Execution context
423
+ * @param options Options for agent invocation
424
+ */
425
+ async preprocess(_, options) {
426
+ this.checkContextStatus(options);
427
+ this.checkAgentInvokesUsage(options);
428
+ }
429
+ async checkResponseByGuideRails(input, output, options) {
430
+ if (!this.guideRails?.length)
431
+ return output;
432
+ const result = await output;
433
+ if (result instanceof ReadableStream) {
434
+ return (0, stream_utils_js_1.onAgentResponseStreamEnd)(result, async (result) => {
435
+ const error = await this.runGuideRails(input, result, options);
436
+ if (error) {
437
+ return {
438
+ ...(await this.onGuideRailError(error)),
439
+ $status: "GuideRailError",
440
+ };
441
+ }
442
+ });
443
+ }
444
+ const error = await this.runGuideRails(input, result, options);
445
+ if (!error)
446
+ return output;
447
+ return { ...(await this.onGuideRailError(error)), $status: "GuideRailError" };
448
+ }
449
+ async runGuideRails(input, output, options) {
450
+ const result = await Promise.all((this.guideRails ?? []).map((i) => options.context.invoke(i, { input, output })));
451
+ return result.find((i) => !!i.abort);
452
+ }
453
+ /**
454
+ * Handle errors detected by GuideRail agents
455
+ *
456
+ * This method is called when a GuideRail agent aborts the process, providing
457
+ * a way for agents to customize error handling behavior. By default, it simply
458
+ * returns the original error, but subclasses can override this method to:
459
+ * - Transform the error into a more specific response
460
+ * - Apply recovery strategies
461
+ * - Log or report the error in a custom format
462
+ * - Return a fallback output instead of an error
463
+ *
464
+ * @param error The GuideRail agent output containing abort=true and a reason
465
+ * @returns Either the original/modified error or a substitute output object
466
+ * which will be tagged with $status: "GuideRailError"
370
467
  */
371
- preprocess(_, context) {
372
- this.checkContextStatus(context);
373
- this.checkAgentInvokesUsage(context);
468
+ async onGuideRailError(error) {
469
+ return error;
374
470
  }
375
471
  /**
376
472
  * Post-processing operations after handling output
@@ -381,26 +477,26 @@ class Agent {
381
477
  *
382
478
  * @param input Input message
383
479
  * @param output Output message
384
- * @param context Execution context
480
+ * @param options Options for agent invocation
385
481
  */
386
- postprocess(input, output, context) {
387
- this.checkContextStatus(context);
388
- this.publishToTopics(output, context);
482
+ async postprocess(input, output, options) {
483
+ this.checkContextStatus(options);
484
+ this.publishToTopics(output, options);
389
485
  for (const memory of this.memories) {
390
486
  if (memory.autoUpdate) {
391
- memory.record({
487
+ await memory.record({
392
488
  content: [
393
489
  { role: "user", content: input },
394
490
  { role: "agent", content: (0, types_js_1.replaceTransferAgentToName)(output), source: this.name },
395
491
  ],
396
- }, context);
492
+ }, options.context);
397
493
  }
398
494
  }
399
495
  }
400
- async publishToTopics(output, context) {
496
+ async publishToTopics(output, options) {
401
497
  const publishTopics = typeof this.publishTopic === "function" ? await this.publishTopic(output) : this.publishTopic;
402
498
  if (publishTopics?.length) {
403
- context.publish(publishTopics, {
499
+ options.context.publish(publishTopics, {
404
500
  role: this.constructor.name === "UserAgent" ? "user" : "agent",
405
501
  source: this.name,
406
502
  message: output,
@@ -553,11 +649,11 @@ class FunctionAgent extends Agent {
553
649
  * Process input implementation, calls the configured processing function
554
650
  *
555
651
  * @param input Input message
556
- * @param context Execution context
652
+ * @param options Invocation options
557
653
  * @returns Processing result
558
654
  */
559
- process(input, context) {
560
- return this._process(input, context);
655
+ process(input, options) {
656
+ return this._process(input, options);
561
657
  }
562
658
  }
563
659
  exports.FunctionAgent = FunctionAgent;
@@ -1,10 +1,9 @@
1
1
  import { type ZodObject, type ZodType, z } from "zod";
2
- import type { Context } from "../aigne/context.js";
3
- import { type DefaultMemoryOptions } from "../memory/default-memory.js";
4
- import { ChatModel } from "../models/chat-model.js";
5
- import type { ChatModelInput } from "../models/chat-model.js";
2
+ import { type DefaultMemoryOptions } from "../memory/default-memory/index.js";
6
3
  import { PromptBuilder } from "../prompt/prompt-builder.js";
7
- import { Agent, type AgentOptions, type AgentProcessAsyncGenerator, type Message } from "./agent.js";
4
+ import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessAsyncGenerator, type Message } from "./agent.js";
5
+ import { ChatModel, type ChatModelInput } from "./chat-model.js";
6
+ import type { GuideRailAgentOutput } from "./guide-rail-agent.js";
8
7
  /**
9
8
  * Configuration options for an AI Agent
10
9
  *
@@ -215,7 +214,8 @@ export declare class AIAgent<I extends Message = Message, O extends Message = Me
215
214
  *
216
215
  * @protected
217
216
  */
218
- process(input: I, context: Context): AgentProcessAsyncGenerator<O>;
217
+ process(input: I, options: AgentInvokeOptions): AgentProcessAsyncGenerator<O>;
218
+ protected onGuideRailError(error: GuideRailAgentOutput): Promise<O | GuideRailAgentOutput>;
219
219
  /**
220
220
  * Process router mode requests
221
221
  *
@@ -224,5 +224,5 @@ export declare class AIAgent<I extends Message = Message, O extends Message = Me
224
224
  *
225
225
  * @protected
226
226
  */
227
- _processRouter(input: I, model: ChatModel, modelInput: ChatModelInput, context: Context, toolsMap: Map<string, Agent>): AgentProcessAsyncGenerator<O>;
227
+ _processRouter(input: I, model: ChatModel, modelInput: ChatModelInput, options: AgentInvokeOptions, toolsMap: Map<string, Agent>): AgentProcessAsyncGenerator<O>;
228
228
  }
@@ -2,13 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AIAgent = exports.aiAgentOptionsSchema = exports.aiAgentToolChoiceSchema = exports.AIAgentToolChoice = void 0;
4
4
  const zod_1 = require("zod");
5
- const default_memory_js_1 = require("../memory/default-memory.js");
5
+ const index_js_1 = require("../memory/default-memory/index.js");
6
6
  const memory_js_1 = require("../memory/memory.js");
7
- const chat_model_js_1 = require("../models/chat-model.js");
8
7
  const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
9
8
  const template_js_1 = require("../prompt/template.js");
10
9
  const type_utils_js_1 = require("../utils/type-utils.js");
11
10
  const agent_js_1 = require("./agent.js");
11
+ const chat_model_js_1 = require("./chat-model.js");
12
12
  const types_js_1 = require("./types.js");
13
13
  /**
14
14
  * Tool choice options for AI agents
@@ -107,7 +107,7 @@ class AIAgent extends agent_js_1.Agent {
107
107
  ? undefined
108
108
  : Array.isArray(options.memory) || options.memory instanceof memory_js_1.MemoryAgent
109
109
  ? options.memory
110
- : new default_memory_js_1.DefaultMemory(options.memory === true ? {} : options.memory),
110
+ : new index_js_1.DefaultMemory(options.memory === true ? {} : options.memory),
111
111
  });
112
112
  (0, type_utils_js_1.checkArguments)("AIAgent", exports.aiAgentOptionsSchema, options);
113
113
  this.model = options.model;
@@ -188,26 +188,26 @@ class AIAgent extends agent_js_1.Agent {
188
188
  *
189
189
  * @protected
190
190
  */
191
- async *process(input, context) {
192
- const model = this.model ?? context.model;
191
+ async *process(input, options) {
192
+ const model = this.model ?? options.context.model;
193
193
  if (!model)
194
194
  throw new Error("model is required to run AIAgent");
195
195
  const { toolAgents, ...modelInput } = await this.instructions.build({
196
196
  agent: this,
197
197
  input,
198
198
  model,
199
- context,
199
+ context: options.context,
200
200
  });
201
201
  const toolsMap = new Map(toolAgents?.map((i) => [i.name, i]));
202
202
  if (this.toolChoice === "router") {
203
- yield* this._processRouter(input, model, modelInput, context, toolsMap);
203
+ yield* this._processRouter(input, model, modelInput, options, toolsMap);
204
204
  return;
205
205
  }
206
206
  const toolCallMessages = [];
207
207
  const outputKey = this.outputKey || prompt_builder_js_1.MESSAGE_KEY;
208
208
  for (;;) {
209
209
  const modelOutput = {};
210
- const stream = await context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
210
+ const stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
211
211
  for await (const value of stream) {
212
212
  if (value.delta.text?.text) {
213
213
  yield { delta: { text: { [outputKey]: value.delta.text.text } } };
@@ -225,9 +225,7 @@ class AIAgent extends agent_js_1.Agent {
225
225
  if (!tool)
226
226
  throw new Error(`Tool not found: ${call.function.name}`);
227
227
  // NOTE: should pass both arguments (model generated) and input (user provided) to the tool
228
- const output = await context
229
- .invoke(tool, { ...input, ...call.function.arguments }, { disableTransfer: true })
230
- .catch((error) => {
228
+ const output = await this.invokeSkill(tool, { ...input, ...call.function.arguments }, options).catch((error) => {
231
229
  if (!this.catchToolsError) {
232
230
  return Promise.reject(error);
233
231
  }
@@ -251,7 +249,7 @@ class AIAgent extends agent_js_1.Agent {
251
249
  }
252
250
  }
253
251
  const result = {};
254
- if (modelInput.responseFormat?.type === "json_schema") {
252
+ if (json) {
255
253
  Object.assign(result, json);
256
254
  }
257
255
  else if (text) {
@@ -263,6 +261,12 @@ class AIAgent extends agent_js_1.Agent {
263
261
  return;
264
262
  }
265
263
  }
264
+ async onGuideRailError(error) {
265
+ const outputKey = this.outputKey || prompt_builder_js_1.MESSAGE_KEY;
266
+ return {
267
+ [outputKey]: error.reason,
268
+ };
269
+ }
266
270
  /**
267
271
  * Process router mode requests
268
272
  *
@@ -271,15 +275,15 @@ class AIAgent extends agent_js_1.Agent {
271
275
  *
272
276
  * @protected
273
277
  */
274
- async *_processRouter(input, model, modelInput, context, toolsMap) {
275
- const { toolCalls: [call] = [], } = await context.invoke(model, modelInput);
278
+ async *_processRouter(input, model, modelInput, options, toolsMap) {
279
+ const { toolCalls: [call] = [], } = await options.context.invoke(model, modelInput);
276
280
  if (!call) {
277
281
  throw new Error("Router toolChoice requires exactly one tool to be executed");
278
282
  }
279
283
  const tool = toolsMap.get(call.function.name);
280
284
  if (!tool)
281
285
  throw new Error(`Tool not found: ${call.function.name}`);
282
- const stream = await context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true });
286
+ const stream = await options.context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true, sourceAgent: this });
283
287
  yield* stream;
284
288
  }
285
289
  }
@@ -1,6 +1,5 @@
1
- import { Agent, type AgentProcessResult, type Message } from "../agents/agent.js";
2
- import type { Context } from "../aigne/context.js";
3
1
  import type { PromiseOrValue } from "../utils/type-utils.js";
2
+ import { Agent, type AgentInvokeOptions, type AgentProcessResult, type Message } from "./agent.js";
4
3
  /**
5
4
  * ChatModel is an abstract base class for interacting with Large Language Models (LLMs).
6
5
  *
@@ -10,19 +9,19 @@ import type { PromiseOrValue } from "../utils/type-utils.js";
10
9
  *
11
10
  * @example
12
11
  * Here's how to implement a custom ChatModel:
13
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model}
12
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model}
14
13
  *
15
14
  * @example
16
15
  * Here's an example showing streaming response with readable stream:
17
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-streaming}
16
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-streaming}
18
17
  *
19
18
  * @example
20
19
  * Here's an example showing streaming response with async generator:
21
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-streaming-async-generator}
20
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-streaming-async-generator}
22
21
  *
23
22
  * @example
24
23
  * Here's an example with tool calls:
25
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
24
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
26
25
  */
27
26
  export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelOutput> {
28
27
  constructor();
@@ -44,16 +43,27 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
44
43
  supportsParallelToolCalls: boolean;
45
44
  };
46
45
  private validateToolNames;
46
+ /**
47
+ * Normalizes tool names to ensure compatibility with language models
48
+ *
49
+ * This method converts tool names to a format that complies with model requirements
50
+ * by replacing hyphens and whitespace characters with underscores. The normalized
51
+ * names are used for tool calls while preserving the original names for reference.
52
+ *
53
+ * @param name - The original tool name to normalize
54
+ * @returns A promise that resolves to the normalized tool name
55
+ */
56
+ protected normalizeToolName(name: string): Promise<string>;
47
57
  /**
48
58
  * Performs preprocessing operations before handling input
49
59
  *
50
60
  * Primarily checks if token usage exceeds limits, throwing an exception if limits are exceeded
51
61
  *
52
62
  * @param input Input message
53
- * @param context Execution context
63
+ * @param options Options for invoking the agent
54
64
  * @throws Error if token usage exceeds maximum limit
55
65
  */
56
- protected preprocess(input: ChatModelInput, context: Context): void;
66
+ protected preprocess(input: ChatModelInput, options: AgentInvokeOptions): Promise<void>;
57
67
  /**
58
68
  * Performs postprocessing operations after handling output
59
69
  *
@@ -61,9 +71,9 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
61
71
  *
62
72
  * @param input Input message
63
73
  * @param output Output message
64
- * @param context Execution context
74
+ * @param options Options for invoking the agent
65
75
  */
66
- protected postprocess(input: ChatModelInput, output: ChatModelOutput, context: Context): void;
76
+ protected postprocess(input: ChatModelInput, output: ChatModelOutput, options: AgentInvokeOptions): Promise<void>;
67
77
  /**
68
78
  * Processes input messages and generates model responses
69
79
  *
@@ -81,10 +91,10 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
81
91
  * - Tool call processing if applicable
82
92
  *
83
93
  * @param input - The standardized input containing messages and model options
84
- * @param context - The execution context with settings and state
94
+ * @param options - The options for invoking the agent, including context and limits
85
95
  * @returns A promise or direct value containing the model's response
86
96
  */
87
- abstract process(input: ChatModelInput, context: Context): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
97
+ abstract process(input: ChatModelInput, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
88
98
  }
89
99
  /**
90
100
  * Input message format for ChatModel
@@ -94,11 +104,11 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
94
104
  *
95
105
  * @example
96
106
  * Here's a basic ChatModel input example:
97
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model}
107
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model}
98
108
  *
99
109
  * @example
100
110
  * Here's an example with tool calling:
101
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
111
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
102
112
  */
103
113
  export interface ChatModelInput extends Message {
104
114
  /**
@@ -213,7 +223,7 @@ export type ChatModelInputResponseFormat = {
213
223
  *
214
224
  * @example
215
225
  * Here's an example showing how to use tools:
216
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
226
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
217
227
  */
218
228
  export interface ChatModelInputTool {
219
229
  /**
@@ -249,7 +259,7 @@ export interface ChatModelInputTool {
249
259
  *
250
260
  * @example
251
261
  * Here's an example showing how to use tools:
252
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
262
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
253
263
  */
254
264
  export type ChatModelInputToolChoice = "auto" | "none" | "required" | {
255
265
  type: "function";
@@ -296,11 +306,11 @@ export interface ChatModelOptions {
296
306
  *
297
307
  * @example
298
308
  * Here's a basic output example:
299
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model}
309
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model}
300
310
  *
301
311
  * @example
302
312
  * Here's an example with tool calls:
303
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
313
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
304
314
  */
305
315
  export interface ChatModelOutput extends Message {
306
316
  /**
@@ -331,7 +341,7 @@ export interface ChatModelOutput extends Message {
331
341
  *
332
342
  * @example
333
343
  * Here's an example with tool calls:
334
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
344
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
335
345
  */
336
346
  export interface ChatModelOutputToolCall {
337
347
  /**