@aigne/core 1.6.0 → 1.8.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 (92) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/lib/cjs/agents/agent.d.ts +5 -2
  3. package/lib/cjs/agents/agent.js +42 -24
  4. package/lib/cjs/agents/ai-agent.d.ts +8 -8
  5. package/lib/cjs/agents/ai-agent.js +5 -2
  6. package/lib/cjs/agents/mcp-agent.d.ts +12 -2
  7. package/lib/cjs/agents/mcp-agent.js +45 -27
  8. package/lib/cjs/agents/user-agent.d.ts +9 -9
  9. package/lib/cjs/agents/user-agent.js +26 -16
  10. package/lib/cjs/execution-engine/context.d.ts +84 -46
  11. package/lib/cjs/execution-engine/context.js +136 -98
  12. package/lib/cjs/execution-engine/execution-engine.d.ts +16 -47
  13. package/lib/cjs/execution-engine/execution-engine.js +14 -41
  14. package/lib/cjs/execution-engine/message-queue.d.ts +3 -3
  15. package/lib/cjs/execution-engine/message-queue.js +32 -2
  16. package/lib/cjs/execution-engine/usage.d.ts +11 -0
  17. package/lib/cjs/execution-engine/usage.js +10 -0
  18. package/lib/cjs/loader/agent-js.js +1 -1
  19. package/lib/cjs/loader/agent-yaml.d.ts +1 -0
  20. package/lib/cjs/loader/agent-yaml.js +4 -0
  21. package/lib/cjs/loader/index.d.ts +72 -1
  22. package/lib/cjs/loader/index.js +13 -13
  23. package/lib/cjs/models/chat-model.d.ts +3 -2
  24. package/lib/cjs/models/chat-model.js +6 -5
  25. package/lib/cjs/models/claude-chat-model.js +11 -8
  26. package/lib/cjs/models/openai-chat-model.js +5 -2
  27. package/lib/cjs/prompt/prompt-builder.d.ts +1 -1
  28. package/lib/cjs/prompt/prompt-builder.js +3 -1
  29. package/lib/cjs/utils/json-schema.js +2 -2
  30. package/lib/cjs/utils/logger.d.ts +3 -15
  31. package/lib/cjs/utils/logger.js +3 -77
  32. package/lib/cjs/utils/mcp-utils.js +1 -5
  33. package/lib/cjs/utils/model-utils.js +2 -2
  34. package/lib/cjs/utils/type-utils.d.ts +1 -0
  35. package/lib/cjs/utils/typed-event-emtter.d.ts +10 -0
  36. package/lib/cjs/utils/typed-event-emtter.js +2 -0
  37. package/lib/dts/agents/agent.d.ts +5 -2
  38. package/lib/dts/agents/ai-agent.d.ts +8 -8
  39. package/lib/dts/agents/mcp-agent.d.ts +12 -2
  40. package/lib/dts/agents/user-agent.d.ts +9 -9
  41. package/lib/dts/execution-engine/context.d.ts +84 -46
  42. package/lib/dts/execution-engine/execution-engine.d.ts +16 -47
  43. package/lib/dts/execution-engine/message-queue.d.ts +3 -3
  44. package/lib/dts/execution-engine/usage.d.ts +11 -0
  45. package/lib/dts/loader/agent-yaml.d.ts +1 -0
  46. package/lib/dts/loader/index.d.ts +72 -1
  47. package/lib/dts/models/chat-model.d.ts +3 -2
  48. package/lib/dts/prompt/prompt-builder.d.ts +1 -1
  49. package/lib/dts/utils/logger.d.ts +3 -15
  50. package/lib/dts/utils/type-utils.d.ts +1 -0
  51. package/lib/dts/utils/typed-event-emtter.d.ts +10 -0
  52. package/lib/esm/agents/agent.d.ts +5 -2
  53. package/lib/esm/agents/agent.js +42 -24
  54. package/lib/esm/agents/ai-agent.d.ts +8 -8
  55. package/lib/esm/agents/ai-agent.js +5 -2
  56. package/lib/esm/agents/mcp-agent.d.ts +12 -2
  57. package/lib/esm/agents/mcp-agent.js +46 -28
  58. package/lib/esm/agents/user-agent.d.ts +9 -9
  59. package/lib/esm/agents/user-agent.js +26 -16
  60. package/lib/esm/execution-engine/context.d.ts +84 -46
  61. package/lib/esm/execution-engine/context.js +135 -98
  62. package/lib/esm/execution-engine/execution-engine.d.ts +16 -47
  63. package/lib/esm/execution-engine/execution-engine.js +15 -39
  64. package/lib/esm/execution-engine/message-queue.d.ts +3 -3
  65. package/lib/esm/execution-engine/message-queue.js +33 -3
  66. package/lib/esm/execution-engine/usage.d.ts +11 -0
  67. package/lib/esm/execution-engine/usage.js +7 -0
  68. package/lib/esm/loader/agent-js.js +1 -1
  69. package/lib/esm/loader/agent-yaml.d.ts +1 -0
  70. package/lib/esm/loader/agent-yaml.js +4 -0
  71. package/lib/esm/loader/index.d.ts +72 -1
  72. package/lib/esm/loader/index.js +13 -14
  73. package/lib/esm/models/chat-model.d.ts +3 -2
  74. package/lib/esm/models/chat-model.js +6 -5
  75. package/lib/esm/models/claude-chat-model.js +11 -8
  76. package/lib/esm/models/openai-chat-model.js +5 -2
  77. package/lib/esm/prompt/prompt-builder.d.ts +1 -1
  78. package/lib/esm/prompt/prompt-builder.js +3 -1
  79. package/lib/esm/utils/json-schema.js +2 -2
  80. package/lib/esm/utils/logger.d.ts +3 -15
  81. package/lib/esm/utils/logger.js +3 -77
  82. package/lib/esm/utils/mcp-utils.js +1 -5
  83. package/lib/esm/utils/model-utils.js +2 -2
  84. package/lib/esm/utils/type-utils.d.ts +1 -0
  85. package/lib/esm/utils/typed-event-emtter.d.ts +10 -0
  86. package/lib/esm/utils/typed-event-emtter.js +1 -0
  87. package/package.json +11 -9
  88. package/lib/cjs/utils/run-chat-loop.d.ts +0 -11
  89. package/lib/cjs/utils/run-chat-loop.js +0 -82
  90. package/lib/dts/utils/run-chat-loop.d.ts +0 -11
  91. package/lib/esm/utils/run-chat-loop.d.ts +0 -11
  92. package/lib/esm/utils/run-chat-loop.js +0 -76
package/CHANGELOG.md CHANGED
@@ -22,6 +22,33 @@
22
22
  * rename @aigne/core-next to @aigne/core ([3a81009](https://github.com/AIGNE-io/aigne-framework/commit/3a8100962c81813217b687ae28e8de604419c622))
23
23
  * use text resource from MCP correctly ([8b9eba8](https://github.com/AIGNE-io/aigne-framework/commit/8b9eba83352ec096a2a5d4f410d4c4bde7420bce))
24
24
 
25
+ ## [1.8.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.7.0...core-v1.8.0) (2025-04-17)
26
+
27
+
28
+ ### Features
29
+
30
+ * **ci:** support coverage examples with model matrix ([#59](https://github.com/AIGNE-io/aigne-framework/issues/59)) ([1edd704](https://github.com/AIGNE-io/aigne-framework/commit/1edd70426b80a69e3751b2d5fe818297711d0777))
31
+ * **cli:** support model and download customization for aigne run ([#61](https://github.com/AIGNE-io/aigne-framework/issues/61)) ([51f6619](https://github.com/AIGNE-io/aigne-framework/commit/51f6619e6c591a84f1f2339b26ef66d89fa9486e))
32
+
33
+
34
+ ### Bug Fixes
35
+
36
+ * **mcp:** set default timeout to 60s ([#67](https://github.com/AIGNE-io/aigne-framework/issues/67)) ([40dc029](https://github.com/AIGNE-io/aigne-framework/commit/40dc029b7795650283a505fd71b9566e5f0a4471))
37
+
38
+ ## [1.7.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.6.0...core-v1.7.0) (2025-04-15)
39
+
40
+
41
+ ### Features
42
+
43
+ * add TerminalTracer for better UX in terminal ([#56](https://github.com/AIGNE-io/aigne-framework/issues/56)) ([9875a5d](https://github.com/AIGNE-io/aigne-framework/commit/9875a5d46abb55073340ffae841fed6bd6b83ff4))
44
+ * **cli:** support run agents from remote URL ([#60](https://github.com/AIGNE-io/aigne-framework/issues/60)) ([5f49920](https://github.com/AIGNE-io/aigne-framework/commit/5f4992089d36f9e780ba55a912a1d35508cad28e))
45
+ * **core:** support oauth for McpAgent with example ([#55](https://github.com/AIGNE-io/aigne-framework/issues/55)) ([9420f3a](https://github.com/AIGNE-io/aigne-framework/commit/9420f3a56cf18986cd45f173044e660be76daab4))
46
+
47
+
48
+ ### Bug Fixes
49
+
50
+ * remove usage of new Node.js exists API for compatibility ([#57](https://github.com/AIGNE-io/aigne-framework/issues/57)) ([c10cc08](https://github.com/AIGNE-io/aigne-framework/commit/c10cc086d8ecd0744f38cdb1367d4c8816b723b3))
51
+
25
52
  ## [1.6.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.5.0...core-v1.6.0) (2025-04-08)
26
53
 
27
54
 
@@ -1,3 +1,4 @@
1
+ import { inspect } from "node:util";
1
2
  import { type ZodType } from "zod";
2
3
  import type { Context } from "../execution-engine/context.js";
3
4
  import { type Nullish, type PromiseOrValue } from "../utils/type-utils.js";
@@ -15,7 +16,7 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
15
16
  outputSchema?: AgentInputOutputSchema<O>;
16
17
  includeInputInOutput?: boolean;
17
18
  tools?: (Agent | FunctionAgentFn)[];
18
- disableLogging?: boolean;
19
+ disableEvents?: boolean;
19
20
  memory?: AgentMemory | AgentMemoryOptions | true;
20
21
  }
21
22
  export declare abstract class Agent<I extends Message = Message, O extends Message = Message> {
@@ -37,7 +38,7 @@ export declare abstract class Agent<I extends Message = Message, O extends Messa
37
38
  readonly tools: Agent<Message, Message>[] & {
38
39
  [key: string]: Agent<Message, Message>;
39
40
  };
40
- private disableLogging?;
41
+ private disableEvents?;
41
42
  /**
42
43
  * Attach agent to context:
43
44
  * - subscribe to topic and call process method when message received
@@ -50,10 +51,12 @@ export declare abstract class Agent<I extends Message = Message, O extends Messa
50
51
  private checkContextStatus;
51
52
  private newDefaultContext;
52
53
  call(input: I | string, context?: Context): Promise<O>;
54
+ protected checkUsageAgentCalls(context: Context): void;
53
55
  protected preprocess(_: I, context: Context): void;
54
56
  protected postprocess(input: I, output: O, context: Context): void;
55
57
  abstract process(input: I, context: Context): Promise<O | TransferAgentOutput>;
56
58
  shutdown(): Promise<void>;
59
+ [inspect.custom](): string;
57
60
  }
58
61
  export type AgentInputOutputSchema<I extends Message = Message> = ZodType<I> | ((agent: Agent) => ZodType<I>);
59
62
  export interface FunctionAgentOptions<I extends Message = Message, O extends Message = Message> extends AgentOptions<I, O> {
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.FunctionAgent = exports.Agent = void 0;
37
+ const node_util_1 = require("node:util");
37
38
  const zod_1 = require("zod");
38
39
  const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
39
40
  const logger_js_1 = require("../utils/logger.js");
@@ -55,7 +56,7 @@ class Agent {
55
56
  this.publishTopic = options.publishTopic;
56
57
  if (options.tools?.length)
57
58
  this.tools.push(...options.tools.map(functionToAgent));
58
- this.disableLogging = options.disableLogging;
59
+ this.disableEvents = options.disableEvents;
59
60
  if (options.memory) {
60
61
  this.memory =
61
62
  options.memory instanceof memory_js_1.AgentMemory
@@ -92,7 +93,7 @@ class Agent {
92
93
  subscribeTopic;
93
94
  publishTopic;
94
95
  tools = (0, type_utils_js_1.createAccessorArray)([], (arr, name) => arr.find((t) => t.name === name));
95
- disableLogging;
96
+ disableEvents;
96
97
  /**
97
98
  * Attach agent to context:
98
99
  * - subscribe to topic and call process method when message received
@@ -107,7 +108,7 @@ class Agent {
107
108
  await context.call(this, message);
108
109
  }
109
110
  catch (error) {
110
- context.emit("error", error);
111
+ context.emit("agentFailed", { agent: this, error });
111
112
  }
112
113
  });
113
114
  }
@@ -131,31 +132,45 @@ class Agent {
131
132
  }
132
133
  async call(input, context) {
133
134
  const ctx = context ?? (await this.newDefaultContext());
134
- const _input = typeof input === "string" ? (0, prompt_builder_js_1.createMessage)(input) : input;
135
- const parsedInput = this.inputSchema.parse(_input);
136
- logger_js_1.logger.debug("Call agent %s start with input: %O", this.name, input);
137
- this.preprocess(parsedInput, ctx);
138
- this.checkContextStatus(ctx);
139
- const result = this.process(parsedInput, ctx)
140
- .then((output) => {
141
- const parsedOutput = this.outputSchema.parse(output);
142
- return this.includeInputInOutput ? { ...parsedInput, ...parsedOutput } : parsedOutput;
143
- })
144
- .then((output) => {
145
- this.postprocess(parsedInput, output, ctx);
135
+ const message = typeof input === "string" ? (0, prompt_builder_js_1.createMessage)(input) : input;
136
+ logger_js_1.logger.core("Call agent %s started with input: %O", this.name, input);
137
+ if (!this.disableEvents)
138
+ ctx.emit("agentStarted", { agent: this, input: message });
139
+ try {
140
+ const parsedInput = this.inputSchema.parse(message);
141
+ this.preprocess(parsedInput, ctx);
142
+ this.checkContextStatus(ctx);
143
+ const output = await this.process(parsedInput, ctx)
144
+ .then((output) => {
145
+ const parsedOutput = this.outputSchema.parse(output);
146
+ return this.includeInputInOutput ? { ...parsedInput, ...parsedOutput } : parsedOutput;
147
+ })
148
+ .then((output) => {
149
+ this.postprocess(parsedInput, output, ctx);
150
+ return output;
151
+ });
152
+ logger_js_1.logger.core("Call agent %s succeed with output: %O", this.name, input);
153
+ if (!this.disableEvents)
154
+ ctx.emit("agentSucceed", { agent: this, output });
146
155
  return output;
147
- });
148
- return logger_js_1.logger.debug.spinner(result, `Call agent ${this.name}`, (output) => logger_js_1.logger.debug("Call agent %s succeed with output: %O", this.name, (0, types_js_1.replaceTransferAgentToName)(output)), { disabled: this.disableLogging });
156
+ }
157
+ catch (error) {
158
+ logger_js_1.logger.core("Call agent %s failed with error: %O", this.name, error);
159
+ if (!this.disableEvents)
160
+ ctx.emit("agentFailed", { agent: this, error });
161
+ throw error;
162
+ }
163
+ }
164
+ checkUsageAgentCalls(context) {
165
+ const { limits, usage } = context;
166
+ if (limits?.maxAgentCalls && usage.agentCalls >= limits.maxAgentCalls) {
167
+ throw new Error(`Exceeded max agent calls ${usage.agentCalls}/${limits.maxAgentCalls}`);
168
+ }
169
+ usage.agentCalls++;
149
170
  }
150
171
  preprocess(_, context) {
151
172
  this.checkContextStatus(context);
152
- if (context) {
153
- const { limits, usage } = context;
154
- if (limits?.maxAgentCalls && usage.agentCalls >= limits.maxAgentCalls) {
155
- throw new Error(`Exceeded max agent calls ${usage.agentCalls}/${limits.maxAgentCalls}`);
156
- }
157
- usage.agentCalls++;
158
- }
173
+ this.checkUsageAgentCalls(context);
159
174
  }
160
175
  postprocess(input, output, context) {
161
176
  this.checkContextStatus(context);
@@ -169,6 +184,9 @@ class Agent {
169
184
  async shutdown() {
170
185
  this.memory?.detach();
171
186
  }
187
+ [node_util_1.inspect.custom]() {
188
+ return this.name;
189
+ }
172
190
  }
173
191
  exports.Agent = Agent;
174
192
  function checkAgentInputOutputSchema(schema) {
@@ -28,6 +28,10 @@ export declare const aiAgentOptionsSchema: z.ZodObject<{
28
28
  memory: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodAny, z.ZodAny]>>;
29
29
  }, "strip", z.ZodTypeAny, {
30
30
  description?: string | undefined;
31
+ memory?: any;
32
+ includeInputInOutput?: boolean | undefined;
33
+ subscribeTopic?: string | string[] | undefined;
34
+ publishTopic?: string | string[] | ((...args: unknown[]) => unknown) | undefined;
31
35
  tools?: (Agent<Message, Message> | ((...args: unknown[]) => unknown))[] | undefined;
32
36
  toolChoice?: Agent<Message, Message> | "auto" | "none" | "required" | "router" | undefined;
33
37
  name?: string | undefined;
@@ -36,13 +40,13 @@ export declare const aiAgentOptionsSchema: z.ZodObject<{
36
40
  outputKey?: string | undefined;
37
41
  enableHistory?: boolean | undefined;
38
42
  maxHistoryMessages?: number | undefined;
39
- includeInputInOutput?: boolean | undefined;
40
- subscribeTopic?: string | string[] | undefined;
41
- publishTopic?: string | string[] | ((...args: unknown[]) => unknown) | undefined;
42
43
  disableLogging?: boolean | undefined;
43
- memory?: any;
44
44
  }, {
45
45
  description?: string | undefined;
46
+ memory?: any;
47
+ includeInputInOutput?: boolean | undefined;
48
+ subscribeTopic?: string | string[] | undefined;
49
+ publishTopic?: string | string[] | ((...args: unknown[]) => unknown) | undefined;
46
50
  tools?: (Agent<Message, Message> | ((...args: unknown[]) => unknown))[] | undefined;
47
51
  toolChoice?: Agent<Message, Message> | "auto" | "none" | "required" | "router" | undefined;
48
52
  name?: string | undefined;
@@ -51,11 +55,7 @@ export declare const aiAgentOptionsSchema: z.ZodObject<{
51
55
  outputKey?: string | undefined;
52
56
  enableHistory?: boolean | undefined;
53
57
  maxHistoryMessages?: number | undefined;
54
- includeInputInOutput?: boolean | undefined;
55
- subscribeTopic?: string | string[] | undefined;
56
- publishTopic?: string | string[] | ((...args: unknown[]) => unknown) | undefined;
57
58
  disableLogging?: boolean | undefined;
58
- memory?: any;
59
59
  }>;
60
60
  export declare class AIAgent<I extends Message = Message, O extends Message = Message> extends Agent<I, O> {
61
61
  static from<I extends Message, O extends Message>(options: AIAgentOptions<I, O>): AIAgent<I, O>;
@@ -62,7 +62,10 @@ class AIAgent extends agent_js_1.Agent {
62
62
  const toolsMap = new Map(toolAgents?.map((i) => [i.name, i]));
63
63
  const toolCallMessages = [];
64
64
  for (;;) {
65
- const { text, json, toolCalls } = await model.call({ ...modelInput, messages: messages.concat(toolCallMessages) }, context);
65
+ const { text, json, toolCalls } = await context.call(model, {
66
+ ...modelInput,
67
+ messages: messages.concat(toolCallMessages),
68
+ });
66
69
  if (toolCalls?.length) {
67
70
  const executedToolCalls = [];
68
71
  // Execute tools
@@ -71,7 +74,7 @@ class AIAgent extends agent_js_1.Agent {
71
74
  if (!tool)
72
75
  throw new Error(`Tool not found: ${call.function.name}`);
73
76
  // NOTE: should pass both arguments (model generated) and input (user provided) to the tool
74
- const output = await tool.call({ ...call.function.arguments, ...input }, context);
77
+ const output = await context.call(tool, { ...call.function.arguments, ...input }, { disableTransfer: true });
75
78
  // NOTE: Return transfer output immediately
76
79
  if ((0, types_js_1.isTransferAgentOutput)(output)) {
77
80
  return output;
@@ -1,4 +1,5 @@
1
1
  import { Client, type ClientOptions } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { type SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
2
3
  import { type StdioServerParameters } from "@modelcontextprotocol/sdk/client/stdio.js";
3
4
  import type { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
5
  import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
@@ -15,6 +16,15 @@ export interface MCPAgentOptions extends AgentOptions {
15
16
  export type MCPServerOptions = SSEServerParameters | StdioServerParameters;
16
17
  export type SSEServerParameters = {
17
18
  url: string;
19
+ /**
20
+ * Additional options to pass to the SSEClientTransport.
21
+ */
22
+ opts?: SSEClientTransportOptions;
23
+ /**
24
+ * The timeout for requests to the server, in milliseconds.
25
+ * @default 60000
26
+ */
27
+ timeout?: number;
18
28
  /**
19
29
  * Whether to automatically reconnect to the server if the connection is lost.
20
30
  * @default 10 set to 0 to disable automatic reconnection
@@ -31,7 +41,7 @@ export declare class MCPAgent extends Agent {
31
41
  static from(options: MCPAgentOptions): MCPAgent;
32
42
  private static fromTransport;
33
43
  constructor(options: MCPAgentOptions);
34
- private client;
44
+ client: Client;
35
45
  readonly prompts: MCPPrompt[] & {
36
46
  [key: string]: MCPPrompt;
37
47
  };
@@ -44,6 +54,7 @@ export declare class MCPAgent extends Agent {
44
54
  }
45
55
  export interface ClientWithReconnectOptions {
46
56
  transportCreator?: () => PromiseOrValue<Transport>;
57
+ timeout?: number;
47
58
  maxReconnects?: number;
48
59
  shouldReconnect?: (error: Error) => boolean;
49
60
  }
@@ -60,7 +71,6 @@ export interface MCPBaseOptions<I extends Message = Message, O extends Message =
60
71
  export declare abstract class MCPBase<I extends Message, O extends Message> extends Agent<I, O> {
61
72
  constructor(options: MCPBaseOptions<I, O>);
62
73
  protected client: ClientWithReconnect;
63
- protected get mcpServer(): string | undefined;
64
74
  }
65
75
  export declare class MCPTool extends MCPBase<Message, CallToolResult> {
66
76
  process(input: Message): Promise<CallToolResult>;
@@ -17,7 +17,11 @@ const agent_js_1 = require("./agent.js");
17
17
  const MCP_AGENT_CLIENT_NAME = "MCPAgent";
18
18
  const MCP_AGENT_CLIENT_VERSION = "0.0.1";
19
19
  const DEFAULT_MAX_RECONNECTS = 10;
20
- const debug = logger_js_1.logger.base.extend("mcp");
20
+ const DEFAULT_TIMEOUT = () => zod_1.z.coerce
21
+ .number()
22
+ .int()
23
+ .min(0)
24
+ .safeParse(process.env.MCP_TIMEOUT || process.env.TIMEOUT).data || 60e3;
21
25
  function isSSEServerParameters(options) {
22
26
  return "url" in options && typeof options.url === "string";
23
27
  }
@@ -37,7 +41,7 @@ class MCPAgent extends agent_js_1.Agent {
37
41
  static from(options) {
38
42
  (0, type_utils_js_1.checkArguments)("MCPAgent.from", mcpAgentOptionsSchema, options);
39
43
  if (isSSEServerParameters(options)) {
40
- const transport = () => new sse_js_1.SSEClientTransport(new URL(options.url));
44
+ const transport = () => new sse_js_1.SSEClientTransport(new URL(options.url), options.opts);
41
45
  return MCPAgent.fromTransport(transport, options);
42
46
  }
43
47
  if (isStdioServerParameters(options)) {
@@ -59,29 +63,36 @@ class MCPAgent extends agent_js_1.Agent {
59
63
  version: MCP_AGENT_CLIENT_VERSION,
60
64
  }, undefined, isSSEServerParameters(options) ? { transportCreator, ...options } : undefined);
61
65
  const transport = transportCreator();
62
- await debug.spinner(client.connect(transport), `Connecting to MCP server: ${getMCPServerString(options)}`);
66
+ logger_js_1.logger.mcp(`Connecting to MCP server: ${getMCPServerString(options)}`);
67
+ await client.connect(transport);
63
68
  const mcpServer = getMCPServerName(client);
64
69
  const { tools: isToolsAvailable, prompts: isPromptsAvailable, resources: isResourcesAvailable, } = client.getServerCapabilities() ?? {};
70
+ logger_js_1.logger.mcp(`Listing tools from ${mcpServer}`);
65
71
  const tools = isToolsAvailable
66
- ? await debug
67
- .spinner(client.listTools(), `Listing tools from ${mcpServer}`, ({ tools }) => debug("%O", tools))
68
- .then(({ tools }) => tools.map((tool) => (0, mcp_utils_js_1.toolFromMCPTool)(tool, { client })))
72
+ ? await client.listTools().then(({ tools }) => {
73
+ logger_js_1.logger.mcp(`Listing tools from ${mcpServer} completed %O`, tools?.map((i) => i.name));
74
+ return tools.map((tool) => (0, mcp_utils_js_1.toolFromMCPTool)(tool, { client }));
75
+ })
69
76
  : undefined;
77
+ logger_js_1.logger.mcp(`Listing prompts from ${mcpServer}`);
70
78
  const prompts = isPromptsAvailable
71
- ? await debug
72
- .spinner(client.listPrompts(), `Listing prompts from ${mcpServer}`, ({ prompts }) => debug("%O", prompts))
73
- .then(({ prompts }) => prompts.map((prompt) => (0, mcp_utils_js_1.promptFromMCPPrompt)(prompt, { client })))
79
+ ? await client.listPrompts().then(({ prompts }) => {
80
+ logger_js_1.logger.mcp(`Listing prompts from ${mcpServer} completed %O`, prompts?.map((i) => i.name));
81
+ return prompts.map((prompt) => (0, mcp_utils_js_1.promptFromMCPPrompt)(prompt, { client }));
82
+ })
74
83
  : undefined;
84
+ logger_js_1.logger.mcp(`Listing resources from ${mcpServer}`);
85
+ // TODO: should conditionally call listResourceTemplates based on the server capabilities
86
+ // but the capability is not correct in the current SDK version
75
87
  const resources = isResourcesAvailable
76
- ? await debug
77
- .spinner(
78
- // TODO: should conditionally call listResourceTemplates based on the server capabilities
79
- // but the capability is not correct in the current SDK version
80
- Promise.all([
88
+ ? await Promise.all([
81
89
  client.listResources().catch(() => ({ resources: [] })),
82
90
  client.listResourceTemplates().catch(() => ({ resourceTemplates: [] })),
83
- ]), `Listing resources from ${mcpServer}`, ([{ resources }, { resourceTemplates }]) => debug("%O\n%O", resources, resourceTemplates))
84
- .then(([{ resources }, { resourceTemplates }]) => [...resources, ...resourceTemplates].map((resource) => (0, mcp_utils_js_1.resourceFromMCPResource)(resource, { client })))
91
+ ]).then(([{ resources }, { resourceTemplates }]) => {
92
+ const result = [...resources, ...resourceTemplates].map((resource) => (0, mcp_utils_js_1.resourceFromMCPResource)(resource, { client }));
93
+ logger_js_1.logger.mcp(`Listing resources from ${mcpServer} completed %O`, result.map((i) => i.name));
94
+ return result;
95
+ })
85
96
  : undefined;
86
97
  return new MCPAgent({
87
98
  name: client.getServerVersion()?.name,
@@ -134,22 +145,28 @@ class ClientWithReconnect extends index_js_1.Client {
134
145
  throw new Error("reconnect requires a transportCreator");
135
146
  await (0, p_retry_1.default)(async () => {
136
147
  await this.close();
137
- await this.connect(await transportCreator());
148
+ await this.connect(await transportCreator(), {
149
+ timeout: this.reconnectOptions?.timeout ?? DEFAULT_TIMEOUT(),
150
+ });
138
151
  }, {
139
152
  retries: this.reconnectOptions?.maxReconnects ?? DEFAULT_MAX_RECONNECTS,
140
153
  shouldRetry: this.shouldReconnect,
141
- onFailedAttempt: (error) => debug("Reconnect attempt failed: %O", error),
154
+ onFailedAttempt: (error) => logger_js_1.logger.mcp("Reconnect attempt failed: %O", error),
142
155
  });
143
156
  }
144
157
  async request(request, resultSchema, options) {
158
+ const mergedOptions = {
159
+ ...options,
160
+ timeout: options?.timeout ?? DEFAULT_TIMEOUT(),
161
+ };
145
162
  try {
146
- return await super.request(request, resultSchema, options);
163
+ return await super.request(request, resultSchema, mergedOptions);
147
164
  }
148
165
  catch (error) {
149
166
  if (this.shouldReconnect(error)) {
150
- debug("Error occurred, reconnecting to MCP server: %O", error);
167
+ logger_js_1.logger.mcp("Error occurred, reconnecting to MCP server: %O", error);
151
168
  await this.reconnect();
152
- return await super.request(request, resultSchema, options);
169
+ return await super.request(request, resultSchema, mergedOptions);
153
170
  }
154
171
  throw error;
155
172
  }
@@ -161,21 +178,18 @@ class MCPBase extends agent_js_1.Agent {
161
178
  this.client = options.client;
162
179
  }
163
180
  client;
164
- get mcpServer() {
165
- return getMCPServerName(this.client);
166
- }
167
181
  }
168
182
  exports.MCPBase = MCPBase;
169
183
  class MCPTool extends MCPBase {
170
184
  async process(input) {
171
- const result = await debug.spinner(this.client.callTool({ name: this.name, arguments: input }), `Call tool ${this.name} from ${this.mcpServer}`, (output) => debug("input: %O\noutput: %O", input, output));
185
+ const result = await this.client.callTool({ name: this.name, arguments: input });
172
186
  return result;
173
187
  }
174
188
  }
175
189
  exports.MCPTool = MCPTool;
176
190
  class MCPPrompt extends MCPBase {
177
191
  async process(input) {
178
- const result = await debug.spinner(this.client.getPrompt({ name: this.name, arguments: input }), `Get prompt ${this.name} from ${this.mcpServer}`, (output) => debug("input: %O\noutput: %O", input, output));
192
+ const result = await this.client.getPrompt({ name: this.name, arguments: input });
179
193
  return result;
180
194
  }
181
195
  }
@@ -188,7 +202,7 @@ class MCPResource extends MCPBase {
188
202
  uri;
189
203
  async process(input) {
190
204
  const uri = new uriTemplate_js_1.UriTemplate(this.uri).expand(input);
191
- const result = await debug.spinner(this.client.readResource({ uri }), `Read resource ${this.name} from ${this.mcpServer}`, (output) => debug("input: %O\noutput: %O", input, output));
205
+ const result = await this.client.readResource({ uri });
192
206
  return result;
193
207
  }
194
208
  }
@@ -208,6 +222,10 @@ const mcpAgentOptionsSchema = zod_1.z.union([
208
222
  }),
209
223
  zod_1.z.object({
210
224
  url: zod_1.z.string(),
225
+ opts: zod_1.z.object({}).optional(),
226
+ timeout: zod_1.z.number().optional(),
227
+ maxReconnects: zod_1.z.number().optional(),
228
+ shouldReconnect: zod_1.z.function().args(zod_1.z.instanceof(Error)).returns(zod_1.z.boolean()).optional(),
211
229
  }),
212
230
  zod_1.z.object({
213
231
  command: zod_1.z.string(),
@@ -1,26 +1,26 @@
1
1
  import { ReadableStream } from "node:stream/web";
2
- import type { Context } from "../execution-engine/context.js";
3
- import type { MessagePayload, MessageQueueListener, Unsubscribe } from "../execution-engine/message-queue.js";
2
+ import { type Context, type Runnable } from "../execution-engine/context.js";
3
+ import type { MessagePayload } from "../execution-engine/message-queue.js";
4
4
  import { type PromiseOrValue } from "../utils/type-utils.js";
5
5
  import { Agent, type AgentOptions, type Message } from "./agent.js";
6
6
  export interface UserAgentOptions<I extends Message = Message, O extends Message = Message> extends AgentOptions<I, O> {
7
7
  context: Context;
8
8
  process?: (input: I, context: Context) => PromiseOrValue<O>;
9
+ activeAgent?: Runnable;
9
10
  }
10
11
  export declare class UserAgent<I extends Message = Message, O extends Message = Message> extends Agent<I, O> {
11
12
  static from<I extends Message, O extends Message>(options: UserAgentOptions<I, O>): UserAgent<I, O>;
12
13
  constructor(options: UserAgentOptions<I, O>);
13
- readonly context: Context;
14
- private get ctx();
14
+ context: Context;
15
15
  private _process?;
16
+ private activeAgent?;
16
17
  call(input: string | I, context?: Context): Promise<O>;
17
18
  process(input: I, context: Context): Promise<O>;
18
- publish(topic: string | string[], message: Message | string): void;
19
- subscribe(topic: string, listener?: undefined): Promise<MessagePayload>;
20
- subscribe(topic: string, listener: MessageQueueListener): Unsubscribe;
21
- subscribe(topic: string, listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
22
- unsubscribe(topic: string, listener: MessageQueueListener): void;
19
+ publish: Context["publish"];
20
+ subscribe: Context["subscribe"];
21
+ unsubscribe: Context["unsubscribe"];
23
22
  get stream(): ReadableStream<MessagePayload & {
24
23
  topic: string;
25
24
  }>;
25
+ protected checkUsageAgentCalls(_context: Context): void;
26
26
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UserAgent = void 0;
4
4
  const web_1 = require("node:stream/web");
5
+ const context_js_1 = require("../execution-engine/context.js");
5
6
  const type_utils_js_1 = require("../utils/type-utils.js");
6
7
  const agent_js_1 = require("./agent.js");
7
8
  class UserAgent extends agent_js_1.Agent {
@@ -9,40 +10,46 @@ class UserAgent extends agent_js_1.Agent {
9
10
  return new UserAgent(options);
10
11
  }
11
12
  constructor(options) {
12
- super({ ...options, disableLogging: true });
13
+ super({ ...options, disableEvents: true });
13
14
  this._process = options.process;
14
15
  this.context = options.context;
16
+ this.activeAgent = options.activeAgent;
15
17
  }
16
18
  context;
17
- get ctx() {
18
- if (!this.context)
19
- throw new Error("UserAgent must have a context");
20
- return this.context;
21
- }
22
19
  _process;
20
+ activeAgent;
23
21
  call(input, context) {
22
+ if (!context)
23
+ this.context = this.context.newContext({ reset: true });
24
24
  return super.call(input, context ?? this.context);
25
25
  }
26
26
  async process(input, context) {
27
27
  if (this._process) {
28
28
  return this._process(input, context);
29
29
  }
30
+ if (this.activeAgent) {
31
+ const [output, agent] = await context.call(this.activeAgent, input, {
32
+ returnActiveAgent: true,
33
+ });
34
+ this.activeAgent = agent;
35
+ return output;
36
+ }
30
37
  const publicTopic = typeof this.publishTopic === "function" ? await this.publishTopic(input) : this.publishTopic;
31
38
  if (publicTopic?.length) {
32
- context.publish(publicTopic, input, this);
39
+ context.publish(publicTopic, (0, context_js_1.createPublishMessage)(input, this));
33
40
  return {};
34
41
  }
35
42
  throw new Error("UserAgent must have a process function or a publishTopic");
36
43
  }
37
- publish(topic, message) {
38
- return this.ctx.publish(topic, message, this);
39
- }
40
- subscribe(topic, listener) {
41
- return this.ctx.subscribe(topic, listener);
42
- }
43
- unsubscribe(topic, listener) {
44
- this.ctx.unsubscribe(topic, listener);
45
- }
44
+ publish = ((...args) => {
45
+ return this.context.publish(...args);
46
+ });
47
+ subscribe = ((...args) => {
48
+ return this.context.subscribe(...args);
49
+ });
50
+ unsubscribe = ((...args) => {
51
+ this.context.unsubscribe(...args);
52
+ });
46
53
  get stream() {
47
54
  let subscriptions = [];
48
55
  return new web_1.ReadableStream({
@@ -59,5 +66,8 @@ class UserAgent extends agent_js_1.Agent {
59
66
  },
60
67
  });
61
68
  }
69
+ checkUsageAgentCalls(_context) {
70
+ // ignore calls usage check for UserAgent
71
+ }
62
72
  }
63
73
  exports.UserAgent = UserAgent;