@aigne/core 1.9.0 → 1.11.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 +25 -0
- package/LICENSE +93 -0
- package/README.md +89 -0
- package/README.zh.md +89 -0
- package/lib/cjs/agents/agent.d.ts +30 -3
- package/lib/cjs/agents/agent.js +51 -22
- package/lib/cjs/agents/ai-agent.d.ts +14 -11
- package/lib/cjs/agents/ai-agent.js +36 -17
- package/lib/cjs/agents/user-agent.d.ts +3 -3
- package/lib/cjs/agents/user-agent.js +14 -8
- package/lib/cjs/execution-engine/context.d.ts +18 -7
- package/lib/cjs/execution-engine/context.js +76 -28
- package/lib/cjs/loader/agent-js.d.ts +2 -2
- package/lib/cjs/loader/agent-js.js +4 -5
- package/lib/cjs/loader/agent-yaml.d.ts +8 -5
- package/lib/cjs/loader/agent-yaml.js +13 -1
- package/lib/cjs/loader/index.d.ts +4 -4
- package/lib/cjs/loader/index.js +4 -15
- package/lib/cjs/models/chat-model.d.ts +4 -0
- package/lib/cjs/models/chat-model.js +6 -0
- package/lib/cjs/models/claude-chat-model.d.ts +3 -1
- package/lib/cjs/models/claude-chat-model.js +75 -60
- package/lib/cjs/models/open-router-chat-model.d.ts +1 -0
- package/lib/cjs/models/open-router-chat-model.js +1 -0
- package/lib/cjs/models/openai-chat-model.d.ts +12 -3
- package/lib/cjs/models/openai-chat-model.js +110 -46
- package/lib/cjs/utils/camelize.d.ts +13 -0
- package/lib/cjs/utils/camelize.js +16 -0
- package/lib/cjs/utils/stream-utils.d.ts +17 -0
- package/lib/cjs/utils/stream-utils.js +165 -0
- package/lib/cjs/utils/type-utils.d.ts +1 -0
- package/lib/cjs/utils/type-utils.js +7 -0
- package/lib/dts/agents/agent.d.ts +30 -3
- package/lib/dts/agents/ai-agent.d.ts +14 -11
- package/lib/dts/agents/user-agent.d.ts +3 -3
- package/lib/dts/execution-engine/context.d.ts +18 -7
- package/lib/dts/loader/agent-js.d.ts +2 -2
- package/lib/dts/loader/agent-yaml.d.ts +8 -5
- package/lib/dts/loader/index.d.ts +4 -4
- package/lib/dts/models/chat-model.d.ts +4 -0
- package/lib/dts/models/claude-chat-model.d.ts +3 -1
- package/lib/dts/models/open-router-chat-model.d.ts +1 -0
- package/lib/dts/models/openai-chat-model.d.ts +12 -3
- package/lib/dts/utils/camelize.d.ts +13 -0
- package/lib/dts/utils/stream-utils.d.ts +17 -0
- package/lib/dts/utils/type-utils.d.ts +1 -0
- package/lib/esm/agents/agent.d.ts +30 -3
- package/lib/esm/agents/agent.js +51 -23
- package/lib/esm/agents/ai-agent.d.ts +14 -11
- package/lib/esm/agents/ai-agent.js +37 -18
- package/lib/esm/agents/user-agent.d.ts +3 -3
- package/lib/esm/agents/user-agent.js +15 -9
- package/lib/esm/execution-engine/context.d.ts +18 -7
- package/lib/esm/execution-engine/context.js +78 -30
- package/lib/esm/loader/agent-js.d.ts +2 -2
- package/lib/esm/loader/agent-js.js +4 -5
- package/lib/esm/loader/agent-yaml.d.ts +8 -5
- package/lib/esm/loader/agent-yaml.js +13 -1
- package/lib/esm/loader/index.d.ts +4 -4
- package/lib/esm/loader/index.js +4 -15
- package/lib/esm/models/chat-model.d.ts +4 -0
- package/lib/esm/models/chat-model.js +6 -0
- package/lib/esm/models/claude-chat-model.d.ts +3 -1
- package/lib/esm/models/claude-chat-model.js +75 -60
- package/lib/esm/models/open-router-chat-model.d.ts +1 -0
- package/lib/esm/models/open-router-chat-model.js +1 -0
- package/lib/esm/models/openai-chat-model.d.ts +12 -3
- package/lib/esm/models/openai-chat-model.js +110 -45
- package/lib/esm/utils/camelize.d.ts +13 -0
- package/lib/esm/utils/camelize.js +10 -0
- package/lib/esm/utils/stream-utils.d.ts +17 -0
- package/lib/esm/utils/stream-utils.js +149 -0
- package/lib/esm/utils/type-utils.d.ts +1 -0
- package/lib/esm/utils/type-utils.js +6 -0
- package/package.json +4 -2
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ReadableStream } from "node:stream/web";
|
|
2
2
|
import { createPublishMessage } from "../execution-engine/context.js";
|
|
3
|
+
import { readableStreamToAsyncIterator } from "../utils/stream-utils.js";
|
|
3
4
|
import { orArrayToArray } from "../utils/type-utils.js";
|
|
4
|
-
import { Agent } from "./agent.js";
|
|
5
|
+
import { Agent, } from "./agent.js";
|
|
5
6
|
export class UserAgent extends Agent {
|
|
6
7
|
static from(options) {
|
|
7
8
|
return new UserAgent(options);
|
|
@@ -15,26 +16,31 @@ export class UserAgent extends Agent {
|
|
|
15
16
|
context;
|
|
16
17
|
_process;
|
|
17
18
|
activeAgent;
|
|
18
|
-
call(input, context) {
|
|
19
|
+
call = ((input, context, options) => {
|
|
19
20
|
if (!context)
|
|
20
21
|
this.context = this.context.newContext({ reset: true });
|
|
21
|
-
return super.call(input, context ?? this.context);
|
|
22
|
-
}
|
|
23
|
-
async process(input, context) {
|
|
22
|
+
return super.call(input, context ?? this.context, options);
|
|
23
|
+
});
|
|
24
|
+
async *process(input, context) {
|
|
24
25
|
if (this._process) {
|
|
25
|
-
|
|
26
|
+
yield { delta: { json: await this._process(input, context) } };
|
|
27
|
+
return;
|
|
26
28
|
}
|
|
27
29
|
if (this.activeAgent) {
|
|
28
30
|
const [output, agent] = await context.call(this.activeAgent, input, {
|
|
29
31
|
returnActiveAgent: true,
|
|
32
|
+
streaming: true,
|
|
33
|
+
});
|
|
34
|
+
agent.then((agent) => {
|
|
35
|
+
this.activeAgent = agent;
|
|
30
36
|
});
|
|
31
|
-
|
|
32
|
-
return
|
|
37
|
+
yield* readableStreamToAsyncIterator(output);
|
|
38
|
+
return;
|
|
33
39
|
}
|
|
34
40
|
const publicTopic = typeof this.publishTopic === "function" ? await this.publishTopic(input) : this.publishTopic;
|
|
35
41
|
if (publicTopic?.length) {
|
|
36
42
|
context.publish(publicTopic, createPublishMessage(input, this));
|
|
37
|
-
return
|
|
43
|
+
return;
|
|
38
44
|
}
|
|
39
45
|
throw new Error("UserAgent must have a process function or a publishTopic");
|
|
40
46
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import EventEmitter from "node:events";
|
|
2
|
-
import { Agent, type FunctionAgentFn, type Message } from "../agents/agent.js";
|
|
2
|
+
import { Agent, type AgentCallOptions, type AgentProcessAsyncGenerator, type AgentResponse, type AgentResponseStream, 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
5
|
import { type OmitPropertiesFromArrayFirstElement } from "../utils/type-utils.js";
|
|
@@ -27,7 +27,7 @@ export interface ContextEventMap {
|
|
|
27
27
|
export type ContextEmitEventMap = {
|
|
28
28
|
[K in keyof ContextEventMap]: OmitPropertiesFromArrayFirstElement<ContextEventMap[K], "contextId" | "parentContextId" | "timestamp">;
|
|
29
29
|
};
|
|
30
|
-
export interface CallOptions {
|
|
30
|
+
export interface CallOptions extends AgentCallOptions {
|
|
31
31
|
returnActiveAgent?: boolean;
|
|
32
32
|
disableTransfer?: boolean;
|
|
33
33
|
}
|
|
@@ -48,19 +48,30 @@ export interface Context extends TypedEventEmitter<ContextEventMap, ContextEmitE
|
|
|
48
48
|
* @param agent Agent to call
|
|
49
49
|
* @param message Message to pass to the agent
|
|
50
50
|
* @param options.returnActiveAgent return the active agent
|
|
51
|
+
* @param options.streaming return a stream of the output
|
|
51
52
|
* @returns the output of the agent and the final active agent
|
|
52
53
|
*/
|
|
53
54
|
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: CallOptions & {
|
|
54
55
|
returnActiveAgent: true;
|
|
56
|
+
streaming?: false;
|
|
55
57
|
}): Promise<[O, Runnable]>;
|
|
58
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: CallOptions & {
|
|
59
|
+
returnActiveAgent: true;
|
|
60
|
+
streaming: true;
|
|
61
|
+
}): Promise<[AgentResponseStream<O>, Promise<Runnable>]>;
|
|
56
62
|
/**
|
|
57
63
|
* Call an agent with a message
|
|
58
64
|
* @param agent Agent to call
|
|
59
65
|
* @param message Message to pass to the agent
|
|
60
66
|
* @returns the output of the agent
|
|
61
67
|
*/
|
|
62
|
-
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options?: CallOptions
|
|
63
|
-
|
|
68
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options?: CallOptions & {
|
|
69
|
+
streaming?: false;
|
|
70
|
+
}): Promise<O>;
|
|
71
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message: I | string, options: CallOptions & {
|
|
72
|
+
streaming: true;
|
|
73
|
+
}): Promise<AgentResponseStream<O>>;
|
|
74
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>, message?: I | string, options?: CallOptions): UserAgent<I, O> | Promise<AgentResponse<O> | [AgentResponse<O>, Runnable]>;
|
|
64
75
|
/**
|
|
65
76
|
* Publish a message to a topic, the engine will call the listeners of the topic
|
|
66
77
|
* @param topic topic name, or an array of topic names
|
|
@@ -99,6 +110,7 @@ export declare class ExecutionContext implements Context {
|
|
|
99
110
|
reset?: boolean;
|
|
100
111
|
}): ExecutionContext;
|
|
101
112
|
call: Context["call"];
|
|
113
|
+
private onCallSuccess;
|
|
102
114
|
publish: Context["publish"];
|
|
103
115
|
subscribe: Context["subscribe"];
|
|
104
116
|
unsubscribe: Context["unsubscribe"];
|
|
@@ -122,9 +134,8 @@ declare class ExecutionContextInternal {
|
|
|
122
134
|
private timer?;
|
|
123
135
|
private initTimeout;
|
|
124
136
|
get status(): "normal" | "timeout";
|
|
125
|
-
call<I extends Message, O extends Message>(agent: Runnable<I, O>, input: I, context: Context, options?: CallOptions):
|
|
126
|
-
|
|
127
|
-
output: O;
|
|
137
|
+
call<I extends Message, O extends Message>(agent: Runnable<I, O>, input: I, context: Context, options?: CallOptions): AgentProcessAsyncGenerator<O & {
|
|
138
|
+
__activeAgent__: Runnable;
|
|
128
139
|
}>;
|
|
129
140
|
private callAgent;
|
|
130
141
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import EventEmitter from "node:events";
|
|
2
2
|
import { v7 } from "uuid";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { Agent } from "../agents/agent.js";
|
|
4
|
+
import { Agent, } from "../agents/agent.js";
|
|
5
5
|
import { isTransferAgentOutput, transferAgentOutputKey } from "../agents/types.js";
|
|
6
6
|
import { UserAgent } from "../agents/user-agent.js";
|
|
7
7
|
import { createMessage } from "../prompt/prompt-builder.js";
|
|
8
|
-
import {
|
|
8
|
+
import { agentResponseStreamToObject, asyncGeneratorToReadableStream, onAgentResponseStreamEnd, readableStreamToAsyncIterator, } from "../utils/stream-utils.js";
|
|
9
|
+
import { checkArguments, isNil, omitBy, } from "../utils/type-utils.js";
|
|
9
10
|
import { MessageQueue, } from "./message-queue.js";
|
|
10
11
|
import { newEmptyContextUsage } from "./usage.js";
|
|
11
12
|
export function createPublishMessage(message, from) {
|
|
@@ -62,23 +63,49 @@ export class ExecutionContext {
|
|
|
62
63
|
}
|
|
63
64
|
const newContext = this.newContext();
|
|
64
65
|
const msg = createMessage(message);
|
|
65
|
-
return newContext.internal
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
: activeAgent.publishTopic;
|
|
72
|
-
if (publishTopics?.length) {
|
|
73
|
-
newContext.publish(publishTopics, createPublishMessage(output, activeAgent));
|
|
66
|
+
return Promise.resolve(newContext.internal.call(agent, msg, newContext, options)).then(async (response) => {
|
|
67
|
+
if (!options?.streaming) {
|
|
68
|
+
const { __activeAgent__: activeAgent, ...output } = await agentResponseStreamToObject(response);
|
|
69
|
+
this.onCallSuccess(activeAgent, output, newContext);
|
|
70
|
+
if (options?.returnActiveAgent) {
|
|
71
|
+
return [output, activeAgent];
|
|
74
72
|
}
|
|
73
|
+
return output;
|
|
75
74
|
}
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
const activeAgentPromise = Promise.withResolvers();
|
|
76
|
+
const stream = onAgentResponseStreamEnd(asyncGeneratorToReadableStream(response), async ({ __activeAgent__: activeAgent, ...output }) => {
|
|
77
|
+
this.onCallSuccess(activeAgent, output, newContext);
|
|
78
|
+
activeAgentPromise.resolve(activeAgent);
|
|
79
|
+
}, {
|
|
80
|
+
processChunk(chunk) {
|
|
81
|
+
if (chunk.delta.json) {
|
|
82
|
+
return {
|
|
83
|
+
...chunk,
|
|
84
|
+
delta: {
|
|
85
|
+
...chunk.delta,
|
|
86
|
+
json: omitBy(chunk.delta.json, (_, k) => k === "__activeAgent__"),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return chunk;
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
if (options.returnActiveAgent) {
|
|
94
|
+
return [stream, activeAgentPromise.promise];
|
|
78
95
|
}
|
|
79
|
-
return
|
|
96
|
+
return stream;
|
|
80
97
|
});
|
|
81
98
|
});
|
|
99
|
+
async onCallSuccess(activeAgent, output, context) {
|
|
100
|
+
if (activeAgent instanceof Agent) {
|
|
101
|
+
const publishTopics = typeof activeAgent.publishTopic === "function"
|
|
102
|
+
? await activeAgent.publishTopic(output)
|
|
103
|
+
: activeAgent.publishTopic;
|
|
104
|
+
if (publishTopics?.length) {
|
|
105
|
+
context.publish(publishTopics, createPublishMessage(output, activeAgent));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
82
109
|
publish = ((topic, payload) => {
|
|
83
110
|
return this.internal.messageQueue.publish(topic, { ...payload, context: this });
|
|
84
111
|
});
|
|
@@ -144,11 +171,11 @@ class ExecutionContextInternal {
|
|
|
144
171
|
get status() {
|
|
145
172
|
return this.abortController.signal.aborted ? "timeout" : "normal";
|
|
146
173
|
}
|
|
147
|
-
|
|
174
|
+
call(agent, input, context, options) {
|
|
148
175
|
this.initTimeout();
|
|
149
176
|
return withAbortSignal(this.abortController.signal, new Error("ExecutionContext is timeout"), () => this.callAgent(agent, input, context, options));
|
|
150
177
|
}
|
|
151
|
-
async callAgent(agent, input, context, options) {
|
|
178
|
+
async *callAgent(agent, input, context, options) {
|
|
152
179
|
let activeAgent = agent;
|
|
153
180
|
let output;
|
|
154
181
|
for (;;) {
|
|
@@ -157,7 +184,16 @@ class ExecutionContextInternal {
|
|
|
157
184
|
result = await activeAgent(input, context);
|
|
158
185
|
}
|
|
159
186
|
else {
|
|
160
|
-
result =
|
|
187
|
+
result = {};
|
|
188
|
+
const stream = await activeAgent.call(input, context, { streaming: true });
|
|
189
|
+
for await (const value of readableStreamToAsyncIterator(stream)) {
|
|
190
|
+
if (value.delta.text) {
|
|
191
|
+
yield { delta: { text: value.delta.text } };
|
|
192
|
+
}
|
|
193
|
+
if (value.delta.json) {
|
|
194
|
+
Object.assign(result, value.delta.json);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
161
197
|
}
|
|
162
198
|
if (result instanceof Agent) {
|
|
163
199
|
activeAgent = result;
|
|
@@ -177,22 +213,34 @@ class ExecutionContextInternal {
|
|
|
177
213
|
}
|
|
178
214
|
if (!output)
|
|
179
215
|
throw new Error("Unexpected empty output");
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
216
|
+
yield {
|
|
217
|
+
delta: {
|
|
218
|
+
json: {
|
|
219
|
+
...output,
|
|
220
|
+
__activeAgent__: activeAgent,
|
|
221
|
+
},
|
|
222
|
+
},
|
|
183
223
|
};
|
|
184
224
|
}
|
|
185
225
|
}
|
|
186
|
-
function withAbortSignal(signal, error, fn) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
226
|
+
async function* withAbortSignal(signal, error, fn) {
|
|
227
|
+
const iterator = fn();
|
|
228
|
+
const timeoutPromise = Promise.withResolvers();
|
|
229
|
+
const listener = () => {
|
|
230
|
+
timeoutPromise.reject(error);
|
|
231
|
+
};
|
|
232
|
+
signal.addEventListener("abort", listener);
|
|
233
|
+
try {
|
|
234
|
+
for (;;) {
|
|
235
|
+
const next = await Promise.race([iterator.next(), timeoutPromise.promise]);
|
|
236
|
+
if (next.done)
|
|
237
|
+
break;
|
|
238
|
+
yield next.value;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
signal.removeEventListener("abort", listener);
|
|
243
|
+
}
|
|
196
244
|
}
|
|
197
245
|
const executionContextCallArgsSchema = z.object({
|
|
198
246
|
agent: z.union([z.function(), z.instanceof(Agent)]),
|
|
@@ -4,12 +4,12 @@ export declare function loadAgentFromJsFile(path: string): Promise<{
|
|
|
4
4
|
name: string;
|
|
5
5
|
fn: (args_0: Message) => Message;
|
|
6
6
|
description?: string | undefined;
|
|
7
|
-
|
|
7
|
+
inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
8
8
|
[x: string]: any;
|
|
9
9
|
}, {
|
|
10
10
|
[x: string]: any;
|
|
11
11
|
}> | undefined;
|
|
12
|
-
|
|
12
|
+
outputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
13
13
|
[x: string]: any;
|
|
14
14
|
}, {
|
|
15
15
|
[x: string]: any;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsonSchemaToZod } from "@aigne/json-schema-to-zod";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { customCamelize } from "../utils/camelize.js";
|
|
3
4
|
import { tryOrThrow } from "../utils/type-utils.js";
|
|
4
5
|
import { inputOutputSchema } from "./schema.js";
|
|
5
6
|
const agentJsFileSchema = z.object({
|
|
@@ -21,11 +22,9 @@ export async function loadAgentFromJsFile(path) {
|
|
|
21
22
|
if (typeof agent !== "function") {
|
|
22
23
|
throw new Error(`Agent file ${path} must export a default function, but got ${typeof agent}`);
|
|
23
24
|
}
|
|
24
|
-
return tryOrThrow(() => agentJsFileSchema.parse({
|
|
25
|
+
return tryOrThrow(() => customCamelize(agentJsFileSchema.parse({
|
|
26
|
+
...agent,
|
|
25
27
|
name: agent.agent_name || agent.name,
|
|
26
|
-
description: agent.description,
|
|
27
|
-
input_schema: agent.input_schema,
|
|
28
|
-
output_schema: agent.output_schema,
|
|
29
28
|
fn: agent,
|
|
30
|
-
}), (error) => new Error(`Failed to parse agent from ${path}: ${error.message}`));
|
|
29
|
+
}), { shallowKeys: ["input_schema", "output_schema"] }), (error) => new Error(`Failed to parse agent from ${path}: ${error.message}`));
|
|
31
30
|
}
|
|
@@ -2,21 +2,24 @@ import { type ZodObject, type ZodType, z } from "zod";
|
|
|
2
2
|
export declare function loadAgentFromYamlFile(path: string): Promise<{
|
|
3
3
|
type: "ai";
|
|
4
4
|
name: string;
|
|
5
|
-
description?: string | undefined;
|
|
6
5
|
tools?: string[] | undefined;
|
|
6
|
+
description?: string | undefined;
|
|
7
7
|
instructions?: string | undefined;
|
|
8
|
-
|
|
8
|
+
memory?: true | {
|
|
9
|
+
subscribeTopic: string[];
|
|
10
|
+
} | undefined;
|
|
11
|
+
inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
9
12
|
[x: string]: any;
|
|
10
13
|
}, {
|
|
11
14
|
[x: string]: any;
|
|
12
15
|
}> | undefined;
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
toolChoice?: "auto" | "none" | "required" | "router" | undefined;
|
|
17
|
+
outputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
15
18
|
[x: string]: any;
|
|
16
19
|
}, {
|
|
17
20
|
[x: string]: any;
|
|
18
21
|
}> | undefined;
|
|
19
|
-
|
|
22
|
+
outputKey?: string | undefined;
|
|
20
23
|
} | {
|
|
21
24
|
type: "mcp";
|
|
22
25
|
url?: string | undefined;
|
|
@@ -2,6 +2,7 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { jsonSchemaToZod } from "@aigne/json-schema-to-zod";
|
|
3
3
|
import { parse } from "yaml";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import { customCamelize } from "../utils/camelize.js";
|
|
5
6
|
import { tryOrThrow } from "../utils/type-utils.js";
|
|
6
7
|
import { inputOutputSchema } from "./schema.js";
|
|
7
8
|
const agentFileSchema = z.discriminatedUnion("type", [
|
|
@@ -34,6 +35,15 @@ const agentFileSchema = z.discriminatedUnion("type", [
|
|
|
34
35
|
.union([z.literal("auto"), z.literal("none"), z.literal("required"), z.literal("router")])
|
|
35
36
|
.nullish()
|
|
36
37
|
.transform((v) => v ?? undefined),
|
|
38
|
+
memory: z
|
|
39
|
+
.union([
|
|
40
|
+
z.boolean(),
|
|
41
|
+
z.object({
|
|
42
|
+
subscribe_topic: z.array(z.string()),
|
|
43
|
+
}),
|
|
44
|
+
])
|
|
45
|
+
.nullish()
|
|
46
|
+
.transform((v) => v || undefined),
|
|
37
47
|
}),
|
|
38
48
|
z.object({
|
|
39
49
|
type: z.literal("mcp"),
|
|
@@ -54,6 +64,8 @@ const agentFileSchema = z.discriminatedUnion("type", [
|
|
|
54
64
|
export async function loadAgentFromYamlFile(path) {
|
|
55
65
|
const raw = await tryOrThrow(() => readFile(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
|
|
56
66
|
const json = await tryOrThrow(() => parse(raw), (error) => new Error(`Failed to parse agent definition from ${path}: ${error.message}`));
|
|
57
|
-
const agent = tryOrThrow(() => agentFileSchema.parse({ ...json, type: json.type ?? "ai" }),
|
|
67
|
+
const agent = tryOrThrow(() => customCamelize(agentFileSchema.parse({ ...json, type: json.type ?? "ai" }), {
|
|
68
|
+
shallowKeys: ["input_schema", "output_schema"],
|
|
69
|
+
}), (error) => new Error(`Failed to validate agent definition from ${path}: ${error.message}`));
|
|
58
70
|
return agent;
|
|
59
71
|
}
|
|
@@ -8,8 +8,8 @@ export declare function load(options: LoadOptions): Promise<{
|
|
|
8
8
|
model: ChatModel | undefined;
|
|
9
9
|
agents: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[];
|
|
10
10
|
tools: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[];
|
|
11
|
-
description?: string | null | undefined;
|
|
12
11
|
name?: string | null | undefined;
|
|
12
|
+
description?: string | null | undefined;
|
|
13
13
|
chat_model?: {
|
|
14
14
|
name?: string | null | undefined;
|
|
15
15
|
temperature?: number | null | undefined;
|
|
@@ -63,9 +63,9 @@ declare const aigneFileSchema: z.ZodObject<{
|
|
|
63
63
|
agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
64
64
|
tools: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
65
65
|
}, "strip", z.ZodTypeAny, {
|
|
66
|
-
description?: string | null | undefined;
|
|
67
66
|
tools?: string[] | null | undefined;
|
|
68
67
|
name?: string | null | undefined;
|
|
68
|
+
description?: string | null | undefined;
|
|
69
69
|
chat_model?: {
|
|
70
70
|
name?: string | null | undefined;
|
|
71
71
|
temperature?: number | null | undefined;
|
|
@@ -76,9 +76,9 @@ declare const aigneFileSchema: z.ZodObject<{
|
|
|
76
76
|
} | null | undefined;
|
|
77
77
|
agents?: string[] | null | undefined;
|
|
78
78
|
}, {
|
|
79
|
-
description?: string | null | undefined;
|
|
80
79
|
tools?: string[] | null | undefined;
|
|
81
80
|
name?: string | null | undefined;
|
|
81
|
+
description?: string | null | undefined;
|
|
82
82
|
chat_model?: string | {
|
|
83
83
|
name?: string | null | undefined;
|
|
84
84
|
temperature?: number | null | undefined;
|
|
@@ -90,9 +90,9 @@ declare const aigneFileSchema: z.ZodObject<{
|
|
|
90
90
|
agents?: string[] | null | undefined;
|
|
91
91
|
}>;
|
|
92
92
|
export declare function loadAIGNEFile(path: string): Promise<{
|
|
93
|
-
description?: string | null | undefined;
|
|
94
93
|
tools?: string[] | null | undefined;
|
|
95
94
|
name?: string | null | undefined;
|
|
95
|
+
description?: string | null | undefined;
|
|
96
96
|
chat_model?: {
|
|
97
97
|
name?: string | null | undefined;
|
|
98
98
|
temperature?: number | null | undefined;
|
package/lib/esm/loader/index.js
CHANGED
|
@@ -33,26 +33,15 @@ export async function load(options) {
|
|
|
33
33
|
export async function loadAgent(path) {
|
|
34
34
|
if (extname(path) === ".js") {
|
|
35
35
|
const agent = await loadAgentFromJsFile(path);
|
|
36
|
-
return FunctionAgent.from(
|
|
37
|
-
name: agent.name,
|
|
38
|
-
description: agent.description,
|
|
39
|
-
inputSchema: agent.input_schema,
|
|
40
|
-
outputSchema: agent.output_schema,
|
|
41
|
-
fn: agent.fn,
|
|
42
|
-
});
|
|
36
|
+
return FunctionAgent.from(agent);
|
|
43
37
|
}
|
|
44
38
|
if (extname(path) === ".yaml" || extname(path) === ".yml") {
|
|
45
39
|
const agent = await loadAgentFromYamlFile(path);
|
|
46
40
|
if (agent.type === "ai") {
|
|
47
41
|
return AIAgent.from({
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
inputSchema: agent.input_schema,
|
|
52
|
-
outputSchema: agent.output_schema,
|
|
53
|
-
outputKey: agent.output_key,
|
|
54
|
-
tools: await Promise.all((agent.tools ?? []).map((filename) => loadAgent(join(dirname(path), filename)))),
|
|
55
|
-
toolChoice: agent.tool_choice,
|
|
42
|
+
...agent,
|
|
43
|
+
tools: agent.tools &&
|
|
44
|
+
(await Promise.all(agent.tools.map((filename) => loadAgent(join(dirname(path), filename))))),
|
|
56
45
|
});
|
|
57
46
|
}
|
|
58
47
|
if (agent.type === "mcp") {
|
|
@@ -2,6 +2,10 @@ import { Agent, type Message } from "../agents/agent.js";
|
|
|
2
2
|
import type { Context } from "../execution-engine/context.js";
|
|
3
3
|
export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelOutput> {
|
|
4
4
|
constructor();
|
|
5
|
+
protected supportsParallelToolCalls: boolean;
|
|
6
|
+
getModelCapabilities(): {
|
|
7
|
+
supportsParallelToolCalls: boolean;
|
|
8
|
+
};
|
|
5
9
|
protected preprocess(input: ChatModelInput, context: Context): void;
|
|
6
10
|
protected postprocess(input: ChatModelInput, output: ChatModelOutput, context: Context): void;
|
|
7
11
|
}
|
|
@@ -7,6 +7,12 @@ export class ChatModel extends Agent {
|
|
|
7
7
|
outputSchema: chatModelOutputSchema,
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
+
supportsParallelToolCalls = true;
|
|
11
|
+
getModelCapabilities() {
|
|
12
|
+
return {
|
|
13
|
+
supportsParallelToolCalls: this.supportsParallelToolCalls,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
10
16
|
preprocess(input, context) {
|
|
11
17
|
super.preprocess(input, context);
|
|
12
18
|
const { limits, usage } = context;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import type { AgentCallOptions, AgentResponse } from "../agents/agent.js";
|
|
4
|
+
import type { Context } from "../execution-engine/context.js";
|
|
3
5
|
import { ChatModel, type ChatModelInput, type ChatModelOptions, type ChatModelOutput } from "./chat-model.js";
|
|
4
6
|
export interface ClaudeChatModelOptions {
|
|
5
7
|
apiKey?: string;
|
|
@@ -60,7 +62,7 @@ export declare class ClaudeChatModel extends ChatModel {
|
|
|
60
62
|
protected _client?: Anthropic;
|
|
61
63
|
get client(): Anthropic;
|
|
62
64
|
get modelOptions(): ChatModelOptions | undefined;
|
|
63
|
-
process(input: ChatModelInput): Promise<ChatModelOutput
|
|
65
|
+
process(input: ChatModelInput, _context: Context, options?: AgentCallOptions): Promise<AgentResponse<ChatModelOutput>>;
|
|
64
66
|
private extractResultFromClaudeStream;
|
|
65
67
|
private requestStructuredOutput;
|
|
66
68
|
}
|