@aigne/core 1.5.1-2 → 1.7.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 (97) hide show
  1. package/CHANGELOG.md +28 -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 +11 -0
  7. package/lib/cjs/agents/mcp-agent.js +37 -23
  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 +20 -47
  13. package/lib/cjs/execution-engine/execution-engine.js +20 -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/{esm/loader/function-agent.d.ts → cjs/loader/agent-js.d.ts} +1 -5
  19. package/lib/cjs/loader/{function-agent.js → agent-js.js} +2 -2
  20. package/lib/cjs/loader/{ai-agent.d.ts → agent-yaml.d.ts} +7 -4
  21. package/lib/cjs/loader/agent-yaml.js +58 -0
  22. package/lib/cjs/loader/index.d.ts +14 -4
  23. package/lib/cjs/loader/index.js +57 -22
  24. package/lib/cjs/models/chat-model.d.ts +3 -2
  25. package/lib/cjs/models/chat-model.js +6 -5
  26. package/lib/cjs/models/claude-chat-model.js +10 -7
  27. package/lib/cjs/models/openai-chat-model.js +5 -2
  28. package/lib/cjs/prompt/prompt-builder.d.ts +1 -1
  29. package/lib/cjs/prompt/prompt-builder.js +3 -1
  30. package/lib/cjs/utils/json-schema.js +2 -2
  31. package/lib/cjs/utils/logger.d.ts +3 -15
  32. package/lib/cjs/utils/logger.js +3 -77
  33. package/lib/cjs/utils/mcp-utils.js +1 -5
  34. package/lib/cjs/utils/model-utils.js +2 -2
  35. package/lib/cjs/utils/type-utils.d.ts +1 -0
  36. package/lib/cjs/utils/typed-event-emtter.d.ts +10 -0
  37. package/lib/cjs/utils/typed-event-emtter.js +2 -0
  38. package/lib/dts/agents/agent.d.ts +5 -2
  39. package/lib/dts/agents/ai-agent.d.ts +8 -8
  40. package/lib/dts/agents/mcp-agent.d.ts +11 -0
  41. package/lib/dts/agents/user-agent.d.ts +9 -9
  42. package/lib/dts/execution-engine/context.d.ts +84 -46
  43. package/lib/dts/execution-engine/execution-engine.d.ts +20 -47
  44. package/lib/dts/execution-engine/message-queue.d.ts +3 -3
  45. package/lib/dts/execution-engine/usage.d.ts +11 -0
  46. package/lib/dts/loader/{function-agent.d.ts → agent-js.d.ts} +1 -5
  47. package/lib/dts/loader/{ai-agent.d.ts → agent-yaml.d.ts} +7 -4
  48. package/lib/dts/loader/index.d.ts +14 -4
  49. package/lib/dts/models/chat-model.d.ts +3 -2
  50. package/lib/dts/prompt/prompt-builder.d.ts +1 -1
  51. package/lib/dts/utils/logger.d.ts +3 -15
  52. package/lib/dts/utils/type-utils.d.ts +1 -0
  53. package/lib/dts/utils/typed-event-emtter.d.ts +10 -0
  54. package/lib/esm/agents/agent.d.ts +5 -2
  55. package/lib/esm/agents/agent.js +42 -24
  56. package/lib/esm/agents/ai-agent.d.ts +8 -8
  57. package/lib/esm/agents/ai-agent.js +5 -2
  58. package/lib/esm/agents/mcp-agent.d.ts +11 -0
  59. package/lib/esm/agents/mcp-agent.js +38 -24
  60. package/lib/esm/agents/user-agent.d.ts +9 -9
  61. package/lib/esm/agents/user-agent.js +26 -16
  62. package/lib/esm/execution-engine/context.d.ts +84 -46
  63. package/lib/esm/execution-engine/context.js +135 -98
  64. package/lib/esm/execution-engine/execution-engine.d.ts +20 -47
  65. package/lib/esm/execution-engine/execution-engine.js +21 -39
  66. package/lib/esm/execution-engine/message-queue.d.ts +3 -3
  67. package/lib/esm/execution-engine/message-queue.js +33 -3
  68. package/lib/esm/execution-engine/usage.d.ts +11 -0
  69. package/lib/esm/execution-engine/usage.js +7 -0
  70. package/lib/{cjs/loader/function-agent.d.ts → esm/loader/agent-js.d.ts} +1 -5
  71. package/lib/esm/loader/{function-agent.js → agent-js.js} +2 -2
  72. package/lib/esm/loader/{ai-agent.d.ts → agent-yaml.d.ts} +7 -4
  73. package/lib/esm/loader/agent-yaml.js +55 -0
  74. package/lib/esm/loader/index.d.ts +14 -4
  75. package/lib/esm/loader/index.js +56 -21
  76. package/lib/esm/models/chat-model.d.ts +3 -2
  77. package/lib/esm/models/chat-model.js +6 -5
  78. package/lib/esm/models/claude-chat-model.js +10 -7
  79. package/lib/esm/models/openai-chat-model.js +5 -2
  80. package/lib/esm/prompt/prompt-builder.d.ts +1 -1
  81. package/lib/esm/prompt/prompt-builder.js +3 -1
  82. package/lib/esm/utils/json-schema.js +2 -2
  83. package/lib/esm/utils/logger.d.ts +3 -15
  84. package/lib/esm/utils/logger.js +3 -77
  85. package/lib/esm/utils/mcp-utils.js +1 -5
  86. package/lib/esm/utils/model-utils.js +2 -2
  87. package/lib/esm/utils/type-utils.d.ts +1 -0
  88. package/lib/esm/utils/typed-event-emtter.d.ts +10 -0
  89. package/lib/esm/utils/typed-event-emtter.js +1 -0
  90. package/package.json +10 -10
  91. package/lib/cjs/loader/ai-agent.js +0 -40
  92. package/lib/cjs/utils/run-chat-loop.d.ts +0 -11
  93. package/lib/cjs/utils/run-chat-loop.js +0 -82
  94. package/lib/dts/utils/run-chat-loop.d.ts +0 -11
  95. package/lib/esm/loader/ai-agent.js +0 -37
  96. package/lib/esm/utils/run-chat-loop.d.ts +0 -11
  97. package/lib/esm/utils/run-chat-loop.js +0 -76
@@ -2,19 +2,36 @@ import EventEmitter from "node:events";
2
2
  import { Agent, type FunctionAgentFn, type Message } from "../agents/agent.js";
3
3
  import { UserAgent } from "../agents/user-agent.js";
4
4
  import type { ChatModel } from "../models/chat-model.js";
5
+ import { type OmitPropertiesFromArrayFirstElement } from "../utils/type-utils.js";
6
+ import type { Args, Listener, TypedEventEmitter } from "../utils/typed-event-emtter.js";
5
7
  import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
8
+ import { type ContextLimits, type ContextUsage } from "./usage.js";
6
9
  export type Runnable<I extends Message = Message, O extends Message = Message> = Agent<I, O> | FunctionAgentFn;
7
- export interface ContextUsage {
8
- promptTokens: number;
9
- completionTokens: number;
10
- agentCalls: number;
10
+ export interface AgentEvent {
11
+ parentContextId?: string;
12
+ contextId: string;
13
+ timestamp: number;
14
+ agent: Agent;
11
15
  }
12
- export interface ContextLimits {
13
- maxTokens?: number;
14
- maxAgentCalls?: number;
15
- timeout?: number;
16
+ export interface ContextEventMap {
17
+ agentStarted: [AgentEvent & {
18
+ input: Message;
19
+ }];
20
+ agentSucceed: [AgentEvent & {
21
+ output: Message;
22
+ }];
23
+ agentFailed: [AgentEvent & {
24
+ error: Error;
25
+ }];
16
26
  }
17
- export interface Context extends EventEmitter {
27
+ export type ContextEmitEventMap = {
28
+ [K in keyof ContextEventMap]: OmitPropertiesFromArrayFirstElement<ContextEventMap[K], "contextId" | "parentContextId" | "timestamp">;
29
+ };
30
+ export interface CallOptions {
31
+ returnActiveAgent?: boolean;
32
+ disableTransfer?: boolean;
33
+ }
34
+ export interface Context extends TypedEventEmitter<ContextEventMap, ContextEmitEventMap> {
18
35
  model?: ChatModel;
19
36
  tools?: Agent[];
20
37
  usage: ContextUsage;
@@ -26,13 +43,6 @@ export interface Context extends EventEmitter {
26
43
  * @returns User agent
27
44
  */
28
45
  call<I extends Message, O extends Message>(agent: Runnable<I, O>): UserAgent<I, O>;
29
- /**
30
- * Call an agent with a message
31
- * @param agent Agent to call
32
- * @param message Message to pass to the agent
33
- * @returns the output of the agent
34
- */
35
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string): Promise<O>;
36
46
  /**
37
47
  * Call an agent with a message and return the output and the active agent
38
48
  * @param agent Agent to call
@@ -40,54 +50,82 @@ export interface Context extends EventEmitter {
40
50
  * @param options.returnActiveAgent return the active agent
41
51
  * @returns the output of the agent and the final active agent
42
52
  */
43
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: {
53
+ call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: CallOptions & {
44
54
  returnActiveAgent: true;
45
55
  }): Promise<[O, Runnable]>;
46
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options?: {
47
- returnActiveAgent?: boolean;
48
- }): UserAgent<I, O> | Promise<O | [O, Runnable]>;
56
+ /**
57
+ * Call an agent with a message
58
+ * @param agent Agent to call
59
+ * @param message Message to pass to the agent
60
+ * @returns the output of the agent
61
+ */
62
+ call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options?: CallOptions): Promise<O>;
63
+ call<I extends Message, O extends Message>(agent: Runnable<I, O>, message?: I | string, options?: CallOptions): UserAgent<I, O> | Promise<O | [O, Runnable]>;
49
64
  /**
50
65
  * Publish a message to a topic, the engine will call the listeners of the topic
51
66
  * @param topic topic name, or an array of topic names
52
- * @param message message to publish
53
- * @param from the agent who publish the message, if not provided, it will be treated as a user message
67
+ * @param payload message to publish
54
68
  */
55
- publish(topic: string | string[], message: Message | string, from?: Agent): void;
69
+ publish(topic: string | string[], payload: Omit<MessagePayload, "context">): void;
56
70
  subscribe(topic: string, listener?: undefined): Promise<MessagePayload>;
57
71
  subscribe(topic: string, listener: MessageQueueListener): Unsubscribe;
58
72
  subscribe(topic: string, listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
73
+ subscribe(topic: string, listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
59
74
  unsubscribe(topic: string, listener: MessageQueueListener): void;
75
+ /**
76
+ * Create a child context with the same configuration as the parent context.
77
+ * If `reset` is true, the child context will have a new state (such as: usage).
78
+ *
79
+ * @param options
80
+ * @param options.reset create a new context with initial state (such as: usage)
81
+ * @returns new context
82
+ */
83
+ newContext(options?: {
84
+ reset?: boolean;
85
+ }): Context;
86
+ }
87
+ export declare function createPublishMessage(message: string | Message, from?: Agent): Omit<MessagePayload, "context">;
88
+ export declare class ExecutionContext implements Context {
89
+ constructor(parent?: ConstructorParameters<typeof ExecutionContextInternal>[0]);
90
+ parentId?: string;
91
+ id: string;
92
+ readonly internal: ExecutionContextInternal;
93
+ get model(): ChatModel | undefined;
94
+ get tools(): Agent<Message, Message>[] | undefined;
95
+ get limits(): ContextLimits | undefined;
96
+ get status(): "normal" | "timeout";
97
+ get usage(): ContextUsage;
98
+ newContext({ reset }?: {
99
+ reset?: boolean;
100
+ }): ExecutionContext;
101
+ call: Context["call"];
102
+ publish: Context["publish"];
103
+ subscribe: Context["subscribe"];
104
+ unsubscribe: Context["unsubscribe"];
105
+ emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
106
+ on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
107
+ once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
108
+ off<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
60
109
  }
61
- export declare class ExecutionContext extends EventEmitter implements Context {
62
- private readonly engine?;
63
- constructor(engine?: {
64
- model?: ChatModel;
65
- tools?: Agent[];
66
- limits?: ContextLimits;
110
+ declare class ExecutionContextInternal {
111
+ private readonly parent?;
112
+ constructor(parent?: (Pick<Context, "model" | "tools" | "limits"> & {
67
113
  messageQueue?: MessageQueue;
68
- emit?: EventEmitter["emit"];
69
- } | undefined);
70
- private messageQueue;
114
+ }) | undefined);
115
+ readonly messageQueue: MessageQueue;
116
+ readonly events: EventEmitter<ContextEventMap>;
71
117
  get model(): ChatModel | undefined;
72
118
  get tools(): Agent<Message, Message>[] | undefined;
119
+ get limits(): ContextLimits | undefined;
73
120
  usage: ContextUsage;
74
- limits?: ContextLimits | undefined;
75
121
  private abortController;
76
122
  private timer?;
77
123
  private initTimeout;
78
124
  get status(): "normal" | "timeout";
79
- call<I extends Message, O extends Message>(agent: Runnable<I, O>): UserAgent<I, O>;
80
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string): Promise<O>;
81
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: {
82
- returnActiveAgent: true;
83
- }): Promise<[O, Runnable]>;
84
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message?: I | string, options?: {
85
- returnActiveAgent?: boolean;
86
- }): UserAgent<I, O> | Promise<O | [O, Runnable]>;
87
- publish(topic: string | string[], message: Message | string, from?: Agent): void;
88
- subscribe(topic: string, listener?: undefined): Promise<MessagePayload>;
89
- subscribe(topic: string, listener: MessageQueueListener): Unsubscribe;
90
- unsubscribe(topic: string, listener: MessageQueueListener): void;
91
- emit(eventName: string | symbol, ...args: unknown[]): boolean;
125
+ call<I extends Message, O extends Message>(agent: Runnable<I, O>, input: I, context: Context, options?: CallOptions): Promise<{
126
+ agent: Runnable;
127
+ output: O;
128
+ }>;
92
129
  private callAgent;
93
130
  }
131
+ export {};
@@ -1,134 +1,179 @@
1
1
  import EventEmitter from "node:events";
2
+ import { v7 } from "uuid";
2
3
  import { z } from "zod";
3
4
  import { Agent } from "../agents/agent.js";
4
5
  import { isTransferAgentOutput, transferAgentOutputKey } from "../agents/types.js";
5
6
  import { UserAgent } from "../agents/user-agent.js";
6
7
  import { createMessage } from "../prompt/prompt-builder.js";
7
- import { checkArguments, isNil } from "../utils/type-utils.js";
8
+ import { checkArguments, isNil, } from "../utils/type-utils.js";
8
9
  import { MessageQueue, } from "./message-queue.js";
9
- export class ExecutionContext extends EventEmitter {
10
- engine;
11
- constructor(engine) {
12
- super();
13
- this.engine = engine;
14
- this.limits = engine?.limits;
15
- this.messageQueue = engine?.messageQueue ?? new MessageQueue();
10
+ import { newEmptyContextUsage } from "./usage.js";
11
+ export function createPublishMessage(message, from) {
12
+ return {
13
+ role: !from || from instanceof UserAgent ? "user" : "agent",
14
+ source: from?.name,
15
+ message: createMessage(message),
16
+ };
17
+ }
18
+ export class ExecutionContext {
19
+ constructor(parent) {
20
+ if (parent instanceof ExecutionContext) {
21
+ this.parentId = parent.id;
22
+ this.internal = parent.internal;
23
+ }
24
+ else {
25
+ this.internal = new ExecutionContextInternal(parent);
26
+ }
16
27
  }
17
- messageQueue;
28
+ parentId;
29
+ id = v7();
30
+ internal;
18
31
  get model() {
19
- return this.engine?.model;
32
+ return this.internal.model;
20
33
  }
21
34
  get tools() {
22
- return this.engine?.tools;
35
+ return this.internal.tools;
23
36
  }
24
- usage = {
25
- promptTokens: 0,
26
- completionTokens: 0,
27
- agentCalls: 0,
28
- };
29
- limits;
30
- abortController = new AbortController();
31
- timer;
32
- initTimeout() {
33
- if (this.timer)
34
- return;
35
- const timeout = this.limits?.timeout;
36
- if (timeout) {
37
- this.timer = setTimeout(() => {
38
- this.abortController.abort();
39
- }, timeout);
40
- }
37
+ get limits() {
38
+ return this.internal.limits;
41
39
  }
42
40
  get status() {
43
- return this.abortController.signal.aborted ? "timeout" : "normal";
41
+ return this.internal.status;
42
+ }
43
+ get usage() {
44
+ return this.internal.usage;
45
+ }
46
+ newContext({ reset } = {}) {
47
+ if (reset)
48
+ return new ExecutionContext(this.internal);
49
+ return new ExecutionContext(this);
44
50
  }
45
- call(agent, message, options) {
46
- checkArguments("ExecutionEngine._call", executionEngineCallArgsSchema, {
51
+ call = ((agent, message, options) => {
52
+ checkArguments("ExecutionContext.call", executionContextCallArgsSchema, {
47
53
  agent,
48
54
  message,
49
55
  options,
50
56
  });
51
57
  if (isNil(message)) {
52
- let activeAgent = agent;
53
58
  return UserAgent.from({
54
59
  context: this,
55
- process: async (input, context) => {
56
- const [output, agent] = await context.call(activeAgent, input, {
57
- returnActiveAgent: true,
58
- });
59
- activeAgent = agent;
60
- return output;
61
- },
60
+ activeAgent: agent,
62
61
  });
63
62
  }
64
- return withAbortSignal(this.abortController.signal, new Error("ExecutionEngine is timeout"), async () => {
65
- this.initTimeout();
66
- const msg = createMessageFromInput(message);
67
- return this.callAgent(agent, msg).then(async ({ output, agent: activeAgent }) => {
68
- if (activeAgent instanceof Agent) {
69
- const publishTopics = typeof activeAgent.publishTopic === "function"
70
- ? await activeAgent.publishTopic(output)
71
- : activeAgent.publishTopic;
72
- if (publishTopics?.length) {
73
- this.publish(publishTopics, output, activeAgent);
74
- }
63
+ const newContext = this.newContext();
64
+ const msg = createMessage(message);
65
+ return newContext.internal
66
+ .call(agent, msg, newContext, options)
67
+ .then(async ({ output, agent: activeAgent }) => {
68
+ if (activeAgent instanceof Agent) {
69
+ const publishTopics = typeof activeAgent.publishTopic === "function"
70
+ ? await activeAgent.publishTopic(output)
71
+ : activeAgent.publishTopic;
72
+ if (publishTopics?.length) {
73
+ newContext.publish(publishTopics, createPublishMessage(output, activeAgent));
75
74
  }
76
- if (options?.returnActiveAgent) {
77
- return [output, activeAgent];
78
- }
79
- return output;
80
- });
81
- });
82
- }
83
- publish(topic, message, from) {
84
- checkArguments("ExecutionEngineContext.publish", executionEnginePublishArgsSchema, {
85
- topic,
86
- message,
87
- from,
75
+ }
76
+ if (options?.returnActiveAgent) {
77
+ return [output, activeAgent];
78
+ }
79
+ return output;
88
80
  });
89
- const request = {
90
- role: !from || from instanceof UserAgent ? "user" : "agent",
91
- source: from?.name,
92
- message: createMessageFromInput(message),
93
- context: this,
81
+ });
82
+ publish = ((topic, payload) => {
83
+ return this.internal.messageQueue.publish(topic, { ...payload, context: this });
84
+ });
85
+ subscribe = ((...args) => {
86
+ return this.internal.messageQueue.subscribe(...args);
87
+ });
88
+ unsubscribe = ((...args) => {
89
+ return this.internal.messageQueue.unsubscribe(...args);
90
+ });
91
+ emit(eventName, ...args) {
92
+ const b = {
93
+ ...args[0],
94
+ contextId: this.id,
95
+ parentContextId: this.parentId,
96
+ timestamp: Date.now(),
94
97
  };
95
- this.messageQueue.publish(topic, request);
98
+ const newArgs = [b, ...args.slice(1)];
99
+ return this.internal.events.emit(eventName, ...newArgs);
96
100
  }
97
- subscribe(topic, listener) {
98
- return this.messageQueue.subscribe(topic, listener);
101
+ on(eventName, listener) {
102
+ this.internal.events.on(eventName, listener);
103
+ return this;
99
104
  }
100
- unsubscribe(topic, listener) {
101
- this.messageQueue.unsubscribe(topic, listener);
105
+ once(eventName, listener) {
106
+ this.internal.events.once(eventName, listener);
107
+ return this;
102
108
  }
103
- emit(eventName, ...args) {
104
- if (this.engine?.emit)
105
- return this.engine.emit(eventName, ...args);
106
- return super.emit(eventName, ...args);
109
+ off(eventName, listener) {
110
+ this.internal.events.off(eventName, listener);
111
+ return this;
112
+ }
113
+ }
114
+ class ExecutionContextInternal {
115
+ parent;
116
+ constructor(parent) {
117
+ this.parent = parent;
118
+ this.messageQueue = this.parent?.messageQueue ?? new MessageQueue();
119
+ }
120
+ messageQueue;
121
+ events = new EventEmitter();
122
+ get model() {
123
+ return this.parent?.model;
124
+ }
125
+ get tools() {
126
+ return this.parent?.tools;
107
127
  }
108
- async callAgent(agent, input) {
128
+ get limits() {
129
+ return this.parent?.limits;
130
+ }
131
+ usage = newEmptyContextUsage();
132
+ abortController = new AbortController();
133
+ timer;
134
+ initTimeout() {
135
+ if (this.timer)
136
+ return;
137
+ const timeout = this.limits?.timeout;
138
+ if (timeout) {
139
+ this.timer = setTimeout(() => {
140
+ this.abortController.abort();
141
+ }, timeout);
142
+ }
143
+ }
144
+ get status() {
145
+ return this.abortController.signal.aborted ? "timeout" : "normal";
146
+ }
147
+ async call(agent, input, context, options) {
148
+ this.initTimeout();
149
+ return withAbortSignal(this.abortController.signal, new Error("ExecutionContext is timeout"), () => this.callAgent(agent, input, context, options));
150
+ }
151
+ async callAgent(agent, input, context, options) {
109
152
  let activeAgent = agent;
110
153
  let output;
111
154
  for (;;) {
112
155
  let result;
113
156
  if (typeof activeAgent === "function") {
114
- result = await activeAgent(input, this);
157
+ result = await activeAgent(input, context);
115
158
  }
116
159
  else {
117
- result = await activeAgent.call(input, this);
160
+ result = await activeAgent.call(input, context);
161
+ }
162
+ if (result instanceof Agent) {
163
+ activeAgent = result;
164
+ continue;
118
165
  }
119
- if (!(result instanceof Agent))
120
- output = result;
121
- const transferToAgent = result instanceof Agent
122
- ? result
123
- : isTransferAgentOutput(result)
166
+ if (!options?.disableTransfer) {
167
+ const transferToAgent = isTransferAgentOutput(result)
124
168
  ? result[transferAgentOutputKey].agent
125
169
  : undefined;
126
- if (transferToAgent) {
127
- activeAgent = transferToAgent;
128
- }
129
- else {
130
- break;
170
+ if (transferToAgent) {
171
+ activeAgent = transferToAgent;
172
+ continue;
173
+ }
131
174
  }
175
+ output = result;
176
+ break;
132
177
  }
133
178
  if (!output)
134
179
  throw new Error("Unexpected empty output");
@@ -149,15 +194,7 @@ function withAbortSignal(signal, error, fn) {
149
194
  });
150
195
  });
151
196
  }
152
- function createMessageFromInput(message) {
153
- return typeof message === "string" ? createMessage(message) : message;
154
- }
155
- const executionEnginePublishArgsSchema = z.object({
156
- topic: z.union([z.string(), z.array(z.string())]),
157
- message: z.union([z.string(), z.record(z.unknown())]),
158
- from: z.instanceof(Agent).optional(),
159
- });
160
- const executionEngineCallArgsSchema = z.object({
197
+ const executionContextCallArgsSchema = z.object({
161
198
  agent: z.union([z.function(), z.instanceof(Agent)]),
162
199
  message: z.union([z.record(z.unknown()), z.string()]).optional(),
163
200
  options: z.object({ returnActiveAgent: z.boolean().optional() }).optional(),
@@ -1,68 +1,41 @@
1
- import EventEmitter from "node:events";
2
- import { Agent, type Message } from "../agents/agent.js";
3
- import type { UserAgent } from "../agents/user-agent.js";
1
+ import { Agent } from "../agents/agent.js";
4
2
  import { ChatModel } from "../models/chat-model.js";
5
- import { type ContextLimits, ExecutionContext, type Runnable } from "./context.js";
6
- import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
3
+ import { type Context, ExecutionContext } from "./context.js";
4
+ import { MessageQueue } from "./message-queue.js";
5
+ import type { ContextLimits } from "./usage.js";
7
6
  export interface ExecutionEngineOptions {
7
+ name?: string;
8
+ description?: string;
8
9
  model?: ChatModel;
9
10
  tools?: Agent[];
10
11
  agents?: Agent[];
11
12
  limits?: ContextLimits;
12
13
  }
13
- export declare class ExecutionEngine extends EventEmitter {
14
+ export interface ExecutionEngineRunOptions {
15
+ returnActiveAgent?: boolean;
16
+ }
17
+ export declare class ExecutionEngine {
14
18
  static load({ path, ...options }: {
15
19
  path: string;
16
20
  } & ExecutionEngineOptions): Promise<ExecutionEngine>;
17
21
  constructor(options?: ExecutionEngineOptions);
22
+ name?: string;
23
+ description?: string;
18
24
  readonly messageQueue: MessageQueue;
19
25
  model?: ChatModel;
20
- readonly tools: Agent<Message, Message>[] & {
21
- [key: string]: Agent<Message, Message>;
26
+ readonly tools: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[] & {
27
+ [key: string]: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>;
22
28
  };
23
- readonly agents: Agent<Message, Message>[] & {
24
- [key: string]: Agent<Message, Message>;
29
+ readonly agents: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[] & {
30
+ [key: string]: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>;
25
31
  };
26
32
  limits?: ContextLimits;
27
33
  addAgent(...agents: Agent[]): void;
28
34
  newContext(): ExecutionContext;
29
- /**
30
- * Publish a message to a topic, the engine will call the listeners of the topic
31
- * @param topic topic name, or an array of topic names
32
- * @param message message to publish
33
- * @param from the agent who publish the message, if not provided, it will be treated as a user message
34
- */
35
- publish(topic: string | string[], message: Message | string, from?: Agent): void;
36
- /**
37
- * Create a user agent to consistently call an agent
38
- * @param agent Agent to call
39
- * @returns User agent
40
- */
41
- call<I extends Message, O extends Message>(agent: Runnable<I, O>): UserAgent<I, O>;
42
- /**
43
- * Call an agent with a message
44
- * @param agent Agent to call
45
- * @param message Message to pass to the agent
46
- * @returns the output of the agent
47
- */
48
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string): Promise<O>;
49
- /**
50
- * Call an agent with a message and return the output and the active agent
51
- * @param agent Agent to call
52
- * @param message Message to pass to the agent
53
- * @param options.returnActiveAgent return the active agent
54
- * @returns the output of the agent and the final active agent
55
- */
56
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: {
57
- returnActiveAgent: true;
58
- }): Promise<[O, Runnable]>;
59
- call<I extends Message, O extends Message>(agent: Runnable<I, O>, message?: I | string, options?: {
60
- returnActiveAgent?: boolean;
61
- }): UserAgent<I, O> | Promise<O | [O, Runnable]>;
62
- subscribe(topic: string, listener?: undefined): Promise<MessagePayload>;
63
- subscribe(topic: string, listener: MessageQueueListener): Unsubscribe;
64
- subscribe(topic: string, listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
65
- unsubscribe(topic: string, listener: MessageQueueListener): void;
35
+ publish: Context["publish"];
36
+ call: Context["call"];
37
+ subscribe: Context["subscribe"];
38
+ unsubscribe: Context["unsubscribe"];
66
39
  shutdown(): Promise<void>;
67
40
  private initProcessExitHandler;
68
41
  }
@@ -1,17 +1,18 @@
1
- import EventEmitter from "node:events";
2
1
  import { z } from "zod";
3
2
  import { Agent } from "../agents/agent.js";
4
3
  import { load } from "../loader/index.js";
5
4
  import { ChatModel } from "../models/chat-model.js";
6
5
  import { checkArguments, createAccessorArray } from "../utils/type-utils.js";
7
6
  import { ExecutionContext } from "./context.js";
8
- import { MessageQueue, } from "./message-queue.js";
9
- export class ExecutionEngine extends EventEmitter {
7
+ import { MessageQueue } from "./message-queue.js";
8
+ export class ExecutionEngine {
10
9
  static async load({ path, ...options }) {
11
- const { model, agents, tools } = await load({ path });
10
+ const { model, agents, tools, ...aigne } = await load({ path });
12
11
  return new ExecutionEngine({
13
12
  model,
14
13
  ...options,
14
+ name: options.name || aigne.name || undefined,
15
+ description: options.description || aigne.description || undefined,
15
16
  agents: agents.concat(options.agents ?? []),
16
17
  tools: tools.concat(options.tools ?? []),
17
18
  });
@@ -19,7 +20,8 @@ export class ExecutionEngine extends EventEmitter {
19
20
  constructor(options) {
20
21
  if (options)
21
22
  checkArguments("ExecutionEngine", executionEngineOptionsSchema, options);
22
- super();
23
+ this.name = options?.name;
24
+ this.description = options?.description;
23
25
  this.model = options?.model;
24
26
  this.limits = options?.limits;
25
27
  if (options?.tools?.length)
@@ -28,6 +30,8 @@ export class ExecutionEngine extends EventEmitter {
28
30
  this.addAgent(...options.agents);
29
31
  this.initProcessExitHandler();
30
32
  }
33
+ name;
34
+ description;
31
35
  messageQueue = new MessageQueue();
32
36
  model;
33
37
  tools = createAccessorArray([], (arr, name) => arr.find((i) => i.name === name));
@@ -43,32 +47,18 @@ export class ExecutionEngine extends EventEmitter {
43
47
  newContext() {
44
48
  return new ExecutionContext(this);
45
49
  }
46
- /**
47
- * Publish a message to a topic, the engine will call the listeners of the topic
48
- * @param topic topic name, or an array of topic names
49
- * @param message message to publish
50
- * @param from the agent who publish the message, if not provided, it will be treated as a user message
51
- */
52
- publish(topic, message, from) {
53
- return new ExecutionContext(this).publish(topic, message, from);
54
- }
55
- call(agent, message, options) {
56
- return new ExecutionContext(this).call(agent, message, options);
57
- }
58
- subscribe(topic, listener) {
59
- checkArguments("ExecutionEngine.subscribe", executionEngineSubscribeArgsSchema, {
60
- topic,
61
- listener,
62
- });
63
- return this.messageQueue.subscribe(topic, listener);
64
- }
65
- unsubscribe(topic, listener) {
66
- checkArguments("ExecutionEngine.unsubscribe", executionEngineUnsubscribeArgsSchema, {
67
- topic,
68
- listener,
69
- });
70
- this.messageQueue.unsubscribe(topic, listener);
71
- }
50
+ publish = ((...args) => {
51
+ return new ExecutionContext(this).publish(...args);
52
+ });
53
+ call = ((...args) => {
54
+ return new ExecutionContext(this).call(...args);
55
+ });
56
+ subscribe = ((...args) => {
57
+ return this.messageQueue.subscribe(...args);
58
+ });
59
+ unsubscribe = ((...args) => {
60
+ this.messageQueue.unsubscribe(...args);
61
+ });
72
62
  async shutdown() {
73
63
  for (const tool of this.tools) {
74
64
  await tool.shutdown();
@@ -89,11 +79,3 @@ const executionEngineOptionsSchema = z.object({
89
79
  agents: z.array(z.instanceof(Agent)).optional(),
90
80
  });
91
81
  const executionEngineAddAgentArgsSchema = z.array(z.instanceof(Agent));
92
- const executionEngineSubscribeArgsSchema = z.object({
93
- topic: z.string(),
94
- listener: z.function(z.tuple([z.any()]), z.any()).optional(),
95
- });
96
- const executionEngineUnsubscribeArgsSchema = z.object({
97
- topic: z.string(),
98
- listener: z.function(z.tuple([z.any()]), z.any()),
99
- });
@@ -1,3 +1,4 @@
1
+ import { EventEmitter } from "node:events";
1
2
  import type { Message } from "../agents/agent.js";
2
3
  import type { Context } from "./context.js";
3
4
  export declare const UserInputTopic = "UserInputTopic";
@@ -9,11 +10,10 @@ export interface MessagePayload {
9
10
  context: Context;
10
11
  }
11
12
  export type MessageQueueListener = (message: MessagePayload) => void;
12
- export type MessageRequest = MessagePayload;
13
13
  export type Unsubscribe = () => void;
14
14
  export declare class MessageQueue {
15
- private events;
16
- publish(topic: string | string[], message: MessageRequest): void;
15
+ events: EventEmitter<[never]>;
16
+ publish(topic: string | string[], payload: MessagePayload): void;
17
17
  error(error: Error): void;
18
18
  subscribe(topic: string, listener?: undefined): Promise<MessagePayload>;
19
19
  subscribe(topic: string, listener: MessageQueueListener): Unsubscribe;