@aigne/core 1.11.0 → 1.13.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 (143) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +11 -10
  3. package/README.zh.md +7 -6
  4. package/lib/cjs/agents/agent.d.ts +20 -20
  5. package/lib/cjs/agents/agent.js +25 -26
  6. package/lib/cjs/agents/ai-agent.d.ts +17 -18
  7. package/lib/cjs/agents/ai-agent.js +6 -6
  8. package/lib/cjs/agents/mcp-agent.d.ts +10 -4
  9. package/lib/cjs/agents/mcp-agent.js +12 -6
  10. package/lib/cjs/agents/memory.d.ts +1 -1
  11. package/lib/cjs/agents/team-agent.d.ts +28 -0
  12. package/lib/cjs/agents/team-agent.js +93 -0
  13. package/lib/cjs/agents/user-agent.d.ts +9 -10
  14. package/lib/cjs/agents/user-agent.js +10 -13
  15. package/lib/{esm/execution-engine/execution-engine.d.ts → cjs/aigne/aigne.d.ts} +9 -12
  16. package/lib/cjs/{execution-engine/execution-engine.js → aigne/aigne.js} +19 -19
  17. package/lib/cjs/{execution-engine → aigne}/context.d.ts +31 -32
  18. package/lib/cjs/{execution-engine → aigne}/context.js +30 -40
  19. package/lib/cjs/aigne/index.d.ts +4 -0
  20. package/lib/cjs/{execution-engine → aigne}/index.js +2 -2
  21. package/lib/cjs/{execution-engine → aigne}/usage.d.ts +1 -1
  22. package/lib/cjs/client/client.d.ts +19 -0
  23. package/lib/cjs/client/client.js +49 -0
  24. package/lib/cjs/index.d.ts +2 -1
  25. package/lib/cjs/index.js +2 -1
  26. package/lib/cjs/loader/agent-yaml.d.ts +3 -3
  27. package/lib/cjs/loader/agent-yaml.js +10 -3
  28. package/lib/cjs/loader/index.d.ts +9 -9
  29. package/lib/cjs/loader/index.js +8 -6
  30. package/lib/cjs/models/bedrock-chat-model.d.ts +70 -0
  31. package/lib/cjs/models/bedrock-chat-model.js +273 -0
  32. package/lib/cjs/models/chat-model.d.ts +2 -1
  33. package/lib/cjs/models/chat-model.js +8 -0
  34. package/lib/cjs/models/claude-chat-model.d.ts +3 -3
  35. package/lib/cjs/models/gemini-chat-model.d.ts +1 -0
  36. package/lib/cjs/models/gemini-chat-model.js +1 -0
  37. package/lib/cjs/models/openai-chat-model.d.ts +6 -3
  38. package/lib/cjs/models/openai-chat-model.js +100 -100
  39. package/lib/cjs/prompt/prompt-builder.d.ts +1 -1
  40. package/lib/cjs/prompt/prompt-builder.js +3 -3
  41. package/lib/cjs/server/error.d.ts +4 -0
  42. package/lib/cjs/server/error.js +11 -0
  43. package/lib/cjs/server/server.d.ts +54 -0
  44. package/lib/cjs/server/server.js +130 -0
  45. package/lib/cjs/utils/event-stream.d.ts +11 -0
  46. package/lib/cjs/utils/event-stream.js +91 -0
  47. package/lib/cjs/utils/mcp-utils.js +4 -1
  48. package/lib/cjs/utils/prompts.js +1 -1
  49. package/lib/cjs/utils/stream-utils.d.ts +7 -2
  50. package/lib/cjs/utils/stream-utils.js +43 -34
  51. package/lib/cjs/utils/type-utils.d.ts +5 -2
  52. package/lib/cjs/utils/type-utils.js +22 -2
  53. package/lib/dts/agents/agent.d.ts +20 -20
  54. package/lib/dts/agents/ai-agent.d.ts +17 -18
  55. package/lib/dts/agents/mcp-agent.d.ts +10 -4
  56. package/lib/dts/agents/memory.d.ts +1 -1
  57. package/lib/dts/agents/team-agent.d.ts +28 -0
  58. package/lib/dts/agents/user-agent.d.ts +9 -10
  59. package/lib/dts/{execution-engine/execution-engine.d.ts → aigne/aigne.d.ts} +9 -12
  60. package/lib/dts/{execution-engine → aigne}/context.d.ts +31 -32
  61. package/lib/dts/aigne/index.d.ts +4 -0
  62. package/lib/dts/{execution-engine → aigne}/usage.d.ts +1 -1
  63. package/lib/dts/client/client.d.ts +19 -0
  64. package/lib/dts/index.d.ts +2 -1
  65. package/lib/dts/loader/agent-yaml.d.ts +3 -3
  66. package/lib/dts/loader/index.d.ts +9 -9
  67. package/lib/dts/models/bedrock-chat-model.d.ts +70 -0
  68. package/lib/dts/models/chat-model.d.ts +2 -1
  69. package/lib/dts/models/claude-chat-model.d.ts +3 -3
  70. package/lib/dts/models/gemini-chat-model.d.ts +1 -0
  71. package/lib/dts/models/openai-chat-model.d.ts +6 -3
  72. package/lib/dts/prompt/prompt-builder.d.ts +1 -1
  73. package/lib/dts/server/error.d.ts +4 -0
  74. package/lib/dts/server/server.d.ts +54 -0
  75. package/lib/dts/utils/event-stream.d.ts +11 -0
  76. package/lib/dts/utils/stream-utils.d.ts +7 -2
  77. package/lib/dts/utils/type-utils.d.ts +5 -2
  78. package/lib/esm/agents/agent.d.ts +20 -20
  79. package/lib/esm/agents/agent.js +25 -26
  80. package/lib/esm/agents/ai-agent.d.ts +17 -18
  81. package/lib/esm/agents/ai-agent.js +6 -6
  82. package/lib/esm/agents/mcp-agent.d.ts +10 -4
  83. package/lib/esm/agents/mcp-agent.js +12 -6
  84. package/lib/esm/agents/memory.d.ts +1 -1
  85. package/lib/esm/agents/team-agent.d.ts +28 -0
  86. package/lib/esm/agents/team-agent.js +89 -0
  87. package/lib/esm/agents/user-agent.d.ts +9 -10
  88. package/lib/esm/agents/user-agent.js +11 -14
  89. package/lib/{cjs/execution-engine/execution-engine.d.ts → esm/aigne/aigne.d.ts} +9 -12
  90. package/lib/esm/{execution-engine/execution-engine.js → aigne/aigne.js} +18 -18
  91. package/lib/esm/{execution-engine → aigne}/context.d.ts +31 -32
  92. package/lib/esm/{execution-engine → aigne}/context.js +28 -38
  93. package/lib/esm/aigne/index.d.ts +4 -0
  94. package/lib/esm/aigne/index.js +4 -0
  95. package/lib/esm/{execution-engine → aigne}/usage.d.ts +1 -1
  96. package/lib/esm/client/client.d.ts +19 -0
  97. package/lib/esm/client/client.js +45 -0
  98. package/lib/esm/index.d.ts +2 -1
  99. package/lib/esm/index.js +2 -1
  100. package/lib/esm/loader/agent-yaml.d.ts +3 -3
  101. package/lib/esm/loader/agent-yaml.js +10 -3
  102. package/lib/esm/loader/index.d.ts +9 -9
  103. package/lib/esm/loader/index.js +8 -6
  104. package/lib/esm/models/bedrock-chat-model.d.ts +70 -0
  105. package/lib/esm/models/bedrock-chat-model.js +268 -0
  106. package/lib/esm/models/chat-model.d.ts +2 -1
  107. package/lib/esm/models/chat-model.js +8 -0
  108. package/lib/esm/models/claude-chat-model.d.ts +3 -3
  109. package/lib/esm/models/gemini-chat-model.d.ts +1 -0
  110. package/lib/esm/models/gemini-chat-model.js +1 -0
  111. package/lib/esm/models/openai-chat-model.d.ts +6 -3
  112. package/lib/esm/models/openai-chat-model.js +100 -100
  113. package/lib/esm/prompt/prompt-builder.d.ts +1 -1
  114. package/lib/esm/prompt/prompt-builder.js +4 -4
  115. package/lib/esm/server/error.d.ts +4 -0
  116. package/lib/esm/server/error.js +7 -0
  117. package/lib/esm/server/server.d.ts +54 -0
  118. package/lib/esm/server/server.js +123 -0
  119. package/lib/esm/utils/event-stream.d.ts +11 -0
  120. package/lib/esm/utils/event-stream.js +85 -0
  121. package/lib/esm/utils/mcp-utils.js +4 -1
  122. package/lib/esm/utils/prompts.js +1 -1
  123. package/lib/esm/utils/stream-utils.d.ts +7 -2
  124. package/lib/esm/utils/stream-utils.js +42 -33
  125. package/lib/esm/utils/type-utils.d.ts +5 -2
  126. package/lib/esm/utils/type-utils.js +20 -2
  127. package/package.json +20 -4
  128. package/lib/cjs/execution-engine/index.d.ts +0 -4
  129. package/lib/cjs/execution-engine/utils.d.ts +0 -4
  130. package/lib/cjs/execution-engine/utils.js +0 -34
  131. package/lib/dts/execution-engine/index.d.ts +0 -4
  132. package/lib/dts/execution-engine/utils.d.ts +0 -4
  133. package/lib/esm/execution-engine/index.d.ts +0 -4
  134. package/lib/esm/execution-engine/index.js +0 -4
  135. package/lib/esm/execution-engine/utils.d.ts +0 -4
  136. package/lib/esm/execution-engine/utils.js +0 -30
  137. /package/lib/cjs/{execution-engine → aigne}/message-queue.d.ts +0 -0
  138. /package/lib/cjs/{execution-engine → aigne}/message-queue.js +0 -0
  139. /package/lib/cjs/{execution-engine → aigne}/usage.js +0 -0
  140. /package/lib/dts/{execution-engine → aigne}/message-queue.d.ts +0 -0
  141. /package/lib/esm/{execution-engine → aigne}/message-queue.d.ts +0 -0
  142. /package/lib/esm/{execution-engine → aigne}/message-queue.js +0 -0
  143. /package/lib/esm/{execution-engine → aigne}/usage.js +0 -0
@@ -6,6 +6,6 @@ export interface ContextUsage {
6
6
  export declare function newEmptyContextUsage(): ContextUsage;
7
7
  export interface ContextLimits {
8
8
  maxTokens?: number;
9
- maxAgentCalls?: number;
9
+ maxAgentInvokes?: number;
10
10
  timeout?: number;
11
11
  }
@@ -0,0 +1,19 @@
1
+ import type { AgentInvokeOptions, AgentResponse, AgentResponseStream, Message } from "../agents/agent.js";
2
+ export interface AIGNEClientOptions {
3
+ url: string;
4
+ }
5
+ export interface AIGNEClientInvokeOptions extends AgentInvokeOptions {
6
+ fetchOptions?: Partial<RequestInit>;
7
+ }
8
+ export declare class AIGNEClient {
9
+ options: AIGNEClientOptions;
10
+ constructor(options: AIGNEClientOptions);
11
+ invoke<I extends Message, O extends Message>(agent: string, input: I, options: AIGNEClientInvokeOptions & {
12
+ streaming: true;
13
+ }): Promise<AgentResponseStream<O>>;
14
+ invoke<I extends Message, O extends Message>(agent: string, input: I, options?: AIGNEClientInvokeOptions & {
15
+ streaming?: false;
16
+ }): Promise<O>;
17
+ invoke<I extends Message, O extends Message>(agent: string, input: I, options?: AIGNEClientInvokeOptions): Promise<AgentResponse<O>>;
18
+ fetch(...args: Parameters<typeof globalThis.fetch>): Promise<Response>;
19
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AIGNEClient = void 0;
4
+ const event_stream_js_1 = require("../utils/event-stream.js");
5
+ const type_utils_js_1 = require("../utils/type-utils.js");
6
+ class AIGNEClient {
7
+ options;
8
+ constructor(options) {
9
+ this.options = options;
10
+ }
11
+ async invoke(agent, input, options) {
12
+ const response = await this.fetch(this.options.url, {
13
+ ...options?.fetchOptions,
14
+ method: "POST",
15
+ headers: {
16
+ "Content-Type": "application/json",
17
+ ...options?.fetchOptions?.headers,
18
+ },
19
+ body: JSON.stringify({ agent, input, options }),
20
+ });
21
+ if (!options?.streaming) {
22
+ return await response.json();
23
+ }
24
+ const stream = response.body;
25
+ if (!stream)
26
+ throw new Error("Response body is not a stream");
27
+ return stream
28
+ .pipeThrough(new TextDecoderStream())
29
+ .pipeThrough(new event_stream_js_1.EventStreamParser())
30
+ .pipeThrough(new event_stream_js_1.AgentResponseStreamParser());
31
+ }
32
+ async fetch(...args) {
33
+ const result = await globalThis.fetch(...args);
34
+ if (!result.ok) {
35
+ let message;
36
+ try {
37
+ const text = await result.text();
38
+ const json = (0, type_utils_js_1.tryOrThrow)(() => JSON.parse(text));
39
+ message = json?.error?.message || text;
40
+ }
41
+ catch {
42
+ // ignore
43
+ }
44
+ throw new Error(`Failed to fetch url ${args[0]} with status ${result.status}: ${message}`);
45
+ }
46
+ return result;
47
+ }
48
+ }
49
+ exports.AIGNEClient = AIGNEClient;
@@ -2,9 +2,10 @@ export * from "./agents/agent.js";
2
2
  export * from "./agents/ai-agent.js";
3
3
  export * from "./agents/mcp-agent.js";
4
4
  export * from "./agents/memory.js";
5
+ export * from "./agents/team-agent.js";
5
6
  export * from "./agents/types.js";
6
7
  export * from "./agents/user-agent.js";
7
- export * from "./execution-engine/index.js";
8
+ export * from "./aigne/index.js";
8
9
  export * from "./models/chat-model.js";
9
10
  export * from "./prompt/prompt-builder.js";
10
11
  export * from "./prompt/template.js";
package/lib/cjs/index.js CHANGED
@@ -18,9 +18,10 @@ __exportStar(require("./agents/agent.js"), exports);
18
18
  __exportStar(require("./agents/ai-agent.js"), exports);
19
19
  __exportStar(require("./agents/mcp-agent.js"), exports);
20
20
  __exportStar(require("./agents/memory.js"), exports);
21
+ __exportStar(require("./agents/team-agent.js"), exports);
21
22
  __exportStar(require("./agents/types.js"), exports);
22
23
  __exportStar(require("./agents/user-agent.js"), exports);
23
- __exportStar(require("./execution-engine/index.js"), exports);
24
+ __exportStar(require("./aigne/index.js"), exports);
24
25
  __exportStar(require("./models/chat-model.js"), exports);
25
26
  __exportStar(require("./prompt/prompt-builder.js"), exports);
26
27
  __exportStar(require("./prompt/template.js"), exports);
@@ -2,12 +2,12 @@ import { type ZodObject, type ZodType, z } from "zod";
2
2
  export declare function loadAgentFromYamlFile(path: string): Promise<{
3
3
  type: "ai";
4
4
  name: string;
5
- tools?: string[] | undefined;
6
5
  description?: string | undefined;
7
- instructions?: string | undefined;
8
6
  memory?: true | {
9
- subscribeTopic: string[];
7
+ subscribeTopic?: string[] | undefined;
10
8
  } | undefined;
9
+ skills?: string[] | undefined;
10
+ instructions?: string | undefined;
11
11
  inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
12
12
  [x: string]: any;
13
13
  }, {
@@ -30,7 +30,7 @@ const agentFileSchema = zod_1.z.discriminatedUnion("type", [
30
30
  .string()
31
31
  .nullish()
32
32
  .transform((v) => v ?? undefined),
33
- tools: zod_1.z
33
+ skills: zod_1.z
34
34
  .array(zod_1.z.string())
35
35
  .nullish()
36
36
  .transform((v) => v ?? undefined),
@@ -42,7 +42,10 @@ const agentFileSchema = zod_1.z.discriminatedUnion("type", [
42
42
  .union([
43
43
  zod_1.z.boolean(),
44
44
  zod_1.z.object({
45
- subscribe_topic: zod_1.z.array(zod_1.z.string()),
45
+ subscribe_topic: zod_1.z
46
+ .array(zod_1.z.string())
47
+ .nullish()
48
+ .transform((v) => v ?? undefined),
46
49
  }),
47
50
  ])
48
51
  .nullish()
@@ -67,7 +70,11 @@ const agentFileSchema = zod_1.z.discriminatedUnion("type", [
67
70
  async function loadAgentFromYamlFile(path) {
68
71
  const raw = await (0, type_utils_js_1.tryOrThrow)(() => (0, promises_1.readFile)(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
69
72
  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}`));
70
- const agent = (0, type_utils_js_1.tryOrThrow)(() => (0, camelize_js_1.customCamelize)(agentFileSchema.parse({ ...json, type: json.type ?? "ai" }), {
73
+ const agent = (0, type_utils_js_1.tryOrThrow)(() => (0, camelize_js_1.customCamelize)(agentFileSchema.parse({
74
+ ...json,
75
+ type: json.type ?? "ai",
76
+ skills: json.skills ?? json.tools,
77
+ }), {
71
78
  shallowKeys: ["input_schema", "output_schema"],
72
79
  }), (error) => new Error(`Failed to validate agent definition from ${path}: ${error.message}`));
73
80
  return agent;
@@ -7,9 +7,9 @@ export interface LoadOptions {
7
7
  export declare function load(options: LoadOptions): Promise<{
8
8
  model: ChatModel | undefined;
9
9
  agents: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[];
10
- tools: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[];
11
- name?: string | null | undefined;
10
+ skills: Agent<import("../agents/agent.js").Message, import("../agents/agent.js").Message>[];
12
11
  description?: string | null | undefined;
12
+ name?: string | null | undefined;
13
13
  chat_model?: {
14
14
  name?: string | null | undefined;
15
15
  temperature?: number | null | undefined;
@@ -61,11 +61,11 @@ declare const aigneFileSchema: z.ZodObject<{
61
61
  presence_penalty?: number | null | undefined;
62
62
  } | null | undefined>;
63
63
  agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
64
- tools: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
64
+ skills: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
65
65
  }, "strip", z.ZodTypeAny, {
66
- tools?: string[] | null | undefined;
67
- name?: string | null | undefined;
68
66
  description?: string | null | undefined;
67
+ name?: string | null | undefined;
68
+ skills?: string[] | null | undefined;
69
69
  chat_model?: {
70
70
  name?: string | null | undefined;
71
71
  temperature?: number | null | undefined;
@@ -76,9 +76,9 @@ declare const aigneFileSchema: z.ZodObject<{
76
76
  } | null | undefined;
77
77
  agents?: string[] | null | undefined;
78
78
  }, {
79
- tools?: string[] | null | undefined;
80
- name?: string | null | undefined;
81
79
  description?: string | null | undefined;
80
+ name?: string | null | undefined;
81
+ skills?: string[] | null | undefined;
82
82
  chat_model?: string | {
83
83
  name?: string | null | undefined;
84
84
  temperature?: number | null | undefined;
@@ -90,9 +90,9 @@ declare const aigneFileSchema: z.ZodObject<{
90
90
  agents?: string[] | null | undefined;
91
91
  }>;
92
92
  export declare function loadAIGNEFile(path: string): Promise<{
93
- tools?: string[] | null | undefined;
94
- name?: string | null | undefined;
95
93
  description?: string | null | undefined;
94
+ name?: string | null | undefined;
95
+ skills?: string[] | null | undefined;
96
96
  chat_model?: {
97
97
  name?: string | null | undefined;
98
98
  temperature?: number | null | undefined;
@@ -11,6 +11,7 @@ const zod_1 = require("zod");
11
11
  const agent_js_1 = require("../agents/agent.js");
12
12
  const ai_agent_js_1 = require("../agents/ai-agent.js");
13
13
  const mcp_agent_js_1 = require("../agents/mcp-agent.js");
14
+ const bedrock_chat_model_js_1 = require("../models/bedrock-chat-model.js");
14
15
  const claude_chat_model_js_1 = require("../models/claude-chat-model.js");
15
16
  const deepseek_chat_model_js_1 = require("../models/deepseek-chat-model.js");
16
17
  const gemini_chat_model_js_1 = require("../models/gemini-chat-model.js");
@@ -28,12 +29,12 @@ async function load(options) {
28
29
  const rootDir = (0, node_path_1.dirname)(aigneFilePath);
29
30
  const aigne = await loadAIGNEFile(aigneFilePath);
30
31
  const agents = await Promise.all((aigne.agents ?? []).map((filename) => loadAgent((0, node_path_1.join)(rootDir, filename))));
31
- const tools = await Promise.all((aigne.tools ?? []).map((filename) => loadAgent((0, node_path_1.join)(rootDir, filename))));
32
+ const skills = await Promise.all((aigne.skills ?? []).map((filename) => loadAgent((0, node_path_1.join)(rootDir, filename))));
32
33
  return {
33
34
  ...aigne,
34
35
  model: await loadModel(aigne.chat_model),
35
36
  agents,
36
- tools,
37
+ skills,
37
38
  };
38
39
  }
39
40
  async function loadAgent(path) {
@@ -46,8 +47,8 @@ async function loadAgent(path) {
46
47
  if (agent.type === "ai") {
47
48
  return ai_agent_js_1.AIAgent.from({
48
49
  ...agent,
49
- tools: agent.tools &&
50
- (await Promise.all(agent.tools.map((filename) => loadAgent((0, node_path_1.join)((0, node_path_1.dirname)(path), filename))))),
50
+ skills: agent.skills &&
51
+ (await Promise.all(agent.skills.map((filename) => loadAgent((0, node_path_1.join)((0, node_path_1.dirname)(path), filename))))),
51
52
  });
52
53
  }
53
54
  if (agent.type === "mcp") {
@@ -86,6 +87,7 @@ async function loadModel(model, modelOptions) {
86
87
  deepseek_chat_model_js_1.DeepSeekChatModel,
87
88
  open_router_chat_model_js_1.OpenRouterChatModel,
88
89
  ollama_chat_model_js_1.OllamaChatModel,
90
+ bedrock_chat_model_js_1.BedrockChatModel,
89
91
  ];
90
92
  const M = availableModels.find((m) => m.name
91
93
  .toLowerCase()
@@ -112,12 +114,12 @@ const aigneFileSchema = zod_1.z.object({
112
114
  .nullish()
113
115
  .transform((v) => (typeof v === "string" ? { name: v } : v)),
114
116
  agents: zod_1.z.array(zod_1.z.string()).nullish(),
115
- tools: zod_1.z.array(zod_1.z.string()).nullish(),
117
+ skills: zod_1.z.array(zod_1.z.string()).nullish(),
116
118
  });
117
119
  async function loadAIGNEFile(path) {
118
120
  const raw = await (0, type_utils_js_1.tryOrThrow)(() => (0, promises_1.readFile)(path, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${path}: ${error.message}`));
119
121
  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}`));
120
- const agent = (0, type_utils_js_1.tryOrThrow)(() => aigneFileSchema.parse(json), (error) => new Error(`Failed to validate aigne.yaml from ${path}: ${error.message}`));
122
+ 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}`));
121
123
  return agent;
122
124
  }
123
125
  async function getAIGNEFilePath(path) {
@@ -0,0 +1,70 @@
1
+ import { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime";
2
+ import { z } from "zod";
3
+ import type { AgentInvokeOptions, AgentResponse } from "../agents/agent.js";
4
+ import type { Context } from "../aigne/context.js";
5
+ import { ChatModel, type ChatModelInput, type ChatModelOptions, type ChatModelOutput } from "./chat-model.js";
6
+ export declare function extractLastJsonObject(text: string): string | null;
7
+ export interface BedrockChatModelOptions {
8
+ accessKeyId?: string;
9
+ secretAccessKey?: string;
10
+ region?: string;
11
+ model?: string;
12
+ modelOptions?: ChatModelOptions;
13
+ }
14
+ export declare const bedrockChatModelOptionsSchema: z.ZodObject<{
15
+ region: z.ZodOptional<z.ZodString>;
16
+ model: z.ZodOptional<z.ZodString>;
17
+ modelOptions: z.ZodOptional<z.ZodObject<{
18
+ model: z.ZodOptional<z.ZodString>;
19
+ temperature: z.ZodOptional<z.ZodNumber>;
20
+ topP: z.ZodOptional<z.ZodNumber>;
21
+ frequencyPenalty: z.ZodOptional<z.ZodNumber>;
22
+ presencePenalty: z.ZodOptional<z.ZodNumber>;
23
+ parallelToolCalls: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
24
+ }, "strip", z.ZodTypeAny, {
25
+ parallelToolCalls: boolean;
26
+ model?: string | undefined;
27
+ temperature?: number | undefined;
28
+ topP?: number | undefined;
29
+ frequencyPenalty?: number | undefined;
30
+ presencePenalty?: number | undefined;
31
+ }, {
32
+ model?: string | undefined;
33
+ temperature?: number | undefined;
34
+ topP?: number | undefined;
35
+ frequencyPenalty?: number | undefined;
36
+ presencePenalty?: number | undefined;
37
+ parallelToolCalls?: boolean | undefined;
38
+ }>>;
39
+ }, "strip", z.ZodTypeAny, {
40
+ modelOptions?: {
41
+ parallelToolCalls: boolean;
42
+ model?: string | undefined;
43
+ temperature?: number | undefined;
44
+ topP?: number | undefined;
45
+ frequencyPenalty?: number | undefined;
46
+ presencePenalty?: number | undefined;
47
+ } | undefined;
48
+ model?: string | undefined;
49
+ region?: string | undefined;
50
+ }, {
51
+ modelOptions?: {
52
+ model?: string | undefined;
53
+ temperature?: number | undefined;
54
+ topP?: number | undefined;
55
+ frequencyPenalty?: number | undefined;
56
+ presencePenalty?: number | undefined;
57
+ parallelToolCalls?: boolean | undefined;
58
+ } | undefined;
59
+ model?: string | undefined;
60
+ region?: string | undefined;
61
+ }>;
62
+ export declare class BedrockChatModel extends ChatModel {
63
+ options?: BedrockChatModelOptions | undefined;
64
+ constructor(options?: BedrockChatModelOptions | undefined);
65
+ protected _client?: BedrockRuntimeClient;
66
+ get client(): BedrockRuntimeClient;
67
+ get modelOptions(): ChatModelOptions | undefined;
68
+ process(input: ChatModelInput, _context: Context, options?: AgentInvokeOptions): Promise<AgentResponse<ChatModelOutput>>;
69
+ private extractResultFromStream;
70
+ }
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BedrockChatModel = exports.bedrockChatModelOptionsSchema = void 0;
4
+ exports.extractLastJsonObject = extractLastJsonObject;
5
+ const client_bedrock_runtime_1 = require("@aws-sdk/client-bedrock-runtime");
6
+ const nanoid_1 = require("nanoid");
7
+ const zod_1 = require("zod");
8
+ const json_schema_js_1 = require("../utils/json-schema.js");
9
+ const prompts_js_1 = require("../utils/prompts.js");
10
+ const stream_utils_js_1 = require("../utils/stream-utils.js");
11
+ const type_utils_js_1 = require("../utils/type-utils.js");
12
+ const chat_model_js_1 = require("./chat-model.js");
13
+ function extractLastJsonObject(text) {
14
+ return text.replace(/<thinking>[\s\S]*?<\/thinking>/g, "").trim();
15
+ }
16
+ const BEDROCK_DEFAULT_CHAT_MODEL = "us.amazon.nova-lite-v1:0";
17
+ exports.bedrockChatModelOptionsSchema = zod_1.z.object({
18
+ region: zod_1.z.string().optional(),
19
+ model: zod_1.z.string().optional(),
20
+ modelOptions: zod_1.z
21
+ .object({
22
+ model: zod_1.z.string().optional(),
23
+ temperature: zod_1.z.number().optional(),
24
+ topP: zod_1.z.number().optional(),
25
+ frequencyPenalty: zod_1.z.number().optional(),
26
+ presencePenalty: zod_1.z.number().optional(),
27
+ parallelToolCalls: zod_1.z.boolean().optional().default(true),
28
+ })
29
+ .optional(),
30
+ });
31
+ class BedrockChatModel extends chat_model_js_1.ChatModel {
32
+ options;
33
+ constructor(options) {
34
+ if (options)
35
+ (0, type_utils_js_1.checkArguments)("BedrockChatModel", exports.bedrockChatModelOptionsSchema, options);
36
+ super();
37
+ this.options = options;
38
+ }
39
+ _client;
40
+ get client() {
41
+ const credentials = this.options?.accessKeyId && this.options?.secretAccessKey
42
+ ? {
43
+ accessKeyId: this.options.accessKeyId,
44
+ secretAccessKey: this.options.secretAccessKey,
45
+ }
46
+ : undefined;
47
+ this._client ??= new client_bedrock_runtime_1.BedrockRuntimeClient({
48
+ region: this.options?.region,
49
+ credentials,
50
+ });
51
+ return this._client;
52
+ }
53
+ get modelOptions() {
54
+ return this.options?.modelOptions;
55
+ }
56
+ async process(input, _context, options) {
57
+ const modelId = input.modelOptions?.model ?? this.modelOptions?.model ?? BEDROCK_DEFAULT_CHAT_MODEL;
58
+ const { messages, system } = getRunMessages(input);
59
+ const toolConfig = convertTools(input);
60
+ const body = {
61
+ modelId,
62
+ messages,
63
+ system,
64
+ toolConfig,
65
+ inferenceConfig: {
66
+ temperature: input.modelOptions?.temperature ?? this.modelOptions?.temperature,
67
+ topP: input.modelOptions?.topP ?? this.modelOptions?.topP,
68
+ },
69
+ };
70
+ const command = new client_bedrock_runtime_1.ConverseStreamCommand(body);
71
+ const response = await this.client.send(command);
72
+ const jsonMode = input.responseFormat?.type === "json_schema";
73
+ if (options?.streaming && !jsonMode) {
74
+ return this.extractResultFromStream(response.stream, modelId, false, true);
75
+ }
76
+ const result = await this.extractResultFromStream(response.stream, modelId, jsonMode, false);
77
+ return result;
78
+ }
79
+ async extractResultFromStream(stream, modelId, jsonMode, streaming) {
80
+ if (!stream)
81
+ throw new Error("Unable to get AI model response.");
82
+ const result = new ReadableStream({
83
+ start: async (controller) => {
84
+ try {
85
+ controller.enqueue({ delta: { json: { model: modelId } } });
86
+ const toolCalls = [];
87
+ let text = "";
88
+ let usage;
89
+ for await (const chunk of stream) {
90
+ if (chunk.contentBlockStart?.start?.toolUse) {
91
+ const toolUse = chunk.contentBlockStart.start.toolUse;
92
+ if (!toolUse.name)
93
+ throw new Error("Tool use is invalid");
94
+ if (chunk.contentBlockStart.contentBlockIndex === undefined)
95
+ throw new Error("Tool use content block index is required");
96
+ toolCalls[chunk.contentBlockStart.contentBlockIndex] = {
97
+ type: "function",
98
+ id: toolUse.toolUseId || (0, nanoid_1.nanoid)(),
99
+ function: {
100
+ name: toolUse.name,
101
+ arguments: {},
102
+ },
103
+ args: "",
104
+ };
105
+ }
106
+ if (chunk.contentBlockDelta) {
107
+ const block = chunk.contentBlockDelta;
108
+ const delta = block.delta;
109
+ if (delta?.text) {
110
+ text += delta.text;
111
+ if (!jsonMode) {
112
+ controller.enqueue({ delta: { text: { text: delta.text } } });
113
+ }
114
+ }
115
+ if (delta?.toolUse) {
116
+ if (block.contentBlockIndex === undefined)
117
+ throw new Error("Content block index is required");
118
+ const call = toolCalls[block.contentBlockIndex];
119
+ if (!call)
120
+ throw new Error("Tool call not found");
121
+ call.args += delta.toolUse.input;
122
+ }
123
+ }
124
+ if (chunk.metadata) {
125
+ usage = chunk.metadata.usage;
126
+ }
127
+ }
128
+ if (jsonMode && text) {
129
+ const match = extractLastJsonObject(text);
130
+ if (!match)
131
+ throw new Error("Failed to extract JSON object from model output");
132
+ controller.enqueue({
133
+ delta: { json: { json: (0, json_schema_js_1.parseJSON)(match) } },
134
+ });
135
+ }
136
+ if (toolCalls.length) {
137
+ controller.enqueue({
138
+ delta: {
139
+ json: {
140
+ toolCalls: toolCalls
141
+ .map(({ args, ...c }) => ({
142
+ ...c,
143
+ function: { ...c.function, arguments: (0, json_schema_js_1.parseJSON)(args) },
144
+ }))
145
+ .filter(type_utils_js_1.isNonNullable),
146
+ },
147
+ },
148
+ });
149
+ }
150
+ controller.enqueue({ delta: { json: { usage } } });
151
+ controller.close();
152
+ }
153
+ catch (error) {
154
+ controller.error(error);
155
+ }
156
+ },
157
+ });
158
+ return streaming ? result : await (0, stream_utils_js_1.agentResponseStreamToObject)(result);
159
+ }
160
+ }
161
+ exports.BedrockChatModel = BedrockChatModel;
162
+ const getRunMessages = ({ messages: msgs, responseFormat, }) => {
163
+ const system = [];
164
+ const messages = [];
165
+ for (const msg of msgs) {
166
+ if (msg.role === "system") {
167
+ if (typeof msg.content !== "string")
168
+ throw new Error("System message must have content");
169
+ system.push({ text: msg.content });
170
+ }
171
+ else if (msg.role === "tool") {
172
+ if (!msg.toolCallId)
173
+ throw new Error("Tool message must have toolCallId");
174
+ if (typeof msg.content !== "string")
175
+ throw new Error("Tool message must have string content");
176
+ if (messages.at(-1)?.role === "user") {
177
+ messages.at(-1)?.content?.push({
178
+ toolResult: { toolUseId: msg.toolCallId, content: [{ json: (0, json_schema_js_1.parseJSON)(msg.content) }] },
179
+ });
180
+ }
181
+ else {
182
+ messages.push({
183
+ role: "user",
184
+ content: [
185
+ {
186
+ toolResult: {
187
+ toolUseId: msg.toolCallId,
188
+ content: [{ json: (0, json_schema_js_1.parseJSON)(msg.content) }],
189
+ },
190
+ },
191
+ ],
192
+ });
193
+ }
194
+ }
195
+ else if (msg.role === "user") {
196
+ if (!msg.content)
197
+ throw new Error("User message must have content");
198
+ messages.push({ role: "user", content: convertContent(msg.content) });
199
+ }
200
+ else if (msg.role === "agent") {
201
+ if (msg.toolCalls?.length) {
202
+ messages.push({
203
+ role: "assistant",
204
+ content: msg.toolCalls.map((i) => ({
205
+ toolUse: {
206
+ toolUseId: i.id,
207
+ name: i.function.name,
208
+ input: i.function.arguments,
209
+ },
210
+ })),
211
+ });
212
+ }
213
+ else if (msg.content) {
214
+ messages.push({ role: "assistant", content: convertContent(msg.content) });
215
+ }
216
+ else {
217
+ throw new Error("Agent message must have content or toolCalls");
218
+ }
219
+ }
220
+ }
221
+ if (messages.at(0)?.role !== "user") {
222
+ messages.unshift({ role: "user", content: [{ text: "." }] });
223
+ }
224
+ if (responseFormat?.type === "json_schema") {
225
+ system.push({
226
+ text: (0, prompts_js_1.getJsonOutputPrompt)(responseFormat.jsonSchema.schema),
227
+ });
228
+ }
229
+ return { messages, system };
230
+ };
231
+ function convertContent(content) {
232
+ if (typeof content === "string")
233
+ return [{ text: content }];
234
+ if (Array.isArray(content)) {
235
+ const blocks = [];
236
+ for (const item of content) {
237
+ if (item.type === "text")
238
+ blocks.push({ text: item.text });
239
+ }
240
+ return blocks;
241
+ }
242
+ throw new Error("Invalid chat message content");
243
+ }
244
+ function convertTools({ tools, toolChoice }) {
245
+ if (!tools?.length || toolChoice === "none")
246
+ return undefined;
247
+ let choice;
248
+ if (typeof toolChoice === "object" && "type" in toolChoice && toolChoice.type === "function") {
249
+ choice = { tool: { name: toolChoice.function.name } };
250
+ }
251
+ else if (toolChoice === "required") {
252
+ choice = { any: {} };
253
+ }
254
+ else if (toolChoice === "auto") {
255
+ choice = { auto: {} };
256
+ }
257
+ return {
258
+ tools: tools.map((i) => {
259
+ const parameters = i.function.parameters;
260
+ if (Object.keys(parameters).length === 0) {
261
+ parameters.type = "object";
262
+ }
263
+ return {
264
+ toolSpec: {
265
+ name: i.function.name,
266
+ description: i.function.description,
267
+ inputSchema: { json: parameters },
268
+ },
269
+ };
270
+ }),
271
+ toolChoice: choice,
272
+ };
273
+ }
@@ -1,11 +1,12 @@
1
1
  import { Agent, type Message } from "../agents/agent.js";
2
- import type { Context } from "../execution-engine/context.js";
2
+ import type { Context } from "../aigne/context.js";
3
3
  export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelOutput> {
4
4
  constructor();
5
5
  protected supportsParallelToolCalls: boolean;
6
6
  getModelCapabilities(): {
7
7
  supportsParallelToolCalls: boolean;
8
8
  };
9
+ private validateToolNames;
9
10
  protected preprocess(input: ChatModelInput, context: Context): void;
10
11
  protected postprocess(input: ChatModelInput, output: ChatModelOutput, context: Context): void;
11
12
  }
@@ -16,6 +16,13 @@ class ChatModel extends agent_js_1.Agent {
16
16
  supportsParallelToolCalls: this.supportsParallelToolCalls,
17
17
  };
18
18
  }
19
+ validateToolNames(tools) {
20
+ for (const tool of tools ?? []) {
21
+ if (!/^[a-zA-Z0-9_]+$/.test(tool.function.name)) {
22
+ throw new Error(`Tool name "${tool.function.name}" can only contain letters, numbers, and underscores`);
23
+ }
24
+ }
25
+ }
19
26
  preprocess(input, context) {
20
27
  super.preprocess(input, context);
21
28
  const { limits, usage } = context;
@@ -23,6 +30,7 @@ class ChatModel extends agent_js_1.Agent {
23
30
  if (limits?.maxTokens && usedTokens >= limits.maxTokens) {
24
31
  throw new Error(`Exceeded max tokens ${usedTokens}/${limits.maxTokens}`);
25
32
  }
33
+ this.validateToolNames(input.tools);
26
34
  }
27
35
  postprocess(input, output, context) {
28
36
  super.postprocess(input, output, context);
@@ -1,7 +1,7 @@
1
1
  import Anthropic from "@anthropic-ai/sdk";
2
2
  import { z } from "zod";
3
- import type { AgentCallOptions, AgentResponse } from "../agents/agent.js";
4
- import type { Context } from "../execution-engine/context.js";
3
+ import type { AgentInvokeOptions, AgentResponse } from "../agents/agent.js";
4
+ import type { Context } from "../aigne/context.js";
5
5
  import { ChatModel, type ChatModelInput, type ChatModelOptions, type ChatModelOutput } from "./chat-model.js";
6
6
  export interface ClaudeChatModelOptions {
7
7
  apiKey?: string;
@@ -62,7 +62,7 @@ export declare class ClaudeChatModel extends ChatModel {
62
62
  protected _client?: Anthropic;
63
63
  get client(): Anthropic;
64
64
  get modelOptions(): ChatModelOptions | undefined;
65
- process(input: ChatModelInput, _context: Context, options?: AgentCallOptions): Promise<AgentResponse<ChatModelOutput>>;
65
+ process(input: ChatModelInput, _context: Context, options?: AgentInvokeOptions): Promise<AgentResponse<ChatModelOutput>>;
66
66
  private extractResultFromClaudeStream;
67
67
  private requestStructuredOutput;
68
68
  }
@@ -5,4 +5,5 @@ export declare class GeminiChatModel extends OpenAIChatModel {
5
5
  protected supportsEndWithSystemMessage: boolean;
6
6
  protected supportsToolsUseWithJsonSchema: boolean;
7
7
  protected supportsParallelToolCalls: boolean;
8
+ protected supportsToolStreaming: boolean;
8
9
  }