@aigne/core 1.4.1-9 → 1.5.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/lib/cjs/agents/agent.d.ts +8 -4
- package/lib/cjs/agents/agent.js +69 -8
- package/lib/cjs/agents/ai-agent.d.ts +5 -5
- package/lib/cjs/agents/ai-agent.js +1 -3
- package/lib/cjs/agents/memory.d.ts +1 -1
- package/lib/cjs/agents/user-agent.d.ts +4 -3
- package/lib/cjs/agents/user-agent.js +5 -5
- package/lib/cjs/execution-engine/context.d.ts +58 -5
- package/lib/cjs/execution-engine/context.js +169 -0
- package/lib/cjs/execution-engine/execution-engine.d.ts +10 -13
- package/lib/cjs/execution-engine/execution-engine.js +7 -96
- package/lib/cjs/execution-engine/message-queue.d.ts +2 -0
- package/lib/cjs/execution-engine/utils.d.ts +2 -2
- package/lib/cjs/execution-engine/utils.js +11 -15
- package/lib/cjs/index.d.ts +0 -7
- package/lib/cjs/index.js +0 -7
- package/lib/cjs/models/chat-model.d.ts +8 -0
- package/lib/cjs/models/chat-model.js +21 -0
- package/lib/cjs/models/claude-chat-model.js +24 -4
- package/lib/cjs/models/openai-chat-model.d.ts +2 -1
- package/lib/cjs/models/openai-chat-model.js +13 -1
- package/lib/cjs/models/xai-chat-model.d.ts +1 -2
- package/lib/cjs/models/xai-chat-model.js +0 -2
- package/lib/cjs/prompt/prompt-builder.js +3 -3
- package/lib/cjs/utils/json-schema.js +1 -2
- package/lib/cjs/utils/logger.d.ts +9 -1
- package/lib/cjs/utils/logger.js +47 -3
- package/lib/cjs/utils/model-utils.d.ts +3 -0
- package/lib/cjs/utils/model-utils.js +9 -0
- package/lib/cjs/utils/type-utils.d.ts +2 -3
- package/lib/cjs/utils/type-utils.js +16 -11
- package/lib/dts/agents/agent.d.ts +8 -4
- package/lib/dts/agents/ai-agent.d.ts +5 -5
- package/lib/dts/agents/memory.d.ts +1 -1
- package/lib/dts/agents/user-agent.d.ts +4 -3
- package/lib/dts/execution-engine/context.d.ts +58 -5
- package/lib/dts/execution-engine/execution-engine.d.ts +10 -13
- package/lib/dts/execution-engine/message-queue.d.ts +2 -0
- package/lib/dts/execution-engine/utils.d.ts +2 -2
- package/lib/dts/index.d.ts +0 -7
- package/lib/dts/models/chat-model.d.ts +8 -0
- package/lib/dts/models/openai-chat-model.d.ts +2 -1
- package/lib/dts/models/xai-chat-model.d.ts +1 -2
- package/lib/dts/utils/logger.d.ts +9 -1
- package/lib/dts/utils/model-utils.d.ts +3 -0
- package/lib/dts/utils/type-utils.d.ts +2 -3
- package/lib/esm/agents/agent.d.ts +8 -4
- package/lib/esm/agents/agent.js +36 -8
- package/lib/esm/agents/ai-agent.d.ts +5 -5
- package/lib/esm/agents/ai-agent.js +1 -3
- package/lib/esm/agents/memory.d.ts +1 -1
- package/lib/esm/agents/user-agent.d.ts +4 -3
- package/lib/esm/agents/user-agent.js +5 -5
- package/lib/esm/execution-engine/context.d.ts +58 -5
- package/lib/esm/execution-engine/context.js +164 -1
- package/lib/esm/execution-engine/execution-engine.d.ts +10 -13
- package/lib/esm/execution-engine/execution-engine.js +7 -96
- package/lib/esm/execution-engine/message-queue.d.ts +2 -0
- package/lib/esm/execution-engine/utils.d.ts +2 -2
- package/lib/esm/execution-engine/utils.js +11 -15
- package/lib/esm/index.d.ts +0 -7
- package/lib/esm/index.js +0 -7
- package/lib/esm/models/chat-model.d.ts +8 -0
- package/lib/esm/models/chat-model.js +21 -0
- package/lib/esm/models/claude-chat-model.js +24 -4
- package/lib/esm/models/openai-chat-model.d.ts +2 -1
- package/lib/esm/models/openai-chat-model.js +13 -1
- package/lib/esm/models/xai-chat-model.d.ts +1 -2
- package/lib/esm/models/xai-chat-model.js +0 -2
- package/lib/esm/prompt/prompt-builder.js +1 -1
- package/lib/esm/utils/json-schema.js +1 -2
- package/lib/esm/utils/logger.d.ts +9 -1
- package/lib/esm/utils/logger.js +15 -3
- package/lib/esm/utils/model-utils.d.ts +3 -0
- package/lib/esm/utils/model-utils.js +6 -0
- package/lib/esm/utils/type-utils.d.ts +2 -3
- package/lib/esm/utils/type-utils.js +12 -8
- package/package.json +31 -13
|
@@ -1,11 +1,31 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import EventEmitter from "node:events";
|
|
2
|
+
import { Agent, type FunctionAgentFn, type Message } from "../agents/agent.js";
|
|
3
|
+
import { UserAgent } from "../agents/user-agent.js";
|
|
3
4
|
import type { ChatModel } from "../models/chat-model.js";
|
|
4
|
-
import type
|
|
5
|
+
import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
|
|
5
6
|
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;
|
|
11
|
+
}
|
|
12
|
+
export interface ContextLimits {
|
|
13
|
+
maxTokens?: number;
|
|
14
|
+
maxAgentCalls?: number;
|
|
15
|
+
timeout?: number;
|
|
16
|
+
}
|
|
6
17
|
export interface Context extends EventEmitter {
|
|
7
18
|
model?: ChatModel;
|
|
8
19
|
tools?: Agent[];
|
|
20
|
+
usage: ContextUsage;
|
|
21
|
+
limits?: ContextLimits;
|
|
22
|
+
status?: "normal" | "timeout";
|
|
23
|
+
/**
|
|
24
|
+
* Create a user agent to consistently call an agent
|
|
25
|
+
* @param agent Agent to call
|
|
26
|
+
* @returns User agent
|
|
27
|
+
*/
|
|
28
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>): UserAgent<I, O>;
|
|
9
29
|
/**
|
|
10
30
|
* Call an agent with a message
|
|
11
31
|
* @param agent Agent to call
|
|
@@ -21,11 +41,11 @@ export interface Context extends EventEmitter {
|
|
|
21
41
|
* @returns the output of the agent and the final active agent
|
|
22
42
|
*/
|
|
23
43
|
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: {
|
|
24
|
-
returnActiveAgent
|
|
44
|
+
returnActiveAgent: true;
|
|
25
45
|
}): Promise<[O, Runnable]>;
|
|
26
46
|
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options?: {
|
|
27
47
|
returnActiveAgent?: boolean;
|
|
28
|
-
}): Promise<O | [O, Runnable]>;
|
|
48
|
+
}): UserAgent<I, O> | Promise<O | [O, Runnable]>;
|
|
29
49
|
/**
|
|
30
50
|
* Publish a message to a topic, the engine will call the listeners of the topic
|
|
31
51
|
* @param topic topic name, or an array of topic names
|
|
@@ -38,3 +58,36 @@ export interface Context extends EventEmitter {
|
|
|
38
58
|
subscribe(topic: string, listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
|
|
39
59
|
unsubscribe(topic: string, listener: MessageQueueListener): void;
|
|
40
60
|
}
|
|
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;
|
|
67
|
+
messageQueue?: MessageQueue;
|
|
68
|
+
emit?: EventEmitter["emit"];
|
|
69
|
+
} | undefined);
|
|
70
|
+
private messageQueue;
|
|
71
|
+
get model(): ChatModel | undefined;
|
|
72
|
+
get tools(): Agent<Message, Message>[] | undefined;
|
|
73
|
+
usage: ContextUsage;
|
|
74
|
+
limits?: ContextLimits | undefined;
|
|
75
|
+
private abortController;
|
|
76
|
+
private timer?;
|
|
77
|
+
private initTimeout;
|
|
78
|
+
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;
|
|
92
|
+
private callAgent;
|
|
93
|
+
}
|
|
@@ -1 +1,164 @@
|
|
|
1
|
-
|
|
1
|
+
import EventEmitter from "node:events";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { Agent } from "../agents/agent.js";
|
|
4
|
+
import { isTransferAgentOutput, transferAgentOutputKey } from "../agents/types.js";
|
|
5
|
+
import { UserAgent } from "../agents/user-agent.js";
|
|
6
|
+
import { createMessage } from "../prompt/prompt-builder.js";
|
|
7
|
+
import { checkArguments, isNil } from "../utils/type-utils.js";
|
|
8
|
+
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();
|
|
16
|
+
}
|
|
17
|
+
messageQueue;
|
|
18
|
+
get model() {
|
|
19
|
+
return this.engine?.model;
|
|
20
|
+
}
|
|
21
|
+
get tools() {
|
|
22
|
+
return this.engine?.tools;
|
|
23
|
+
}
|
|
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
|
+
}
|
|
41
|
+
}
|
|
42
|
+
get status() {
|
|
43
|
+
return this.abortController.signal.aborted ? "timeout" : "normal";
|
|
44
|
+
}
|
|
45
|
+
call(agent, message, options) {
|
|
46
|
+
checkArguments("ExecutionEngine._call", executionEngineCallArgsSchema, {
|
|
47
|
+
agent,
|
|
48
|
+
message,
|
|
49
|
+
options,
|
|
50
|
+
});
|
|
51
|
+
if (isNil(message)) {
|
|
52
|
+
let activeAgent = agent;
|
|
53
|
+
return UserAgent.from({
|
|
54
|
+
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
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
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
|
+
}
|
|
75
|
+
}
|
|
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,
|
|
88
|
+
});
|
|
89
|
+
const request = {
|
|
90
|
+
role: !from || from instanceof UserAgent ? "user" : "agent",
|
|
91
|
+
source: from?.name,
|
|
92
|
+
message: createMessageFromInput(message),
|
|
93
|
+
context: this,
|
|
94
|
+
};
|
|
95
|
+
this.messageQueue.publish(topic, request);
|
|
96
|
+
}
|
|
97
|
+
subscribe(topic, listener) {
|
|
98
|
+
return this.messageQueue.subscribe(topic, listener);
|
|
99
|
+
}
|
|
100
|
+
unsubscribe(topic, listener) {
|
|
101
|
+
this.messageQueue.unsubscribe(topic, listener);
|
|
102
|
+
}
|
|
103
|
+
emit(eventName, ...args) {
|
|
104
|
+
if (this.engine?.emit)
|
|
105
|
+
return this.engine.emit(eventName, ...args);
|
|
106
|
+
return super.emit(eventName, ...args);
|
|
107
|
+
}
|
|
108
|
+
async callAgent(agent, input) {
|
|
109
|
+
let activeAgent = agent;
|
|
110
|
+
let output;
|
|
111
|
+
for (;;) {
|
|
112
|
+
let result;
|
|
113
|
+
if (typeof activeAgent === "function") {
|
|
114
|
+
result = await activeAgent(input, this);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
result = await activeAgent.call(input, this);
|
|
118
|
+
}
|
|
119
|
+
if (!(result instanceof Agent))
|
|
120
|
+
output = result;
|
|
121
|
+
const transferToAgent = result instanceof Agent
|
|
122
|
+
? result
|
|
123
|
+
: isTransferAgentOutput(result)
|
|
124
|
+
? result[transferAgentOutputKey].agent
|
|
125
|
+
: undefined;
|
|
126
|
+
if (transferToAgent) {
|
|
127
|
+
activeAgent = transferToAgent;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (!output)
|
|
134
|
+
throw new Error("Unexpected empty output");
|
|
135
|
+
return {
|
|
136
|
+
agent: activeAgent,
|
|
137
|
+
output,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function withAbortSignal(signal, error, fn) {
|
|
142
|
+
return new Promise((resolve, reject) => {
|
|
143
|
+
const listener = () => reject(error);
|
|
144
|
+
signal.addEventListener("abort", listener);
|
|
145
|
+
fn()
|
|
146
|
+
.then(resolve, reject)
|
|
147
|
+
.finally(() => {
|
|
148
|
+
signal.removeEventListener("abort", listener);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
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({
|
|
161
|
+
agent: z.union([z.function(), z.instanceof(Agent)]),
|
|
162
|
+
message: z.union([z.record(z.unknown()), z.string()]).optional(),
|
|
163
|
+
options: z.object({ returnActiveAgent: z.boolean().optional() }).optional(),
|
|
164
|
+
});
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import EventEmitter from "node:events";
|
|
2
2
|
import { Agent, type Message } from "../agents/agent.js";
|
|
3
|
-
import { UserAgent } from "../agents/user-agent.js";
|
|
3
|
+
import type { UserAgent } from "../agents/user-agent.js";
|
|
4
4
|
import { ChatModel } from "../models/chat-model.js";
|
|
5
|
-
import type
|
|
5
|
+
import { type ContextLimits, ExecutionContext, type Runnable } from "./context.js";
|
|
6
6
|
import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
|
|
7
7
|
export interface ExecutionEngineOptions {
|
|
8
8
|
model?: ChatModel;
|
|
9
9
|
tools?: Agent[];
|
|
10
10
|
agents?: Agent[];
|
|
11
|
+
limits?: ContextLimits;
|
|
11
12
|
}
|
|
12
|
-
export declare class ExecutionEngine extends EventEmitter
|
|
13
|
+
export declare class ExecutionEngine extends EventEmitter {
|
|
13
14
|
constructor(options?: ExecutionEngineOptions);
|
|
14
15
|
readonly messageQueue: MessageQueue;
|
|
15
16
|
model?: ChatModel;
|
|
16
17
|
tools: Agent[];
|
|
17
18
|
private agents;
|
|
19
|
+
limits?: ContextLimits;
|
|
18
20
|
addAgent(...agents: Agent[]): void;
|
|
19
|
-
|
|
21
|
+
newContext(): ExecutionContext;
|
|
20
22
|
/**
|
|
21
23
|
* Publish a message to a topic, the engine will call the listeners of the topic
|
|
22
24
|
* @param topic topic name, or an array of topic names
|
|
@@ -45,20 +47,15 @@ export declare class ExecutionEngine extends EventEmitter implements Context {
|
|
|
45
47
|
* @returns the output of the agent and the final active agent
|
|
46
48
|
*/
|
|
47
49
|
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: {
|
|
48
|
-
returnActiveAgent
|
|
50
|
+
returnActiveAgent: true;
|
|
49
51
|
}): Promise<[O, Runnable]>;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* @param message Message to pass to the agent
|
|
54
|
-
* @returns the output of the agent and the final active agent
|
|
55
|
-
*/
|
|
56
|
-
private _call;
|
|
52
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message?: I | string, options?: {
|
|
53
|
+
returnActiveAgent?: boolean;
|
|
54
|
+
}): UserAgent<I, O> | Promise<O | [O, Runnable]>;
|
|
57
55
|
subscribe(topic: string, listener?: undefined): Promise<MessagePayload>;
|
|
58
56
|
subscribe(topic: string, listener: MessageQueueListener): Unsubscribe;
|
|
59
57
|
subscribe(topic: string, listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
|
|
60
58
|
unsubscribe(topic: string, listener: MessageQueueListener): void;
|
|
61
|
-
private callAgent;
|
|
62
59
|
shutdown(): Promise<void>;
|
|
63
60
|
private initProcessExitHandler;
|
|
64
61
|
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import EventEmitter from "node:events";
|
|
2
|
-
import { isNil } from "lodash-es";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { Agent } from "../agents/agent.js";
|
|
5
|
-
import { isTransferAgentOutput, transferAgentOutputKey } from "../agents/types.js";
|
|
6
|
-
import { UserAgent } from "../agents/user-agent.js";
|
|
7
4
|
import { ChatModel } from "../models/chat-model.js";
|
|
8
|
-
import { createMessage } from "../prompt/prompt-builder.js";
|
|
9
5
|
import { checkArguments } from "../utils/type-utils.js";
|
|
6
|
+
import { ExecutionContext } from "./context.js";
|
|
10
7
|
import { MessageQueue, } from "./message-queue.js";
|
|
11
8
|
export class ExecutionEngine extends EventEmitter {
|
|
12
9
|
constructor(options) {
|
|
@@ -15,6 +12,7 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
15
12
|
super();
|
|
16
13
|
this.model = options?.model;
|
|
17
14
|
this.tools = options?.tools ?? [];
|
|
15
|
+
this.limits = options?.limits;
|
|
18
16
|
if (options?.agents?.length)
|
|
19
17
|
this.addAgent(...options.agents);
|
|
20
18
|
this.initProcessExitHandler();
|
|
@@ -23,6 +21,7 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
23
21
|
model;
|
|
24
22
|
tools;
|
|
25
23
|
agents = [];
|
|
24
|
+
limits;
|
|
26
25
|
addAgent(...agents) {
|
|
27
26
|
checkArguments("ExecutionEngine.addAgent", executionEngineAddAgentArgsSchema, agents);
|
|
28
27
|
for (const agent of agents) {
|
|
@@ -30,8 +29,8 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
30
29
|
agent.attach(this);
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
return
|
|
32
|
+
newContext() {
|
|
33
|
+
return new ExecutionContext(this);
|
|
35
34
|
}
|
|
36
35
|
/**
|
|
37
36
|
* Publish a message to a topic, the engine will call the listeners of the topic
|
|
@@ -40,56 +39,10 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
40
39
|
* @param from the agent who publish the message, if not provided, it will be treated as a user message
|
|
41
40
|
*/
|
|
42
41
|
publish(topic, message, from) {
|
|
43
|
-
|
|
44
|
-
topic,
|
|
45
|
-
message,
|
|
46
|
-
from,
|
|
47
|
-
});
|
|
48
|
-
const request = {
|
|
49
|
-
role: !from || from instanceof UserAgent ? "user" : "agent",
|
|
50
|
-
source: from?.name,
|
|
51
|
-
message: this.createMessageFromInput(message),
|
|
52
|
-
};
|
|
53
|
-
this.messageQueue.publish(topic, request);
|
|
42
|
+
return new ExecutionContext(this).publish(topic, message, from);
|
|
54
43
|
}
|
|
55
44
|
call(agent, message, options) {
|
|
56
|
-
|
|
57
|
-
agent,
|
|
58
|
-
message,
|
|
59
|
-
options,
|
|
60
|
-
});
|
|
61
|
-
if (isNil(message)) {
|
|
62
|
-
let activeAgent = agent;
|
|
63
|
-
return UserAgent.from({
|
|
64
|
-
context: this,
|
|
65
|
-
process: async (input, context) => {
|
|
66
|
-
const [output, agent] = await context.call(activeAgent, input, {
|
|
67
|
-
returnActiveAgent: true,
|
|
68
|
-
});
|
|
69
|
-
activeAgent = agent;
|
|
70
|
-
return output;
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return this._call(agent, this.createMessageFromInput(message)).then((result) => options?.returnActiveAgent ? [result.output, result.agent] : result.output);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Call an agent with a message and return the output and the active agent
|
|
78
|
-
* @param agent Agent to call
|
|
79
|
-
* @param message Message to pass to the agent
|
|
80
|
-
* @returns the output of the agent and the final active agent
|
|
81
|
-
*/
|
|
82
|
-
async _call(agent, message) {
|
|
83
|
-
const { output, agent: activeAgent } = await this.callAgent(agent, message);
|
|
84
|
-
if (activeAgent instanceof Agent) {
|
|
85
|
-
const publishTopics = typeof activeAgent.publishTopic === "function"
|
|
86
|
-
? await activeAgent.publishTopic(output)
|
|
87
|
-
: activeAgent.publishTopic;
|
|
88
|
-
if (publishTopics?.length) {
|
|
89
|
-
this.publish(publishTopics, output, activeAgent);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return { output, agent: activeAgent };
|
|
45
|
+
return new ExecutionContext(this).call(agent, message, options);
|
|
93
46
|
}
|
|
94
47
|
subscribe(topic, listener) {
|
|
95
48
|
checkArguments("ExecutionEngine.subscribe", executionEngineSubscribeArgsSchema, {
|
|
@@ -105,38 +58,6 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
105
58
|
});
|
|
106
59
|
this.messageQueue.unsubscribe(topic, listener);
|
|
107
60
|
}
|
|
108
|
-
async callAgent(agent, input) {
|
|
109
|
-
let activeAgent = agent;
|
|
110
|
-
let output;
|
|
111
|
-
for (;;) {
|
|
112
|
-
let result;
|
|
113
|
-
if (typeof activeAgent === "function") {
|
|
114
|
-
result = await activeAgent(input, this);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
result = await activeAgent.call(input, this);
|
|
118
|
-
}
|
|
119
|
-
if (!(result instanceof Agent))
|
|
120
|
-
output = result;
|
|
121
|
-
const transferToAgent = result instanceof Agent
|
|
122
|
-
? result
|
|
123
|
-
: isTransferAgentOutput(result)
|
|
124
|
-
? result[transferAgentOutputKey].agent
|
|
125
|
-
: undefined;
|
|
126
|
-
if (transferToAgent) {
|
|
127
|
-
activeAgent = transferToAgent;
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (!output)
|
|
134
|
-
throw new Error("Unexpected empty output");
|
|
135
|
-
return {
|
|
136
|
-
agent: activeAgent,
|
|
137
|
-
output,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
61
|
async shutdown() {
|
|
141
62
|
for (const tool of this.tools) {
|
|
142
63
|
await tool.shutdown();
|
|
@@ -157,16 +78,6 @@ const executionEngineOptionsSchema = z.object({
|
|
|
157
78
|
agents: z.array(z.instanceof(Agent)).optional(),
|
|
158
79
|
});
|
|
159
80
|
const executionEngineAddAgentArgsSchema = z.array(z.instanceof(Agent));
|
|
160
|
-
const executionEnginePublishArgsSchema = z.object({
|
|
161
|
-
topic: z.union([z.string(), z.array(z.string())]),
|
|
162
|
-
message: z.union([z.string(), z.record(z.unknown())]),
|
|
163
|
-
from: z.instanceof(Agent).optional(),
|
|
164
|
-
});
|
|
165
|
-
const executionEngineCallArgsSchema = z.object({
|
|
166
|
-
agent: z.union([z.function(), z.instanceof(Agent)]),
|
|
167
|
-
message: z.union([z.record(z.unknown()), z.string()]).optional(),
|
|
168
|
-
options: z.object({ returnActiveAgent: z.boolean().optional() }).optional(),
|
|
169
|
-
});
|
|
170
81
|
const executionEngineSubscribeArgsSchema = z.object({
|
|
171
82
|
topic: z.string(),
|
|
172
83
|
listener: z.function(z.tuple([z.any()]), z.any()).optional(),
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Message } from "../agents/agent.js";
|
|
2
|
+
import type { Context } from "./context.js";
|
|
2
3
|
export declare const UserInputTopic = "UserInputTopic";
|
|
3
4
|
export declare const UserOutputTopic = "UserOutputTopic";
|
|
4
5
|
export interface MessagePayload {
|
|
5
6
|
role: "user" | "agent";
|
|
6
7
|
source?: string;
|
|
7
8
|
message: Message;
|
|
9
|
+
context: Context;
|
|
8
10
|
}
|
|
9
11
|
export type MessageQueueListener = (message: MessagePayload) => void;
|
|
10
12
|
export type MessageRequest = MessagePayload;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type FunctionAgentFn } from "../agents/agent.js";
|
|
2
2
|
import type { Runnable } from "./context.js";
|
|
3
|
-
export declare function sequential(...
|
|
4
|
-
export declare function parallel(...
|
|
3
|
+
export declare function sequential(...agents: [Runnable, ...Runnable[]]): FunctionAgentFn;
|
|
4
|
+
export declare function parallel(...agents: [Runnable, ...Runnable[]]): FunctionAgentFn;
|
|
@@ -1,32 +1,28 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { Agent } from "../agents/agent.js";
|
|
3
3
|
import { checkArguments } from "../utils/type-utils.js";
|
|
4
|
-
export function sequential(...
|
|
5
|
-
checkArguments("sequential", agentArraySchema,
|
|
6
|
-
let
|
|
4
|
+
export function sequential(...agents) {
|
|
5
|
+
checkArguments("sequential", agentArraySchema, agents);
|
|
6
|
+
let _agents = [...agents];
|
|
7
7
|
return async (input, context) => {
|
|
8
|
-
if (!context)
|
|
9
|
-
throw new Error("Context is required for executing sequential agents. Please provide a valid context.");
|
|
10
8
|
const output = {};
|
|
11
9
|
// Clone the agents to run, so that we can update the agents list during the loop
|
|
12
|
-
const agentsToRun = [...
|
|
13
|
-
|
|
10
|
+
const agentsToRun = [..._agents];
|
|
11
|
+
_agents = [];
|
|
14
12
|
for (const agent of agentsToRun) {
|
|
15
13
|
const [o, transferToAgent] = await context.call(agent, { ...input, ...output }, { returnActiveAgent: true });
|
|
16
14
|
Object.assign(output, o);
|
|
17
|
-
|
|
15
|
+
_agents.push(transferToAgent);
|
|
18
16
|
}
|
|
19
17
|
return output;
|
|
20
18
|
};
|
|
21
19
|
}
|
|
22
|
-
export function parallel(...
|
|
23
|
-
checkArguments("parallel", agentArraySchema,
|
|
24
|
-
let
|
|
20
|
+
export function parallel(...agents) {
|
|
21
|
+
checkArguments("parallel", agentArraySchema, agents);
|
|
22
|
+
let _agents = [...agents];
|
|
25
23
|
return async (input, context) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const result = await Promise.all(agents.map((agent) => context.call(agent, input, { returnActiveAgent: true })));
|
|
29
|
-
agents = result.map((i) => i[1]);
|
|
24
|
+
const result = await Promise.all(_agents.map((agent) => context.call(agent, input, { returnActiveAgent: true })));
|
|
25
|
+
_agents = result.map((i) => i[1]);
|
|
30
26
|
const outputs = result.map((i) => i[0]);
|
|
31
27
|
return Object.assign({}, ...outputs);
|
|
32
28
|
};
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -6,12 +6,5 @@ export * from "./agents/types.js";
|
|
|
6
6
|
export * from "./agents/user-agent.js";
|
|
7
7
|
export * from "./execution-engine/index.js";
|
|
8
8
|
export * from "./models/chat-model.js";
|
|
9
|
-
export * from "./models/claude-chat-model.js";
|
|
10
|
-
export * from "./models/openai-chat-model.js";
|
|
11
|
-
export * from "./models/xai-chat-model.js";
|
|
12
9
|
export * from "./prompt/prompt-builder.js";
|
|
13
10
|
export * from "./prompt/template.js";
|
|
14
|
-
export * from "./utils/json-schema.js";
|
|
15
|
-
export * from "./utils/logger.js";
|
|
16
|
-
export * from "./utils/run-chat-loop.js";
|
|
17
|
-
export * from "./utils/type-utils.js";
|
package/lib/esm/index.js
CHANGED
|
@@ -6,12 +6,5 @@ export * from "./agents/types.js";
|
|
|
6
6
|
export * from "./agents/user-agent.js";
|
|
7
7
|
export * from "./execution-engine/index.js";
|
|
8
8
|
export * from "./models/chat-model.js";
|
|
9
|
-
export * from "./models/claude-chat-model.js";
|
|
10
|
-
export * from "./models/openai-chat-model.js";
|
|
11
|
-
export * from "./models/xai-chat-model.js";
|
|
12
9
|
export * from "./prompt/prompt-builder.js";
|
|
13
10
|
export * from "./prompt/template.js";
|
|
14
|
-
export * from "./utils/json-schema.js";
|
|
15
|
-
export * from "./utils/logger.js";
|
|
16
|
-
export * from "./utils/run-chat-loop.js";
|
|
17
|
-
export * from "./utils/type-utils.js";
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Agent, type Message } from "../agents/agent.js";
|
|
2
|
+
import type { Context } from "../execution-engine/context.js";
|
|
2
3
|
export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelOutput> {
|
|
3
4
|
constructor();
|
|
5
|
+
protected preprocess(input: ChatModelInput, context: Context): void;
|
|
6
|
+
protected postprocess(input: ChatModelInput, output: ChatModelOutput, context: Context): void;
|
|
4
7
|
}
|
|
5
8
|
export interface ChatModelInput extends Message {
|
|
6
9
|
messages: ChatModelInputMessage[];
|
|
@@ -71,6 +74,7 @@ export interface ChatModelOutput extends Message {
|
|
|
71
74
|
text?: string;
|
|
72
75
|
json?: object;
|
|
73
76
|
toolCalls?: ChatModelOutputToolCall[];
|
|
77
|
+
usage?: ChatModelOutputUsage;
|
|
74
78
|
}
|
|
75
79
|
export interface ChatModelOutputToolCall {
|
|
76
80
|
id: string;
|
|
@@ -80,3 +84,7 @@ export interface ChatModelOutputToolCall {
|
|
|
80
84
|
arguments: Message;
|
|
81
85
|
};
|
|
82
86
|
}
|
|
87
|
+
export interface ChatModelOutputUsage {
|
|
88
|
+
promptTokens: number;
|
|
89
|
+
completionTokens: number;
|
|
90
|
+
}
|
|
@@ -7,6 +7,22 @@ export class ChatModel extends Agent {
|
|
|
7
7
|
outputSchema: chatModelOutputSchema,
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
+
preprocess(input, context) {
|
|
11
|
+
super.preprocess(input, context);
|
|
12
|
+
const { limits, usage } = context;
|
|
13
|
+
const usedTokens = usage.completionTokens + usage.promptTokens;
|
|
14
|
+
if (limits?.maxTokens && usedTokens >= limits.maxTokens) {
|
|
15
|
+
throw new Error(`Exceeded max tokens ${usedTokens}/${limits.maxTokens}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
postprocess(input, output, context) {
|
|
19
|
+
super.postprocess(input, output, context);
|
|
20
|
+
const { usage } = output;
|
|
21
|
+
if (usage) {
|
|
22
|
+
context.usage.completionTokens += usage.completionTokens;
|
|
23
|
+
context.usage.promptTokens += usage.promptTokens;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
10
26
|
}
|
|
11
27
|
const chatModelInputMessageSchema = z.object({
|
|
12
28
|
role: z.union([z.literal("system"), z.literal("user"), z.literal("agent"), z.literal("tool")]),
|
|
@@ -81,8 +97,13 @@ const chatModelOutputToolCallSchema = z.object({
|
|
|
81
97
|
arguments: z.record(z.unknown()),
|
|
82
98
|
}),
|
|
83
99
|
});
|
|
100
|
+
const chatModelOutputUsageSchema = z.object({
|
|
101
|
+
promptTokens: z.number(),
|
|
102
|
+
completionTokens: z.number(),
|
|
103
|
+
});
|
|
84
104
|
const chatModelOutputSchema = z.object({
|
|
85
105
|
text: z.string().optional(),
|
|
86
106
|
json: z.record(z.unknown()).optional(),
|
|
87
107
|
toolCalls: z.array(chatModelOutputToolCallSchema).optional(),
|
|
108
|
+
usage: chatModelOutputUsageSchema.optional(),
|
|
88
109
|
});
|