@aigne/core 1.32.2 → 1.33.1

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 (38) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +0 -2
  3. package/lib/cjs/agents/chat-model.js +5 -5
  4. package/lib/cjs/agents/mcp-agent.js +1 -1
  5. package/lib/cjs/agents/team-agent.js +2 -0
  6. package/lib/cjs/aigne/aigne.d.ts +9 -0
  7. package/lib/cjs/aigne/aigne.js +7 -1
  8. package/lib/cjs/aigne/context.js +1 -1
  9. package/lib/cjs/aigne/message-queue.js +3 -3
  10. package/lib/cjs/loader/agent-js.js +8 -8
  11. package/lib/cjs/loader/agent-yaml.d.ts +2 -2
  12. package/lib/cjs/loader/agent-yaml.js +5 -5
  13. package/lib/cjs/loader/index.d.ts +44 -74
  14. package/lib/cjs/loader/index.js +37 -28
  15. package/lib/cjs/loader/schema.d.ts +9 -2
  16. package/lib/cjs/loader/schema.js +43 -6
  17. package/lib/cjs/prompt/template.js +2 -2
  18. package/lib/dts/aigne/aigne.d.ts +9 -0
  19. package/lib/dts/loader/agent-yaml.d.ts +2 -2
  20. package/lib/dts/loader/index.d.ts +44 -74
  21. package/lib/dts/loader/schema.d.ts +9 -2
  22. package/lib/esm/agents/chat-model.js +5 -5
  23. package/lib/esm/agents/mcp-agent.js +1 -1
  24. package/lib/esm/agents/team-agent.js +2 -0
  25. package/lib/esm/aigne/aigne.d.ts +9 -0
  26. package/lib/esm/aigne/aigne.js +7 -1
  27. package/lib/esm/aigne/context.js +1 -1
  28. package/lib/esm/aigne/message-queue.js +3 -3
  29. package/lib/esm/loader/agent-js.js +8 -8
  30. package/lib/esm/loader/agent-yaml.d.ts +2 -2
  31. package/lib/esm/loader/agent-yaml.js +5 -5
  32. package/lib/esm/loader/index.d.ts +44 -74
  33. package/lib/esm/loader/index.js +34 -28
  34. package/lib/esm/loader/schema.d.ts +9 -2
  35. package/lib/esm/loader/schema.js +42 -6
  36. package/lib/esm/prompt/template.js +2 -2
  37. package/package.json +6 -6
  38. package/README.zh.md +0 -79
@@ -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
  }
@@ -1,5 +1,7 @@
1
1
  import { type ZodType, z } from "zod";
2
- export declare const inputOutputSchema: z.ZodObject<{
2
+ export declare const inputOutputSchema: ({ path }: {
3
+ path: string;
4
+ }) => z.ZodUnion<[ZodType<any, z.ZodTypeDef, any>, z.ZodEffects<z.ZodObject<{
3
5
  type: z.ZodLiteral<"object">;
4
6
  properties: z.ZodRecord<z.ZodString, z.ZodAny>;
5
7
  required: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
@@ -14,5 +16,10 @@ export declare const inputOutputSchema: z.ZodObject<{
14
16
  properties: Record<string, any>;
15
17
  required?: string[] | undefined;
16
18
  additionalProperties?: boolean | undefined;
17
- }>;
19
+ }>, any, {
20
+ type: "object";
21
+ properties: Record<string, any>;
22
+ required?: string[] | undefined;
23
+ additionalProperties?: boolean | undefined;
24
+ }>]>;
18
25
  export declare function optionalize<T>(schema: ZodType<T>): ZodType<T | undefined>;
@@ -1,10 +1,46 @@
1
+ import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
+ import { parse } from "yaml";
1
3
  import { z } from "zod";
2
- export const inputOutputSchema = z.object({
3
- type: z.literal("object"),
4
- properties: z.record(z.any()),
5
- required: z.array(z.string()).optional(),
6
- additionalProperties: z.boolean().optional(),
7
- });
4
+ export const inputOutputSchema = ({ path }) => {
5
+ const jsonSchemaSchema = z
6
+ .object({
7
+ type: z.literal("object"),
8
+ properties: z.record(z.any()),
9
+ required: z.array(z.string()).optional(),
10
+ additionalProperties: z.boolean().optional(),
11
+ })
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
+ });
35
+ return z.union([
36
+ z
37
+ .string()
38
+ .transform((v) => nodejs.fs
39
+ .readFile(nodejs.path.join(nodejs.path.dirname(path), v), "utf8")
40
+ .then((raw) => jsonSchemaSchema.parseAsync(parse(raw)))),
41
+ jsonSchemaSchema,
42
+ ]);
43
+ };
8
44
  export function optionalize(schema) {
9
45
  return schema.nullish().transform((v) => v ?? undefined);
10
46
  }
@@ -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(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.32.2",
3
+ "version": "1.33.1",
4
4
  "description": "AIGNE core library for building AI-powered applications",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -63,7 +63,7 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@aigne/json-schema-to-zod": "^1.3.3",
66
- "@modelcontextprotocol/sdk": "^1.13.3",
66
+ "@modelcontextprotocol/sdk": "^1.15.0",
67
67
  "@types/debug": "^4.1.12",
68
68
  "camelize-ts": "^3.0.0",
69
69
  "content-type": "^1.0.5",
@@ -83,16 +83,16 @@
83
83
  "yaml": "^2.8.0",
84
84
  "zod": "^3.25.67",
85
85
  "zod-to-json-schema": "^3.24.6",
86
- "@aigne/observability-api": "^0.7.1",
87
- "@aigne/platform-helpers": "^0.3.0"
86
+ "@aigne/observability-api": "^0.7.2",
87
+ "@aigne/platform-helpers": "^0.3.1"
88
88
  },
89
89
  "devDependencies": {
90
- "@types/bun": "^1.2.17",
90
+ "@types/bun": "^1.2.18",
91
91
  "@types/compression": "^1.8.1",
92
92
  "@types/content-type": "^1.1.9",
93
93
  "@types/express": "^5.0.3",
94
94
  "@types/mustache": "^4.2.6",
95
- "@types/node": "^24.0.10",
95
+ "@types/node": "^24.0.12",
96
96
  "@types/nunjucks": "^3.2.6",
97
97
  "compression": "^1.8.0",
98
98
  "detect-port": "^2.1.0",
package/README.zh.md DELETED
@@ -1,79 +0,0 @@
1
- # @aigne/core
2
-
3
- [![GitHub star chart](https://img.shields.io/github/stars/AIGNE-io/aigne-framework?style=flat-square)](https://star-history.com/#AIGNE-io/aigne-framework)
4
- [![Open Issues](https://img.shields.io/github/issues-raw/AIGNE-io/aigne-framework?style=flat-square)](https://github.com/AIGNE-io/aigne-framework/issues)
5
- [![codecov](https://codecov.io/gh/AIGNE-io/aigne-framework/graph/badge.svg?token=DO07834RQL)](https://codecov.io/gh/AIGNE-io/aigne-framework)
6
- [![NPM Version](https://img.shields.io/npm/v/@aigne/core)](https://www.npmjs.com/package/@aigne/core)
7
- [![Elastic-2.0 licensed](https://img.shields.io/npm/l/@aigne/core)](https://github.com/AIGNE-io/aigne-framework/blob/main/LICENSE)
8
-
9
- [English](./README.md) | **中文**
10
-
11
- [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) 的核心库,用于构建 AI 驱动的应用程序。
12
-
13
- ## 简介
14
-
15
- `@aigne/core` 是 [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) 的基础组件,提供构建 AI 驱动应用程序所需的核心模块和工具。该包实现了框架的核心功能,包括代理系统、aigne 环境、模型集成和工作流模式支持。
16
-
17
- ## 特性
18
-
19
- * **多 AI 模型支持**:内置支持 OpenAI、Gemini、Claude、Nova 等主流 AI 模型,可轻松扩展支持其他模型
20
- * **代理系统**:强大的代理抽象,支持 AI 代理、功能代理、MCP 代理等
21
- * **AIGNE 环境**:灵活处理代理之间的通信和工作流执行
22
- * **工作流模式**:支持顺序、并发、路由、交接等多种工作流模式
23
- * **MCP 协议集成**:通过模型上下文协议与外部系统无缝集成
24
- * **TypeScript 支持**:全面的类型定义,提供出色的开发体验
25
-
26
- ## 安装
27
-
28
- ### 使用 npm
29
-
30
- ```bash
31
- npm install @aigne/core
32
- ```
33
-
34
- ### 使用 yarn
35
-
36
- ```bash
37
- yarn add @aigne/core
38
- ```
39
-
40
- ### 使用 pnpm
41
-
42
- ```bash
43
- pnpm add @aigne/core
44
- ```
45
-
46
- ## 基本用法
47
-
48
- ```typescript
49
- import { AIAgent, AIGNE } from "@aigne/core";
50
- import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js";
51
-
52
- // 创建 AI 模型实例
53
- const model = new OpenAIChatModel({
54
- apiKey: process.env.OPENAI_API_KEY,
55
- model: process.env.DEFAULT_CHAT_MODEL || "gpt-4-turbo",
56
- });
57
-
58
- // 创建 AI 代理
59
- const agent = AIAgent.from({
60
- name: "Assistant",
61
- instructions: "You are a helpful assistant.",
62
- });
63
-
64
- // AIGNE: AIGNE Framework 的主要执行引擎
65
- const aigne = new AIGNE({ model });
66
-
67
- // 使用 AIGNE 调用代理
68
- const userAgent = await aigne.invoke(agent);
69
-
70
- // 向代理发送消息
71
- const response = await userAgent.invoke(
72
- "Hello, can you help me write a short article?",
73
- );
74
- console.log(response);
75
- ```
76
-
77
- ## 许可证
78
-
79
- Elastic-2.0