@aigne/core 1.8.0 → 1.10.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 (76) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/lib/cjs/agents/agent.d.ts +29 -3
  3. package/lib/cjs/agents/agent.js +48 -23
  4. package/lib/cjs/agents/ai-agent.d.ts +3 -2
  5. package/lib/cjs/agents/ai-agent.js +22 -9
  6. package/lib/cjs/agents/user-agent.d.ts +3 -3
  7. package/lib/cjs/agents/user-agent.js +14 -8
  8. package/lib/cjs/execution-engine/context.d.ts +18 -7
  9. package/lib/cjs/execution-engine/context.js +76 -28
  10. package/lib/cjs/loader/index.js +20 -4
  11. package/lib/cjs/models/chat-model.d.ts +4 -0
  12. package/lib/cjs/models/chat-model.js +6 -0
  13. package/lib/cjs/models/deepseek-chat-model.d.ts +7 -0
  14. package/lib/cjs/models/deepseek-chat-model.js +19 -0
  15. package/lib/cjs/models/gemini-chat-model.d.ts +8 -0
  16. package/lib/cjs/models/gemini-chat-model.js +20 -0
  17. package/lib/cjs/models/ollama-chat-model.d.ts +6 -0
  18. package/lib/cjs/models/ollama-chat-model.js +18 -0
  19. package/lib/cjs/models/open-router-chat-model.d.ts +6 -0
  20. package/lib/cjs/models/open-router-chat-model.js +18 -0
  21. package/lib/cjs/models/openai-chat-model.d.ts +33 -2
  22. package/lib/cjs/models/openai-chat-model.js +250 -80
  23. package/lib/cjs/models/xai-chat-model.d.ts +3 -11
  24. package/lib/cjs/models/xai-chat-model.js +1 -14
  25. package/lib/cjs/prompt/prompt-builder.js +3 -0
  26. package/lib/cjs/utils/prompts.d.ts +1 -0
  27. package/lib/cjs/utils/prompts.js +13 -0
  28. package/lib/cjs/utils/stream-utils.d.ts +15 -0
  29. package/lib/cjs/utils/stream-utils.js +159 -0
  30. package/lib/cjs/utils/type-utils.d.ts +2 -1
  31. package/lib/cjs/utils/type-utils.js +8 -1
  32. package/lib/dts/agents/agent.d.ts +29 -3
  33. package/lib/dts/agents/ai-agent.d.ts +3 -2
  34. package/lib/dts/agents/user-agent.d.ts +3 -3
  35. package/lib/dts/execution-engine/context.d.ts +18 -7
  36. package/lib/dts/models/chat-model.d.ts +4 -0
  37. package/lib/dts/models/deepseek-chat-model.d.ts +7 -0
  38. package/lib/dts/models/gemini-chat-model.d.ts +8 -0
  39. package/lib/dts/models/ollama-chat-model.d.ts +6 -0
  40. package/lib/dts/models/open-router-chat-model.d.ts +6 -0
  41. package/lib/dts/models/openai-chat-model.d.ts +33 -2
  42. package/lib/dts/models/xai-chat-model.d.ts +3 -11
  43. package/lib/dts/utils/prompts.d.ts +1 -0
  44. package/lib/dts/utils/stream-utils.d.ts +15 -0
  45. package/lib/dts/utils/type-utils.d.ts +2 -1
  46. package/lib/esm/agents/agent.d.ts +29 -3
  47. package/lib/esm/agents/agent.js +49 -24
  48. package/lib/esm/agents/ai-agent.d.ts +3 -2
  49. package/lib/esm/agents/ai-agent.js +23 -10
  50. package/lib/esm/agents/user-agent.d.ts +3 -3
  51. package/lib/esm/agents/user-agent.js +15 -9
  52. package/lib/esm/execution-engine/context.d.ts +18 -7
  53. package/lib/esm/execution-engine/context.js +78 -30
  54. package/lib/esm/loader/index.js +20 -4
  55. package/lib/esm/models/chat-model.d.ts +4 -0
  56. package/lib/esm/models/chat-model.js +6 -0
  57. package/lib/esm/models/deepseek-chat-model.d.ts +7 -0
  58. package/lib/esm/models/deepseek-chat-model.js +15 -0
  59. package/lib/esm/models/gemini-chat-model.d.ts +8 -0
  60. package/lib/esm/models/gemini-chat-model.js +16 -0
  61. package/lib/esm/models/ollama-chat-model.d.ts +6 -0
  62. package/lib/esm/models/ollama-chat-model.js +14 -0
  63. package/lib/esm/models/open-router-chat-model.d.ts +6 -0
  64. package/lib/esm/models/open-router-chat-model.js +14 -0
  65. package/lib/esm/models/openai-chat-model.d.ts +33 -2
  66. package/lib/esm/models/openai-chat-model.js +247 -80
  67. package/lib/esm/models/xai-chat-model.d.ts +3 -11
  68. package/lib/esm/models/xai-chat-model.js +1 -11
  69. package/lib/esm/prompt/prompt-builder.js +3 -0
  70. package/lib/esm/utils/prompts.d.ts +1 -0
  71. package/lib/esm/utils/prompts.js +10 -0
  72. package/lib/esm/utils/stream-utils.d.ts +15 -0
  73. package/lib/esm/utils/stream-utils.js +144 -0
  74. package/lib/esm/utils/type-utils.d.ts +2 -1
  75. package/lib/esm/utils/type-utils.js +7 -1
  76. package/package.json +2 -1
@@ -0,0 +1,14 @@
1
+ import { OpenAIChatModel } from "./openai-chat-model.js";
2
+ const OPEN_ROUTER_DEFAULT_CHAT_MODEL = "openai/gpt-4o";
3
+ const OPEN_ROUTER_BASE_URL = "https://openrouter.ai/api/v1";
4
+ export class OpenRouterChatModel extends OpenAIChatModel {
5
+ constructor(options) {
6
+ super({
7
+ ...options,
8
+ model: options?.model || OPEN_ROUTER_DEFAULT_CHAT_MODEL,
9
+ baseURL: options?.baseURL || OPEN_ROUTER_BASE_URL,
10
+ });
11
+ }
12
+ apiKeyEnvName = "OPEN_ROUTER_API_KEY";
13
+ supportsParallelToolCalls = false;
14
+ }
@@ -1,6 +1,17 @@
1
1
  import OpenAI from "openai";
2
+ import type { ChatCompletionMessageParam, ChatCompletionTool } from "openai/resources";
2
3
  import { z } from "zod";
3
- import { ChatModel, type ChatModelInput, type ChatModelOptions, type ChatModelOutput } from "./chat-model.js";
4
+ import type { AgentCallOptions, AgentResponse } from "../agents/agent.js";
5
+ import type { Context } from "../execution-engine/context.js";
6
+ import { ChatModel, type ChatModelInput, type ChatModelInputMessage, type ChatModelInputTool, type ChatModelOptions, type ChatModelOutput, type Role } from "./chat-model.js";
7
+ export interface OpenAIChatModelCapabilities {
8
+ supportsNativeStructuredOutputs: boolean;
9
+ supportsEndWithSystemMessage: boolean;
10
+ supportsToolsUseWithJsonSchema: boolean;
11
+ supportsParallelToolCalls: boolean;
12
+ supportsToolsEmptyParameters: boolean;
13
+ supportsTemperature: boolean;
14
+ }
4
15
  export interface OpenAIChatModelOptions {
5
16
  apiKey?: string;
6
17
  baseURL?: string;
@@ -62,7 +73,27 @@ export declare class OpenAIChatModel extends ChatModel {
62
73
  options?: OpenAIChatModelOptions | undefined;
63
74
  constructor(options?: OpenAIChatModelOptions | undefined);
64
75
  protected _client?: OpenAI;
76
+ protected apiKeyEnvName: string;
77
+ protected apiKeyDefault: string | undefined;
78
+ protected supportsNativeStructuredOutputs: boolean;
79
+ protected supportsEndWithSystemMessage: boolean;
80
+ protected supportsToolsUseWithJsonSchema: boolean;
81
+ protected supportsParallelToolCalls: boolean;
82
+ protected supportsToolsEmptyParameters: boolean;
83
+ protected supportsTemperature: boolean;
65
84
  get client(): OpenAI;
66
85
  get modelOptions(): ChatModelOptions | undefined;
67
- process(input: ChatModelInput): Promise<ChatModelOutput>;
86
+ process(input: ChatModelInput, _context: Context, options?: AgentCallOptions): Promise<AgentResponse<ChatModelOutput>>;
87
+ private getParallelToolCalls;
88
+ private getRunMessages;
89
+ private getRunResponseFormat;
90
+ private requestStructuredOutput;
68
91
  }
92
+ export declare const ROLE_MAP: {
93
+ [key in Role]: ChatCompletionMessageParam["role"];
94
+ };
95
+ export declare function contentsFromInputMessages(messages: ChatModelInputMessage[]): Promise<ChatCompletionMessageParam[]>;
96
+ export declare function toolsFromInputTools(tools?: ChatModelInputTool[], options?: {
97
+ addTypeToEmptyParameters?: boolean;
98
+ }): ChatCompletionTool[] | undefined;
99
+ export declare function jsonSchemaToOpenAIJsonSchema(schema: Record<string, unknown>): Record<string, unknown>;
@@ -2,9 +2,16 @@ import { nanoid } from "nanoid";
2
2
  import OpenAI from "openai";
3
3
  import { z } from "zod";
4
4
  import { parseJSON } from "../utils/json-schema.js";
5
+ import { mergeUsage } from "../utils/model-utils.js";
6
+ import { getJsonOutputPrompt } from "../utils/prompts.js";
7
+ import { agentResponseStreamToObject } from "../utils/stream-utils.js";
5
8
  import { checkArguments, isNonNullable } from "../utils/type-utils.js";
6
9
  import { ChatModel, } from "./chat-model.js";
7
10
  const CHAT_MODEL_OPENAI_DEFAULT_MODEL = "gpt-4o-mini";
11
+ const OPENAI_CHAT_MODEL_CAPABILITIES = {
12
+ "o4-mini": { supportsParallelToolCalls: false, supportsTemperature: false },
13
+ "o3-mini": { supportsParallelToolCalls: false, supportsTemperature: false },
14
+ };
8
15
  export const openAIChatModelOptionsSchema = z.object({
9
16
  apiKey: z.string().optional(),
10
17
  baseURL: z.string().optional(),
@@ -23,16 +30,26 @@ export const openAIChatModelOptionsSchema = z.object({
23
30
  export class OpenAIChatModel extends ChatModel {
24
31
  options;
25
32
  constructor(options) {
26
- if (options)
27
- checkArguments("OpenAIChatModel", openAIChatModelOptionsSchema, options);
28
33
  super();
29
34
  this.options = options;
35
+ if (options)
36
+ checkArguments(this.name, openAIChatModelOptionsSchema, options);
37
+ const preset = options?.model ? OPENAI_CHAT_MODEL_CAPABILITIES[options.model] : undefined;
38
+ Object.assign(this, preset);
30
39
  }
31
40
  _client;
41
+ apiKeyEnvName = "OPENAI_API_KEY";
42
+ apiKeyDefault;
43
+ supportsNativeStructuredOutputs = true;
44
+ supportsEndWithSystemMessage = true;
45
+ supportsToolsUseWithJsonSchema = true;
46
+ supportsParallelToolCalls = true;
47
+ supportsToolsEmptyParameters = true;
48
+ supportsTemperature = true;
32
49
  get client() {
33
- const apiKey = this.options?.apiKey || process.env.OPENAI_API_KEY;
50
+ const apiKey = this.options?.apiKey || process.env[this.apiKeyEnvName] || this.apiKeyDefault;
34
51
  if (!apiKey)
35
- throw new Error("Api Key is required for OpenAIChatModel");
52
+ throw new Error(`Api Key is required for ${this.name}`);
36
53
  this._client ??= new OpenAI({
37
54
  baseURL: this.options?.baseURL,
38
55
  apiKey,
@@ -42,92 +59,111 @@ export class OpenAIChatModel extends ChatModel {
42
59
  get modelOptions() {
43
60
  return this.options?.modelOptions;
44
61
  }
45
- async process(input) {
46
- const res = await this.client.chat.completions.create({
62
+ async process(input, _context, options) {
63
+ const messages = await this.getRunMessages(input);
64
+ const body = {
47
65
  model: this.options?.model || CHAT_MODEL_OPENAI_DEFAULT_MODEL,
48
- temperature: input.modelOptions?.temperature ?? this.modelOptions?.temperature,
66
+ temperature: this.supportsTemperature
67
+ ? (input.modelOptions?.temperature ?? this.modelOptions?.temperature)
68
+ : undefined,
49
69
  top_p: input.modelOptions?.topP ?? this.modelOptions?.topP,
50
70
  frequency_penalty: input.modelOptions?.frequencyPenalty ?? this.modelOptions?.frequencyPenalty,
51
71
  presence_penalty: input.modelOptions?.presencePenalty ?? this.modelOptions?.presencePenalty,
52
- messages: await contentsFromInputMessages(input.messages),
53
- tools: toolsFromInputTools(input.tools),
54
- tool_choice: input.toolChoice,
55
- parallel_tool_calls: !input.tools?.length
56
- ? undefined
57
- : (input.modelOptions?.parallelToolCalls ?? this.modelOptions?.parallelToolCalls),
58
- response_format: input.responseFormat?.type === "json_schema"
59
- ? {
60
- type: "json_schema",
61
- json_schema: {
62
- ...input.responseFormat.jsonSchema,
63
- schema: jsonSchemaToOpenAIJsonSchema(input.responseFormat.jsonSchema.schema),
64
- },
65
- }
66
- : undefined,
72
+ messages,
67
73
  stream_options: {
68
74
  include_usage: true,
69
75
  },
70
76
  stream: true,
77
+ };
78
+ const { jsonMode, responseFormat } = await this.getRunResponseFormat(input);
79
+ const stream = await this.client.chat.completions.create({
80
+ ...body,
81
+ tools: toolsFromInputTools(input.tools, {
82
+ addTypeToEmptyParameters: !this.supportsToolsEmptyParameters,
83
+ }),
84
+ tool_choice: input.toolChoice,
85
+ parallel_tool_calls: this.getParallelToolCalls(input),
86
+ response_format: responseFormat,
71
87
  });
72
- let text = "";
73
- const toolCalls = [];
74
- let usage;
75
- let model;
76
- for await (const chunk of res) {
77
- const choice = chunk.choices?.[0];
78
- model ??= chunk.model;
79
- if (choice?.delta.tool_calls?.length) {
80
- for (const call of choice.delta.tool_calls) {
81
- toolCalls[call.index] ??= {
82
- id: call.id || nanoid(),
83
- type: "function",
84
- function: { name: "", arguments: {} },
85
- args: "",
86
- };
87
- const c = toolCalls[call.index];
88
- if (!c)
89
- throw new Error("Tool call not found");
90
- if (call.type)
91
- c.type = call.type;
92
- c.function.name = c.function.name + (call.function?.name || "");
93
- c.args = c.args.concat(call.function?.arguments || "");
94
- }
95
- }
96
- if (choice?.delta.content)
97
- text += choice.delta.content;
98
- if (chunk.usage) {
99
- usage = {
100
- inputTokens: chunk.usage.prompt_tokens,
101
- outputTokens: chunk.usage.completion_tokens,
102
- };
103
- }
88
+ if (options?.streaming && input.responseFormat?.type !== "json_schema") {
89
+ return await extractResultFromStream(stream, false, true);
104
90
  }
105
- const result = {
106
- usage,
107
- model,
108
- };
109
- if (input.responseFormat?.type === "json_schema" && text) {
110
- result.json = parseJSON(text);
91
+ const result = await extractResultFromStream(stream, jsonMode);
92
+ if (!this.supportsToolsUseWithJsonSchema &&
93
+ !result.toolCalls?.length &&
94
+ input.responseFormat?.type === "json_schema" &&
95
+ result.text) {
96
+ const output = await this.requestStructuredOutput(body, input.responseFormat);
97
+ return { ...output, usage: mergeUsage(result.usage, output.usage) };
111
98
  }
112
- else {
113
- result.text = text;
99
+ return result;
100
+ }
101
+ getParallelToolCalls(input) {
102
+ if (!this.supportsParallelToolCalls)
103
+ return undefined;
104
+ if (!input.tools?.length)
105
+ return undefined;
106
+ return input.modelOptions?.parallelToolCalls ?? this.modelOptions?.parallelToolCalls;
107
+ }
108
+ async getRunMessages(input) {
109
+ const messages = await contentsFromInputMessages(input.messages);
110
+ if (!this.supportsEndWithSystemMessage && messages.at(-1)?.role !== "user") {
111
+ messages.push({ role: "user", content: "" });
114
112
  }
115
- if (toolCalls.length) {
116
- result.toolCalls = toolCalls.map(({ args, ...c }) => ({
117
- ...c,
118
- function: { ...c.function, arguments: parseJSON(args) },
119
- }));
113
+ if (!this.supportsToolsUseWithJsonSchema && input.tools?.length)
114
+ return messages;
115
+ if (this.supportsNativeStructuredOutputs)
116
+ return messages;
117
+ if (input.responseFormat?.type === "json_schema") {
118
+ messages.unshift({
119
+ role: "system",
120
+ content: getJsonOutputPrompt(input.responseFormat.jsonSchema.schema),
121
+ });
120
122
  }
121
- return result;
123
+ return messages;
124
+ }
125
+ async getRunResponseFormat(input) {
126
+ if (!this.supportsToolsUseWithJsonSchema && input.tools?.length)
127
+ return { jsonMode: false, responseFormat: undefined };
128
+ if (!this.supportsNativeStructuredOutputs) {
129
+ const jsonMode = input.responseFormat?.type === "json_schema";
130
+ return { jsonMode, responseFormat: jsonMode ? { type: "json_object" } : undefined };
131
+ }
132
+ if (input.responseFormat?.type === "json_schema") {
133
+ return {
134
+ jsonMode: true,
135
+ responseFormat: {
136
+ type: "json_schema",
137
+ json_schema: {
138
+ ...input.responseFormat.jsonSchema,
139
+ schema: jsonSchemaToOpenAIJsonSchema(input.responseFormat.jsonSchema.schema),
140
+ },
141
+ },
142
+ };
143
+ }
144
+ return { jsonMode: false, responseFormat: undefined };
145
+ }
146
+ async requestStructuredOutput(body, responseFormat) {
147
+ if (responseFormat?.type !== "json_schema") {
148
+ throw new Error("Expected json_schema response format");
149
+ }
150
+ const { jsonMode, responseFormat: resolvedResponseFormat } = await this.getRunResponseFormat({
151
+ responseFormat,
152
+ });
153
+ const res = await this.client.chat.completions.create({
154
+ ...body,
155
+ response_format: resolvedResponseFormat,
156
+ });
157
+ return extractResultFromStream(res, jsonMode);
122
158
  }
123
159
  }
124
- const ROLE_MAP = {
160
+ export const ROLE_MAP = {
125
161
  system: "system",
126
162
  user: "user",
127
163
  agent: "assistant",
128
164
  tool: "tool",
129
165
  };
130
- async function contentsFromInputMessages(messages) {
166
+ export async function contentsFromInputMessages(messages) {
131
167
  return messages.map((i) => ({
132
168
  role: ROLE_MAP[i.role],
133
169
  content: typeof i.content === "string"
@@ -156,19 +192,25 @@ async function contentsFromInputMessages(messages) {
156
192
  name: i.name,
157
193
  }));
158
194
  }
159
- function toolsFromInputTools(tools) {
195
+ export function toolsFromInputTools(tools, options) {
160
196
  return tools?.length
161
- ? tools.map((i) => ({
162
- type: "function",
163
- function: {
164
- name: i.function.name,
165
- description: i.function.description,
166
- parameters: i.function.parameters,
167
- },
168
- }))
197
+ ? tools.map((i) => {
198
+ const parameters = i.function.parameters;
199
+ if (options?.addTypeToEmptyParameters && Object.keys(parameters).length === 0) {
200
+ parameters.type = "object";
201
+ }
202
+ return {
203
+ type: "function",
204
+ function: {
205
+ name: i.function.name,
206
+ description: i.function.description,
207
+ parameters,
208
+ },
209
+ };
210
+ })
169
211
  : undefined;
170
212
  }
171
- function jsonSchemaToOpenAIJsonSchema(schema) {
213
+ export function jsonSchemaToOpenAIJsonSchema(schema) {
172
214
  if (schema?.type === "object") {
173
215
  const { required, properties } = schema;
174
216
  return {
@@ -193,3 +235,128 @@ function jsonSchemaToOpenAIJsonSchema(schema) {
193
235
  }
194
236
  return schema;
195
237
  }
238
+ async function extractResultFromStream(stream, jsonMode, streaming) {
239
+ const result = new ReadableStream({
240
+ async start(controller) {
241
+ try {
242
+ let text = "";
243
+ let refusal = "";
244
+ const toolCalls = [];
245
+ let model;
246
+ for await (const chunk of stream) {
247
+ const choice = chunk.choices?.[0];
248
+ if (!model) {
249
+ model = chunk.model;
250
+ controller.enqueue({
251
+ delta: {
252
+ json: {
253
+ model,
254
+ },
255
+ },
256
+ });
257
+ }
258
+ if (choice?.delta.tool_calls?.length) {
259
+ for (const call of choice.delta.tool_calls) {
260
+ // Gemini not support tool call delta
261
+ if (call.index !== undefined) {
262
+ handleToolCallDelta(toolCalls, call);
263
+ }
264
+ else {
265
+ handleCompleteToolCall(toolCalls, call);
266
+ }
267
+ }
268
+ }
269
+ if (choice?.delta.content) {
270
+ text += choice.delta.content;
271
+ if (!jsonMode) {
272
+ controller.enqueue({
273
+ delta: {
274
+ text: {
275
+ text: choice.delta.content,
276
+ },
277
+ },
278
+ });
279
+ }
280
+ }
281
+ if (choice?.delta.refusal) {
282
+ refusal += choice.delta.refusal;
283
+ if (!jsonMode) {
284
+ controller.enqueue({
285
+ delta: {
286
+ text: { text: choice.delta.refusal },
287
+ },
288
+ });
289
+ }
290
+ }
291
+ if (chunk.usage) {
292
+ controller.enqueue({
293
+ delta: {
294
+ json: {
295
+ usage: {
296
+ inputTokens: chunk.usage.prompt_tokens,
297
+ outputTokens: chunk.usage.completion_tokens,
298
+ },
299
+ },
300
+ },
301
+ });
302
+ }
303
+ }
304
+ text = text || refusal;
305
+ if (jsonMode && text) {
306
+ controller.enqueue({
307
+ delta: {
308
+ json: {
309
+ json: parseJSON(text),
310
+ },
311
+ },
312
+ });
313
+ }
314
+ if (toolCalls.length) {
315
+ controller.enqueue({
316
+ delta: {
317
+ json: {
318
+ toolCalls: toolCalls.map(({ args, ...c }) => ({
319
+ ...c,
320
+ function: { ...c.function, arguments: parseJSON(args) },
321
+ })),
322
+ },
323
+ },
324
+ });
325
+ }
326
+ }
327
+ catch (error) {
328
+ controller.error(error);
329
+ }
330
+ finally {
331
+ controller.close();
332
+ }
333
+ },
334
+ });
335
+ return streaming ? result : await agentResponseStreamToObject(result);
336
+ }
337
+ function handleToolCallDelta(toolCalls, call) {
338
+ toolCalls[call.index] ??= {
339
+ id: call.id || nanoid(),
340
+ type: "function",
341
+ function: { name: "", arguments: {} },
342
+ args: "",
343
+ };
344
+ const c = toolCalls[call.index];
345
+ if (!c)
346
+ throw new Error("Tool call not found");
347
+ if (call.type)
348
+ c.type = call.type;
349
+ c.function.name = c.function.name + (call.function?.name || "");
350
+ c.args = c.args.concat(call.function?.arguments || "");
351
+ }
352
+ function handleCompleteToolCall(toolCalls, call) {
353
+ toolCalls.push({
354
+ id: call.id || nanoid(),
355
+ type: "function",
356
+ function: {
357
+ name: call.function?.name || "",
358
+ arguments: parseJSON(call.function?.arguments || "{}"),
359
+ },
360
+ args: call.function?.arguments || "",
361
+ });
362
+ }
@@ -1,13 +1,5 @@
1
- import OpenAI from "openai";
2
- import type { ChatModelOptions } from "./chat-model.js";
3
- import { OpenAIChatModel } from "./openai-chat-model.js";
4
- export interface XAIChatModelOptions {
5
- apiKey?: string;
6
- model?: string;
7
- modelOptions?: ChatModelOptions;
8
- baseURL?: string;
9
- }
1
+ import { OpenAIChatModel, type OpenAIChatModelOptions } from "./openai-chat-model.js";
10
2
  export declare class XAIChatModel extends OpenAIChatModel {
11
- constructor(options?: XAIChatModelOptions);
12
- get client(): OpenAI;
3
+ constructor(options?: OpenAIChatModelOptions);
4
+ protected apiKeyEnvName: string;
13
5
  }
@@ -1,4 +1,3 @@
1
- import OpenAI from "openai";
2
1
  import { OpenAIChatModel } from "./openai-chat-model.js";
3
2
  const XAI_DEFAULT_CHAT_MODEL = "grok-2-latest";
4
3
  const XAI_BASE_URL = "https://api.x.ai/v1";
@@ -10,14 +9,5 @@ export class XAIChatModel extends OpenAIChatModel {
10
9
  baseURL: options?.baseURL || XAI_BASE_URL,
11
10
  });
12
11
  }
13
- get client() {
14
- const apiKey = this.options?.apiKey || process.env.XAI_API_KEY;
15
- if (!apiKey)
16
- throw new Error("Api Key is required for XAIChatModel");
17
- this._client ??= new OpenAI({
18
- baseURL: this.options?.baseURL,
19
- apiKey,
20
- });
21
- return this._client;
22
- }
12
+ apiKeyEnvName = "XAI_API_KEY";
23
13
  }
@@ -127,6 +127,7 @@ export class PromptBuilder {
127
127
  },
128
128
  }));
129
129
  let toolChoice;
130
+ const modelOptions = {};
130
131
  // use manual choice if configured in the agent
131
132
  const manualChoice = options.agent?.toolChoice;
132
133
  if (manualChoice) {
@@ -141,6 +142,7 @@ export class PromptBuilder {
141
142
  }
142
143
  else if (manualChoice === "router") {
143
144
  toolChoice = "required";
145
+ modelOptions.parallelToolCalls = false;
144
146
  }
145
147
  else {
146
148
  toolChoice = manualChoice;
@@ -154,6 +156,7 @@ export class PromptBuilder {
154
156
  toolAgents: toolAgents.length ? toolAgents : undefined,
155
157
  tools: tools.length ? tools : undefined,
156
158
  toolChoice,
159
+ modelOptions: Object.keys(modelOptions).length ? modelOptions : undefined,
157
160
  };
158
161
  }
159
162
  }
@@ -0,0 +1 @@
1
+ export declare function getJsonOutputPrompt(schema: Record<string, unknown> | string): string;
@@ -0,0 +1,10 @@
1
+ export function getJsonOutputPrompt(schema) {
2
+ let prompt = "Provide your output as a JSON containing the following fields:";
3
+ if (typeof schema === "string") {
4
+ prompt += `\n<json_fields>\n${schema}\n</json_fields>`;
5
+ }
6
+ else {
7
+ prompt += `\n<json_fields>\n${JSON.stringify(schema)}\n</json_fields>`;
8
+ }
9
+ return prompt;
10
+ }
@@ -0,0 +1,15 @@
1
+ import type { AgentProcessAsyncGenerator, AgentResponseChunk, AgentResponseStream, Message } from "../agents/agent.js";
2
+ import { type PromiseOrValue } from "./type-utils.js";
3
+ export declare function objectToAgentResponseStream<T extends Message>(json: T): AgentResponseStream<T>;
4
+ export declare function mergeAgentResponseChunk<T extends Message>(output: T, chunk: AgentResponseChunk<T>): T;
5
+ export declare function agentResponseStreamToObject<T extends Message>(stream: AgentResponseStream<T> | AgentProcessAsyncGenerator<T>): Promise<T>;
6
+ export declare function asyncGeneratorToReadableStream<T extends Message>(generator: AgentProcessAsyncGenerator<T>): AgentResponseStream<T>;
7
+ export declare function onAgentResponseStreamEnd<T extends Message>(stream: AgentResponseStream<T>, callback: (result: T) => PromiseOrValue<Partial<T> | void>, options?: {
8
+ errorCallback?: (error: Error) => Error;
9
+ processChunk?: (chunk: AgentResponseChunk<T>) => AgentResponseChunk<T>;
10
+ }): ReadableStream<any>;
11
+ export declare function isAsyncGenerator<T extends AsyncGenerator>(value: AsyncGenerator | unknown): value is T;
12
+ export declare function arrayToAgentProcessAsyncGenerator<T extends Message>(chunks: (AgentResponseChunk<T> | Error)[], result?: Partial<T>): AgentProcessAsyncGenerator<T>;
13
+ export declare function arrayToAgentResponseStream<T>(chunks: (AgentResponseChunk<T> | Error)[]): AgentResponseStream<T>;
14
+ export declare function readableStreamToArray<T>(stream: ReadableStream<T>): Promise<T[]>;
15
+ export declare function readableStreamToAsyncIterator<T>(stream: ReadableStream<T>): AsyncIterable<T>;