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