@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.
Files changed (44) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/lib/cjs/agents/agent.d.ts +71 -10
  3. package/lib/cjs/agents/agent.js +73 -28
  4. package/lib/cjs/agents/ai-agent.js +6 -3
  5. package/lib/cjs/agents/team-agent.d.ts +93 -1
  6. package/lib/cjs/agents/team-agent.js +45 -17
  7. package/lib/cjs/aigne/context.d.ts +1 -0
  8. package/lib/cjs/aigne/context.js +25 -10
  9. package/lib/cjs/loader/agent-js.d.ts +2 -17
  10. package/lib/cjs/loader/agent-js.js +4 -16
  11. package/lib/cjs/loader/agent-yaml.d.ts +29 -8
  12. package/lib/cjs/loader/agent-yaml.js +44 -15
  13. package/lib/cjs/loader/index.d.ts +2 -2
  14. package/lib/cjs/loader/index.js +55 -16
  15. package/lib/cjs/loader/schema.d.ts +10 -0
  16. package/lib/cjs/loader/schema.js +17 -1
  17. package/lib/cjs/utils/type-utils.d.ts +1 -1
  18. package/lib/cjs/utils/type-utils.js +2 -4
  19. package/lib/dts/agents/agent.d.ts +71 -10
  20. package/lib/dts/agents/team-agent.d.ts +93 -1
  21. package/lib/dts/aigne/context.d.ts +1 -0
  22. package/lib/dts/loader/agent-js.d.ts +2 -17
  23. package/lib/dts/loader/agent-yaml.d.ts +29 -8
  24. package/lib/dts/loader/index.d.ts +2 -2
  25. package/lib/dts/loader/schema.d.ts +10 -0
  26. package/lib/dts/utils/type-utils.d.ts +1 -1
  27. package/lib/esm/agents/agent.d.ts +71 -10
  28. package/lib/esm/agents/agent.js +73 -28
  29. package/lib/esm/agents/ai-agent.js +6 -3
  30. package/lib/esm/agents/team-agent.d.ts +93 -1
  31. package/lib/esm/agents/team-agent.js +44 -16
  32. package/lib/esm/aigne/context.d.ts +1 -0
  33. package/lib/esm/aigne/context.js +25 -10
  34. package/lib/esm/loader/agent-js.d.ts +2 -17
  35. package/lib/esm/loader/agent-js.js +4 -13
  36. package/lib/esm/loader/agent-yaml.d.ts +29 -8
  37. package/lib/esm/loader/agent-yaml.js +44 -13
  38. package/lib/esm/loader/index.d.ts +2 -2
  39. package/lib/esm/loader/index.js +56 -17
  40. package/lib/esm/loader/schema.d.ts +10 -0
  41. package/lib/esm/loader/schema.js +12 -0
  42. package/lib/esm/utils/type-utils.d.ts +1 -1
  43. package/lib/esm/utils/type-utils.js +2 -4
  44. 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._process(input, options);
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._process({ ...input, [key]: arr, ...item }, { ...options, streaming: false }));
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
- _process(input, options) {
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
- // Clone the agents to run, so that we can update the agents list during the loop
175
- const agents = [...this.skills];
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 result = await Promise.all(this.skills.map((agent) => options.context.invoke(agent, input, { returnActiveAgent: true, streaming: true })));
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>;
@@ -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 = new strict_event_emitter_1.Emitter();
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.onHandoff?.({
320
- context,
321
- source: options.sourceAgent,
322
- target: activeAgent,
323
- input,
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, { ...options, context, streaming: true });
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 { type ZodObject, type ZodType, z } from "zod";
2
- import { Agent, type FunctionAgentFn } from "../agents/agent.js";
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 schema_js_1 = require("./schema.js");
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)(() => agentJsFileSchema.parseAsync((0, camelize_ts_1.default)({
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
- })), (error) => new Error(`Failed to parse agent from ${path}: ${error.message}`));
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 BaseAgentSchema {
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?: (string | AgentSchema)[];
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
- type AgentSchema = AIAgentSchema | MCPAgentSchema | TeamAgentSchema | TransformAgentSchema;
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 loadAgentFromYamlFile(path) {
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
- skills: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.union([zod_1.z.string(), agentSchema]))),
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 && index_js_1.nodejs.fs.readFile(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), v.url), "utf8")),
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.object({
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, camelize_ts_1.default)((0, yaml_1.parse)(raw)), (error) => new Error(`Failed to parse agent definition from ${path}: ${error.message}`));
72
- const agent = await (0, type_utils_js_1.tryOrThrow)(async () => await agentSchema.parseAsync({
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>;
@@ -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 agent_js_1.FunctionAgent.from(agent);
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 parseAgent(path, agent, options) {
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) => typeof skill === "string"
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
- ...agent,
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
- ...agent,
92
- memory,
93
- skills,
127
+ ...baseOptions,
94
128
  });
95
129
  }
96
130
  case "transform": {
97
131
  return transform_agent_js_1.TransformAgent.from({
98
- ...agent,
99
- memory,
100
- skills,
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>;
@@ -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?: T | T[]): T[];
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
  };