@aigne/core 1.16.0 → 1.18.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 (100) hide show
  1. package/CHANGELOG.md +37 -16
  2. package/lib/cjs/agents/agent.d.ts +69 -37
  3. package/lib/cjs/agents/agent.js +93 -65
  4. package/lib/cjs/agents/ai-agent.d.ts +4 -7
  5. package/lib/cjs/agents/ai-agent.js +10 -19
  6. package/lib/cjs/agents/chat-model.d.ts +7 -8
  7. package/lib/cjs/agents/chat-model.js +9 -9
  8. package/lib/cjs/agents/mcp-agent.d.ts +4 -5
  9. package/lib/cjs/agents/mcp-agent.js +7 -13
  10. package/lib/cjs/agents/team-agent.d.ts +7 -8
  11. package/lib/cjs/agents/team-agent.js +10 -10
  12. package/lib/cjs/agents/user-agent.d.ts +4 -5
  13. package/lib/cjs/agents/user-agent.js +11 -12
  14. package/lib/cjs/aigne/aigne.d.ts +10 -9
  15. package/lib/cjs/aigne/aigne.js +5 -4
  16. package/lib/cjs/aigne/context.d.ts +18 -9
  17. package/lib/cjs/aigne/context.js +23 -12
  18. package/lib/cjs/aigne/message-queue.d.ts +6 -2
  19. package/lib/cjs/aigne/message-queue.js +2 -2
  20. package/lib/cjs/index.d.ts +3 -1
  21. package/lib/cjs/index.js +3 -1
  22. package/lib/cjs/loader/agent-js.d.ts +1 -1
  23. package/lib/cjs/loader/agent-yaml.d.ts +3 -2
  24. package/lib/cjs/loader/agent-yaml.js +3 -2
  25. package/lib/cjs/loader/index.d.ts +5 -1
  26. package/lib/cjs/loader/index.js +25 -16
  27. package/lib/cjs/memory/memory.d.ts +3 -2
  28. package/lib/cjs/memory/memory.js +1 -1
  29. package/lib/cjs/memory/retriever.d.ts +2 -2
  30. package/lib/cjs/prompt/prompt-builder.d.ts +9 -7
  31. package/lib/cjs/prompt/prompt-builder.js +14 -10
  32. package/lib/cjs/prompt/template.js +1 -3
  33. package/lib/cjs/utils/logger.js +3 -3
  34. package/lib/cjs/utils/nodejs.d.ts +8 -0
  35. package/lib/cjs/utils/nodejs.js +24 -0
  36. package/lib/cjs/utils/type-utils.d.ts +2 -2
  37. package/lib/dts/agents/agent.d.ts +69 -37
  38. package/lib/dts/agents/ai-agent.d.ts +4 -7
  39. package/lib/dts/agents/chat-model.d.ts +7 -8
  40. package/lib/dts/agents/mcp-agent.d.ts +4 -5
  41. package/lib/dts/agents/team-agent.d.ts +7 -8
  42. package/lib/dts/agents/user-agent.d.ts +4 -5
  43. package/lib/dts/aigne/aigne.d.ts +10 -9
  44. package/lib/dts/aigne/context.d.ts +18 -9
  45. package/lib/dts/aigne/message-queue.d.ts +6 -2
  46. package/lib/dts/index.d.ts +3 -1
  47. package/lib/dts/loader/agent-js.d.ts +1 -1
  48. package/lib/dts/loader/agent-yaml.d.ts +3 -2
  49. package/lib/dts/loader/index.d.ts +5 -1
  50. package/lib/dts/memory/memory.d.ts +3 -2
  51. package/lib/dts/memory/retriever.d.ts +2 -2
  52. package/lib/dts/prompt/prompt-builder.d.ts +9 -7
  53. package/lib/dts/utils/nodejs.d.ts +8 -0
  54. package/lib/dts/utils/type-utils.d.ts +2 -2
  55. package/lib/esm/agents/agent.d.ts +69 -37
  56. package/lib/esm/agents/agent.js +94 -66
  57. package/lib/esm/agents/ai-agent.d.ts +4 -7
  58. package/lib/esm/agents/ai-agent.js +10 -19
  59. package/lib/esm/agents/chat-model.d.ts +7 -8
  60. package/lib/esm/agents/chat-model.js +9 -9
  61. package/lib/esm/agents/mcp-agent.d.ts +4 -5
  62. package/lib/esm/agents/mcp-agent.js +7 -13
  63. package/lib/esm/agents/team-agent.d.ts +7 -8
  64. package/lib/esm/agents/team-agent.js +10 -10
  65. package/lib/esm/agents/user-agent.d.ts +4 -5
  66. package/lib/esm/agents/user-agent.js +10 -11
  67. package/lib/esm/aigne/aigne.d.ts +10 -9
  68. package/lib/esm/aigne/aigne.js +5 -4
  69. package/lib/esm/aigne/context.d.ts +18 -9
  70. package/lib/esm/aigne/context.js +24 -10
  71. package/lib/esm/aigne/message-queue.d.ts +6 -2
  72. package/lib/esm/aigne/message-queue.js +2 -2
  73. package/lib/esm/index.d.ts +3 -1
  74. package/lib/esm/index.js +3 -1
  75. package/lib/esm/loader/agent-js.d.ts +1 -1
  76. package/lib/esm/loader/agent-yaml.d.ts +3 -2
  77. package/lib/esm/loader/agent-yaml.js +3 -2
  78. package/lib/esm/loader/index.d.ts +5 -1
  79. package/lib/esm/loader/index.js +25 -16
  80. package/lib/esm/memory/memory.d.ts +3 -2
  81. package/lib/esm/memory/memory.js +2 -2
  82. package/lib/esm/memory/retriever.d.ts +2 -2
  83. package/lib/esm/prompt/prompt-builder.d.ts +9 -7
  84. package/lib/esm/prompt/prompt-builder.js +15 -11
  85. package/lib/esm/prompt/template.js +1 -3
  86. package/lib/esm/utils/logger.js +3 -3
  87. package/lib/esm/utils/nodejs.d.ts +8 -0
  88. package/lib/esm/utils/nodejs.js +21 -0
  89. package/lib/esm/utils/type-utils.d.ts +2 -2
  90. package/package.json +4 -3
  91. package/lib/cjs/memory/default-memory.d.ts +0 -16
  92. package/lib/cjs/memory/default-memory.js +0 -70
  93. package/lib/cjs/utils/fs.d.ts +0 -2
  94. package/lib/cjs/utils/fs.js +0 -25
  95. package/lib/dts/memory/default-memory.d.ts +0 -16
  96. package/lib/dts/utils/fs.d.ts +0 -2
  97. package/lib/esm/memory/default-memory.d.ts +0 -16
  98. package/lib/esm/memory/default-memory.js +0 -63
  99. package/lib/esm/utils/fs.d.ts +0 -2
  100. package/lib/esm/utils/fs.js +0 -21
@@ -1,6 +1,4 @@
1
1
  import { z } from "zod";
2
- import { DefaultMemory } from "../memory/default-memory.js";
3
- import { MemoryAgent } from "../memory/memory.js";
4
2
  import { MESSAGE_KEY, PromptBuilder } from "../prompt/prompt-builder.js";
5
3
  import { AgentMessageTemplate, ToolMessageTemplate } from "../prompt/template.js";
6
4
  import { checkArguments, isEmpty } from "../utils/type-utils.js";
@@ -98,14 +96,7 @@ export class AIAgent extends Agent {
98
96
  * @param options Configuration options for the AI agent
99
97
  */
100
98
  constructor(options) {
101
- super({
102
- ...options,
103
- memory: !options.memory
104
- ? undefined
105
- : Array.isArray(options.memory) || options.memory instanceof MemoryAgent
106
- ? options.memory
107
- : new DefaultMemory(options.memory === true ? {} : options.memory),
108
- });
99
+ super(options);
109
100
  checkArguments("AIAgent", aiAgentOptionsSchema, options);
110
101
  this.model = options.model;
111
102
  this.instructions =
@@ -185,26 +176,26 @@ export class AIAgent extends Agent {
185
176
  *
186
177
  * @protected
187
178
  */
188
- async *process(input, context) {
189
- const model = this.model ?? context.model;
179
+ async *process(input, options) {
180
+ const model = this.model ?? options.context.model;
190
181
  if (!model)
191
182
  throw new Error("model is required to run AIAgent");
192
183
  const { toolAgents, ...modelInput } = await this.instructions.build({
184
+ ...options,
193
185
  agent: this,
194
186
  input,
195
187
  model,
196
- context,
197
188
  });
198
189
  const toolsMap = new Map(toolAgents?.map((i) => [i.name, i]));
199
190
  if (this.toolChoice === "router") {
200
- yield* this._processRouter(input, model, modelInput, context, toolsMap);
191
+ yield* this._processRouter(input, model, modelInput, options, toolsMap);
201
192
  return;
202
193
  }
203
194
  const toolCallMessages = [];
204
195
  const outputKey = this.outputKey || MESSAGE_KEY;
205
196
  for (;;) {
206
197
  const modelOutput = {};
207
- const stream = await context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
198
+ const stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
208
199
  for await (const value of stream) {
209
200
  if (value.delta.text?.text) {
210
201
  yield { delta: { text: { [outputKey]: value.delta.text.text } } };
@@ -222,7 +213,7 @@ export class AIAgent extends Agent {
222
213
  if (!tool)
223
214
  throw new Error(`Tool not found: ${call.function.name}`);
224
215
  // NOTE: should pass both arguments (model generated) and input (user provided) to the tool
225
- const output = await this.invokeSkill(tool, { ...input, ...call.function.arguments }, context).catch((error) => {
216
+ const output = await this.invokeSkill(tool, { ...input, ...call.function.arguments }, options).catch((error) => {
226
217
  if (!this.catchToolsError) {
227
218
  return Promise.reject(error);
228
219
  }
@@ -272,15 +263,15 @@ export class AIAgent extends Agent {
272
263
  *
273
264
  * @protected
274
265
  */
275
- async *_processRouter(input, model, modelInput, context, toolsMap) {
276
- const { toolCalls: [call] = [], } = await context.invoke(model, modelInput);
266
+ async *_processRouter(input, model, modelInput, options, toolsMap) {
267
+ const { toolCalls: [call] = [], } = await options.context.invoke(model, modelInput);
277
268
  if (!call) {
278
269
  throw new Error("Router toolChoice requires exactly one tool to be executed");
279
270
  }
280
271
  const tool = toolsMap.get(call.function.name);
281
272
  if (!tool)
282
273
  throw new Error(`Tool not found: ${call.function.name}`);
283
- const stream = await context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true, sourceAgent: this });
274
+ const stream = await options.context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true, sourceAgent: this });
284
275
  yield* stream;
285
276
  }
286
277
  }
@@ -1,6 +1,5 @@
1
- import type { Context } from "../aigne/context.js";
2
1
  import type { PromiseOrValue } from "../utils/type-utils.js";
3
- import { Agent, type AgentProcessResult, type Message } from "./agent.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
  *
@@ -61,10 +60,10 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
61
60
  * Primarily checks if token usage exceeds limits, throwing an exception if limits are exceeded
62
61
  *
63
62
  * @param input Input message
64
- * @param context Execution context
63
+ * @param options Options for invoking the agent
65
64
  * @throws Error if token usage exceeds maximum limit
66
65
  */
67
- protected preprocess(input: ChatModelInput, context: Context): Promise<void>;
66
+ protected preprocess(input: ChatModelInput, options: AgentInvokeOptions): Promise<void>;
68
67
  /**
69
68
  * Performs postprocessing operations after handling output
70
69
  *
@@ -72,9 +71,9 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
72
71
  *
73
72
  * @param input Input message
74
73
  * @param output Output message
75
- * @param context Execution context
74
+ * @param options Options for invoking the agent
76
75
  */
77
- protected postprocess(input: ChatModelInput, output: ChatModelOutput, context: Context): void;
76
+ protected postprocess(input: ChatModelInput, output: ChatModelOutput, options: AgentInvokeOptions): Promise<void>;
78
77
  /**
79
78
  * Processes input messages and generates model responses
80
79
  *
@@ -92,10 +91,10 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
92
91
  * - Tool call processing if applicable
93
92
  *
94
93
  * @param input - The standardized input containing messages and model options
95
- * @param context - The execution context with settings and state
94
+ * @param options - The options for invoking the agent, including context and limits
96
95
  * @returns A promise or direct value containing the model's response
97
96
  */
98
- abstract process(input: ChatModelInput, context: Context): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
97
+ abstract process(input: ChatModelInput, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
99
98
  }
100
99
  /**
101
100
  * Input message format for ChatModel
@@ -75,12 +75,12 @@ export class ChatModel extends Agent {
75
75
  * Primarily checks if token usage exceeds limits, throwing an exception if limits are exceeded
76
76
  *
77
77
  * @param input Input message
78
- * @param context Execution context
78
+ * @param options Options for invoking the agent
79
79
  * @throws Error if token usage exceeds maximum limit
80
80
  */
81
- async preprocess(input, context) {
82
- super.preprocess(input, context);
83
- const { limits, usage } = context;
81
+ async preprocess(input, options) {
82
+ super.preprocess(input, options);
83
+ const { limits, usage } = options.context;
84
84
  const usedTokens = usage.outputTokens + usage.inputTokens;
85
85
  if (limits?.maxTokens && usedTokens >= limits.maxTokens) {
86
86
  throw new Error(`Exceeded max tokens ${usedTokens}/${limits.maxTokens}`);
@@ -109,9 +109,9 @@ export class ChatModel extends Agent {
109
109
  *
110
110
  * @param input Input message
111
111
  * @param output Output message
112
- * @param context Execution context
112
+ * @param options Options for invoking the agent
113
113
  */
114
- postprocess(input, output, context) {
114
+ async postprocess(input, output, options) {
115
115
  // Restore original tool names in the output
116
116
  if (output.toolCalls?.length) {
117
117
  const toolsMap = input._toolsMap;
@@ -125,11 +125,11 @@ export class ChatModel extends Agent {
125
125
  }
126
126
  }
127
127
  }
128
- super.postprocess(input, output, context);
128
+ super.postprocess(input, output, options);
129
129
  const { usage } = output;
130
130
  if (usage) {
131
- context.usage.outputTokens += usage.outputTokens;
132
- context.usage.inputTokens += usage.inputTokens;
131
+ options.context.usage.outputTokens += usage.outputTokens;
132
+ options.context.usage.inputTokens += usage.inputTokens;
133
133
  }
134
134
  }
135
135
  }
@@ -1,14 +1,13 @@
1
1
  import { Client, type ClientOptions } from "@modelcontextprotocol/sdk/client/index.js";
2
2
  import { type SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
3
- import { type StdioServerParameters } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import type { StdioServerParameters } from "@modelcontextprotocol/sdk/client/stdio.js";
4
4
  import { type StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
5
  import type { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
6
6
  import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
7
7
  import type { CallToolResult, GetPromptResult, Implementation, ReadResourceResult, Request } from "@modelcontextprotocol/sdk/types.js";
8
8
  import { type ZodType, z } from "zod";
9
- import type { Context } from "../aigne/context.js";
10
9
  import { type PromiseOrValue } from "../utils/type-utils.js";
11
- import { Agent, type AgentOptions, type Message } from "./agent.js";
10
+ import { Agent, type AgentInvokeOptions, type AgentOptions, type Message } from "./agent.js";
12
11
  export interface MCPAgentOptions extends AgentOptions {
13
12
  client: Client;
14
13
  prompts?: MCPPrompt[];
@@ -150,10 +149,10 @@ export declare class MCPAgent extends Agent {
150
149
  * throws an error if called.
151
150
  *
152
151
  * @param _input Input message (unused)
153
- * @param _context Execution context (unused)
152
+ * @param _options AgentInvokeOptions (unused)
154
153
  * @throws Error This method always throws an error since MCPAgent is not directly invokable
155
154
  */
156
- process(_input: Message, _context?: Context): Promise<Message>;
155
+ process(_input: Message, _options: AgentInvokeOptions): Promise<Message>;
157
156
  /**
158
157
  * Shut down the agent and close the MCP connection.
159
158
  *
@@ -1,12 +1,13 @@
1
+ import { createStdioClientTransport } from "@aigne/platform-helpers/mcp/stdio-client-transport.js";
1
2
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
3
  import { SSEClientTransport, } from "@modelcontextprotocol/sdk/client/sse.js";
3
- import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js";
4
4
  import { StreamableHTTPClientTransport, } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
5
  import { UriTemplate } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
6
6
  import pRetry from "p-retry";
7
7
  import { z } from "zod";
8
8
  import { logger } from "../utils/logger.js";
9
9
  import { promptFromMCPPrompt, resourceFromMCPResource, toolFromMCPTool, } from "../utils/mcp-utils.js";
10
+ import { nodejs } from "../utils/nodejs.js";
10
11
  import { checkArguments, createAccessorArray } from "../utils/type-utils.js";
11
12
  import { Agent } from "./agent.js";
12
13
  const MCP_AGENT_CLIENT_NAME = "AIGNE/MCPAgent";
@@ -16,7 +17,7 @@ const DEFAULT_TIMEOUT = () => z.coerce
16
17
  .number()
17
18
  .int()
18
19
  .min(0)
19
- .safeParse(process.env.MCP_TIMEOUT || process.env.TIMEOUT).data || 60e3;
20
+ .safeParse(nodejs.env.MCP_TIMEOUT || nodejs.env.TIMEOUT).data || 60e3;
20
21
  function isSSEServerParameters(options) {
21
22
  return "url" in options && typeof options.url === "string";
22
23
  }
@@ -60,14 +61,7 @@ export class MCPAgent extends Agent {
60
61
  return MCPAgent.fromTransport(transport, options);
61
62
  }
62
63
  if (isStdioServerParameters(options)) {
63
- const transport = () => new StdioClientTransport({
64
- ...options,
65
- env: {
66
- ...getDefaultEnvironment(),
67
- ...options.env,
68
- },
69
- stderr: "pipe",
70
- });
64
+ const transport = async () => createStdioClientTransport(options);
71
65
  return MCPAgent.fromTransport(transport, options);
72
66
  }
73
67
  return new MCPAgent(options);
@@ -77,7 +71,7 @@ export class MCPAgent extends Agent {
77
71
  name: MCP_AGENT_CLIENT_NAME,
78
72
  version: MCP_AGENT_CLIENT_VERSION,
79
73
  }, undefined, isSSEServerParameters(options) ? { transportCreator, ...options } : undefined);
80
- const transport = transportCreator();
74
+ const transport = await transportCreator();
81
75
  logger.debug(`Connecting to MCP server: ${getMCPServerString(options)}`);
82
76
  await client.connect(transport);
83
77
  const mcpServer = getMCPServerName(client);
@@ -177,10 +171,10 @@ export class MCPAgent extends Agent {
177
171
  * throws an error if called.
178
172
  *
179
173
  * @param _input Input message (unused)
180
- * @param _context Execution context (unused)
174
+ * @param _options AgentInvokeOptions (unused)
181
175
  * @throws Error This method always throws an error since MCPAgent is not directly invokable
182
176
  */
183
- async process(_input, _context) {
177
+ async process(_input, _options) {
184
178
  throw new Error("Method not implemented.");
185
179
  }
186
180
  /**
@@ -1,6 +1,5 @@
1
- import type { Context } from "../aigne/context.js";
2
1
  import { type PromiseOrValue } from "../utils/type-utils.js";
3
- import { Agent, type AgentOptions, type AgentProcessResult, type Message } from "./agent.js";
2
+ import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessResult, type Message } from "./agent.js";
4
3
  /**
5
4
  * Defines the processing modes available for a TeamAgent.
6
5
  *
@@ -89,10 +88,10 @@ export declare class TeamAgent<I extends Message, O extends Message> extends Age
89
88
  * - In parallel mode: Process input through all agents simultaneously and combine their outputs
90
89
  *
91
90
  * @param input The message to process
92
- * @param context The execution context
91
+ * @param options The invocation options
93
92
  * @returns A stream of message chunks that collectively form the response
94
93
  */
95
- process(input: I, context: Context): PromiseOrValue<AgentProcessResult<O>>;
94
+ process(input: I, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<O>>;
96
95
  /**
97
96
  * Process input sequentially through each agent in the team.
98
97
  *
@@ -103,12 +102,12 @@ export declare class TeamAgent<I extends Message, O extends Message> extends Age
103
102
  * 4. Updates the team's agent list with any changes that occurred during processing
104
103
  *
105
104
  * @param input The message to process
106
- * @param context The execution context
105
+ * @param options The invocation options
107
106
  * @returns A stream of message chunks from all agents
108
107
  *
109
108
  * @private
110
109
  */
111
- _processSequential(input: I, context: Context): PromiseOrValue<AgentProcessResult<O>>;
110
+ _processSequential(input: I, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<O>>;
112
111
  /**
113
112
  * Process input in parallel through all agents in the team.
114
113
  *
@@ -118,10 +117,10 @@ export declare class TeamAgent<I extends Message, O extends Message> extends Age
118
117
  * 3. Updates the team's agent list with any changes that occurred during processing
119
118
  *
120
119
  * @param input The message to process
121
- * @param context The execution context
120
+ * @param options The invocation options
122
121
  * @returns A stream of combined message chunks from all agents
123
122
  *
124
123
  * @private
125
124
  */
126
- _processParallel(input: I, context: Context): PromiseOrValue<AgentProcessResult<O>>;
125
+ _processParallel(input: I, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<O>>;
127
126
  }
@@ -83,15 +83,15 @@ export class TeamAgent extends Agent {
83
83
  * - In parallel mode: Process input through all agents simultaneously and combine their outputs
84
84
  *
85
85
  * @param input The message to process
86
- * @param context The execution context
86
+ * @param options The invocation options
87
87
  * @returns A stream of message chunks that collectively form the response
88
88
  */
89
- process(input, context) {
89
+ process(input, options) {
90
90
  switch (this.mode) {
91
91
  case ProcessMode.sequential:
92
- return this._processSequential(input, context);
92
+ return this._processSequential(input, options);
93
93
  case ProcessMode.parallel:
94
- return this._processParallel(input, context);
94
+ return this._processParallel(input, options);
95
95
  }
96
96
  }
97
97
  /**
@@ -104,18 +104,18 @@ export class TeamAgent extends Agent {
104
104
  * 4. Updates the team's agent list with any changes that occurred during processing
105
105
  *
106
106
  * @param input The message to process
107
- * @param context The execution context
107
+ * @param options The invocation options
108
108
  * @returns A stream of message chunks from all agents
109
109
  *
110
110
  * @private
111
111
  */
112
- async *_processSequential(input, context) {
112
+ async *_processSequential(input, options) {
113
113
  const output = {};
114
114
  // Clone the agents to run, so that we can update the agents list during the loop
115
115
  const agents = [...this.skills];
116
116
  const newAgents = [];
117
117
  for (const agent of agents) {
118
- const [o, transferToAgent] = await context.invoke(agent, { ...input, ...output }, { returnActiveAgent: true, streaming: true });
118
+ const [o, transferToAgent] = await options.context.invoke(agent, { ...input, ...output }, { returnActiveAgent: true, streaming: true });
119
119
  for await (const chunk of o) {
120
120
  yield chunk;
121
121
  mergeAgentResponseChunk(output, chunk);
@@ -134,13 +134,13 @@ export class TeamAgent extends Agent {
134
134
  * 3. Updates the team's agent list with any changes that occurred during processing
135
135
  *
136
136
  * @param input The message to process
137
- * @param context The execution context
137
+ * @param options The invocation options
138
138
  * @returns A stream of combined message chunks from all agents
139
139
  *
140
140
  * @private
141
141
  */
142
- async *_processParallel(input, context) {
143
- const result = await Promise.all(this.skills.map((agent) => context.invoke(agent, input, { returnActiveAgent: true, streaming: true })));
142
+ async *_processParallel(input, options) {
143
+ const result = await Promise.all(this.skills.map((agent) => options.context.invoke(agent, input, { returnActiveAgent: true, streaming: true })));
144
144
  const streams = result.map((i) => i[0]);
145
145
  const read = async (index, reader) => {
146
146
  const promise = reader.read();
@@ -1,7 +1,6 @@
1
- import { ReadableStream } from "node:stream/web";
2
1
  import type { Context } from "../aigne/context.js";
3
2
  import { type MessagePayload } from "../aigne/message-queue.js";
4
- import { Agent, type AgentOptions, type AgentProcessResult, type FunctionAgentFn, type Message } from "./agent.js";
3
+ import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessResult, type FunctionAgentFn, type Message } from "./agent.js";
5
4
  export interface UserAgentOptions<I extends Message = Message, O extends Message = Message> extends AgentOptions<I, O> {
6
5
  context: Context;
7
6
  process?: FunctionAgentFn<I, O>;
@@ -14,14 +13,14 @@ export declare class UserAgent<I extends Message = Message, O extends Message =
14
13
  private _process?;
15
14
  private activeAgent?;
16
15
  protected subscribeToTopics(context: Pick<Context, "subscribe">): void;
17
- protected publishToTopics(output: O, context: Context): Promise<void>;
16
+ protected publishToTopics(output: O, options: AgentInvokeOptions): Promise<void>;
18
17
  invoke: Agent<I, O>["invoke"];
19
- process(input: I, context: Context): Promise<AgentProcessResult<O>>;
18
+ process(input: I, options: AgentInvokeOptions): Promise<AgentProcessResult<O>>;
20
19
  publish: Context["publish"];
21
20
  subscribe: Context["subscribe"];
22
21
  unsubscribe: Context["unsubscribe"];
23
22
  get stream(): ReadableStream<MessagePayload & {
24
23
  topic: string;
25
24
  }>;
26
- protected checkAgentInvokesUsage(_context: Context): void;
25
+ protected checkAgentInvokesUsage(_options: AgentInvokeOptions): void;
27
26
  }
@@ -1,4 +1,3 @@
1
- import { ReadableStream } from "node:stream/web";
2
1
  import { toMessagePayload } from "../aigne/message-queue.js";
3
2
  import { orArrayToArray } from "../utils/type-utils.js";
4
3
  import { Agent, } from "./agent.js";
@@ -19,21 +18,21 @@ export class UserAgent extends Agent {
19
18
  if (this._process)
20
19
  super.subscribeToTopics(context);
21
20
  }
22
- async publishToTopics(output, context) {
21
+ async publishToTopics(output, options) {
23
22
  if (this._process)
24
- super.publishToTopics(output, context);
23
+ super.publishToTopics(output, options);
25
24
  }
26
- invoke = ((input, context, options) => {
27
- if (!context)
25
+ invoke = ((input, options = {}) => {
26
+ if (!options.context)
28
27
  this.context = this.context.newContext({ reset: true });
29
- return super.invoke(input, context ?? this.context, options);
28
+ return super.invoke(input, { ...options, context: this.context });
30
29
  });
31
- async process(input, context) {
30
+ async process(input, options) {
32
31
  if (this._process) {
33
- return this._process(input, context);
32
+ return this._process(input, options);
34
33
  }
35
34
  if (this.activeAgent) {
36
- const [output, agent] = await context.invoke(this.activeAgent, input, {
35
+ const [output, agent] = await options.context.invoke(this.activeAgent, input, {
37
36
  returnActiveAgent: true,
38
37
  streaming: true,
39
38
  });
@@ -44,7 +43,7 @@ export class UserAgent extends Agent {
44
43
  }
45
44
  const publicTopic = typeof this.publishTopic === "function" ? await this.publishTopic(input) : this.publishTopic;
46
45
  if (publicTopic?.length) {
47
- context.publish(publicTopic, input);
46
+ options.context.publish(publicTopic, input);
48
47
  if (this.subscribeTopic) {
49
48
  return this.subscribe(this.subscribeTopic).then((res) => res.message);
50
49
  }
@@ -77,7 +76,7 @@ export class UserAgent extends Agent {
77
76
  },
78
77
  });
79
78
  }
80
- checkAgentInvokesUsage(_context) {
79
+ checkAgentInvokesUsage(_options) {
81
80
  // ignore calls usage check for UserAgent
82
81
  }
83
82
  }
@@ -2,7 +2,7 @@ import { Agent, type AgentResponse, type AgentResponseStream, type Message } fro
2
2
  import { ChatModel } from "../agents/chat-model.js";
3
3
  import type { UserAgent } from "../agents/user-agent.js";
4
4
  import { type LoadOptions } from "../loader/index.js";
5
- import { AIGNEContext, type InvokeOptions } from "./context.js";
5
+ import { AIGNEContext, type Context, type InvokeOptions, type UserContext } from "./context.js";
6
6
  import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
7
7
  import type { ContextLimits } from "./usage.js";
8
8
  /**
@@ -46,7 +46,7 @@ export interface AIGNEOptions {
46
46
  * Here's an example of how to use AIGNE with streaming response:
47
47
  * {@includeCode ../../test/aigne/aigne.test.ts#example-streaming}
48
48
  */
49
- export declare class AIGNE {
49
+ export declare class AIGNE<U extends UserContext = UserContext> {
50
50
  /**
51
51
  * Loads an AIGNE instance from a directory containing an aigne.yaml file and agent definitions.
52
52
  * This static method provides a convenient way to initialize an AIGNE system from configuration files.
@@ -111,7 +111,7 @@ export declare class AIGNE {
111
111
  *
112
112
  * @returns A new AIGNEContext instance bound to this AIGNE.
113
113
  */
114
- newContext(): AIGNEContext;
114
+ newContext(options?: Partial<Context>): AIGNEContext;
115
115
  /**
116
116
  * Creates a user agent for consistent interactions with a specified agent.
117
117
  * This method allows you to create a wrapper around an agent for repeated invocations.
@@ -134,7 +134,7 @@ export declare class AIGNE {
134
134
  * @param options.streaming - Must be false to return a response stream
135
135
  * @returns A promise resolving to a tuple containing the agent's response and the final active agent
136
136
  */
137
- invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options: InvokeOptions & {
137
+ invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options: InvokeOptions<U> & {
138
138
  returnActiveAgent: true;
139
139
  streaming?: false;
140
140
  }): Promise<[O, Agent]>;
@@ -148,7 +148,7 @@ export declare class AIGNE {
148
148
  * @param options.streaming - Must be true to return a response stream
149
149
  * @returns A promise resolving to a tuple containing the agent's response stream and a promise for the final agent
150
150
  */
151
- invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options: InvokeOptions & {
151
+ invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options: InvokeOptions<U> & {
152
152
  returnActiveAgent: true;
153
153
  streaming: true;
154
154
  }): Promise<[AgentResponseStream<O>, Promise<Agent>]>;
@@ -165,7 +165,7 @@ export declare class AIGNE {
165
165
  * Here's a simple example of how to invoke an agent:
166
166
  * {@includeCode ../../test/aigne/aigne.test.ts#example-simple}
167
167
  */
168
- invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options?: InvokeOptions & {
168
+ invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options?: InvokeOptions<U> & {
169
169
  returnActiveAgent?: false;
170
170
  streaming?: false;
171
171
  }): Promise<O>;
@@ -182,7 +182,7 @@ export declare class AIGNE {
182
182
  * Here's an example of how to invoke an agent with streaming response:
183
183
  * {@includeCode ../../test/aigne/aigne.test.ts#example-streaming}
184
184
  */
185
- invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options: InvokeOptions & {
185
+ invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message: I | string, options: InvokeOptions<U> & {
186
186
  returnActiveAgent?: false;
187
187
  streaming: true;
188
188
  }): Promise<AgentResponseStream<O>>;
@@ -196,7 +196,7 @@ export declare class AIGNE {
196
196
  * @returns Either a UserAgent (when no message provided) or a promise resolving to the agent's response
197
197
  * with optional active agent information based on the provided options
198
198
  */
199
- invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message?: I | string, options?: InvokeOptions): UserAgent<I, O> | Promise<AgentResponse<O> | [AgentResponse<O>, Agent]>;
199
+ invoke<I extends Message, O extends Message>(agent: Agent<I, O>, message?: I | string, options?: InvokeOptions<U>): UserAgent<I, O> | Promise<AgentResponse<O> | [AgentResponse<O>, Agent]>;
200
200
  /**
201
201
  * Publishes a message to the message queue for inter-agent communication.
202
202
  * This method broadcasts a message to all subscribers of the specified topic(s).
@@ -204,12 +204,13 @@ export declare class AIGNE {
204
204
  *
205
205
  * @param topic - The topic or array of topics to publish the message to
206
206
  * @param payload - The message payload to be delivered to subscribers
207
+ * @param options - Optional configuration parameters for the publish operation
207
208
  *
208
209
  * @example
209
210
  * Here's an example of how to publish a message:
210
211
  * {@includeCode ../../test/aigne/aigne.test.ts#example-publish-message}
211
212
  */
212
- publish(topic: string | string[], payload: Omit<MessagePayload, "context"> | Message | string): void;
213
+ publish(topic: string | string[], payload: Omit<MessagePayload, "context"> | Message | string, options?: InvokeOptions<U>): void;
213
214
  /**
214
215
  * Subscribes to receive the next message on a specific topic.
215
216
  * This overload returns a Promise that resolves with the next message published to the topic.
@@ -106,8 +106,8 @@ export class AIGNE {
106
106
  *
107
107
  * @returns A new AIGNEContext instance bound to this AIGNE.
108
108
  */
109
- newContext() {
110
- return new AIGNEContext(this);
109
+ newContext(options) {
110
+ return new AIGNEContext(this, options);
111
111
  }
112
112
  invoke(agent, message, options) {
113
113
  return new AIGNEContext(this).invoke(agent, message, options);
@@ -119,13 +119,14 @@ export class AIGNE {
119
119
  *
120
120
  * @param topic - The topic or array of topics to publish the message to
121
121
  * @param payload - The message payload to be delivered to subscribers
122
+ * @param options - Optional configuration parameters for the publish operation
122
123
  *
123
124
  * @example
124
125
  * Here's an example of how to publish a message:
125
126
  * {@includeCode ../../test/aigne/aigne.test.ts#example-publish-message}
126
127
  */
127
- publish(topic, payload) {
128
- return new AIGNEContext(this).publish(topic, payload);
128
+ publish(topic, payload, options) {
129
+ return new AIGNEContext(this).publish(topic, payload, options);
129
130
  }
130
131
  subscribe(topic, listener) {
131
132
  return this.messageQueue.subscribe(topic, listener);
@@ -1,4 +1,4 @@
1
- import EventEmitter from "node:events";
1
+ import { Emitter } from "strict-event-emitter";
2
2
  import { Agent, type AgentInvokeOptions, type AgentProcessAsyncGenerator, type AgentResponse, type AgentResponseStream, type Message } from "../agents/agent.js";
3
3
  import type { ChatModel } from "../agents/chat-model.js";
4
4
  import { UserAgent } from "../agents/user-agent.js";
@@ -38,7 +38,7 @@ export type ContextEmitEventMap = {
38
38
  /**
39
39
  * @hidden
40
40
  */
41
- export interface InvokeOptions extends AgentInvokeOptions {
41
+ export interface InvokeOptions<U extends UserContext = UserContext> extends Partial<Omit<AgentInvokeOptions<U>, "context">> {
42
42
  returnActiveAgent?: boolean;
43
43
  disableTransfer?: boolean;
44
44
  sourceAgent?: Agent;
@@ -46,12 +46,18 @@ export interface InvokeOptions extends AgentInvokeOptions {
46
46
  /**
47
47
  * @hidden
48
48
  */
49
- export interface Context extends TypedEventEmitter<ContextEventMap, ContextEmitEventMap> {
49
+ export interface UserContext extends Record<string, unknown> {
50
+ }
51
+ /**
52
+ * @hidden
53
+ */
54
+ export interface Context<U extends UserContext = UserContext> extends TypedEventEmitter<ContextEventMap, ContextEmitEventMap> {
50
55
  model?: ChatModel;
51
56
  skills?: Agent[];
52
57
  usage: ContextUsage;
53
58
  limits?: ContextLimits;
54
59
  status?: "normal" | "timeout";
60
+ userContext: U;
55
61
  /**
56
62
  * Create a user agent to consistently invoke an agent
57
63
  * @param agent Agent to invoke
@@ -92,7 +98,7 @@ export interface Context extends TypedEventEmitter<ContextEventMap, ContextEmitE
92
98
  * @param topic topic name, or an array of topic names
93
99
  * @param payload message to publish
94
100
  */
95
- publish(topic: string | string[], payload: Omit<MessagePayload, "context"> | Message | string): void;
101
+ publish(topic: string | string[], payload: Omit<MessagePayload, "context"> | Message | string, options?: InvokeOptions): void;
96
102
  subscribe(topic: string | string[], listener?: undefined): Promise<MessagePayload>;
97
103
  subscribe(topic: string | string[], listener: MessageQueueListener): Unsubscribe;
98
104
  subscribe(topic: string | string[], listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
@@ -114,15 +120,17 @@ export interface Context extends TypedEventEmitter<ContextEventMap, ContextEmitE
114
120
  * @hidden
115
121
  */
116
122
  export declare class AIGNEContext implements Context {
117
- constructor(parent?: ConstructorParameters<typeof AIGNEContextInternal>[0]);
123
+ constructor(...[parent, ...args]: ConstructorParameters<typeof AIGNEContextShared>);
118
124
  parentId?: string;
119
125
  id: string;
120
- readonly internal: AIGNEContextInternal;
126
+ readonly internal: AIGNEContextShared;
121
127
  get model(): ChatModel | undefined;
122
128
  get skills(): Agent<Message, Message>[] | undefined;
123
129
  get limits(): ContextLimits | undefined;
124
130
  get status(): "normal" | "timeout";
125
131
  get usage(): ContextUsage;
132
+ get userContext(): Context["userContext"];
133
+ set userContext(userContext: Context["userContext"]);
126
134
  newContext({ reset }?: {
127
135
  reset?: boolean;
128
136
  }): AIGNEContext;
@@ -135,17 +143,18 @@ export declare class AIGNEContext implements Context {
135
143
  once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
136
144
  off<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
137
145
  }
138
- declare class AIGNEContextInternal {
146
+ declare class AIGNEContextShared {
139
147
  private readonly parent?;
140
148
  constructor(parent?: (Pick<Context, "model" | "skills" | "limits"> & {
141
149
  messageQueue?: MessageQueue;
142
- }) | undefined);
150
+ }) | undefined, overrides?: Partial<Context>);
143
151
  readonly messageQueue: MessageQueue;
144
- readonly events: EventEmitter<ContextEventMap>;
152
+ readonly events: Emitter<any>;
145
153
  get model(): ChatModel | undefined;
146
154
  get skills(): Agent<Message, Message>[] | undefined;
147
155
  get limits(): ContextLimits | undefined;
148
156
  usage: ContextUsage;
157
+ userContext: Context["userContext"];
149
158
  private abortController;
150
159
  private timer?;
151
160
  private initTimeout;