@aigne/core 1.34.0 → 1.37.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 +26 -0
- package/lib/cjs/agents/agent.d.ts +71 -10
- package/lib/cjs/agents/agent.js +73 -28
- package/lib/cjs/agents/ai-agent.js +6 -3
- package/lib/cjs/agents/team-agent.d.ts +93 -1
- package/lib/cjs/agents/team-agent.js +45 -17
- package/lib/cjs/aigne/context.d.ts +1 -0
- package/lib/cjs/aigne/context.js +25 -10
- package/lib/cjs/loader/agent-js.d.ts +2 -17
- package/lib/cjs/loader/agent-js.js +4 -16
- package/lib/cjs/loader/agent-yaml.d.ts +29 -8
- package/lib/cjs/loader/agent-yaml.js +44 -15
- package/lib/cjs/loader/index.d.ts +2 -2
- package/lib/cjs/loader/index.js +55 -16
- package/lib/cjs/loader/schema.d.ts +10 -0
- package/lib/cjs/loader/schema.js +17 -1
- package/lib/cjs/utils/type-utils.d.ts +1 -1
- package/lib/cjs/utils/type-utils.js +2 -4
- package/lib/dts/agents/agent.d.ts +71 -10
- package/lib/dts/agents/team-agent.d.ts +93 -1
- package/lib/dts/aigne/context.d.ts +1 -0
- package/lib/dts/loader/agent-js.d.ts +2 -17
- package/lib/dts/loader/agent-yaml.d.ts +29 -8
- package/lib/dts/loader/index.d.ts +2 -2
- package/lib/dts/loader/schema.d.ts +10 -0
- package/lib/dts/utils/type-utils.d.ts +1 -1
- package/lib/esm/agents/agent.d.ts +71 -10
- package/lib/esm/agents/agent.js +73 -28
- package/lib/esm/agents/ai-agent.js +6 -3
- package/lib/esm/agents/team-agent.d.ts +93 -1
- package/lib/esm/agents/team-agent.js +44 -16
- package/lib/esm/aigne/context.d.ts +1 -0
- package/lib/esm/aigne/context.js +25 -10
- package/lib/esm/loader/agent-js.d.ts +2 -17
- package/lib/esm/loader/agent-js.js +4 -13
- package/lib/esm/loader/agent-yaml.d.ts +29 -8
- package/lib/esm/loader/agent-yaml.js +44 -13
- package/lib/esm/loader/index.d.ts +2 -2
- package/lib/esm/loader/index.js +56 -17
- package/lib/esm/loader/schema.d.ts +10 -0
- package/lib/esm/loader/schema.js +12 -0
- package/lib/esm/utils/type-utils.d.ts +1 -1
- package/lib/esm/utils/type-utils.js +2 -4
- package/package.json +3 -3
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.TeamAgent = exports.ProcessMode = void 0;
|
|
6
|
+
exports.TeamAgent = exports.DEFAULT_REFLECTION_MAX_ITERATIONS = exports.ProcessMode = void 0;
|
|
7
7
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
8
|
const immer_1 = require("immer");
|
|
9
9
|
const stream_utils_js_1 = require("../utils/stream-utils.js");
|
|
@@ -32,6 +32,7 @@ var ProcessMode;
|
|
|
32
32
|
*/
|
|
33
33
|
ProcessMode["parallel"] = "parallel";
|
|
34
34
|
})(ProcessMode || (exports.ProcessMode = ProcessMode = {}));
|
|
35
|
+
exports.DEFAULT_REFLECTION_MAX_ITERATIONS = 3;
|
|
35
36
|
/**
|
|
36
37
|
* TeamAgent coordinates a group of agents working together to accomplish tasks.
|
|
37
38
|
*
|
|
@@ -76,6 +77,10 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
76
77
|
constructor(options) {
|
|
77
78
|
super(options);
|
|
78
79
|
this.mode = options.mode ?? ProcessMode.sequential;
|
|
80
|
+
this.reflection = options.reflection && {
|
|
81
|
+
...options.reflection,
|
|
82
|
+
maxIterations: options.reflection.maxIterations ?? exports.DEFAULT_REFLECTION_MAX_ITERATIONS,
|
|
83
|
+
};
|
|
79
84
|
this.iterateOn = options.iterateOn;
|
|
80
85
|
this.iterateWithPreviousOutput = options.iterateWithPreviousOutput;
|
|
81
86
|
}
|
|
@@ -85,6 +90,14 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
85
90
|
* This can be either sequential (one after another) or parallel (all at once).
|
|
86
91
|
*/
|
|
87
92
|
mode;
|
|
93
|
+
/**
|
|
94
|
+
* The reflection mode configuration with guaranteed maxIterations value.
|
|
95
|
+
*
|
|
96
|
+
* This is the internal representation after processing the user-provided
|
|
97
|
+
* reflection configuration, ensuring that maxIterations always has a value
|
|
98
|
+
* (defaulting to DEFAULT_REFLECTION_MAX_ITERATIONS if not specified).
|
|
99
|
+
*/
|
|
100
|
+
reflection;
|
|
88
101
|
/**
|
|
89
102
|
* The input field key to iterate over when processing array inputs.
|
|
90
103
|
*
|
|
@@ -119,10 +132,35 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
119
132
|
process(input, options) {
|
|
120
133
|
if (!this.skills.length)
|
|
121
134
|
throw new Error("TeamAgent must have at least one skill defined.");
|
|
135
|
+
if (this.reflection)
|
|
136
|
+
return this._processReflection(input, options);
|
|
137
|
+
return this._processNonReflection(input, options);
|
|
138
|
+
}
|
|
139
|
+
_processNonReflection(input, options) {
|
|
122
140
|
if (this.iterateOn) {
|
|
123
141
|
return this._processIterator(this.iterateOn, input, options);
|
|
124
142
|
}
|
|
125
|
-
return this.
|
|
143
|
+
return this._processNonIterator(input, options);
|
|
144
|
+
}
|
|
145
|
+
async _processReflection(input, options) {
|
|
146
|
+
(0, node_assert_1.default)(this.reflection, "Reflection mode must be defined for reflection processing");
|
|
147
|
+
let iterations = 0;
|
|
148
|
+
const previousOutput = { ...input };
|
|
149
|
+
for (;;) {
|
|
150
|
+
const output = await (0, agent_js_1.agentProcessResultToObject)(await this._processNonReflection(previousOutput, options));
|
|
151
|
+
Object.assign(previousOutput, output);
|
|
152
|
+
const reviewOutput = await options.context.invoke(this.reflection.reviewer, previousOutput);
|
|
153
|
+
Object.assign(previousOutput, reviewOutput);
|
|
154
|
+
const approved = await this.reflection.isApproved(reviewOutput);
|
|
155
|
+
if (approved)
|
|
156
|
+
return output;
|
|
157
|
+
if (++iterations >= this.reflection.maxIterations) {
|
|
158
|
+
if (this.reflection.returnLastOnMaxIterations)
|
|
159
|
+
return output;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
throw new Error(`Reflection mode exceeded max iterations ${this.reflection.maxIterations}. Please review the feedback and try again.`);
|
|
126
164
|
}
|
|
127
165
|
async *_processIterator(key, input, options) {
|
|
128
166
|
(0, node_assert_1.default)(this.iterateOn, "iterateInputKey must be defined for iterator processing");
|
|
@@ -133,7 +171,7 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
133
171
|
const item = arr[i];
|
|
134
172
|
if (!(0, type_utils_js_1.isRecord)(item))
|
|
135
173
|
throw new TypeError(`Expected ${String(key)} to be an object, got ${typeof item}`);
|
|
136
|
-
const res = await (0, agent_js_1.agentProcessResultToObject)(await this.
|
|
174
|
+
const res = await (0, agent_js_1.agentProcessResultToObject)(await this._processNonIterator({ ...input, [key]: arr, ...item }, { ...options, streaming: false }));
|
|
137
175
|
// Merge the item result with the original item used for next iteration
|
|
138
176
|
if (this.iterateWithPreviousOutput) {
|
|
139
177
|
arr = (0, immer_1.produce)(arr, (draft) => {
|
|
@@ -146,7 +184,7 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
146
184
|
yield { delta: { json: { [key]: result } } };
|
|
147
185
|
}
|
|
148
186
|
}
|
|
149
|
-
|
|
187
|
+
_processNonIterator(input, options) {
|
|
150
188
|
switch (this.mode) {
|
|
151
189
|
case ProcessMode.sequential:
|
|
152
190
|
return this._processSequential(input, options);
|
|
@@ -171,19 +209,13 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
171
209
|
*/
|
|
172
210
|
async *_processSequential(input, options) {
|
|
173
211
|
const output = {};
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const newAgents = [];
|
|
177
|
-
for (const agent of agents) {
|
|
178
|
-
const [o, transferToAgent] = await options.context.invoke(agent, { ...input, ...output }, { returnActiveAgent: true, streaming: true });
|
|
212
|
+
for (const agent of this.skills) {
|
|
213
|
+
const o = await options.context.invoke(agent, { ...input, ...output }, { ...options, streaming: true });
|
|
179
214
|
for await (const chunk of o) {
|
|
180
215
|
yield chunk;
|
|
181
216
|
(0, stream_utils_js_1.mergeAgentResponseChunk)(output, chunk);
|
|
182
217
|
}
|
|
183
|
-
newAgents.push(await transferToAgent);
|
|
184
218
|
}
|
|
185
|
-
this.skills.splice(0);
|
|
186
|
-
this.skills.push(...newAgents);
|
|
187
219
|
}
|
|
188
220
|
/**
|
|
189
221
|
* Process input in parallel through all agents in the team.
|
|
@@ -200,8 +232,7 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
200
232
|
* @private
|
|
201
233
|
*/
|
|
202
234
|
async *_processParallel(input, options) {
|
|
203
|
-
const
|
|
204
|
-
const streams = result.map((i) => i[0]);
|
|
235
|
+
const streams = await Promise.all(this.skills.map((agent) => options.context.invoke(agent, input, { ...options, streaming: true })));
|
|
205
236
|
const read = async (index, reader) => {
|
|
206
237
|
const promise = reader.read();
|
|
207
238
|
return promise.then((result) => ({ ...result, reader, index }));
|
|
@@ -236,9 +267,6 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
236
267
|
yield { delta: { ...delta, text } };
|
|
237
268
|
}
|
|
238
269
|
}
|
|
239
|
-
const agents = await Promise.all(result.map((i) => i[1]));
|
|
240
|
-
this.skills.splice(0);
|
|
241
|
-
this.skills.push(...agents);
|
|
242
270
|
}
|
|
243
271
|
}
|
|
244
272
|
exports.TeamAgent = TeamAgent;
|
|
@@ -180,6 +180,7 @@ declare class AIGNEContextShared {
|
|
|
180
180
|
span?: Span;
|
|
181
181
|
constructor(parent?: (Pick<Context, "model" | "skills" | "limits" | "observer"> & {
|
|
182
182
|
messageQueue?: MessageQueue;
|
|
183
|
+
events?: Emitter<any>;
|
|
183
184
|
}) | undefined);
|
|
184
185
|
readonly messageQueue: MessageQueue;
|
|
185
186
|
readonly events: Emitter<any>;
|
package/lib/cjs/aigne/context.js
CHANGED
|
@@ -40,7 +40,7 @@ class AIGNEContext {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
this.internal = new AIGNEContextShared(parent);
|
|
43
|
+
this.internal = new AIGNEContextShared(parent instanceof AIGNEContext ? parent.internal : parent);
|
|
44
44
|
this.span = tracer?.startSpan("AIGNEContext");
|
|
45
45
|
// 修改了 rootId 是否会之前的有影响?,之前为 this.id
|
|
46
46
|
this.rootId = this.span?.spanContext?.().traceId ?? (0, uuid_1.v7)();
|
|
@@ -272,9 +272,10 @@ class AIGNEContextShared {
|
|
|
272
272
|
constructor(parent) {
|
|
273
273
|
this.parent = parent;
|
|
274
274
|
this.messageQueue = this.parent?.messageQueue ?? new message_queue_js_1.MessageQueue();
|
|
275
|
+
this.events = this.parent?.events ?? new strict_event_emitter_1.Emitter();
|
|
275
276
|
}
|
|
276
277
|
messageQueue;
|
|
277
|
-
events
|
|
278
|
+
events;
|
|
278
279
|
get model() {
|
|
279
280
|
return this.parent?.model;
|
|
280
281
|
}
|
|
@@ -309,21 +310,35 @@ class AIGNEContextShared {
|
|
|
309
310
|
this.initTimeout();
|
|
310
311
|
return withAbortSignal(this.abortController.signal, new Error("AIGNEContext is timeout"), () => this.invokeAgent(agent, input, context, options));
|
|
311
312
|
}
|
|
312
|
-
async *invokeAgent(agent, input, context, options) {
|
|
313
|
+
async *invokeAgent(agent, input, context, options = {}) {
|
|
313
314
|
const startedAt = Date.now();
|
|
314
315
|
try {
|
|
315
316
|
let activeAgent = agent;
|
|
316
317
|
for (;;) {
|
|
317
318
|
const result = {};
|
|
318
319
|
if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
|
|
319
|
-
options.sourceAgent.hooks
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
320
|
+
for (const { onHandoff } of [options.hooks ?? {}, ...options.sourceAgent.hooks]) {
|
|
321
|
+
if (!onHandoff)
|
|
322
|
+
continue;
|
|
323
|
+
await (typeof onHandoff === "function"
|
|
324
|
+
? onHandoff({
|
|
325
|
+
context,
|
|
326
|
+
source: options.sourceAgent,
|
|
327
|
+
target: activeAgent,
|
|
328
|
+
input,
|
|
329
|
+
})
|
|
330
|
+
: context.invoke(onHandoff, {
|
|
331
|
+
source: options.sourceAgent,
|
|
332
|
+
target: activeAgent,
|
|
333
|
+
input,
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
325
336
|
}
|
|
326
|
-
const stream = await activeAgent.invoke(input, {
|
|
337
|
+
const stream = await activeAgent.invoke(input, {
|
|
338
|
+
hooks: options.hooks,
|
|
339
|
+
context,
|
|
340
|
+
streaming: true,
|
|
341
|
+
});
|
|
327
342
|
for await (const value of stream) {
|
|
328
343
|
if ((0, agent_js_1.isAgentResponseDelta)(value)) {
|
|
329
344
|
if (value.delta.json) {
|
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare function loadAgentFromJsFile(path: string): Promise<Agent<any, any> | {
|
|
4
|
-
process: FunctionAgentFn;
|
|
5
|
-
name: string;
|
|
6
|
-
description?: string | undefined;
|
|
7
|
-
inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
8
|
-
[x: string]: any;
|
|
9
|
-
}, {
|
|
10
|
-
[x: string]: any;
|
|
11
|
-
}> | undefined;
|
|
12
|
-
outputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
13
|
-
[x: string]: any;
|
|
14
|
-
}, {
|
|
15
|
-
[x: string]: any;
|
|
16
|
-
}> | undefined;
|
|
17
|
-
}>;
|
|
1
|
+
import { Agent } from "../agents/agent.js";
|
|
2
|
+
export declare function loadAgentFromJsFile(path: string): Promise<Agent<any, any> | import("./agent-yaml.js").AgentSchema>;
|
|
@@ -32,34 +32,22 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.loadAgentFromJsFile = loadAgentFromJsFile;
|
|
40
|
-
const json_schema_to_zod_1 = require("@aigne/json-schema-to-zod");
|
|
41
|
-
const camelize_ts_1 = __importDefault(require("camelize-ts"));
|
|
42
|
-
const zod_1 = require("zod");
|
|
43
37
|
const agent_js_1 = require("../agents/agent.js");
|
|
44
38
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
45
|
-
const
|
|
39
|
+
const agent_yaml_js_1 = require("./agent-yaml.js");
|
|
46
40
|
async function loadAgentFromJsFile(path) {
|
|
47
|
-
const agentJsFileSchema = zod_1.z.object({
|
|
48
|
-
name: zod_1.z.string(),
|
|
49
|
-
description: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
50
|
-
inputSchema: (0, schema_js_1.optionalize)((0, schema_js_1.inputOutputSchema)({ path })).transform((v) => v ? (0, json_schema_to_zod_1.jsonSchemaToZod)(v) : undefined),
|
|
51
|
-
outputSchema: (0, schema_js_1.optionalize)((0, schema_js_1.inputOutputSchema)({ path })).transform((v) => v ? (0, json_schema_to_zod_1.jsonSchemaToZod)(v) : undefined),
|
|
52
|
-
process: zod_1.z.custom(),
|
|
53
|
-
});
|
|
54
41
|
const { default: agent } = await (0, type_utils_js_1.tryOrThrow)(() => Promise.resolve(`${path}`).then(s => __importStar(require(s))), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
|
|
55
42
|
if (agent instanceof agent_js_1.Agent)
|
|
56
43
|
return agent;
|
|
57
44
|
if (typeof agent !== "function") {
|
|
58
45
|
throw new Error(`Agent file ${path} must export a default function, but got ${typeof agent}`);
|
|
59
46
|
}
|
|
60
|
-
return (0, type_utils_js_1.tryOrThrow)(() =>
|
|
47
|
+
return (0, type_utils_js_1.tryOrThrow)(() => (0, agent_yaml_js_1.parseAgentFile)(path, {
|
|
61
48
|
...agent,
|
|
49
|
+
type: "function",
|
|
62
50
|
name: agent.agent_name || agent.agentName || agent.name,
|
|
63
51
|
process: agent,
|
|
64
|
-
})
|
|
52
|
+
}), (error) => new Error(`Failed to parse agent from ${path}: ${error.message}`));
|
|
65
53
|
}
|
|
@@ -1,39 +1,60 @@
|
|
|
1
1
|
import { type ZodType } from "zod";
|
|
2
|
+
import type { FunctionAgentFn } from "../agents/agent.js";
|
|
2
3
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
3
4
|
import { ProcessMode } from "../agents/team-agent.js";
|
|
4
|
-
interface
|
|
5
|
+
export interface HooksSchema {
|
|
6
|
+
onStart?: NestAgentSchema;
|
|
7
|
+
onSuccess?: NestAgentSchema;
|
|
8
|
+
onError?: NestAgentSchema;
|
|
9
|
+
onEnd?: NestAgentSchema;
|
|
10
|
+
onSkillStart?: NestAgentSchema;
|
|
11
|
+
onSkillEnd?: NestAgentSchema;
|
|
12
|
+
onHandoff?: NestAgentSchema;
|
|
13
|
+
}
|
|
14
|
+
export type NestAgentSchema = string | {
|
|
15
|
+
url: string;
|
|
16
|
+
defaultInput?: Record<string, any>;
|
|
17
|
+
hooks?: HooksSchema | HooksSchema[];
|
|
18
|
+
} | AgentSchema;
|
|
19
|
+
export interface BaseAgentSchema {
|
|
5
20
|
name?: string;
|
|
6
21
|
description?: string;
|
|
7
22
|
inputSchema?: ZodType<Record<string, any>>;
|
|
23
|
+
defaultInput?: Record<string, any>;
|
|
8
24
|
outputSchema?: ZodType<Record<string, any>>;
|
|
9
|
-
skills?:
|
|
25
|
+
skills?: NestAgentSchema[];
|
|
26
|
+
hooks?: HooksSchema | HooksSchema[];
|
|
10
27
|
memory?: boolean | {
|
|
11
28
|
provider: string;
|
|
12
29
|
subscribeTopic?: string[];
|
|
13
30
|
};
|
|
14
31
|
}
|
|
15
|
-
interface AIAgentSchema extends BaseAgentSchema {
|
|
32
|
+
export interface AIAgentSchema extends BaseAgentSchema {
|
|
16
33
|
type: "ai";
|
|
17
34
|
instructions?: string;
|
|
18
35
|
inputKey?: string;
|
|
19
36
|
outputKey?: string;
|
|
20
37
|
toolChoice?: AIAgentToolChoice;
|
|
21
38
|
}
|
|
22
|
-
interface MCPAgentSchema {
|
|
39
|
+
export interface MCPAgentSchema extends BaseAgentSchema {
|
|
23
40
|
type: "mcp";
|
|
24
41
|
url?: string;
|
|
25
42
|
command?: string;
|
|
26
43
|
args?: string[];
|
|
27
44
|
}
|
|
28
|
-
interface TeamAgentSchema extends BaseAgentSchema {
|
|
45
|
+
export interface TeamAgentSchema extends BaseAgentSchema {
|
|
29
46
|
type: "team";
|
|
30
47
|
mode?: ProcessMode;
|
|
31
48
|
iterateOn?: string;
|
|
32
49
|
}
|
|
33
|
-
interface TransformAgentSchema extends BaseAgentSchema {
|
|
50
|
+
export interface TransformAgentSchema extends BaseAgentSchema {
|
|
34
51
|
type: "transform";
|
|
35
52
|
jsonata: string;
|
|
36
53
|
}
|
|
37
|
-
|
|
54
|
+
export interface FunctionAgentSchema extends BaseAgentSchema {
|
|
55
|
+
type: "function";
|
|
56
|
+
process: FunctionAgentFn;
|
|
57
|
+
}
|
|
58
|
+
export type AgentSchema = AIAgentSchema | MCPAgentSchema | TeamAgentSchema | TransformAgentSchema | FunctionAgentSchema;
|
|
59
|
+
export declare function parseAgentFile(path: string, data: object): Promise<AgentSchema>;
|
|
38
60
|
export declare function loadAgentFromYamlFile(path: string): Promise<AgentSchema>;
|
|
39
|
-
export {};
|
|
@@ -1,35 +1,52 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAgentFile = parseAgentFile;
|
|
6
4
|
exports.loadAgentFromYamlFile = loadAgentFromYamlFile;
|
|
7
5
|
const json_schema_to_zod_1 = require("@aigne/json-schema-to-zod");
|
|
8
6
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
9
|
-
const camelize_ts_1 = __importDefault(require("camelize-ts"));
|
|
10
7
|
const yaml_1 = require("yaml");
|
|
11
8
|
const zod_1 = require("zod");
|
|
12
9
|
const ai_agent_js_1 = require("../agents/ai-agent.js");
|
|
13
10
|
const team_agent_js_1 = require("../agents/team-agent.js");
|
|
14
11
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
15
12
|
const schema_js_1 = require("./schema.js");
|
|
16
|
-
async function
|
|
13
|
+
async function parseAgentFile(path, data) {
|
|
17
14
|
const agentSchema = zod_1.z.lazy(() => {
|
|
15
|
+
const nestAgentSchema = zod_1.z.lazy(() => zod_1.z.union([
|
|
16
|
+
agentSchema,
|
|
17
|
+
zod_1.z.string(),
|
|
18
|
+
(0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
19
|
+
url: zod_1.z.string(),
|
|
20
|
+
defaultInput: (0, schema_js_1.optionalize)(schema_js_1.defaultInputSchema),
|
|
21
|
+
hooks: (0, schema_js_1.optionalize)(zod_1.z.union([hooksSchema, zod_1.z.array(hooksSchema)])),
|
|
22
|
+
})),
|
|
23
|
+
]));
|
|
24
|
+
const hooksSchema = (0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
25
|
+
onStart: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
26
|
+
onSuccess: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
27
|
+
onError: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
28
|
+
onEnd: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
29
|
+
onSkillStart: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
30
|
+
onSkillEnd: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
31
|
+
onHandoff: (0, schema_js_1.optionalize)(nestAgentSchema),
|
|
32
|
+
}));
|
|
18
33
|
const baseAgentSchema = zod_1.z.object({
|
|
19
34
|
name: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
20
35
|
description: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
21
36
|
inputSchema: (0, schema_js_1.optionalize)((0, schema_js_1.inputOutputSchema)({ path })).transform((v) => v ? (0, json_schema_to_zod_1.jsonSchemaToZod)(v) : undefined),
|
|
37
|
+
defaultInput: (0, schema_js_1.optionalize)(schema_js_1.defaultInputSchema),
|
|
22
38
|
outputSchema: (0, schema_js_1.optionalize)((0, schema_js_1.inputOutputSchema)({ path })).transform((v) => v ? (0, json_schema_to_zod_1.jsonSchemaToZod)(v) : undefined),
|
|
23
|
-
|
|
39
|
+
hooks: (0, schema_js_1.optionalize)(zod_1.z.union([hooksSchema, zod_1.z.array(hooksSchema)])),
|
|
40
|
+
skills: (0, schema_js_1.optionalize)(zod_1.z.array(nestAgentSchema)),
|
|
24
41
|
memory: (0, schema_js_1.optionalize)(zod_1.z.union([
|
|
25
42
|
zod_1.z.boolean(),
|
|
26
|
-
zod_1.z.object({
|
|
43
|
+
(0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
27
44
|
provider: zod_1.z.string(),
|
|
28
45
|
subscribeTopic: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.string())),
|
|
29
|
-
}),
|
|
46
|
+
})),
|
|
30
47
|
])),
|
|
31
48
|
});
|
|
32
|
-
return zod_1.z.discriminatedUnion("type", [
|
|
49
|
+
return (0, schema_js_1.camelizeSchema)(zod_1.z.discriminatedUnion("type", [
|
|
33
50
|
zod_1.z
|
|
34
51
|
.object({
|
|
35
52
|
type: zod_1.z.literal("ai"),
|
|
@@ -40,18 +57,21 @@ async function loadAgentFromYamlFile(path) {
|
|
|
40
57
|
}),
|
|
41
58
|
])).transform((v) => typeof v === "string"
|
|
42
59
|
? v
|
|
43
|
-
: v &&
|
|
60
|
+
: v &&
|
|
61
|
+
index_js_1.nodejs.fs.readFile(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), v.url), "utf8")),
|
|
44
62
|
inputKey: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
45
63
|
outputKey: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
46
64
|
toolChoice: (0, schema_js_1.optionalize)(zod_1.z.nativeEnum(ai_agent_js_1.AIAgentToolChoice)),
|
|
47
65
|
})
|
|
48
66
|
.extend(baseAgentSchema.shape),
|
|
49
|
-
zod_1.z
|
|
67
|
+
zod_1.z
|
|
68
|
+
.object({
|
|
50
69
|
type: zod_1.z.literal("mcp"),
|
|
51
70
|
url: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
52
71
|
command: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
53
72
|
args: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.string())),
|
|
54
|
-
})
|
|
73
|
+
})
|
|
74
|
+
.extend(baseAgentSchema.shape),
|
|
55
75
|
zod_1.z
|
|
56
76
|
.object({
|
|
57
77
|
type: zod_1.z.literal("team"),
|
|
@@ -65,11 +85,20 @@ async function loadAgentFromYamlFile(path) {
|
|
|
65
85
|
jsonata: zod_1.z.string(),
|
|
66
86
|
})
|
|
67
87
|
.extend(baseAgentSchema.shape),
|
|
68
|
-
|
|
88
|
+
zod_1.z
|
|
89
|
+
.object({
|
|
90
|
+
type: zod_1.z.literal("function"),
|
|
91
|
+
process: zod_1.z.custom(),
|
|
92
|
+
})
|
|
93
|
+
.extend(baseAgentSchema.shape),
|
|
94
|
+
]));
|
|
69
95
|
});
|
|
96
|
+
return agentSchema.parseAsync(data);
|
|
97
|
+
}
|
|
98
|
+
async function loadAgentFromYamlFile(path) {
|
|
70
99
|
const raw = await (0, type_utils_js_1.tryOrThrow)(() => index_js_1.nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
|
|
71
|
-
const json = (0, type_utils_js_1.tryOrThrow)(() => (0,
|
|
72
|
-
const agent = await (0, type_utils_js_1.tryOrThrow)(async () => await
|
|
100
|
+
const json = (0, type_utils_js_1.tryOrThrow)(() => (0, yaml_1.parse)(raw), (error) => new Error(`Failed to parse agent definition from ${path}: ${error.message}`));
|
|
101
|
+
const agent = await (0, type_utils_js_1.tryOrThrow)(async () => await parseAgentFile(path, {
|
|
73
102
|
...json,
|
|
74
103
|
type: json.type ?? "ai",
|
|
75
104
|
skills: json.skills ?? json.tools,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Camelize } from "camelize-ts";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { Agent } from "../agents/agent.js";
|
|
3
|
+
import { Agent, type AgentOptions } from "../agents/agent.js";
|
|
4
4
|
import type { ChatModel, ChatModelOptions } from "../agents/chat-model.js";
|
|
5
5
|
import type { AIGNEOptions } from "../aigne/aigne.js";
|
|
6
6
|
import type { MemoryAgent, MemoryAgentOptions } from "../memory/memory.js";
|
|
@@ -25,7 +25,7 @@ export interface LoadOptions {
|
|
|
25
25
|
path: string;
|
|
26
26
|
}
|
|
27
27
|
export declare function load(options: LoadOptions): Promise<AIGNEOptions>;
|
|
28
|
-
export declare function loadAgent(path: string, options?: LoadOptions): Promise<Agent>;
|
|
28
|
+
export declare function loadAgent(path: string, options?: LoadOptions, agentOptions?: AgentOptions): Promise<Agent>;
|
|
29
29
|
export declare function loadModel(models: LoadableModel[], model?: Camelize<z.infer<typeof aigneFileSchema>["model"]>, modelOptions?: ChatModelOptions): Promise<ChatModel | undefined>;
|
|
30
30
|
declare const aigneFileSchema: z.ZodObject<{
|
|
31
31
|
name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
|
package/lib/cjs/loader/index.js
CHANGED
|
@@ -39,47 +39,83 @@ async function load(options) {
|
|
|
39
39
|
skills,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
async function loadAgent(path, options) {
|
|
42
|
+
async function loadAgent(path, options, agentOptions) {
|
|
43
43
|
if ([".js", ".mjs", ".ts", ".mts"].includes(index_js_1.nodejs.path.extname(path))) {
|
|
44
44
|
const agent = await (0, agent_js_js_1.loadAgentFromJsFile)(path);
|
|
45
45
|
if (agent instanceof agent_js_1.Agent)
|
|
46
46
|
return agent;
|
|
47
|
-
return
|
|
47
|
+
return parseAgent(path, agent, options, agentOptions);
|
|
48
48
|
}
|
|
49
49
|
if ([".yml", ".yaml"].includes(index_js_1.nodejs.path.extname(path))) {
|
|
50
50
|
const agent = await (0, agent_yaml_js_1.loadAgentFromYamlFile)(path);
|
|
51
|
-
return parseAgent(path, agent, options);
|
|
51
|
+
return parseAgent(path, agent, options, agentOptions);
|
|
52
52
|
}
|
|
53
53
|
throw new Error(`Unsupported agent file type: ${path}`);
|
|
54
54
|
}
|
|
55
|
-
async function
|
|
55
|
+
async function loadNestAgent(path, agent, options) {
|
|
56
|
+
return typeof agent === "object" && "type" in agent
|
|
57
|
+
? parseAgent(path, agent, options)
|
|
58
|
+
: typeof agent === "string"
|
|
59
|
+
? loadAgent(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), agent), options)
|
|
60
|
+
: loadAgent(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), agent.url), options, {
|
|
61
|
+
defaultInput: agent.defaultInput,
|
|
62
|
+
hooks: await parseHooks(path, agent.hooks, options),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async function parseHooks(path, hooks, options) {
|
|
66
|
+
hooks = [hooks].flat().filter(type_utils_js_1.isNonNullable);
|
|
67
|
+
if (!hooks.length)
|
|
68
|
+
return undefined;
|
|
69
|
+
return await Promise.all(hooks.map(async (hook) => ({
|
|
70
|
+
onStart: hook.onStart ? await loadNestAgent(path, hook.onStart, options) : undefined,
|
|
71
|
+
onSuccess: hook.onSuccess ? await loadNestAgent(path, hook.onSuccess, options) : undefined,
|
|
72
|
+
onError: hook.onError ? await loadNestAgent(path, hook.onError, options) : undefined,
|
|
73
|
+
onEnd: hook.onEnd ? await loadNestAgent(path, hook.onEnd, options) : undefined,
|
|
74
|
+
onSkillStart: hook.onSkillStart
|
|
75
|
+
? await loadNestAgent(path, hook.onSkillStart, options)
|
|
76
|
+
: undefined,
|
|
77
|
+
onSkillEnd: hook.onSkillEnd
|
|
78
|
+
? await loadNestAgent(path, hook.onSkillEnd, options)
|
|
79
|
+
: undefined,
|
|
80
|
+
onHandoff: hook.onHandoff ? await loadNestAgent(path, hook.onHandoff, options) : undefined,
|
|
81
|
+
})));
|
|
82
|
+
}
|
|
83
|
+
async function parseAgent(path, agent, options, agentOptions) {
|
|
56
84
|
const skills = "skills" in agent
|
|
57
85
|
? agent.skills &&
|
|
58
|
-
(await Promise.all(agent.skills.map((skill) =>
|
|
59
|
-
? loadAgent(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), skill), options)
|
|
60
|
-
: parseAgent(path, skill, options))))
|
|
86
|
+
(await Promise.all(agent.skills.map((skill) => loadNestAgent(path, skill, options))))
|
|
61
87
|
: undefined;
|
|
62
88
|
const memory = "memory" in agent && options?.memories?.length
|
|
63
89
|
? await loadMemory(options.memories, typeof agent.memory === "object" ? agent.memory.provider : undefined, typeof agent.memory === "object" ? agent.memory : {})
|
|
64
90
|
: undefined;
|
|
91
|
+
const baseOptions = {
|
|
92
|
+
...agentOptions,
|
|
93
|
+
...agent,
|
|
94
|
+
skills,
|
|
95
|
+
memory,
|
|
96
|
+
hooks: [
|
|
97
|
+
...((await parseHooks(path, agent.hooks, options)) ?? []),
|
|
98
|
+
...[agentOptions?.hooks].flat().filter(type_utils_js_1.isNonNullable),
|
|
99
|
+
],
|
|
100
|
+
};
|
|
65
101
|
switch (agent.type) {
|
|
66
102
|
case "ai": {
|
|
67
103
|
return ai_agent_js_1.AIAgent.from({
|
|
68
|
-
...
|
|
104
|
+
...baseOptions,
|
|
69
105
|
instructions: agent.instructions &&
|
|
70
106
|
prompt_builder_js_1.PromptBuilder.from(agent.instructions, { workingDir: index_js_1.nodejs.path.dirname(path) }),
|
|
71
|
-
memory,
|
|
72
|
-
skills,
|
|
73
107
|
});
|
|
74
108
|
}
|
|
75
109
|
case "mcp": {
|
|
76
110
|
if (agent.url) {
|
|
77
111
|
return mcp_agent_js_1.MCPAgent.from({
|
|
112
|
+
...baseOptions,
|
|
78
113
|
url: agent.url,
|
|
79
114
|
});
|
|
80
115
|
}
|
|
81
116
|
if (agent.command) {
|
|
82
117
|
return mcp_agent_js_1.MCPAgent.from({
|
|
118
|
+
...baseOptions,
|
|
83
119
|
command: agent.command,
|
|
84
120
|
args: agent.args,
|
|
85
121
|
});
|
|
@@ -88,16 +124,19 @@ async function parseAgent(path, agent, options) {
|
|
|
88
124
|
}
|
|
89
125
|
case "team": {
|
|
90
126
|
return team_agent_js_1.TeamAgent.from({
|
|
91
|
-
...
|
|
92
|
-
memory,
|
|
93
|
-
skills,
|
|
127
|
+
...baseOptions,
|
|
94
128
|
});
|
|
95
129
|
}
|
|
96
130
|
case "transform": {
|
|
97
131
|
return transform_agent_js_1.TransformAgent.from({
|
|
98
|
-
...
|
|
99
|
-
|
|
100
|
-
|
|
132
|
+
...baseOptions,
|
|
133
|
+
jsonata: agent.jsonata,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
case "function": {
|
|
137
|
+
return agent_js_1.FunctionAgent.from({
|
|
138
|
+
...baseOptions,
|
|
139
|
+
process: agent.process,
|
|
101
140
|
});
|
|
102
141
|
}
|
|
103
142
|
}
|
|
@@ -22,4 +22,14 @@ export declare const inputOutputSchema: ({ path }: {
|
|
|
22
22
|
required?: string[] | undefined;
|
|
23
23
|
additionalProperties?: boolean | undefined;
|
|
24
24
|
}>]>;
|
|
25
|
+
export declare const defaultInputSchema: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
|
|
26
|
+
$get: z.ZodString;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
$get: string;
|
|
29
|
+
}, {
|
|
30
|
+
$get: string;
|
|
31
|
+
}>, z.ZodUnknown]>>;
|
|
25
32
|
export declare function optionalize<T>(schema: ZodType<T>): ZodType<T | undefined>;
|
|
33
|
+
export declare function camelizeSchema<T>(schema: ZodType<T>, { shallow }?: {
|
|
34
|
+
shallow?: boolean;
|
|
35
|
+
}): ZodType<T>;
|
package/lib/cjs/loader/schema.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.inputOutputSchema = void 0;
|
|
6
|
+
exports.defaultInputSchema = exports.inputOutputSchema = void 0;
|
|
4
7
|
exports.optionalize = optionalize;
|
|
8
|
+
exports.camelizeSchema = camelizeSchema;
|
|
5
9
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
10
|
+
const camelize_ts_1 = __importDefault(require("camelize-ts"));
|
|
6
11
|
const yaml_1 = require("yaml");
|
|
7
12
|
const zod_1 = require("zod");
|
|
13
|
+
const agent_js_1 = require("../agents/agent.js");
|
|
14
|
+
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
8
15
|
const inputOutputSchema = ({ path }) => {
|
|
9
16
|
const includeExternalSchema = async (schema) => {
|
|
10
17
|
if (schema?.type === "object" && schema.properties) {
|
|
@@ -50,6 +57,15 @@ const inputOutputSchema = ({ path }) => {
|
|
|
50
57
|
]);
|
|
51
58
|
};
|
|
52
59
|
exports.inputOutputSchema = inputOutputSchema;
|
|
60
|
+
exports.defaultInputSchema = zod_1.z.record(zod_1.z.string(), zod_1.z.union([
|
|
61
|
+
zod_1.z.object({
|
|
62
|
+
[agent_js_1.DEFAULT_INPUT_ACTION_GET]: zod_1.z.string(),
|
|
63
|
+
}),
|
|
64
|
+
zod_1.z.unknown(),
|
|
65
|
+
]));
|
|
53
66
|
function optionalize(schema) {
|
|
54
67
|
return schema.nullish().transform((v) => v ?? undefined);
|
|
55
68
|
}
|
|
69
|
+
function camelizeSchema(schema, { shallow = true } = {}) {
|
|
70
|
+
return zod_1.z.preprocess((v) => ((0, type_utils_js_1.isRecord)(v) ? (0, camelize_ts_1.default)(v, shallow) : v), schema);
|
|
71
|
+
}
|
|
@@ -19,7 +19,7 @@ export declare function pick<T extends object, K extends keyof T>(obj: T, ...key
|
|
|
19
19
|
export declare function omit<T extends object, K extends keyof T>(obj: T, ...keys: (K | K[])[]): Omit<T, K>;
|
|
20
20
|
export declare function omitDeep<T, K>(obj: T, ...keys: (K | K[])[]): unknown;
|
|
21
21
|
export declare function omitBy<T extends Record<string, unknown>, K extends keyof T>(obj: T, predicate: (value: T[K], key: K) => boolean): Partial<T>;
|
|
22
|
-
export declare function flat<T>(value
|
|
22
|
+
export declare function flat<T>(...value: (T | T[])[]): NonNullable<T>[];
|
|
23
23
|
export declare function createAccessorArray<T>(array: T[], accessor: (array: T[], name: string) => T | undefined): T[] & {
|
|
24
24
|
[key: string]: T;
|
|
25
25
|
};
|