@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.
package/CHANGELOG.md CHANGED
@@ -12,6 +12,30 @@
12
12
  * dependencies
13
13
  * @aigne/observability bumped to 0.1.0
14
14
 
15
+ ## [1.33.2](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.33.1...core-v1.33.2) (2025-07-14)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **core:** fix error of external schema with array type ([#251](https://github.com/AIGNE-io/aigne-framework/issues/251)) ([bd80921](https://github.com/AIGNE-io/aigne-framework/commit/bd80921bbbe8385645eb7c52fd719ce48d672da9))
21
+
22
+ ## [1.33.1](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.33.0...core-v1.33.1) (2025-07-14)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **cli:** print pretty error message for cli ([#249](https://github.com/AIGNE-io/aigne-framework/issues/249)) ([d68e0f7](https://github.com/AIGNE-io/aigne-framework/commit/d68e0f7151259a05696de77d9f00793b6f5b36b2))
28
+ * **core:** check if skills is empty before TeamAgent processes ([#250](https://github.com/AIGNE-io/aigne-framework/issues/250)) ([f0fff7e](https://github.com/AIGNE-io/aigne-framework/commit/f0fff7e41512cf06f106a0d7fe03a7d98206f136))
29
+ * **deps:** update deps to latest version ([#247](https://github.com/AIGNE-io/aigne-framework/issues/247)) ([3972f88](https://github.com/AIGNE-io/aigne-framework/commit/3972f887a9abff20c26da6b51c1071cbd54c0bf1))
30
+
31
+
32
+ ### Dependencies
33
+
34
+ * The following workspace dependencies were updated
35
+ * dependencies
36
+ * @aigne/observability-api bumped to 0.7.2
37
+ * @aigne/platform-helpers bumped to 0.3.1
38
+
15
39
  ## [1.33.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.32.2...core-v1.33.0) (2025-07-10)
16
40
 
17
41
 
@@ -155,7 +155,7 @@ const chatModelInputMessageSchema = zod_1.z.object({
155
155
  type: zod_1.z.literal("function"),
156
156
  function: zod_1.z.object({
157
157
  name: zod_1.z.string(),
158
- arguments: zod_1.z.record(zod_1.z.unknown()),
158
+ arguments: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
159
159
  }),
160
160
  }))
161
161
  .optional(),
@@ -169,7 +169,7 @@ const chatModelInputResponseFormatSchema = zod_1.z.discriminatedUnion("type", [
169
169
  jsonSchema: zod_1.z.object({
170
170
  name: zod_1.z.string(),
171
171
  description: zod_1.z.string().optional(),
172
- schema: zod_1.z.record(zod_1.z.unknown()),
172
+ schema: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
173
173
  strict: zod_1.z.boolean().optional(),
174
174
  }),
175
175
  }),
@@ -179,7 +179,7 @@ const chatModelInputToolSchema = zod_1.z.object({
179
179
  function: zod_1.z.object({
180
180
  name: zod_1.z.string(),
181
181
  description: zod_1.z.string().optional(),
182
- parameters: zod_1.z.record(zod_1.z.unknown()),
182
+ parameters: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
183
183
  }),
184
184
  });
185
185
  const chatModelInputToolChoiceSchema = zod_1.z.union([
@@ -208,7 +208,7 @@ const chatModelOutputToolCallSchema = zod_1.z.object({
208
208
  type: zod_1.z.literal("function"),
209
209
  function: zod_1.z.object({
210
210
  name: zod_1.z.string(),
211
- arguments: zod_1.z.record(zod_1.z.unknown()),
211
+ arguments: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
212
212
  }),
213
213
  });
214
214
  const chatModelOutputUsageSchema = zod_1.z.object({
@@ -217,7 +217,7 @@ const chatModelOutputUsageSchema = zod_1.z.object({
217
217
  });
218
218
  const chatModelOutputSchema = zod_1.z.object({
219
219
  text: zod_1.z.string().optional(),
220
- json: zod_1.z.record(zod_1.z.unknown()).optional(),
220
+ json: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
221
221
  toolCalls: zod_1.z.array(chatModelOutputToolCallSchema).optional(),
222
222
  usage: chatModelOutputUsageSchema.optional(),
223
223
  model: zod_1.z.string().optional(),
@@ -313,6 +313,6 @@ const mcpAgentOptionsSchema = zod_1.z.union([
313
313
  zod_1.z.object({
314
314
  command: zod_1.z.string(),
315
315
  args: zod_1.z.array(zod_1.z.string()).optional(),
316
- env: zod_1.z.record(zod_1.z.string()).optional(),
316
+ env: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
317
317
  }),
318
318
  ]);
@@ -117,6 +117,8 @@ class TeamAgent extends agent_js_1.Agent {
117
117
  * @returns A stream of message chunks that collectively form the response
118
118
  */
119
119
  process(input, options) {
120
+ if (!this.skills.length)
121
+ throw new Error("TeamAgent must have at least one skill defined.");
120
122
  if (this.iterateOn) {
121
123
  return this._processIterator(this.iterateOn, input, options);
122
124
  }
@@ -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
  */
@@ -29,9 +29,10 @@ class AIGNE {
29
29
  * @returns A fully initialized AIGNE instance with configured agents and skills.
30
30
  */
31
31
  static async load(path, options) {
32
- const { model, agents, skills, ...aigne } = await (0, index_js_1.load)({ ...options, path });
32
+ const { model, agents = [], skills = [], ...aigne } = await (0, index_js_1.load)({ ...options, path });
33
33
  return new AIGNE({
34
34
  ...options,
35
+ rootDir: aigne.rootDir,
35
36
  model: options?.model || model,
36
37
  name: options?.name || aigne.name || undefined,
37
38
  description: options?.description || aigne.description || undefined,
@@ -47,6 +48,7 @@ class AIGNE {
47
48
  constructor(options) {
48
49
  if (options)
49
50
  (0, type_utils_js_1.checkArguments)("AIGNE", aigneOptionsSchema, options);
51
+ this.rootDir = options?.rootDir;
50
52
  this.name = options?.name;
51
53
  this.description = options?.description;
52
54
  this.model = options?.model;
@@ -62,6 +64,10 @@ class AIGNE {
62
64
  this.observer?.serve();
63
65
  this.initProcessExitHandler();
64
66
  }
67
+ /**
68
+ * Optional root directory for this AIGNE instance.
69
+ */
70
+ rootDir;
65
71
  /**
66
72
  * Optional name identifier for this AIGNE instance.
67
73
  */
@@ -388,6 +388,6 @@ async function* withAbortSignal(signal, error, fn) {
388
388
  }
389
389
  const aigneContextInvokeArgsSchema = zod_1.z.object({
390
390
  agent: zod_1.z.union([zod_1.z.custom(), zod_1.z.custom()]),
391
- message: zod_1.z.union([zod_1.z.record(zod_1.z.unknown()), zod_1.z.string()]).optional(),
391
+ message: zod_1.z.union([zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()), zod_1.z.string()]).optional(),
392
392
  options: zod_1.z.object({ returnActiveAgent: zod_1.z.boolean().optional() }).optional(),
393
393
  });
@@ -92,18 +92,18 @@ function once(events, event, listener) {
92
92
  }
93
93
  const subscribeArgsSchema = zod_1.z.object({
94
94
  topic: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]),
95
- listener: zod_1.z.function(zod_1.z.tuple([zod_1.z.any()]), zod_1.z.any()).optional(),
95
+ listener: zod_1.z.custom().optional(),
96
96
  });
97
97
  const unsubscribeArgsSchema = zod_1.z.object({
98
98
  topic: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]),
99
- listener: zod_1.z.function(zod_1.z.tuple([zod_1.z.any()]), zod_1.z.any()),
99
+ listener: zod_1.z.custom(),
100
100
  });
101
101
  const publishArgsSchema = zod_1.z.object({
102
102
  topic: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]),
103
103
  payload: zod_1.z.object({
104
104
  role: zod_1.z.union([zod_1.z.literal("user"), zod_1.z.literal("agent")]),
105
105
  source: zod_1.z.string().optional(),
106
- message: zod_1.z.union([zod_1.z.string(), zod_1.z.record(zod_1.z.unknown())]),
106
+ message: zod_1.z.union([zod_1.z.string(), zod_1.z.record(zod_1.z.string(), zod_1.z.unknown())]),
107
107
  context: zod_1.z.any(),
108
108
  }),
109
109
  });
@@ -68,11 +68,11 @@ async function loadAgentFromYamlFile(path) {
68
68
  ]);
69
69
  });
70
70
  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 = await (0, type_utils_js_1.tryOrThrow)(() => (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((0, camelize_ts_1.default)({
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({
73
73
  ...json,
74
74
  type: json.type ?? "ai",
75
75
  skills: json.skills ?? json.tools,
76
- })), (error) => new Error(`Failed to validate agent definition from ${path}: ${error.message}`));
76
+ }), (error) => new Error(`Failed to validate agent definition from ${path}: ${error.message}`));
77
77
  return agent;
78
78
  }
@@ -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,10 +1,14 @@
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
6
  exports.load = load;
4
7
  exports.loadAgent = loadAgent;
5
8
  exports.loadModel = loadModel;
6
9
  exports.loadAIGNEFile = loadAIGNEFile;
7
10
  const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
11
+ const camelize_ts_1 = __importDefault(require("camelize-ts"));
8
12
  const yaml_1 = require("yaml");
9
13
  const zod_1 = require("zod");
10
14
  const agent_js_1 = require("../agents/agent.js");
@@ -16,21 +20,21 @@ const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
16
20
  const type_utils_js_1 = require("../utils/type-utils.js");
17
21
  const agent_js_js_1 = require("./agent-js.js");
18
22
  const agent_yaml_js_1 = require("./agent-yaml.js");
23
+ const schema_js_1 = require("./schema.js");
19
24
  const AIGNE_FILE_NAME = ["aigne.yaml", "aigne.yml"];
20
25
  async function load(options) {
21
- const aigneFilePath = await getAIGNEFilePath(options.path);
22
- const rootDir = index_js_1.nodejs.path.dirname(aigneFilePath);
23
- const aigne = await loadAIGNEFile(aigneFilePath);
26
+ const { aigne, rootDir } = await loadAIGNEFile(options.path);
24
27
  const agents = await Promise.all((aigne.agents ?? []).map((filename) => loadAgent(index_js_1.nodejs.path.join(rootDir, filename), options)));
25
28
  const skills = await Promise.all((aigne.skills ?? []).map((filename) => loadAgent(index_js_1.nodejs.path.join(rootDir, filename), options)));
26
29
  return {
27
30
  ...aigne,
31
+ rootDir,
28
32
  model: await loadModel(options.models.map((i) => typeof i === "function"
29
33
  ? {
30
34
  name: i.name,
31
35
  create: (options) => new i(options),
32
36
  }
33
- : i), aigne.chat_model),
37
+ : i), aigne.model),
34
38
  agents,
35
39
  skills,
36
40
  };
@@ -127,39 +131,44 @@ async function loadModel(models, model, modelOptions) {
127
131
  });
128
132
  }
129
133
  const aigneFileSchema = zod_1.z.object({
130
- name: zod_1.z.string().nullish(),
131
- description: zod_1.z.string().nullish(),
132
- chat_model: zod_1.z
133
- .union([
134
+ name: (0, schema_js_1.optionalize)(zod_1.z.string()),
135
+ description: (0, schema_js_1.optionalize)(zod_1.z.string()),
136
+ model: (0, schema_js_1.optionalize)(zod_1.z.union([
134
137
  zod_1.z.string(),
135
138
  zod_1.z.object({
136
139
  provider: zod_1.z.string().nullish(),
137
140
  name: zod_1.z.string().nullish(),
138
141
  temperature: zod_1.z.number().min(0).max(2).nullish(),
139
- top_p: zod_1.z.number().min(0).nullish(),
140
- frequency_penalty: zod_1.z.number().min(-2).max(2).nullish(),
141
- presence_penalty: zod_1.z.number().min(-2).max(2).nullish(),
142
+ topP: zod_1.z.number().min(0).nullish(),
143
+ frequencyPenalty: zod_1.z.number().min(-2).max(2).nullish(),
144
+ presencePenalty: zod_1.z.number().min(-2).max(2).nullish(),
142
145
  }),
143
- ])
144
- .nullish()
145
- .transform((v) => (typeof v === "string" ? { name: v } : v)),
146
- agents: zod_1.z.array(zod_1.z.string()).nullish(),
147
- skills: zod_1.z.array(zod_1.z.string()).nullish(),
146
+ ])).transform((v) => (typeof v === "string" ? { name: v } : v)),
147
+ agents: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.string())),
148
+ skills: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.string())),
148
149
  });
149
150
  async function loadAIGNEFile(path) {
150
- const raw = await (0, type_utils_js_1.tryOrThrow)(() => index_js_1.nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${path}: ${error.message}`));
151
- const json = await (0, type_utils_js_1.tryOrThrow)(() => (0, yaml_1.parse)(raw), (error) => new Error(`Failed to parse aigne.yaml from ${path}: ${error.message}`));
152
- const agent = (0, type_utils_js_1.tryOrThrow)(() => aigneFileSchema.parse({ ...json, skills: json.skills ?? json.tools }), (error) => new Error(`Failed to validate aigne.yaml from ${path}: ${error.message}`));
153
- return agent;
151
+ const file = await findAIGNEFile(path);
152
+ const raw = await (0, type_utils_js_1.tryOrThrow)(() => index_js_1.nodejs.fs.readFile(file, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${file}: ${error.message}`));
153
+ const json = (0, type_utils_js_1.tryOrThrow)(() => (0, camelize_ts_1.default)((0, yaml_1.parse)(raw)), (error) => new Error(`Failed to parse aigne.yaml from ${file}: ${error.message}`));
154
+ const aigne = (0, type_utils_js_1.tryOrThrow)(() => aigneFileSchema.parse({
155
+ ...json,
156
+ model: json.model ?? json.chatModel,
157
+ skills: json.skills ?? json.tools,
158
+ }), (error) => new Error(`Failed to validate aigne.yaml from ${file}: ${error.message}`));
159
+ return { aigne, rootDir: index_js_1.nodejs.path.dirname(file) };
154
160
  }
155
- async function getAIGNEFilePath(path) {
156
- const s = await index_js_1.nodejs.fs.stat(path);
157
- if (s.isDirectory()) {
158
- for (const file of AIGNE_FILE_NAME) {
159
- const filePath = index_js_1.nodejs.path.join(path, file);
160
- if ((await index_js_1.nodejs.fs.stat(filePath)).isFile())
161
- return filePath;
161
+ async function findAIGNEFile(path) {
162
+ const possibleFiles = AIGNE_FILE_NAME.includes(index_js_1.nodejs.path.basename(path))
163
+ ? [path]
164
+ : AIGNE_FILE_NAME.map((name) => index_js_1.nodejs.path.join(path, name));
165
+ for (const file of possibleFiles) {
166
+ try {
167
+ const stat = await index_js_1.nodejs.fs.stat(file);
168
+ if (stat.isFile())
169
+ return file;
162
170
  }
171
+ catch { }
163
172
  }
164
- return path;
173
+ throw new Error(`aigne.yaml not found in ${path}. Please ensure you are in the correct directory or provide a valid path.`);
165
174
  }
@@ -6,6 +6,32 @@ const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
6
6
  const yaml_1 = require("yaml");
7
7
  const zod_1 = require("zod");
8
8
  const inputOutputSchema = ({ path }) => {
9
+ const includeExternalSchema = async (schema) => {
10
+ if (schema?.type === "object" && schema.properties) {
11
+ return {
12
+ ...schema,
13
+ properties: Object.fromEntries(await Promise.all(Object.entries(schema.properties).map(async ([key, value]) => [
14
+ key,
15
+ await includeExternalSchema(value),
16
+ ]))),
17
+ };
18
+ }
19
+ if (schema?.type === "array" && schema.items) {
20
+ return { ...schema, items: await includeExternalSchema(schema.items) };
21
+ }
22
+ // Load nested schemas from file
23
+ if (typeof schema === "string") {
24
+ const raw = await index_js_1.nodejs.fs.readFile(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), schema), "utf8");
25
+ return nestedJsonSchema.parseAsync((0, yaml_1.parse)(raw));
26
+ }
27
+ return schema;
28
+ };
29
+ const nestedJsonSchema = zod_1.z
30
+ .object({
31
+ type: zod_1.z.string(),
32
+ })
33
+ .passthrough()
34
+ .transform((v) => includeExternalSchema(v));
9
35
  const jsonSchemaSchema = zod_1.z
10
36
  .object({
11
37
  type: zod_1.z.literal("object"),
@@ -13,29 +39,7 @@ const inputOutputSchema = ({ path }) => {
13
39
  required: zod_1.z.array(zod_1.z.string()).optional(),
14
40
  additionalProperties: zod_1.z.boolean().optional(),
15
41
  })
16
- .transform((v) => {
17
- const t = async (schema) => {
18
- if (schema?.type === "object" && schema.properties) {
19
- return {
20
- ...schema,
21
- properties: Object.fromEntries(await Promise.all(Object.entries(schema.properties).map(async ([key, value]) => [
22
- key,
23
- await t(value),
24
- ]))),
25
- };
26
- }
27
- if (schema?.type === "array" && schema.items) {
28
- return { ...schema, items: await t(schema.items) };
29
- }
30
- // Load nested schemas from file
31
- if (typeof schema === "string") {
32
- const raw = await index_js_1.nodejs.fs.readFile(index_js_1.nodejs.path.join(index_js_1.nodejs.path.dirname(path), schema), "utf8");
33
- return jsonSchemaSchema.parseAsync((0, yaml_1.parse)(raw));
34
- }
35
- return schema;
36
- };
37
- return t(v);
38
- });
42
+ .transform((v) => includeExternalSchema(v));
39
43
  return zod_1.z.union([
40
44
  zod_1.z
41
45
  .string()
@@ -167,7 +167,7 @@ const chatModelOutputToolCallSchema = zod_1.z.object({
167
167
  type: zod_1.z.literal("function"),
168
168
  function: zod_1.z.object({
169
169
  name: zod_1.z.string(),
170
- arguments: zod_1.z.record(zod_1.z.unknown()),
170
+ arguments: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
171
171
  }),
172
172
  });
173
173
  const agentChatMessageSchema = zod_1.z.object({
@@ -179,7 +179,7 @@ const agentChatMessageSchema = zod_1.z.object({
179
179
  const toolChatMessageSchema = zod_1.z.object({
180
180
  role: zod_1.z.literal("tool"),
181
181
  content: zod_1.z
182
- .union([zod_1.z.string(), zod_1.z.record(zod_1.z.unknown())])
182
+ .union([zod_1.z.string(), zod_1.z.record(zod_1.z.string(), zod_1.z.unknown())])
183
183
  .transform((val) => (typeof val !== "string" ? JSON.stringify(val) : val)),
184
184
  toolCallId: zod_1.z.string(),
185
185
  name: zod_1.z.string().optional(),
@@ -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
  */