@aigne/core 1.58.3 → 1.60.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 (46) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/lib/cjs/agents/agent.d.ts +9 -0
  3. package/lib/cjs/agents/agent.js +13 -3
  4. package/lib/cjs/agents/ai-agent.d.ts +0 -12
  5. package/lib/cjs/agents/ai-agent.js +4 -11
  6. package/lib/cjs/agents/chat-model.d.ts +9 -3
  7. package/lib/cjs/agents/chat-model.js +22 -3
  8. package/lib/cjs/agents/image-agent.d.ts +1 -3
  9. package/lib/cjs/agents/image-agent.js +3 -6
  10. package/lib/cjs/agents/image-model.d.ts +3 -3
  11. package/lib/cjs/agents/team-agent.js +6 -3
  12. package/lib/cjs/agents/user-agent.js +2 -1
  13. package/lib/cjs/aigne/context.js +2 -0
  14. package/lib/cjs/loader/agent-yaml.d.ts +5 -2
  15. package/lib/cjs/loader/agent-yaml.js +6 -1
  16. package/lib/cjs/loader/index.d.ts +23 -33
  17. package/lib/cjs/loader/index.js +12 -24
  18. package/lib/cjs/loader/schema.d.ts +29 -0
  19. package/lib/cjs/loader/schema.js +21 -1
  20. package/lib/dts/agents/agent.d.ts +9 -0
  21. package/lib/dts/agents/ai-agent.d.ts +0 -12
  22. package/lib/dts/agents/chat-model.d.ts +9 -3
  23. package/lib/dts/agents/image-agent.d.ts +1 -3
  24. package/lib/dts/agents/image-model.d.ts +3 -3
  25. package/lib/dts/loader/agent-yaml.d.ts +5 -2
  26. package/lib/dts/loader/index.d.ts +23 -33
  27. package/lib/dts/loader/schema.d.ts +29 -0
  28. package/lib/esm/agents/agent.d.ts +9 -0
  29. package/lib/esm/agents/agent.js +13 -3
  30. package/lib/esm/agents/ai-agent.d.ts +0 -12
  31. package/lib/esm/agents/ai-agent.js +4 -11
  32. package/lib/esm/agents/chat-model.d.ts +9 -3
  33. package/lib/esm/agents/chat-model.js +22 -3
  34. package/lib/esm/agents/image-agent.d.ts +1 -3
  35. package/lib/esm/agents/image-agent.js +3 -6
  36. package/lib/esm/agents/image-model.d.ts +3 -3
  37. package/lib/esm/agents/team-agent.js +6 -3
  38. package/lib/esm/agents/user-agent.js +2 -1
  39. package/lib/esm/aigne/context.js +2 -0
  40. package/lib/esm/loader/agent-yaml.d.ts +5 -2
  41. package/lib/esm/loader/agent-yaml.js +7 -2
  42. package/lib/esm/loader/index.d.ts +23 -33
  43. package/lib/esm/loader/index.js +14 -26
  44. package/lib/esm/loader/schema.d.ts +29 -0
  45. package/lib/esm/loader/schema.js +20 -0
  46. package/package.json +3 -3
@@ -3,6 +3,10 @@ import { type PromiseOrValue } from "../utils/type-utils.js";
3
3
  import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessResult, type AgentResponse, type AgentResponseStream, type Message } from "./agent.js";
4
4
  export declare class StructuredOutputError extends Error {
5
5
  }
6
+ export interface ChatModelOptions extends Omit<AgentOptions<ChatModelInput, ChatModelOutput>, "model" | "inputSchema" | "outputSchema"> {
7
+ model?: string;
8
+ modelOptions?: Omit<ModelOptions, "model">;
9
+ }
6
10
  /**
7
11
  * ChatModel is an abstract base class for interacting with Large Language Models (LLMs).
8
12
  *
@@ -27,8 +31,9 @@ export declare class StructuredOutputError extends Error {
27
31
  * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
28
32
  */
29
33
  export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelOutput> {
34
+ options?: ChatModelOptions | undefined;
30
35
  tag: string;
31
- constructor(options?: Omit<AgentOptions<ChatModelInput, ChatModelOutput>, "inputSchema" | "outputSchema">);
36
+ constructor(options?: ChatModelOptions | undefined);
32
37
  get credential(): PromiseOrValue<{
33
38
  url?: string;
34
39
  apiKey?: string;
@@ -145,7 +150,7 @@ export interface ChatModelInput extends Message {
145
150
  /**
146
151
  * Model-specific configuration options
147
152
  */
148
- modelOptions?: ChatModelOptions;
153
+ modelOptions?: ModelOptions;
149
154
  }
150
155
  /**
151
156
  * Message role types
@@ -578,7 +583,7 @@ export type Modality = "text" | "image" | "audio";
578
583
  *
579
584
  * Contains various parameters for controlling model behavior, such as model name, temperature, etc.
580
585
  */
581
- export interface ChatModelOptions {
586
+ export interface ModelOptions {
582
587
  /**
583
588
  * Model name or version
584
589
  */
@@ -604,6 +609,7 @@ export interface ChatModelOptions {
604
609
  */
605
610
  parallelToolCalls?: boolean;
606
611
  modalities?: Modality[];
612
+ preferFileInputType?: "file" | "url";
607
613
  }
608
614
  /**
609
615
  * Output message format for ChatModel
@@ -36,10 +36,11 @@ export class StructuredOutputError extends Error {
36
36
  * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
37
37
  */
38
38
  export class ChatModel extends Agent {
39
+ options;
39
40
  tag = "ChatModelAgent";
40
41
  constructor(options) {
41
42
  if (options)
42
- checkArguments("ChatModel", agentOptionsSchema, options);
43
+ checkArguments("ChatModel", chatModelOptionsSchema, options);
43
44
  const retryOnError = options?.retryOnError === false
44
45
  ? false
45
46
  : options?.retryOnError === true
@@ -53,7 +54,9 @@ export class ChatModel extends Agent {
53
54
  inputSchema: chatModelInputSchema,
54
55
  outputSchema: chatModelOutputSchema,
55
56
  retryOnError,
57
+ model: undefined,
56
58
  });
59
+ this.options = options;
57
60
  }
58
61
  get credential() {
59
62
  return {};
@@ -148,6 +151,18 @@ export class ChatModel extends Agent {
148
151
  mimeType: item.mimeType || ChatModel.getMimeType(item.filename || item.path),
149
152
  };
150
153
  }
154
+ if ((input.modelOptions?.preferFileInputType ||
155
+ this.options?.modelOptions?.preferFileInputType) !== "url") {
156
+ if (item.type === "url") {
157
+ return {
158
+ ...item,
159
+ type: "file",
160
+ data: Buffer.from(await (await this.downloadFile(item.url)).arrayBuffer()).toString("base64"),
161
+ url: undefined,
162
+ mimeType: item.mimeType || ChatModel.getMimeType(item.filename || item.url),
163
+ };
164
+ }
165
+ }
151
166
  return item;
152
167
  })),
153
168
  };
@@ -338,7 +353,7 @@ const chatModelInputToolChoiceSchema = z.union([
338
353
  z.literal("required"),
339
354
  chatModelInputToolSchema,
340
355
  ]);
341
- const chatModelOptionsSchema = z.object({
356
+ const modelOptionsSchema = z.object({
342
357
  model: z.string().optional(),
343
358
  temperature: z.number().optional(),
344
359
  topP: z.number().optional(),
@@ -347,12 +362,16 @@ const chatModelOptionsSchema = z.object({
347
362
  parallelToolCalls: z.boolean().optional().default(true),
348
363
  modalities: z.array(z.enum(["text", "image", "audio"])).optional(),
349
364
  });
365
+ const chatModelOptionsSchema = agentOptionsSchema.extend({
366
+ model: z.string().optional(),
367
+ modelOptions: modelOptionsSchema.optional(),
368
+ });
350
369
  const chatModelInputSchema = z.object({
351
370
  messages: z.array(chatModelInputMessageSchema),
352
371
  responseFormat: chatModelInputResponseFormatSchema.optional(),
353
372
  tools: z.array(chatModelInputToolSchema).optional(),
354
373
  toolChoice: chatModelInputToolChoiceSchema.optional(),
355
- modelOptions: chatModelOptionsSchema.optional(),
374
+ modelOptions: modelOptionsSchema.optional(),
356
375
  });
357
376
  export var FileOutputType;
358
377
  (function (FileOutputType) {
@@ -1,9 +1,8 @@
1
1
  import { type ZodObject, type ZodType } from "zod";
2
2
  import { PromptBuilder } from "../prompt/prompt-builder.js";
3
3
  import { Agent, type AgentInvokeOptions, type AgentOptions, type Message } from "./agent.js";
4
- import { type ImageModel, type ImageModelOutput } from "./image-model.js";
4
+ import { type ImageModelOutput } from "./image-model.js";
5
5
  export interface ImageAgentOptions<I extends Message = any, O extends ImageModelOutput = any> extends Omit<AgentOptions<I, O>, "outputSchema"> {
6
- model?: ImageModel;
7
6
  instructions: string | PromptBuilder;
8
7
  modelOptions?: Record<string, any>;
9
8
  }
@@ -14,7 +13,6 @@ export declare class ImageAgent<I extends Message = any, O extends ImageModelOut
14
13
  tag: string;
15
14
  static from<I extends Message = any, O extends ImageModelOutput = any>(options: ImageAgentOptions<I, O>): ImageAgent<I, O>;
16
15
  constructor(options: ImageAgentOptions<I, O>);
17
- model?: ImageModel;
18
16
  instructions: PromptBuilder;
19
17
  modelOptions?: Record<string, any>;
20
18
  process(input: I, options: AgentInvokeOptions): Promise<O>;
@@ -4,7 +4,6 @@ import { checkArguments } from "../utils/type-utils.js";
4
4
  import { Agent, agentOptionsSchema, } from "./agent.js";
5
5
  import { imageModelOutputSchema } from "./image-model.js";
6
6
  export const imageAgentOptionsSchema = agentOptionsSchema.extend({
7
- model: z.custom().optional(),
8
7
  instructions: z.union([z.string(), z.custom()]),
9
8
  modelOptions: z.record(z.any()).optional(),
10
9
  });
@@ -16,21 +15,19 @@ export class ImageAgent extends Agent {
16
15
  constructor(options) {
17
16
  super({ ...options, outputSchema: imageModelOutputSchema });
18
17
  checkArguments("ImageAgent", imageAgentOptionsSchema, options);
19
- this.model = options.model;
20
18
  this.instructions =
21
19
  typeof options.instructions === "string"
22
20
  ? PromptBuilder.from(options.instructions)
23
21
  : options.instructions;
24
22
  this.modelOptions = options.modelOptions;
25
23
  }
26
- model;
27
24
  instructions;
28
25
  modelOptions;
29
26
  async process(input, options) {
30
- const model = this.model ?? options.context.imageModel;
31
- if (!model)
27
+ const imageModel = this.imageModel || options.imageModel || options.context.imageModel;
28
+ if (!imageModel)
32
29
  throw new Error("image model is required to run ImageAgent");
33
30
  const { prompt } = await this.instructions.buildImagePrompt({ input });
34
- return (await options.context.invoke(model, { ...input, ...this.modelOptions, prompt }, { ...options, streaming: false }));
31
+ return (await this.invokeChildAgent(imageModel, { ...input, ...this.modelOptions, prompt }, { ...options, streaming: false }));
35
32
  }
36
33
  }
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import type { PromiseOrValue } from "../utils/type-utils.js";
3
3
  import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessResult, type Message } from "./agent.js";
4
4
  import { type ChatModelOutputUsage } from "./chat-model.js";
5
- export interface ImageModelOptions<I extends ImageModelInput = ImageModelInput, O extends ImageModelOutput = ImageModelOutput> extends AgentOptions<I, O> {
5
+ export interface ImageModelOptions<I extends ImageModelInput = ImageModelInput, O extends ImageModelOutput = ImageModelOutput> extends Omit<AgentOptions<I, O>, "model"> {
6
6
  }
7
7
  export declare abstract class ImageModel<I extends ImageModelInput = ImageModelInput, O extends ImageModelOutput = ImageModelOutput> extends Agent<I, O> {
8
8
  tag: string;
@@ -32,14 +32,14 @@ export declare const imageModelInputSchema: z.ZodObject<{
32
32
  }, "strip", z.ZodTypeAny, {
33
33
  prompt: string;
34
34
  model?: string | undefined;
35
- responseFormat?: "base64" | "url" | undefined;
36
35
  image?: string | string[] | undefined;
36
+ responseFormat?: "base64" | "url" | undefined;
37
37
  n?: number | undefined;
38
38
  }, {
39
39
  prompt: string;
40
40
  model?: string | undefined;
41
- responseFormat?: "base64" | "url" | undefined;
42
41
  image?: string | string[] | undefined;
42
+ responseFormat?: "base64" | "url" | undefined;
43
43
  n?: number | undefined;
44
44
  }>;
45
45
  export interface ImageModelOutput extends Message {
@@ -171,7 +171,10 @@ export class TeamAgent extends Agent {
171
171
  for (;;) {
172
172
  const output = await agentProcessResultToObject(await this._processNonReflection(previousOutput, options));
173
173
  Object.assign(previousOutput, output);
174
- const reviewOutput = await options.context.invoke(this.reflection.reviewer, previousOutput);
174
+ const reviewOutput = await this.invokeChildAgent(this.reflection.reviewer, previousOutput, {
175
+ ...options,
176
+ streaming: false,
177
+ });
175
178
  Object.assign(previousOutput, reviewOutput);
176
179
  const { isApproved } = this.reflection;
177
180
  const approved = typeof isApproved === "string" ? reviewOutput[isApproved] : await isApproved(reviewOutput);
@@ -246,7 +249,7 @@ export class TeamAgent extends Agent {
246
249
  async *_processSequential(input, options) {
247
250
  const output = {};
248
251
  for (const agent of this.skills) {
249
- const o = await options.context.invoke(agent, { ...input, ...output }, { ...options, streaming: true });
252
+ const o = await this.invokeChildAgent(agent, { ...input, ...output }, { ...options, streaming: true });
250
253
  const isLast = agent === this.skills[this.skills.length - 1];
251
254
  for await (const chunk of o) {
252
255
  // Only yield the chunk if it is the last agent in the sequence
@@ -272,7 +275,7 @@ export class TeamAgent extends Agent {
272
275
  * @private
273
276
  */
274
277
  async *_processParallel(input, options) {
275
- const streams = await Promise.all(this.skills.map((agent) => options.context.invoke(agent, input, { ...options, streaming: true })));
278
+ const streams = await Promise.all(this.skills.map((agent) => this.invokeChildAgent(agent, input, { ...options, streaming: true })));
276
279
  const read = async (index, reader) => {
277
280
  const promise = reader.read();
278
281
  return promise.then((result) => ({ ...result, reader, index }));
@@ -32,7 +32,8 @@ export class UserAgent extends Agent {
32
32
  return this._process(input, options);
33
33
  }
34
34
  if (this.activeAgent) {
35
- const [output, agent] = await options.context.invoke(this.activeAgent, input, {
35
+ const [output, agent] = await this.invokeChildAgent(this.activeAgent, input, {
36
+ ...options,
36
37
  returnActiveAgent: true,
37
38
  streaming: true,
38
39
  // Do not create a new context for the nested agent invocation,
@@ -347,6 +347,8 @@ class AIGNEContextShared {
347
347
  hooks: options.hooks,
348
348
  context,
349
349
  streaming: true,
350
+ model: options.model,
351
+ imageModel: options.imageModel,
350
352
  });
351
353
  for await (const value of stream) {
352
354
  if (isAgentResponseDelta(value)) {
@@ -1,7 +1,8 @@
1
- import { type ZodType } from "zod";
1
+ import { type ZodType, z } from "zod";
2
2
  import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
3
3
  import { AIAgentToolChoice } from "../agents/ai-agent.js";
4
4
  import { ProcessMode, type ReflectionMode } from "../agents/team-agent.js";
5
+ import { chatModelSchema, imageModelSchema } from "./schema.js";
5
6
  export interface HooksSchema {
6
7
  priority?: AgentHooks["priority"];
7
8
  onStart?: NestAgentSchema;
@@ -20,6 +21,8 @@ export type NestAgentSchema = string | {
20
21
  export interface BaseAgentSchema {
21
22
  name?: string;
22
23
  description?: string;
24
+ model?: z.infer<typeof chatModelSchema>;
25
+ imageModel?: z.infer<typeof imageModelSchema>;
23
26
  taskTitle?: string;
24
27
  taskRenderMode?: TaskRenderMode;
25
28
  inputSchema?: ZodType<Record<string, any>>;
@@ -74,5 +77,5 @@ export interface FunctionAgentSchema extends BaseAgentSchema {
74
77
  process: FunctionAgentFn;
75
78
  }
76
79
  export type AgentSchema = AIAgentSchema | ImageAgentSchema | MCPAgentSchema | TeamAgentSchema | TransformAgentSchema | FunctionAgentSchema;
77
- export declare function parseAgentFile(path: string, data: object): Promise<AgentSchema>;
80
+ export declare function parseAgentFile(path: string, data: any): Promise<AgentSchema>;
78
81
  export declare function loadAgentFromYamlFile(path: string): Promise<AgentSchema>;
@@ -5,7 +5,7 @@ import { z } from "zod";
5
5
  import { AIAgentToolChoice } from "../agents/ai-agent.js";
6
6
  import { ProcessMode } from "../agents/team-agent.js";
7
7
  import { tryOrThrow } from "../utils/type-utils.js";
8
- import { camelizeSchema, defaultInputSchema, inputOutputSchema, optionalize } from "./schema.js";
8
+ import { camelizeSchema, chatModelSchema, defaultInputSchema, imageModelSchema, inputOutputSchema, optionalize, } from "./schema.js";
9
9
  export async function parseAgentFile(path, data) {
10
10
  const agentSchema = z.lazy(() => {
11
11
  const nestAgentSchema = z.lazy(() => z.union([
@@ -31,6 +31,8 @@ export async function parseAgentFile(path, data) {
31
31
  name: optionalize(z.string()),
32
32
  alias: optionalize(z.array(z.string())),
33
33
  description: optionalize(z.string()),
34
+ model: optionalize(chatModelSchema),
35
+ imageModel: optionalize(imageModelSchema),
34
36
  taskTitle: optionalize(z.string()),
35
37
  taskRenderMode: optionalize(z.union([z.literal("hide"), z.literal("collapse")])),
36
38
  inputSchema: optionalize(inputOutputSchema({ path })).transform((v) => v ? jsonSchemaToZod(v) : undefined),
@@ -114,7 +116,10 @@ export async function parseAgentFile(path, data) {
114
116
  .extend(baseAgentSchema.shape),
115
117
  ]));
116
118
  });
117
- return agentSchema.parseAsync(data);
119
+ return agentSchema.parseAsync({
120
+ ...data,
121
+ model: data.model || data.chatModel || data.chat_model,
122
+ });
118
123
  }
119
124
  export async function loadAgentFromYamlFile(path) {
120
125
  const raw = await tryOrThrow(() => nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
@@ -9,7 +9,7 @@ export interface LoadOptions {
9
9
  memories?: {
10
10
  new (parameters?: MemoryAgentOptions): MemoryAgent;
11
11
  }[];
12
- model?: ChatModel | ((model?: z.infer<typeof aigneFileSchema>["chatModel"]) => PromiseOrValue<ChatModel | undefined>);
12
+ model?: ChatModel | ((model?: z.infer<typeof aigneFileSchema>["model"]) => PromiseOrValue<ChatModel | undefined>);
13
13
  imageModel?: ImageModel | ((model?: z.infer<typeof aigneFileSchema>["imageModel"]) => PromiseOrValue<ImageModel | undefined>);
14
14
  key?: string | number;
15
15
  }
@@ -18,38 +18,22 @@ export declare function loadAgent(path: string, options?: LoadOptions, agentOpti
18
18
  declare const aigneFileSchema: z.ZodObject<{
19
19
  name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
20
20
  description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
21
- chatModel: z.ZodEffects<z.ZodEffects<z.ZodType<string | {
21
+ model: z.ZodType<{
22
22
  model?: string | undefined;
23
23
  temperature?: number | undefined;
24
24
  topP?: number | undefined;
25
25
  frequencyPenalty?: number | undefined;
26
26
  presencePenalty?: number | undefined;
27
- } | undefined, z.ZodTypeDef, string | {
28
- model?: string | undefined;
29
- temperature?: number | undefined;
30
- topP?: number | undefined;
31
- frequencyPenalty?: number | undefined;
32
- presencePenalty?: number | undefined;
33
- } | undefined>, string | {
34
- model?: string | undefined;
35
- temperature?: number | undefined;
36
- topP?: number | undefined;
37
- frequencyPenalty?: number | undefined;
38
- presencePenalty?: number | undefined;
39
- } | undefined, unknown>, {
27
+ } | undefined, z.ZodTypeDef, {
40
28
  model?: string | undefined;
41
29
  temperature?: number | undefined;
42
30
  topP?: number | undefined;
43
31
  frequencyPenalty?: number | undefined;
44
32
  presencePenalty?: number | undefined;
45
- } | undefined, unknown>;
46
- imageModel: z.ZodEffects<z.ZodType<string | {
47
- model?: string | undefined;
48
- } | undefined, z.ZodTypeDef, string | {
49
- model?: string | undefined;
50
- } | undefined>, {
33
+ } | undefined>;
34
+ imageModel: z.ZodType<{
51
35
  model?: string | undefined;
52
- } | undefined, string | {
36
+ } | undefined, z.ZodTypeDef, {
53
37
  model?: string | undefined;
54
38
  } | undefined>;
55
39
  agents: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
@@ -67,20 +51,20 @@ declare const aigneFileSchema: z.ZodObject<{
67
51
  chat?: string | undefined;
68
52
  } | undefined>;
69
53
  }, "strip", z.ZodTypeAny, {
70
- name?: string | undefined;
71
- description?: string | undefined;
72
- skills?: string[] | undefined;
73
- imageModel?: {
74
- model?: string | undefined;
75
- } | undefined;
76
- agents?: string[] | undefined;
77
- chatModel?: {
54
+ model?: {
78
55
  model?: string | undefined;
79
56
  temperature?: number | undefined;
80
57
  topP?: number | undefined;
81
58
  frequencyPenalty?: number | undefined;
82
59
  presencePenalty?: number | undefined;
83
60
  } | undefined;
61
+ name?: string | undefined;
62
+ description?: string | undefined;
63
+ imageModel?: {
64
+ model?: string | undefined;
65
+ } | undefined;
66
+ skills?: string[] | undefined;
67
+ agents?: string[] | undefined;
84
68
  mcpServer?: {
85
69
  agents?: string[] | undefined;
86
70
  } | undefined;
@@ -89,14 +73,20 @@ declare const aigneFileSchema: z.ZodObject<{
89
73
  chat?: string | undefined;
90
74
  } | undefined;
91
75
  }, {
76
+ model?: {
77
+ model?: string | undefined;
78
+ temperature?: number | undefined;
79
+ topP?: number | undefined;
80
+ frequencyPenalty?: number | undefined;
81
+ presencePenalty?: number | undefined;
82
+ } | undefined;
92
83
  name?: string | undefined;
93
84
  description?: string | undefined;
94
- skills?: string[] | undefined;
95
- imageModel?: string | {
85
+ imageModel?: {
96
86
  model?: string | undefined;
97
87
  } | undefined;
88
+ skills?: string[] | undefined;
98
89
  agents?: string[] | undefined;
99
- chatModel?: unknown;
100
90
  mcpServer?: {
101
91
  agents?: string[] | undefined;
102
92
  } | undefined;
@@ -8,10 +8,10 @@ import { MCPAgent } from "../agents/mcp-agent.js";
8
8
  import { TeamAgent } from "../agents/team-agent.js";
9
9
  import { TransformAgent } from "../agents/transform-agent.js";
10
10
  import { PromptBuilder } from "../prompt/prompt-builder.js";
11
- import { flat, isNonNullable, isRecord, tryOrThrow, } from "../utils/type-utils.js";
11
+ import { flat, isNonNullable, tryOrThrow } from "../utils/type-utils.js";
12
12
  import { loadAgentFromJsFile } from "./agent-js.js";
13
13
  import { loadAgentFromYamlFile } from "./agent-yaml.js";
14
- import { camelizeSchema, optionalize } from "./schema.js";
14
+ import { camelizeSchema, chatModelSchema, imageModelSchema, optionalize } from "./schema.js";
15
15
  const AIGNE_FILE_NAME = ["aigne.yaml", "aigne.yml"];
16
16
  export async function load(path, options = {}) {
17
17
  options.key ??= Date.now();
@@ -22,7 +22,7 @@ export async function load(path, options = {}) {
22
22
  return {
23
23
  ...aigne,
24
24
  rootDir,
25
- model: typeof options.model === "function" ? await options.model(aigne.chatModel) : options.model,
25
+ model: typeof options.model === "function" ? await options.model(aigne.model) : options.model,
26
26
  imageModel: typeof options.imageModel === "function"
27
27
  ? await options.imageModel(aigne.imageModel)
28
28
  : options.imageModel,
@@ -87,9 +87,17 @@ async function parseAgent(path, agent, options, agentOptions) {
87
87
  const memory = "memory" in agent && options?.memories?.length
88
88
  ? await loadMemory(options.memories, typeof agent.memory === "object" ? agent.memory.provider : undefined, typeof agent.memory === "object" ? agent.memory : {})
89
89
  : undefined;
90
+ const model = agent.model && typeof options?.model === "function"
91
+ ? await options.model(agent.model)
92
+ : undefined;
93
+ const imageModel = agent.imageModel && typeof options?.imageModel === "function"
94
+ ? await options.imageModel(agent.imageModel)
95
+ : undefined;
90
96
  const baseOptions = {
91
97
  ...agentOptions,
92
98
  ...agent,
99
+ model,
100
+ imageModel,
93
101
  skills,
94
102
  memory,
95
103
  hooks: [
@@ -170,28 +178,8 @@ async function loadMemory(memories, provider, options) {
170
178
  const aigneFileSchema = camelizeSchema(z.object({
171
179
  name: optionalize(z.string()),
172
180
  description: optionalize(z.string()),
173
- chatModel: z
174
- .preprocess((v) => {
175
- if (!isRecord(v))
176
- return v;
177
- return { ...v, model: v.model || `${v.provider || ""}:${v.name || ""}` };
178
- }, optionalize(z.union([
179
- z.string(),
180
- camelizeSchema(z.object({
181
- model: optionalize(z.string()),
182
- temperature: optionalize(z.number().min(0).max(2)),
183
- topP: optionalize(z.number().min(0)),
184
- frequencyPenalty: optionalize(z.number().min(-2).max(2)),
185
- presencePenalty: optionalize(z.number().min(-2).max(2)),
186
- })),
187
- ])))
188
- .transform((v) => (typeof v === "string" ? { model: v } : v)),
189
- imageModel: optionalize(z.union([
190
- z.string(),
191
- camelizeSchema(z.object({
192
- model: optionalize(z.string()),
193
- })),
194
- ])).transform((v) => (typeof v === "string" ? { model: v } : v)),
181
+ model: optionalize(chatModelSchema),
182
+ imageModel: optionalize(imageModelSchema),
195
183
  agents: optionalize(z.array(z.string())),
196
184
  skills: optionalize(z.array(z.string())),
197
185
  mcpServer: optionalize(z.object({
@@ -206,7 +194,7 @@ export async function loadAIGNEFile(path) {
206
194
  const file = await findAIGNEFile(path);
207
195
  const raw = await tryOrThrow(() => nodejs.fs.readFile(file, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${file}: ${error.message}`));
208
196
  const json = tryOrThrow(() => parse(raw), (error) => new Error(`Failed to parse aigne.yaml from ${file}: ${error.message}`));
209
- const aigne = tryOrThrow(() => aigneFileSchema.parse(json), (error) => new Error(`Failed to validate aigne.yaml from ${file}: ${error.message}`));
197
+ const aigne = tryOrThrow(() => aigneFileSchema.parse({ ...json, model: json.model || json.chatModel || json.chat_model }), (error) => new Error(`Failed to validate aigne.yaml from ${file}: ${error.message}`));
210
198
  return { aigne, rootDir: nodejs.path.dirname(file) };
211
199
  }
212
200
  async function findAIGNEFile(path) {
@@ -29,7 +29,36 @@ export declare const defaultInputSchema: z.ZodRecord<z.ZodString, z.ZodUnion<[z.
29
29
  }, {
30
30
  $get: string;
31
31
  }>, z.ZodUnknown]>>;
32
+ declare const chatModelObjectSchema: z.ZodObject<{
33
+ model: ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
34
+ temperature: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
35
+ topP: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
36
+ frequencyPenalty: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
37
+ presencePenalty: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
38
+ }, "strip", z.ZodTypeAny, {
39
+ model?: string | undefined;
40
+ temperature?: number | undefined;
41
+ topP?: number | undefined;
42
+ frequencyPenalty?: number | undefined;
43
+ presencePenalty?: number | undefined;
44
+ }, {
45
+ model?: string | undefined;
46
+ temperature?: number | undefined;
47
+ topP?: number | undefined;
48
+ frequencyPenalty?: number | undefined;
49
+ presencePenalty?: number | undefined;
50
+ }>;
51
+ export declare const chatModelSchema: typeof chatModelObjectSchema;
52
+ declare const imageModelObjectSchema: z.ZodObject<{
53
+ model: ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ model?: string | undefined;
56
+ }, {
57
+ model?: string | undefined;
58
+ }>;
59
+ export declare const imageModelSchema: typeof imageModelObjectSchema;
32
60
  export declare function optionalize<T>(schema: ZodType<T>): ZodType<T | undefined>;
33
61
  export declare function camelizeSchema<T extends ZodType>(schema: T, { shallow }?: {
34
62
  shallow?: boolean;
35
63
  }): T;
64
+ export {};
@@ -54,6 +54,26 @@ export const defaultInputSchema = z.record(z.string(), z.union([
54
54
  }),
55
55
  z.unknown(),
56
56
  ]));
57
+ const chatModelObjectSchema = camelizeSchema(z.object({
58
+ model: optionalize(z.string()),
59
+ temperature: optionalize(z.number().min(0).max(2)),
60
+ topP: optionalize(z.number().min(0)),
61
+ frequencyPenalty: optionalize(z.number().min(-2).max(2)),
62
+ presencePenalty: optionalize(z.number().min(-2).max(2)),
63
+ }));
64
+ export const chatModelSchema = z
65
+ .preprocess((v) => {
66
+ if (!isRecord(v))
67
+ return v;
68
+ return { ...v, model: v.model || `${v.provider || ""}:${v.name || ""}` };
69
+ }, z.union([z.string(), chatModelObjectSchema]))
70
+ .transform((v) => typeof v === "string" ? { model: v } : v);
71
+ const imageModelObjectSchema = camelizeSchema(z.object({
72
+ model: optionalize(z.string()),
73
+ }));
74
+ export const imageModelSchema = z
75
+ .union([z.string(), imageModelObjectSchema])
76
+ .transform((v) => typeof v === "string" ? { model: v } : v);
57
77
  export function optionalize(schema) {
58
78
  return schema.nullish().transform((v) => v ?? undefined);
59
79
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.58.3",
3
+ "version": "1.60.0",
4
4
  "description": "The functional core of agentic AI",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -92,8 +92,8 @@
92
92
  "yaml": "^2.8.0",
93
93
  "zod": "^3.25.67",
94
94
  "zod-to-json-schema": "^3.24.6",
95
- "@aigne/platform-helpers": "^0.6.2",
96
- "@aigne/observability-api": "^0.10.2"
95
+ "@aigne/observability-api": "^0.10.3",
96
+ "@aigne/platform-helpers": "^0.6.2"
97
97
  },
98
98
  "devDependencies": {
99
99
  "@types/bun": "^1.2.18",