@discomedia/utils 1.0.24 → 1.0.26
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/dist/index-frontend.cjs +194 -127
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +194 -128
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +323 -137
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +323 -138
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +2 -2
- package/dist/test.js +5343 -1060
- package/dist/test.js.map +1 -1
- package/dist/types/index-frontend.d.ts +1 -1
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/json-tools.d.ts +1 -3
- package/dist/types/json-tools.d.ts.map +1 -1
- package/dist/types/llm-config.d.ts.map +1 -1
- package/dist/types/llm-deepseek.d.ts +1 -1
- package/dist/types/llm-deepseek.d.ts.map +1 -1
- package/dist/types/llm-images.d.ts.map +1 -1
- package/dist/types/llm-openai.d.ts +8 -2
- package/dist/types/llm-openai.d.ts.map +1 -1
- package/dist/types/llm-openrouter.d.ts +28 -0
- package/dist/types/llm-openrouter.d.ts.map +1 -0
- package/dist/types/misc-utils.d.ts.map +1 -1
- package/dist/types/types/llm-types.d.ts +27 -4
- package/dist/types/types/llm-types.d.ts.map +1 -1
- package/dist/types/types/logging-types.d.ts +1 -1
- package/dist/types/types/logging-types.d.ts.map +1 -1
- package/dist/types-frontend/index-frontend.d.ts +1 -1
- package/dist/types-frontend/index.d.ts +3 -1
- package/dist/types-frontend/index.d.ts.map +1 -1
- package/dist/types-frontend/json-tools.d.ts +1 -3
- package/dist/types-frontend/json-tools.d.ts.map +1 -1
- package/dist/types-frontend/llm-config.d.ts.map +1 -1
- package/dist/types-frontend/llm-deepseek.d.ts +1 -1
- package/dist/types-frontend/llm-deepseek.d.ts.map +1 -1
- package/dist/types-frontend/llm-images.d.ts.map +1 -1
- package/dist/types-frontend/llm-openai.d.ts +8 -2
- package/dist/types-frontend/llm-openai.d.ts.map +1 -1
- package/dist/types-frontend/llm-openrouter.d.ts +28 -0
- package/dist/types-frontend/llm-openrouter.d.ts.map +1 -0
- package/dist/types-frontend/misc-utils.d.ts.map +1 -1
- package/dist/types-frontend/types/llm-types.d.ts +27 -4
- package/dist/types-frontend/types/llm-types.d.ts.map +1 -1
- package/dist/types-frontend/types/logging-types.d.ts +1 -1
- package/dist/types-frontend/types/logging-types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/types/old-test.d.ts +0 -2
- package/dist/types/old-test.d.ts.map +0 -1
- package/dist/types-frontend/old-test.d.ts +0 -2
- package/dist/types-frontend/old-test.d.ts.map +0 -1
package/dist/index-frontend.mjs
CHANGED
|
@@ -12,8 +12,28 @@ import require$$0$4 from 'fs';
|
|
|
12
12
|
import require$$1$1 from 'path';
|
|
13
13
|
import require$$2$1 from 'os';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Type guard to check if a model is an OpenRouter model
|
|
17
|
+
*/
|
|
18
|
+
function isOpenRouterModel(model) {
|
|
19
|
+
const openRouterModels = [
|
|
20
|
+
'openai/gpt-5',
|
|
21
|
+
'openai/gpt-5-mini',
|
|
22
|
+
'openai/gpt-5-nano',
|
|
23
|
+
'openai/gpt-oss-120b',
|
|
24
|
+
'z.ai/glm-4.5',
|
|
25
|
+
'z.ai/glm-4.5-air',
|
|
26
|
+
'google/gemini-2.5-flash',
|
|
27
|
+
'google/gemini-2.5-flash-lite',
|
|
28
|
+
'deepseek/deepseek-r1-0528',
|
|
29
|
+
'deepseek/deepseek-chat-v3-0324',
|
|
30
|
+
];
|
|
31
|
+
return openRouterModels.includes(model);
|
|
32
|
+
}
|
|
33
|
+
|
|
15
34
|
var Types = /*#__PURE__*/Object.freeze({
|
|
16
|
-
__proto__: null
|
|
35
|
+
__proto__: null,
|
|
36
|
+
isOpenRouterModel: isOpenRouterModel
|
|
17
37
|
});
|
|
18
38
|
|
|
19
39
|
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
@@ -247,7 +267,7 @@ const safeJSON = (text) => {
|
|
|
247
267
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
248
268
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
249
269
|
|
|
250
|
-
const VERSION = '5.12.
|
|
270
|
+
const VERSION = '5.12.2'; // x-release-please-version
|
|
251
271
|
|
|
252
272
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
253
273
|
const isRunningInBrowser = () => {
|
|
@@ -1880,8 +1900,119 @@ let Messages$1 = class Messages extends APIResource {
|
|
|
1880
1900
|
}
|
|
1881
1901
|
};
|
|
1882
1902
|
|
|
1883
|
-
function
|
|
1884
|
-
return
|
|
1903
|
+
function isChatCompletionFunctionTool(tool) {
|
|
1904
|
+
return tool !== undefined && 'function' in tool && tool.function !== undefined;
|
|
1905
|
+
}
|
|
1906
|
+
function isAutoParsableResponseFormat(response_format) {
|
|
1907
|
+
return response_format?.['$brand'] === 'auto-parseable-response-format';
|
|
1908
|
+
}
|
|
1909
|
+
function isAutoParsableTool$1(tool) {
|
|
1910
|
+
return tool?.['$brand'] === 'auto-parseable-tool';
|
|
1911
|
+
}
|
|
1912
|
+
function maybeParseChatCompletion(completion, params) {
|
|
1913
|
+
if (!params || !hasAutoParseableInput$1(params)) {
|
|
1914
|
+
return {
|
|
1915
|
+
...completion,
|
|
1916
|
+
choices: completion.choices.map((choice) => {
|
|
1917
|
+
assertToolCallsAreChatCompletionFunctionToolCalls(choice.message.tool_calls);
|
|
1918
|
+
return {
|
|
1919
|
+
...choice,
|
|
1920
|
+
message: {
|
|
1921
|
+
...choice.message,
|
|
1922
|
+
parsed: null,
|
|
1923
|
+
...(choice.message.tool_calls ?
|
|
1924
|
+
{
|
|
1925
|
+
tool_calls: choice.message.tool_calls,
|
|
1926
|
+
}
|
|
1927
|
+
: undefined),
|
|
1928
|
+
},
|
|
1929
|
+
};
|
|
1930
|
+
}),
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
return parseChatCompletion(completion, params);
|
|
1934
|
+
}
|
|
1935
|
+
function parseChatCompletion(completion, params) {
|
|
1936
|
+
const choices = completion.choices.map((choice) => {
|
|
1937
|
+
if (choice.finish_reason === 'length') {
|
|
1938
|
+
throw new LengthFinishReasonError();
|
|
1939
|
+
}
|
|
1940
|
+
if (choice.finish_reason === 'content_filter') {
|
|
1941
|
+
throw new ContentFilterFinishReasonError();
|
|
1942
|
+
}
|
|
1943
|
+
assertToolCallsAreChatCompletionFunctionToolCalls(choice.message.tool_calls);
|
|
1944
|
+
return {
|
|
1945
|
+
...choice,
|
|
1946
|
+
message: {
|
|
1947
|
+
...choice.message,
|
|
1948
|
+
...(choice.message.tool_calls ?
|
|
1949
|
+
{
|
|
1950
|
+
tool_calls: choice.message.tool_calls?.map((toolCall) => parseToolCall$1(params, toolCall)) ?? undefined,
|
|
1951
|
+
}
|
|
1952
|
+
: undefined),
|
|
1953
|
+
parsed: choice.message.content && !choice.message.refusal ?
|
|
1954
|
+
parseResponseFormat(params, choice.message.content)
|
|
1955
|
+
: null,
|
|
1956
|
+
},
|
|
1957
|
+
};
|
|
1958
|
+
});
|
|
1959
|
+
return { ...completion, choices };
|
|
1960
|
+
}
|
|
1961
|
+
function parseResponseFormat(params, content) {
|
|
1962
|
+
if (params.response_format?.type !== 'json_schema') {
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
if (params.response_format?.type === 'json_schema') {
|
|
1966
|
+
if ('$parseRaw' in params.response_format) {
|
|
1967
|
+
const response_format = params.response_format;
|
|
1968
|
+
return response_format.$parseRaw(content);
|
|
1969
|
+
}
|
|
1970
|
+
return JSON.parse(content);
|
|
1971
|
+
}
|
|
1972
|
+
return null;
|
|
1973
|
+
}
|
|
1974
|
+
function parseToolCall$1(params, toolCall) {
|
|
1975
|
+
const inputTool = params.tools?.find((inputTool) => isChatCompletionFunctionTool(inputTool) && inputTool.function?.name === toolCall.function.name); // TS doesn't narrow based on isChatCompletionTool
|
|
1976
|
+
return {
|
|
1977
|
+
...toolCall,
|
|
1978
|
+
function: {
|
|
1979
|
+
...toolCall.function,
|
|
1980
|
+
parsed_arguments: isAutoParsableTool$1(inputTool) ? inputTool.$parseRaw(toolCall.function.arguments)
|
|
1981
|
+
: inputTool?.function.strict ? JSON.parse(toolCall.function.arguments)
|
|
1982
|
+
: null,
|
|
1983
|
+
},
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
function shouldParseToolCall(params, toolCall) {
|
|
1987
|
+
if (!params || !('tools' in params) || !params.tools) {
|
|
1988
|
+
return false;
|
|
1989
|
+
}
|
|
1990
|
+
const inputTool = params.tools?.find((inputTool) => isChatCompletionFunctionTool(inputTool) && inputTool.function?.name === toolCall.function.name);
|
|
1991
|
+
return (isChatCompletionFunctionTool(inputTool) &&
|
|
1992
|
+
(isAutoParsableTool$1(inputTool) || inputTool?.function.strict || false));
|
|
1993
|
+
}
|
|
1994
|
+
function hasAutoParseableInput$1(params) {
|
|
1995
|
+
if (isAutoParsableResponseFormat(params.response_format)) {
|
|
1996
|
+
return true;
|
|
1997
|
+
}
|
|
1998
|
+
return (params.tools?.some((t) => isAutoParsableTool$1(t) || (t.type === 'function' && t.function.strict === true)) ?? false);
|
|
1999
|
+
}
|
|
2000
|
+
function assertToolCallsAreChatCompletionFunctionToolCalls(toolCalls) {
|
|
2001
|
+
for (const toolCall of toolCalls || []) {
|
|
2002
|
+
if (toolCall.type !== 'function') {
|
|
2003
|
+
throw new OpenAIError(`Currently only \`function\` tool calls are supported; Received \`${toolCall.type}\``);
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
function validateInputTools(tools) {
|
|
2008
|
+
for (const tool of tools ?? []) {
|
|
2009
|
+
if (tool.type !== 'function') {
|
|
2010
|
+
throw new OpenAIError(`Currently only \`function\` tool types support auto-parsing; Received \`${tool.type}\``);
|
|
2011
|
+
}
|
|
2012
|
+
if (tool.function.strict !== true) {
|
|
2013
|
+
throw new OpenAIError(`The \`${tool.function.name}\` tool is not marked with \`strict: true\`. Only strict function tools can be auto-parsed`);
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
1885
2016
|
}
|
|
1886
2017
|
|
|
1887
2018
|
const isAssistantMessage = (message) => {
|
|
@@ -2075,104 +2206,8 @@ _EventStream_connectedPromise = new WeakMap(), _EventStream_resolveConnectedProm
|
|
|
2075
2206
|
return this._emit('error', new OpenAIError(String(error)));
|
|
2076
2207
|
};
|
|
2077
2208
|
|
|
2078
|
-
function
|
|
2079
|
-
return
|
|
2080
|
-
}
|
|
2081
|
-
function isAutoParsableTool$1(tool) {
|
|
2082
|
-
return tool?.['$brand'] === 'auto-parseable-tool';
|
|
2083
|
-
}
|
|
2084
|
-
function maybeParseChatCompletion(completion, params) {
|
|
2085
|
-
if (!params || !hasAutoParseableInput$1(params)) {
|
|
2086
|
-
return {
|
|
2087
|
-
...completion,
|
|
2088
|
-
choices: completion.choices.map((choice) => ({
|
|
2089
|
-
...choice,
|
|
2090
|
-
message: {
|
|
2091
|
-
...choice.message,
|
|
2092
|
-
parsed: null,
|
|
2093
|
-
...(choice.message.tool_calls ?
|
|
2094
|
-
{
|
|
2095
|
-
tool_calls: choice.message.tool_calls,
|
|
2096
|
-
}
|
|
2097
|
-
: undefined),
|
|
2098
|
-
},
|
|
2099
|
-
})),
|
|
2100
|
-
};
|
|
2101
|
-
}
|
|
2102
|
-
return parseChatCompletion(completion, params);
|
|
2103
|
-
}
|
|
2104
|
-
function parseChatCompletion(completion, params) {
|
|
2105
|
-
const choices = completion.choices.map((choice) => {
|
|
2106
|
-
if (choice.finish_reason === 'length') {
|
|
2107
|
-
throw new LengthFinishReasonError();
|
|
2108
|
-
}
|
|
2109
|
-
if (choice.finish_reason === 'content_filter') {
|
|
2110
|
-
throw new ContentFilterFinishReasonError();
|
|
2111
|
-
}
|
|
2112
|
-
return {
|
|
2113
|
-
...choice,
|
|
2114
|
-
message: {
|
|
2115
|
-
...choice.message,
|
|
2116
|
-
...(choice.message.tool_calls ?
|
|
2117
|
-
{
|
|
2118
|
-
tool_calls: choice.message.tool_calls?.map((toolCall) => parseToolCall$1(params, toolCall)) ?? undefined,
|
|
2119
|
-
}
|
|
2120
|
-
: undefined),
|
|
2121
|
-
parsed: choice.message.content && !choice.message.refusal ?
|
|
2122
|
-
parseResponseFormat(params, choice.message.content)
|
|
2123
|
-
: null,
|
|
2124
|
-
},
|
|
2125
|
-
};
|
|
2126
|
-
});
|
|
2127
|
-
return { ...completion, choices };
|
|
2128
|
-
}
|
|
2129
|
-
function parseResponseFormat(params, content) {
|
|
2130
|
-
if (params.response_format?.type !== 'json_schema') {
|
|
2131
|
-
return null;
|
|
2132
|
-
}
|
|
2133
|
-
if (params.response_format?.type === 'json_schema') {
|
|
2134
|
-
if ('$parseRaw' in params.response_format) {
|
|
2135
|
-
const response_format = params.response_format;
|
|
2136
|
-
return response_format.$parseRaw(content);
|
|
2137
|
-
}
|
|
2138
|
-
return JSON.parse(content);
|
|
2139
|
-
}
|
|
2140
|
-
return null;
|
|
2141
|
-
}
|
|
2142
|
-
function parseToolCall$1(params, toolCall) {
|
|
2143
|
-
const inputTool = params.tools?.find((inputTool) => inputTool.function?.name === toolCall.function.name);
|
|
2144
|
-
return {
|
|
2145
|
-
...toolCall,
|
|
2146
|
-
function: {
|
|
2147
|
-
...toolCall.function,
|
|
2148
|
-
parsed_arguments: isAutoParsableTool$1(inputTool) ? inputTool.$parseRaw(toolCall.function.arguments)
|
|
2149
|
-
: inputTool?.function.strict ? JSON.parse(toolCall.function.arguments)
|
|
2150
|
-
: null,
|
|
2151
|
-
},
|
|
2152
|
-
};
|
|
2153
|
-
}
|
|
2154
|
-
function shouldParseToolCall(params, toolCall) {
|
|
2155
|
-
if (!params) {
|
|
2156
|
-
return false;
|
|
2157
|
-
}
|
|
2158
|
-
const inputTool = params.tools?.find((inputTool) => inputTool.function?.name === toolCall.function.name);
|
|
2159
|
-
return isAutoParsableTool$1(inputTool) || inputTool?.function.strict || false;
|
|
2160
|
-
}
|
|
2161
|
-
function hasAutoParseableInput$1(params) {
|
|
2162
|
-
if (isAutoParsableResponseFormat(params.response_format)) {
|
|
2163
|
-
return true;
|
|
2164
|
-
}
|
|
2165
|
-
return (params.tools?.some((t) => isAutoParsableTool$1(t) || (t.type === 'function' && t.function.strict === true)) ?? false);
|
|
2166
|
-
}
|
|
2167
|
-
function validateInputTools(tools) {
|
|
2168
|
-
for (const tool of tools ?? []) {
|
|
2169
|
-
if (tool.type !== 'function') {
|
|
2170
|
-
throw new OpenAIError(`Currently only \`function\` tool types support auto-parsing; Received \`${tool.type}\``);
|
|
2171
|
-
}
|
|
2172
|
-
if (tool.function.strict !== true) {
|
|
2173
|
-
throw new OpenAIError(`The \`${tool.function.name}\` tool is not marked with \`strict: true\`. Only strict function tools can be auto-parsed`);
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2209
|
+
function isRunnableFunctionWithParse(fn) {
|
|
2210
|
+
return typeof fn.parse === 'function';
|
|
2176
2211
|
}
|
|
2177
2212
|
|
|
2178
2213
|
var _AbstractChatCompletionRunner_instances, _AbstractChatCompletionRunner_getFinalContent, _AbstractChatCompletionRunner_getFinalMessage, _AbstractChatCompletionRunner_getFinalFunctionToolCall, _AbstractChatCompletionRunner_getFinalFunctionToolCallResult, _AbstractChatCompletionRunner_calculateTotalUsage, _AbstractChatCompletionRunner_validateParams, _AbstractChatCompletionRunner_stringifyFunctionCallResult;
|
|
@@ -2298,7 +2333,7 @@ class AbstractChatCompletionRunner extends EventStream {
|
|
|
2298
2333
|
async _runTools(client, params, options) {
|
|
2299
2334
|
const role = 'tool';
|
|
2300
2335
|
const { tool_choice = 'auto', stream, ...restParams } = params;
|
|
2301
|
-
const singleFunctionToCall = typeof tool_choice !== 'string' && tool_choice?.function?.name;
|
|
2336
|
+
const singleFunctionToCall = typeof tool_choice !== 'string' && tool_choice.type === 'function' && tool_choice?.function?.name;
|
|
2302
2337
|
const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {};
|
|
2303
2338
|
// TODO(someday): clean this logic up
|
|
2304
2339
|
const inputTools = params.tools.map((tool) => {
|
|
@@ -2416,7 +2451,7 @@ _AbstractChatCompletionRunner_instances = new WeakSet(), _AbstractChatCompletion
|
|
|
2416
2451
|
for (let i = this.messages.length - 1; i >= 0; i--) {
|
|
2417
2452
|
const message = this.messages[i];
|
|
2418
2453
|
if (isAssistantMessage(message) && message?.tool_calls?.length) {
|
|
2419
|
-
return message.tool_calls.at(-1)?.function;
|
|
2454
|
+
return message.tool_calls.filter((x) => x.type === 'function').at(-1)?.function;
|
|
2420
2455
|
}
|
|
2421
2456
|
}
|
|
2422
2457
|
return;
|
|
@@ -2894,7 +2929,7 @@ class ChatCompletionStream extends AbstractChatCompletionRunner {
|
|
|
2894
2929
|
throw new Error('tool call snapshot missing `type`');
|
|
2895
2930
|
}
|
|
2896
2931
|
if (toolCallSnapshot.type === 'function') {
|
|
2897
|
-
const inputTool = __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.tools?.find((tool) => tool
|
|
2932
|
+
const inputTool = __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.tools?.find((tool) => isChatCompletionFunctionTool(tool) && tool.function.name === toolCallSnapshot.function.name); // TS doesn't narrow based on isChatCompletionTool
|
|
2898
2933
|
this._emit('tool_calls.function.arguments.done', {
|
|
2899
2934
|
name: toolCallSnapshot.function.name,
|
|
2900
2935
|
index: toolCallIndex,
|
|
@@ -6704,7 +6739,7 @@ OpenAI.Evals = Evals;
|
|
|
6704
6739
|
OpenAI.Containers = Containers;
|
|
6705
6740
|
|
|
6706
6741
|
// llm-openai-config.ts
|
|
6707
|
-
const DEFAULT_MODEL
|
|
6742
|
+
const DEFAULT_MODEL = 'gpt-4.1-mini';
|
|
6708
6743
|
/** Token costs in USD per 1M tokens. Last updated Feb 2025. */
|
|
6709
6744
|
const openAiModelCosts = {
|
|
6710
6745
|
'gpt-4o': {
|
|
@@ -6743,6 +6778,18 @@ const openAiModelCosts = {
|
|
|
6743
6778
|
inputCost: 0.1 / 1_000_000,
|
|
6744
6779
|
outputCost: 0.4 / 1_000_000,
|
|
6745
6780
|
},
|
|
6781
|
+
'gpt-5': {
|
|
6782
|
+
inputCost: 1.25 / 1_000_000,
|
|
6783
|
+
outputCost: 10 / 1_000_000,
|
|
6784
|
+
},
|
|
6785
|
+
'gpt-5-mini': {
|
|
6786
|
+
inputCost: 0.25 / 1_000_000,
|
|
6787
|
+
outputCost: 2 / 1_000_000,
|
|
6788
|
+
},
|
|
6789
|
+
'gpt-5-nano': {
|
|
6790
|
+
inputCost: 0.05 / 1_000_000,
|
|
6791
|
+
outputCost: 0.4 / 1_000_000,
|
|
6792
|
+
},
|
|
6746
6793
|
'o4-mini': {
|
|
6747
6794
|
inputCost: 1.1 / 1_000_000,
|
|
6748
6795
|
outputCost: 4.4 / 1_000_000,
|
|
@@ -6810,7 +6857,6 @@ function calculateCost(provider, model, inputTokens, outputTokens, reasoningToke
|
|
|
6810
6857
|
return inputCost + outputCost + reasoningCost;
|
|
6811
6858
|
}
|
|
6812
6859
|
|
|
6813
|
-
const DEFAULT_MODEL = 'gpt-4.1-mini';
|
|
6814
6860
|
/**
|
|
6815
6861
|
* Fix a broken JSON string by attempting to extract and parse valid JSON content. This function is very lenient and will attempt to fix many types of JSON errors, including unbalanced brackets, missing or extra commas, improperly escaped $ signs, unquoted strings, trailing commas, missing closing brackets or braces, etc.
|
|
6816
6862
|
* @param {string} jsonStr - The broken JSON string to fix
|
|
@@ -7016,7 +7062,8 @@ function fixBrokenJson(jsonStr) {
|
|
|
7016
7062
|
return parse();
|
|
7017
7063
|
}
|
|
7018
7064
|
catch (error) {
|
|
7019
|
-
|
|
7065
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
7066
|
+
console.error(`Error parsing JSON at position ${index}: ${msg}`);
|
|
7020
7067
|
return null;
|
|
7021
7068
|
}
|
|
7022
7069
|
}
|
|
@@ -7055,9 +7102,7 @@ function initializeOpenAI(apiKey) {
|
|
|
7055
7102
|
});
|
|
7056
7103
|
}
|
|
7057
7104
|
/**
|
|
7058
|
-
* Fixes broken JSON by sending it to
|
|
7059
|
-
* The GPT-4.1-mini model is a large language model that can understand and generate code,
|
|
7060
|
-
* including JSON. The returned JSON is the fixed version of the input JSON.
|
|
7105
|
+
* Fixes broken JSON by sending it to OpenAI to fix it.
|
|
7061
7106
|
* If the model fails to return valid JSON, an error is thrown.
|
|
7062
7107
|
* @param jsonStr - the broken JSON to fix
|
|
7063
7108
|
* @param apiKey - the OpenAI API key to use, or undefined to use the value of the OPENAI_API_KEY environment variable
|
|
@@ -7201,8 +7246,11 @@ const isSupportedModel = (model) => {
|
|
|
7201
7246
|
'o3-mini',
|
|
7202
7247
|
'gpt-4.1',
|
|
7203
7248
|
'gpt-4.1-mini',
|
|
7204
|
-
'o4-mini',
|
|
7205
7249
|
'gpt-4.1-nano',
|
|
7250
|
+
'gpt-5',
|
|
7251
|
+
'gpt-5-mini',
|
|
7252
|
+
'gpt-5-nano',
|
|
7253
|
+
'o4-mini',
|
|
7206
7254
|
'o3',
|
|
7207
7255
|
].includes(model);
|
|
7208
7256
|
};
|
|
@@ -7213,8 +7261,9 @@ const isSupportedModel = (model) => {
|
|
|
7213
7261
|
*/
|
|
7214
7262
|
function supportsTemperature(model) {
|
|
7215
7263
|
// Reasoning models don't support temperature
|
|
7216
|
-
|
|
7217
|
-
|
|
7264
|
+
// GPT-5 models also do not support temperature
|
|
7265
|
+
const reasoningAndGPT5Models = ['o1', 'o1-mini', 'o3-mini', 'o4-mini', 'o3', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano'];
|
|
7266
|
+
return !reasoningAndGPT5Models.includes(model);
|
|
7218
7267
|
}
|
|
7219
7268
|
/**
|
|
7220
7269
|
* Checks if the given model is a reasoning model. Reasoning models have different tool choice constraints.
|
|
@@ -7225,6 +7274,15 @@ function isReasoningModel(model) {
|
|
|
7225
7274
|
const reasoningModels = ['o1', 'o1-mini', 'o3-mini', 'o4-mini', 'o3'];
|
|
7226
7275
|
return reasoningModels.includes(model);
|
|
7227
7276
|
}
|
|
7277
|
+
/**
|
|
7278
|
+
* Checks if the given model is a GPT-5 model. GPT-5 models don't support tool_choice other than 'auto'.
|
|
7279
|
+
* @param model The model to check.
|
|
7280
|
+
* @returns True if the model is a GPT-5 model, false otherwise.
|
|
7281
|
+
*/
|
|
7282
|
+
function isGPT5Model(model) {
|
|
7283
|
+
const gpt5Models = ['gpt-5', 'gpt-5-mini', 'gpt-5-nano'];
|
|
7284
|
+
return gpt5Models.includes(model);
|
|
7285
|
+
}
|
|
7228
7286
|
/**
|
|
7229
7287
|
* Makes a call to OpenAI's Responses API for more advanced use cases with built-in tools.
|
|
7230
7288
|
*
|
|
@@ -7252,7 +7310,7 @@ function isReasoningModel(model) {
|
|
|
7252
7310
|
* @throws Error if the API call fails
|
|
7253
7311
|
*/
|
|
7254
7312
|
const makeResponsesAPICall = async (input, options = {}) => {
|
|
7255
|
-
const normalizedModel = normalizeModelName(options.model || DEFAULT_MODEL
|
|
7313
|
+
const normalizedModel = normalizeModelName(options.model || DEFAULT_MODEL);
|
|
7256
7314
|
const apiKey = options.apiKey || process.env.OPENAI_API_KEY;
|
|
7257
7315
|
if (!apiKey) {
|
|
7258
7316
|
throw new Error('OpenAI API key is not provided and OPENAI_API_KEY environment variable is not set');
|
|
@@ -7363,7 +7421,7 @@ const makeResponsesAPICall = async (input, options = {}) => {
|
|
|
7363
7421
|
* });
|
|
7364
7422
|
*/
|
|
7365
7423
|
async function makeLLMCall(input, options = {}) {
|
|
7366
|
-
const { apiKey, model = DEFAULT_MODEL
|
|
7424
|
+
const { apiKey, model = DEFAULT_MODEL, responseFormat = 'text', tools, useCodeInterpreter = false, useWebSearch = false, imageBase64, imageDetail = 'high', context, } = options;
|
|
7367
7425
|
// Validate model
|
|
7368
7426
|
const normalizedModel = normalizeModelName(model);
|
|
7369
7427
|
if (!isSupportedModel(normalizedModel)) {
|
|
@@ -7455,8 +7513,8 @@ async function makeLLMCall(input, options = {}) {
|
|
|
7455
7513
|
}
|
|
7456
7514
|
if (useWebSearch) {
|
|
7457
7515
|
responsesOptions.tools = [{ type: 'web_search_preview' }];
|
|
7458
|
-
// For reasoning models, we can't force tool choice - they only support 'auto'
|
|
7459
|
-
if (!isReasoningModel(normalizedModel)) {
|
|
7516
|
+
// For reasoning models and GPT-5 models, we can't force tool choice - they only support 'auto'
|
|
7517
|
+
if (!isReasoningModel(normalizedModel) && !isGPT5Model(normalizedModel)) {
|
|
7460
7518
|
responsesOptions.tool_choice = { type: 'web_search_preview' };
|
|
7461
7519
|
}
|
|
7462
7520
|
}
|
|
@@ -7549,7 +7607,13 @@ async function makeImagesCall(prompt, options = {}) {
|
|
|
7549
7607
|
const enhancedResponse = {
|
|
7550
7608
|
...response,
|
|
7551
7609
|
usage: {
|
|
7552
|
-
|
|
7610
|
+
// OpenAI Images response may not include usage details per image; preserve if present
|
|
7611
|
+
...(response.usage ?? {
|
|
7612
|
+
input_tokens: 0,
|
|
7613
|
+
input_tokens_details: { image_tokens: 0, text_tokens: 0 },
|
|
7614
|
+
output_tokens: 0,
|
|
7615
|
+
total_tokens: 0,
|
|
7616
|
+
}),
|
|
7553
7617
|
provider: 'openai',
|
|
7554
7618
|
model: 'gpt-image-1',
|
|
7555
7619
|
cost,
|
|
@@ -7558,7 +7622,8 @@ async function makeImagesCall(prompt, options = {}) {
|
|
|
7558
7622
|
return enhancedResponse;
|
|
7559
7623
|
}
|
|
7560
7624
|
catch (error) {
|
|
7561
|
-
|
|
7625
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
7626
|
+
throw new Error(`OpenAI Images API call failed: ${message}`);
|
|
7562
7627
|
}
|
|
7563
7628
|
}
|
|
7564
7629
|
|
|
@@ -7783,14 +7848,15 @@ const makeDeepseekCall = async (content, responseFormat = 'json', options = {})
|
|
|
7783
7848
|
const completion = await createDeepseekCompletion(content, responseFormat, mergedOptions);
|
|
7784
7849
|
// Handle tool calls similarly to OpenAI
|
|
7785
7850
|
if (completion.tool_calls && completion.tool_calls.length > 0) {
|
|
7851
|
+
const fnCalls = completion.tool_calls
|
|
7852
|
+
.filter((tc) => tc.type === 'function')
|
|
7853
|
+
.map((tc) => ({
|
|
7854
|
+
id: tc.id,
|
|
7855
|
+
name: tc.function.name,
|
|
7856
|
+
arguments: JSON.parse(tc.function.arguments),
|
|
7857
|
+
}));
|
|
7786
7858
|
return {
|
|
7787
|
-
response: {
|
|
7788
|
-
tool_calls: completion.tool_calls.map((tc) => ({
|
|
7789
|
-
id: tc.id,
|
|
7790
|
-
name: tc.function.name,
|
|
7791
|
-
arguments: JSON.parse(tc.function.arguments),
|
|
7792
|
-
})),
|
|
7793
|
-
},
|
|
7859
|
+
response: { tool_calls: fnCalls },
|
|
7794
7860
|
usage: {
|
|
7795
7861
|
prompt_tokens: completion.usage.prompt_tokens,
|
|
7796
7862
|
completion_tokens: completion.usage.completion_tokens,
|
|
@@ -15947,5 +16013,5 @@ const disco = {
|
|
|
15947
16013
|
},
|
|
15948
16014
|
};
|
|
15949
16015
|
|
|
15950
|
-
export { AlpacaMarketDataAPI, AlpacaTradingAPI, disco };
|
|
16016
|
+
export { AlpacaMarketDataAPI, AlpacaTradingAPI, disco, isOpenRouterModel };
|
|
15951
16017
|
//# sourceMappingURL=index-frontend.mjs.map
|