@aigne/core 1.33.0 → 1.33.2

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.
@@ -2,6 +2,7 @@ import type { Camelize } from "camelize-ts";
2
2
  import { z } from "zod";
3
3
  import { Agent } from "../agents/agent.js";
4
4
  import type { ChatModel, ChatModelOptions } from "../agents/chat-model.js";
5
+ import type { AIGNEOptions } from "../aigne/aigne.js";
5
6
  import type { MemoryAgent, MemoryAgentOptions } from "../memory/memory.js";
6
7
  interface LoadableModelClass {
7
8
  new (parameters: {
@@ -23,103 +24,72 @@ export interface LoadOptions {
23
24
  }[];
24
25
  path: string;
25
26
  }
26
- export declare function load(options: LoadOptions): Promise<{
27
- model: ChatModel | undefined;
28
- agents: Agent<any, any>[];
29
- skills: Agent<any, any>[];
30
- name?: string | null | undefined;
31
- description?: string | null | undefined;
32
- chat_model?: {
33
- name?: string | null | undefined;
34
- temperature?: number | null | undefined;
35
- provider?: string | null | undefined;
36
- top_p?: number | null | undefined;
37
- frequency_penalty?: number | null | undefined;
38
- presence_penalty?: number | null | undefined;
39
- } | null | undefined;
40
- }>;
27
+ export declare function load(options: LoadOptions): Promise<AIGNEOptions>;
41
28
  export declare function loadAgent(path: string, options?: LoadOptions): Promise<Agent>;
42
- export declare function loadModel(models: LoadableModel[], model?: Camelize<z.infer<typeof aigneFileSchema>["chat_model"]>, modelOptions?: ChatModelOptions): Promise<ChatModel | undefined>;
29
+ export declare function loadModel(models: LoadableModel[], model?: Camelize<z.infer<typeof aigneFileSchema>["model"]>, modelOptions?: ChatModelOptions): Promise<ChatModel | undefined>;
43
30
  declare const aigneFileSchema: z.ZodObject<{
44
- name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
45
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
46
- chat_model: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodUnion<[z.ZodString, z.ZodObject<{
47
- provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
48
- name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
49
- temperature: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
50
- top_p: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
51
- frequency_penalty: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
52
- presence_penalty: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
53
- }, "strip", z.ZodTypeAny, {
31
+ name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
32
+ description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
33
+ model: z.ZodEffects<z.ZodType<string | {
54
34
  name?: string | null | undefined;
55
35
  temperature?: number | null | undefined;
36
+ topP?: number | null | undefined;
37
+ frequencyPenalty?: number | null | undefined;
38
+ presencePenalty?: number | null | undefined;
56
39
  provider?: string | null | undefined;
57
- top_p?: number | null | undefined;
58
- frequency_penalty?: number | null | undefined;
59
- presence_penalty?: number | null | undefined;
60
- }, {
40
+ } | undefined, z.ZodTypeDef, string | {
61
41
  name?: string | null | undefined;
62
42
  temperature?: number | null | undefined;
43
+ topP?: number | null | undefined;
44
+ frequencyPenalty?: number | null | undefined;
45
+ presencePenalty?: number | null | undefined;
63
46
  provider?: string | null | undefined;
64
- top_p?: number | null | undefined;
65
- frequency_penalty?: number | null | undefined;
66
- presence_penalty?: number | null | undefined;
67
- }>]>>>, {
47
+ } | undefined>, {
68
48
  name?: string | null | undefined;
69
49
  temperature?: number | null | undefined;
50
+ topP?: number | null | undefined;
51
+ frequencyPenalty?: number | null | undefined;
52
+ presencePenalty?: number | null | undefined;
70
53
  provider?: string | null | undefined;
71
- top_p?: number | null | undefined;
72
- frequency_penalty?: number | null | undefined;
73
- presence_penalty?: number | null | undefined;
74
- } | null | undefined, string | {
54
+ } | undefined, string | {
75
55
  name?: string | null | undefined;
76
56
  temperature?: number | null | undefined;
57
+ topP?: number | null | undefined;
58
+ frequencyPenalty?: number | null | undefined;
59
+ presencePenalty?: number | null | undefined;
77
60
  provider?: string | null | undefined;
78
- top_p?: number | null | undefined;
79
- frequency_penalty?: number | null | undefined;
80
- presence_penalty?: number | null | undefined;
81
- } | null | undefined>;
82
- agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
83
- skills: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
61
+ } | undefined>;
62
+ agents: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
63
+ skills: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
84
64
  }, "strip", z.ZodTypeAny, {
85
- name?: string | null | undefined;
86
- description?: string | null | undefined;
87
- skills?: string[] | null | undefined;
88
- chat_model?: {
65
+ name?: string | undefined;
66
+ description?: string | undefined;
67
+ skills?: string[] | undefined;
68
+ model?: {
89
69
  name?: string | null | undefined;
90
70
  temperature?: number | null | undefined;
71
+ topP?: number | null | undefined;
72
+ frequencyPenalty?: number | null | undefined;
73
+ presencePenalty?: number | null | undefined;
91
74
  provider?: string | null | undefined;
92
- top_p?: number | null | undefined;
93
- frequency_penalty?: number | null | undefined;
94
- presence_penalty?: number | null | undefined;
95
- } | null | undefined;
96
- agents?: string[] | null | undefined;
75
+ } | undefined;
76
+ agents?: string[] | undefined;
97
77
  }, {
98
- name?: string | null | undefined;
99
- description?: string | null | undefined;
100
- skills?: string[] | null | undefined;
101
- chat_model?: string | {
78
+ name?: string | undefined;
79
+ description?: string | undefined;
80
+ skills?: string[] | undefined;
81
+ model?: string | {
102
82
  name?: string | null | undefined;
103
83
  temperature?: number | null | undefined;
84
+ topP?: number | null | undefined;
85
+ frequencyPenalty?: number | null | undefined;
86
+ presencePenalty?: number | null | undefined;
104
87
  provider?: string | null | undefined;
105
- top_p?: number | null | undefined;
106
- frequency_penalty?: number | null | undefined;
107
- presence_penalty?: number | null | undefined;
108
- } | null | undefined;
109
- agents?: string[] | null | undefined;
88
+ } | undefined;
89
+ agents?: string[] | undefined;
110
90
  }>;
111
91
  export declare function loadAIGNEFile(path: string): Promise<{
112
- name?: string | null | undefined;
113
- description?: string | null | undefined;
114
- skills?: string[] | null | undefined;
115
- chat_model?: {
116
- name?: string | null | undefined;
117
- temperature?: number | null | undefined;
118
- provider?: string | null | undefined;
119
- top_p?: number | null | undefined;
120
- frequency_penalty?: number | null | undefined;
121
- presence_penalty?: number | null | undefined;
122
- } | null | undefined;
123
- agents?: string[] | null | undefined;
92
+ aigne: z.infer<typeof aigneFileSchema>;
93
+ rootDir: string;
124
94
  }>;
125
95
  export {};
@@ -151,7 +151,7 @@ const chatModelInputMessageSchema = z.object({
151
151
  type: z.literal("function"),
152
152
  function: z.object({
153
153
  name: z.string(),
154
- arguments: z.record(z.unknown()),
154
+ arguments: z.record(z.string(), z.unknown()),
155
155
  }),
156
156
  }))
157
157
  .optional(),
@@ -165,7 +165,7 @@ const chatModelInputResponseFormatSchema = z.discriminatedUnion("type", [
165
165
  jsonSchema: z.object({
166
166
  name: z.string(),
167
167
  description: z.string().optional(),
168
- schema: z.record(z.unknown()),
168
+ schema: z.record(z.string(), z.unknown()),
169
169
  strict: z.boolean().optional(),
170
170
  }),
171
171
  }),
@@ -175,7 +175,7 @@ const chatModelInputToolSchema = z.object({
175
175
  function: z.object({
176
176
  name: z.string(),
177
177
  description: z.string().optional(),
178
- parameters: z.record(z.unknown()),
178
+ parameters: z.record(z.string(), z.unknown()),
179
179
  }),
180
180
  });
181
181
  const chatModelInputToolChoiceSchema = z.union([
@@ -204,7 +204,7 @@ const chatModelOutputToolCallSchema = z.object({
204
204
  type: z.literal("function"),
205
205
  function: z.object({
206
206
  name: z.string(),
207
- arguments: z.record(z.unknown()),
207
+ arguments: z.record(z.string(), z.unknown()),
208
208
  }),
209
209
  });
210
210
  const chatModelOutputUsageSchema = z.object({
@@ -213,7 +213,7 @@ const chatModelOutputUsageSchema = z.object({
213
213
  });
214
214
  const chatModelOutputSchema = z.object({
215
215
  text: z.string().optional(),
216
- json: z.record(z.unknown()).optional(),
216
+ json: z.record(z.string(), z.unknown()).optional(),
217
217
  toolCalls: z.array(chatModelOutputToolCallSchema).optional(),
218
218
  usage: chatModelOutputUsageSchema.optional(),
219
219
  model: z.string().optional(),
@@ -302,6 +302,6 @@ const mcpAgentOptionsSchema = z.union([
302
302
  z.object({
303
303
  command: z.string(),
304
304
  args: z.array(z.string()).optional(),
305
- env: z.record(z.string()).optional(),
305
+ env: z.record(z.string(), z.string()).optional(),
306
306
  }),
307
307
  ]);
@@ -111,6 +111,8 @@ export class TeamAgent extends Agent {
111
111
  * @returns A stream of message chunks that collectively form the response
112
112
  */
113
113
  process(input, options) {
114
+ if (!this.skills.length)
115
+ throw new Error("TeamAgent must have at least one skill defined.");
114
116
  if (this.iterateOn) {
115
117
  return this._processIterator(this.iterateOn, input, options);
116
118
  }
@@ -10,6 +10,11 @@ import type { ContextLimits } from "./usage.js";
10
10
  * Options for the AIGNE class.
11
11
  */
12
12
  export interface AIGNEOptions {
13
+ /**
14
+ * Optional root directory for this AIGNE instance.
15
+ * This is used to resolve relative paths for agents and skills.
16
+ */
17
+ rootDir?: string;
13
18
  /**
14
19
  * The name of the AIGNE instance.
15
20
  */
@@ -67,6 +72,10 @@ export declare class AIGNE<U extends UserContext = UserContext> {
67
72
  * @param options - Configuration options for the AIGNE instance including name, description, model, and agents.
68
73
  */
69
74
  constructor(options?: AIGNEOptions);
75
+ /**
76
+ * Optional root directory for this AIGNE instance.
77
+ */
78
+ rootDir?: string;
70
79
  /**
71
80
  * Optional name identifier for this AIGNE instance.
72
81
  */
@@ -26,9 +26,10 @@ export class AIGNE {
26
26
  * @returns A fully initialized AIGNE instance with configured agents and skills.
27
27
  */
28
28
  static async load(path, options) {
29
- const { model, agents, skills, ...aigne } = await load({ ...options, path });
29
+ const { model, agents = [], skills = [], ...aigne } = await load({ ...options, path });
30
30
  return new AIGNE({
31
31
  ...options,
32
+ rootDir: aigne.rootDir,
32
33
  model: options?.model || model,
33
34
  name: options?.name || aigne.name || undefined,
34
35
  description: options?.description || aigne.description || undefined,
@@ -44,6 +45,7 @@ export class AIGNE {
44
45
  constructor(options) {
45
46
  if (options)
46
47
  checkArguments("AIGNE", aigneOptionsSchema, options);
48
+ this.rootDir = options?.rootDir;
47
49
  this.name = options?.name;
48
50
  this.description = options?.description;
49
51
  this.model = options?.model;
@@ -59,6 +61,10 @@ export class AIGNE {
59
61
  this.observer?.serve();
60
62
  this.initProcessExitHandler();
61
63
  }
64
+ /**
65
+ * Optional root directory for this AIGNE instance.
66
+ */
67
+ rootDir;
62
68
  /**
63
69
  * Optional name identifier for this AIGNE instance.
64
70
  */
@@ -381,6 +381,6 @@ async function* withAbortSignal(signal, error, fn) {
381
381
  }
382
382
  const aigneContextInvokeArgsSchema = z.object({
383
383
  agent: z.union([z.custom(), z.custom()]),
384
- message: z.union([z.record(z.unknown()), z.string()]).optional(),
384
+ message: z.union([z.record(z.string(), z.unknown()), z.string()]).optional(),
385
385
  options: z.object({ returnActiveAgent: z.boolean().optional() }).optional(),
386
386
  });
@@ -87,18 +87,18 @@ function once(events, event, listener) {
87
87
  }
88
88
  const subscribeArgsSchema = z.object({
89
89
  topic: z.union([z.string(), z.array(z.string())]),
90
- listener: z.function(z.tuple([z.any()]), z.any()).optional(),
90
+ listener: z.custom().optional(),
91
91
  });
92
92
  const unsubscribeArgsSchema = z.object({
93
93
  topic: z.union([z.string(), z.array(z.string())]),
94
- listener: z.function(z.tuple([z.any()]), z.any()),
94
+ listener: z.custom(),
95
95
  });
96
96
  const publishArgsSchema = z.object({
97
97
  topic: z.union([z.string(), z.array(z.string())]),
98
98
  payload: z.object({
99
99
  role: z.union([z.literal("user"), z.literal("agent")]),
100
100
  source: z.string().optional(),
101
- message: z.union([z.string(), z.record(z.unknown())]),
101
+ message: z.union([z.string(), z.record(z.string(), z.unknown())]),
102
102
  context: z.any(),
103
103
  }),
104
104
  });
@@ -62,11 +62,11 @@ export async function loadAgentFromYamlFile(path) {
62
62
  ]);
63
63
  });
64
64
  const raw = await tryOrThrow(() => nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
65
- const json = await tryOrThrow(() => parse(raw), (error) => new Error(`Failed to parse agent definition from ${path}: ${error.message}`));
66
- const agent = await tryOrThrow(async () => await agentSchema.parseAsync(camelize({
65
+ const json = tryOrThrow(() => camelize(parse(raw)), (error) => new Error(`Failed to parse agent definition from ${path}: ${error.message}`));
66
+ const agent = await tryOrThrow(async () => await agentSchema.parseAsync({
67
67
  ...json,
68
68
  type: json.type ?? "ai",
69
69
  skills: json.skills ?? json.tools,
70
- })), (error) => new Error(`Failed to validate agent definition from ${path}: ${error.message}`));
70
+ }), (error) => new Error(`Failed to validate agent definition from ${path}: ${error.message}`));
71
71
  return agent;
72
72
  }
@@ -2,6 +2,7 @@ import type { Camelize } from "camelize-ts";
2
2
  import { z } from "zod";
3
3
  import { Agent } from "../agents/agent.js";
4
4
  import type { ChatModel, ChatModelOptions } from "../agents/chat-model.js";
5
+ import type { AIGNEOptions } from "../aigne/aigne.js";
5
6
  import type { MemoryAgent, MemoryAgentOptions } from "../memory/memory.js";
6
7
  interface LoadableModelClass {
7
8
  new (parameters: {
@@ -23,103 +24,72 @@ export interface LoadOptions {
23
24
  }[];
24
25
  path: string;
25
26
  }
26
- export declare function load(options: LoadOptions): Promise<{
27
- model: ChatModel | undefined;
28
- agents: Agent<any, any>[];
29
- skills: Agent<any, any>[];
30
- name?: string | null | undefined;
31
- description?: string | null | undefined;
32
- chat_model?: {
33
- name?: string | null | undefined;
34
- temperature?: number | null | undefined;
35
- provider?: string | null | undefined;
36
- top_p?: number | null | undefined;
37
- frequency_penalty?: number | null | undefined;
38
- presence_penalty?: number | null | undefined;
39
- } | null | undefined;
40
- }>;
27
+ export declare function load(options: LoadOptions): Promise<AIGNEOptions>;
41
28
  export declare function loadAgent(path: string, options?: LoadOptions): Promise<Agent>;
42
- export declare function loadModel(models: LoadableModel[], model?: Camelize<z.infer<typeof aigneFileSchema>["chat_model"]>, modelOptions?: ChatModelOptions): Promise<ChatModel | undefined>;
29
+ export declare function loadModel(models: LoadableModel[], model?: Camelize<z.infer<typeof aigneFileSchema>["model"]>, modelOptions?: ChatModelOptions): Promise<ChatModel | undefined>;
43
30
  declare const aigneFileSchema: z.ZodObject<{
44
- name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
45
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
46
- chat_model: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodUnion<[z.ZodString, z.ZodObject<{
47
- provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
48
- name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
49
- temperature: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
50
- top_p: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
51
- frequency_penalty: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
52
- presence_penalty: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
53
- }, "strip", z.ZodTypeAny, {
31
+ name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
32
+ description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
33
+ model: z.ZodEffects<z.ZodType<string | {
54
34
  name?: string | null | undefined;
55
35
  temperature?: number | null | undefined;
36
+ topP?: number | null | undefined;
37
+ frequencyPenalty?: number | null | undefined;
38
+ presencePenalty?: number | null | undefined;
56
39
  provider?: string | null | undefined;
57
- top_p?: number | null | undefined;
58
- frequency_penalty?: number | null | undefined;
59
- presence_penalty?: number | null | undefined;
60
- }, {
40
+ } | undefined, z.ZodTypeDef, string | {
61
41
  name?: string | null | undefined;
62
42
  temperature?: number | null | undefined;
43
+ topP?: number | null | undefined;
44
+ frequencyPenalty?: number | null | undefined;
45
+ presencePenalty?: number | null | undefined;
63
46
  provider?: string | null | undefined;
64
- top_p?: number | null | undefined;
65
- frequency_penalty?: number | null | undefined;
66
- presence_penalty?: number | null | undefined;
67
- }>]>>>, {
47
+ } | undefined>, {
68
48
  name?: string | null | undefined;
69
49
  temperature?: number | null | undefined;
50
+ topP?: number | null | undefined;
51
+ frequencyPenalty?: number | null | undefined;
52
+ presencePenalty?: number | null | undefined;
70
53
  provider?: string | null | undefined;
71
- top_p?: number | null | undefined;
72
- frequency_penalty?: number | null | undefined;
73
- presence_penalty?: number | null | undefined;
74
- } | null | undefined, string | {
54
+ } | undefined, string | {
75
55
  name?: string | null | undefined;
76
56
  temperature?: number | null | undefined;
57
+ topP?: number | null | undefined;
58
+ frequencyPenalty?: number | null | undefined;
59
+ presencePenalty?: number | null | undefined;
77
60
  provider?: string | null | undefined;
78
- top_p?: number | null | undefined;
79
- frequency_penalty?: number | null | undefined;
80
- presence_penalty?: number | null | undefined;
81
- } | null | undefined>;
82
- agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
83
- skills: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
61
+ } | undefined>;
62
+ agents: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
63
+ skills: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
84
64
  }, "strip", z.ZodTypeAny, {
85
- name?: string | null | undefined;
86
- description?: string | null | undefined;
87
- skills?: string[] | null | undefined;
88
- chat_model?: {
65
+ name?: string | undefined;
66
+ description?: string | undefined;
67
+ skills?: string[] | undefined;
68
+ model?: {
89
69
  name?: string | null | undefined;
90
70
  temperature?: number | null | undefined;
71
+ topP?: number | null | undefined;
72
+ frequencyPenalty?: number | null | undefined;
73
+ presencePenalty?: number | null | undefined;
91
74
  provider?: string | null | undefined;
92
- top_p?: number | null | undefined;
93
- frequency_penalty?: number | null | undefined;
94
- presence_penalty?: number | null | undefined;
95
- } | null | undefined;
96
- agents?: string[] | null | undefined;
75
+ } | undefined;
76
+ agents?: string[] | undefined;
97
77
  }, {
98
- name?: string | null | undefined;
99
- description?: string | null | undefined;
100
- skills?: string[] | null | undefined;
101
- chat_model?: string | {
78
+ name?: string | undefined;
79
+ description?: string | undefined;
80
+ skills?: string[] | undefined;
81
+ model?: string | {
102
82
  name?: string | null | undefined;
103
83
  temperature?: number | null | undefined;
84
+ topP?: number | null | undefined;
85
+ frequencyPenalty?: number | null | undefined;
86
+ presencePenalty?: number | null | undefined;
104
87
  provider?: string | null | undefined;
105
- top_p?: number | null | undefined;
106
- frequency_penalty?: number | null | undefined;
107
- presence_penalty?: number | null | undefined;
108
- } | null | undefined;
109
- agents?: string[] | null | undefined;
88
+ } | undefined;
89
+ agents?: string[] | undefined;
110
90
  }>;
111
91
  export declare function loadAIGNEFile(path: string): Promise<{
112
- name?: string | null | undefined;
113
- description?: string | null | undefined;
114
- skills?: string[] | null | undefined;
115
- chat_model?: {
116
- name?: string | null | undefined;
117
- temperature?: number | null | undefined;
118
- provider?: string | null | undefined;
119
- top_p?: number | null | undefined;
120
- frequency_penalty?: number | null | undefined;
121
- presence_penalty?: number | null | undefined;
122
- } | null | undefined;
123
- agents?: string[] | null | undefined;
92
+ aigne: z.infer<typeof aigneFileSchema>;
93
+ rootDir: string;
124
94
  }>;
125
95
  export {};
@@ -1,4 +1,5 @@
1
1
  import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
+ import camelize from "camelize-ts";
2
3
  import { parse } from "yaml";
3
4
  import { z } from "zod";
4
5
  import { Agent, FunctionAgent } from "../agents/agent.js";
@@ -10,21 +11,21 @@ import { PromptBuilder } from "../prompt/prompt-builder.js";
10
11
  import { tryOrThrow } from "../utils/type-utils.js";
11
12
  import { loadAgentFromJsFile } from "./agent-js.js";
12
13
  import { loadAgentFromYamlFile } from "./agent-yaml.js";
14
+ import { optionalize } from "./schema.js";
13
15
  const AIGNE_FILE_NAME = ["aigne.yaml", "aigne.yml"];
14
16
  export async function load(options) {
15
- const aigneFilePath = await getAIGNEFilePath(options.path);
16
- const rootDir = nodejs.path.dirname(aigneFilePath);
17
- const aigne = await loadAIGNEFile(aigneFilePath);
17
+ const { aigne, rootDir } = await loadAIGNEFile(options.path);
18
18
  const agents = await Promise.all((aigne.agents ?? []).map((filename) => loadAgent(nodejs.path.join(rootDir, filename), options)));
19
19
  const skills = await Promise.all((aigne.skills ?? []).map((filename) => loadAgent(nodejs.path.join(rootDir, filename), options)));
20
20
  return {
21
21
  ...aigne,
22
+ rootDir,
22
23
  model: await loadModel(options.models.map((i) => typeof i === "function"
23
24
  ? {
24
25
  name: i.name,
25
26
  create: (options) => new i(options),
26
27
  }
27
- : i), aigne.chat_model),
28
+ : i), aigne.model),
28
29
  agents,
29
30
  skills,
30
31
  };
@@ -121,39 +122,44 @@ export async function loadModel(models, model, modelOptions) {
121
122
  });
122
123
  }
123
124
  const aigneFileSchema = z.object({
124
- name: z.string().nullish(),
125
- description: z.string().nullish(),
126
- chat_model: z
127
- .union([
125
+ name: optionalize(z.string()),
126
+ description: optionalize(z.string()),
127
+ model: optionalize(z.union([
128
128
  z.string(),
129
129
  z.object({
130
130
  provider: z.string().nullish(),
131
131
  name: z.string().nullish(),
132
132
  temperature: z.number().min(0).max(2).nullish(),
133
- top_p: z.number().min(0).nullish(),
134
- frequency_penalty: z.number().min(-2).max(2).nullish(),
135
- presence_penalty: z.number().min(-2).max(2).nullish(),
133
+ topP: z.number().min(0).nullish(),
134
+ frequencyPenalty: z.number().min(-2).max(2).nullish(),
135
+ presencePenalty: z.number().min(-2).max(2).nullish(),
136
136
  }),
137
- ])
138
- .nullish()
139
- .transform((v) => (typeof v === "string" ? { name: v } : v)),
140
- agents: z.array(z.string()).nullish(),
141
- skills: z.array(z.string()).nullish(),
137
+ ])).transform((v) => (typeof v === "string" ? { name: v } : v)),
138
+ agents: optionalize(z.array(z.string())),
139
+ skills: optionalize(z.array(z.string())),
142
140
  });
143
141
  export async function loadAIGNEFile(path) {
144
- const raw = await tryOrThrow(() => nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${path}: ${error.message}`));
145
- const json = await tryOrThrow(() => parse(raw), (error) => new Error(`Failed to parse aigne.yaml from ${path}: ${error.message}`));
146
- const agent = tryOrThrow(() => aigneFileSchema.parse({ ...json, skills: json.skills ?? json.tools }), (error) => new Error(`Failed to validate aigne.yaml from ${path}: ${error.message}`));
147
- return agent;
142
+ const file = await findAIGNEFile(path);
143
+ const raw = await tryOrThrow(() => nodejs.fs.readFile(file, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${file}: ${error.message}`));
144
+ const json = tryOrThrow(() => camelize(parse(raw)), (error) => new Error(`Failed to parse aigne.yaml from ${file}: ${error.message}`));
145
+ const aigne = tryOrThrow(() => aigneFileSchema.parse({
146
+ ...json,
147
+ model: json.model ?? json.chatModel,
148
+ skills: json.skills ?? json.tools,
149
+ }), (error) => new Error(`Failed to validate aigne.yaml from ${file}: ${error.message}`));
150
+ return { aigne, rootDir: nodejs.path.dirname(file) };
148
151
  }
149
- async function getAIGNEFilePath(path) {
150
- const s = await nodejs.fs.stat(path);
151
- if (s.isDirectory()) {
152
- for (const file of AIGNE_FILE_NAME) {
153
- const filePath = nodejs.path.join(path, file);
154
- if ((await nodejs.fs.stat(filePath)).isFile())
155
- return filePath;
152
+ async function findAIGNEFile(path) {
153
+ const possibleFiles = AIGNE_FILE_NAME.includes(nodejs.path.basename(path))
154
+ ? [path]
155
+ : AIGNE_FILE_NAME.map((name) => nodejs.path.join(path, name));
156
+ for (const file of possibleFiles) {
157
+ try {
158
+ const stat = await nodejs.fs.stat(file);
159
+ if (stat.isFile())
160
+ return file;
156
161
  }
162
+ catch { }
157
163
  }
158
- return path;
164
+ throw new Error(`aigne.yaml not found in ${path}. Please ensure you are in the correct directory or provide a valid path.`);
159
165
  }
@@ -2,6 +2,32 @@ import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
2
  import { parse } from "yaml";
3
3
  import { z } from "zod";
4
4
  export const inputOutputSchema = ({ path }) => {
5
+ const includeExternalSchema = async (schema) => {
6
+ if (schema?.type === "object" && schema.properties) {
7
+ return {
8
+ ...schema,
9
+ properties: Object.fromEntries(await Promise.all(Object.entries(schema.properties).map(async ([key, value]) => [
10
+ key,
11
+ await includeExternalSchema(value),
12
+ ]))),
13
+ };
14
+ }
15
+ if (schema?.type === "array" && schema.items) {
16
+ return { ...schema, items: await includeExternalSchema(schema.items) };
17
+ }
18
+ // Load nested schemas from file
19
+ if (typeof schema === "string") {
20
+ const raw = await nodejs.fs.readFile(nodejs.path.join(nodejs.path.dirname(path), schema), "utf8");
21
+ return nestedJsonSchema.parseAsync(parse(raw));
22
+ }
23
+ return schema;
24
+ };
25
+ const nestedJsonSchema = z
26
+ .object({
27
+ type: z.string(),
28
+ })
29
+ .passthrough()
30
+ .transform((v) => includeExternalSchema(v));
5
31
  const jsonSchemaSchema = z
6
32
  .object({
7
33
  type: z.literal("object"),
@@ -9,29 +35,7 @@ export const inputOutputSchema = ({ path }) => {
9
35
  required: z.array(z.string()).optional(),
10
36
  additionalProperties: z.boolean().optional(),
11
37
  })
12
- .transform((v) => {
13
- const t = async (schema) => {
14
- if (schema?.type === "object" && schema.properties) {
15
- return {
16
- ...schema,
17
- properties: Object.fromEntries(await Promise.all(Object.entries(schema.properties).map(async ([key, value]) => [
18
- key,
19
- await t(value),
20
- ]))),
21
- };
22
- }
23
- if (schema?.type === "array" && schema.items) {
24
- return { ...schema, items: await t(schema.items) };
25
- }
26
- // Load nested schemas from file
27
- if (typeof schema === "string") {
28
- const raw = await nodejs.fs.readFile(nodejs.path.join(nodejs.path.dirname(path), schema), "utf8");
29
- return jsonSchemaSchema.parseAsync(parse(raw));
30
- }
31
- return schema;
32
- };
33
- return t(v);
34
- });
38
+ .transform((v) => includeExternalSchema(v));
35
39
  return z.union([
36
40
  z
37
41
  .string()
@@ -152,7 +152,7 @@ const chatModelOutputToolCallSchema = z.object({
152
152
  type: z.literal("function"),
153
153
  function: z.object({
154
154
  name: z.string(),
155
- arguments: z.record(z.unknown()),
155
+ arguments: z.record(z.string(), z.unknown()),
156
156
  }),
157
157
  });
158
158
  const agentChatMessageSchema = z.object({
@@ -164,7 +164,7 @@ const agentChatMessageSchema = z.object({
164
164
  const toolChatMessageSchema = z.object({
165
165
  role: z.literal("tool"),
166
166
  content: z
167
- .union([z.string(), z.record(z.unknown())])
167
+ .union([z.string(), z.record(z.string(), z.unknown())])
168
168
  .transform((val) => (typeof val !== "string" ? JSON.stringify(val) : val)),
169
169
  toolCallId: z.string(),
170
170
  name: z.string().optional(),