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