@guidekit/core 0.1.0-beta.2 → 0.1.0-beta.3
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/README.md +1 -1
- package/dist/index.cjs +10 -426
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -126
- package/dist/index.d.ts +2 -126
- package/dist/index.js +11 -426
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1092,7 +1092,7 @@ var DOMScanner = class {
|
|
|
1092
1092
|
const style = window.getComputedStyle(el);
|
|
1093
1093
|
const position = style.position;
|
|
1094
1094
|
const zIndex = parseInt(style.zIndex, 10) || 0;
|
|
1095
|
-
if ((position === "fixed" || position === "absolute") && !isNaN(zIndex) && zIndex >= 1e3) {
|
|
1095
|
+
if ((position === "fixed" || position === "absolute") && !Number.isNaN(zIndex) && zIndex >= 1e3) {
|
|
1096
1096
|
const visible = isElementVisible(el);
|
|
1097
1097
|
if (!visible) return;
|
|
1098
1098
|
const overlayType = this.classifyOverlay(el, style);
|
|
@@ -1120,10 +1120,10 @@ var DOMScanner = class {
|
|
|
1120
1120
|
return "dropdown";
|
|
1121
1121
|
const width = parseFloat(style.width);
|
|
1122
1122
|
const height = parseFloat(style.height);
|
|
1123
|
-
if (typeof window !== "undefined" && !isNaN(width) && !isNaN(height) && width > window.innerWidth * 0.5 && height > window.innerHeight * 0.5) {
|
|
1123
|
+
if (typeof window !== "undefined" && !Number.isNaN(width) && !Number.isNaN(height) && width > window.innerWidth * 0.5 && height > window.innerHeight * 0.5) {
|
|
1124
1124
|
return "modal";
|
|
1125
1125
|
}
|
|
1126
|
-
if (!isNaN(width) && width < 400) return "popover";
|
|
1126
|
+
if (!Number.isNaN(width) && width < 400) return "popover";
|
|
1127
1127
|
return null;
|
|
1128
1128
|
}
|
|
1129
1129
|
// -------------------------------------------------------------------------
|
|
@@ -1839,424 +1839,9 @@ function isGuideKitError(error) {
|
|
|
1839
1839
|
return error instanceof GuideKitError;
|
|
1840
1840
|
}
|
|
1841
1841
|
|
|
1842
|
-
// src/llm/openai-adapter.ts
|
|
1843
|
-
var DEFAULT_OPENAI_MODEL = "gpt-4o";
|
|
1844
|
-
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
1845
|
-
var OPENAI_CHAT_URL = "https://api.openai.com/v1/chat/completions";
|
|
1846
|
-
function emptyUsage() {
|
|
1847
|
-
return { prompt: 0, completion: 0, total: 0 };
|
|
1848
|
-
}
|
|
1849
|
-
var OpenAIAdapter = class {
|
|
1850
|
-
apiKey;
|
|
1851
|
-
model;
|
|
1852
|
-
/** Tracks whether the last extractChunks call emitted a done chunk. */
|
|
1853
|
-
lastExtractEmittedDone = false;
|
|
1854
|
-
/**
|
|
1855
|
-
* Token usage extracted from the most recent `parseResponse` call.
|
|
1856
|
-
* Updated as each SSE chunk is parsed.
|
|
1857
|
-
*/
|
|
1858
|
-
_lastUsage = emptyUsage();
|
|
1859
|
-
constructor(config) {
|
|
1860
|
-
this.apiKey = config.apiKey;
|
|
1861
|
-
this.model = config.model ?? DEFAULT_OPENAI_MODEL;
|
|
1862
|
-
}
|
|
1863
|
-
/** Token usage from the most recent parseResponse call. */
|
|
1864
|
-
get lastUsage() {
|
|
1865
|
-
return this._lastUsage;
|
|
1866
|
-
}
|
|
1867
|
-
// -----------------------------------------------------------------------
|
|
1868
|
-
// LLMProviderAdapter implementation
|
|
1869
|
-
// -----------------------------------------------------------------------
|
|
1870
|
-
/**
|
|
1871
|
-
* Convert GuideKit tool definitions into OpenAI's `tools` format.
|
|
1872
|
-
* Each tool is wrapped as `{ type: 'function', function: { name, description, parameters } }`.
|
|
1873
|
-
*/
|
|
1874
|
-
formatTools(tools) {
|
|
1875
|
-
if (tools.length === 0) return void 0;
|
|
1876
|
-
return tools.map((tool) => ({
|
|
1877
|
-
type: "function",
|
|
1878
|
-
function: {
|
|
1879
|
-
name: tool.name,
|
|
1880
|
-
description: tool.description,
|
|
1881
|
-
parameters: {
|
|
1882
|
-
type: "object",
|
|
1883
|
-
properties: { ...tool.parameters },
|
|
1884
|
-
required: tool.required ?? []
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
}));
|
|
1888
|
-
}
|
|
1889
|
-
/**
|
|
1890
|
-
* Convert an array of `ConversationTurn` objects into OpenAI's messages
|
|
1891
|
-
* format with `role: 'user' | 'assistant'`.
|
|
1892
|
-
*/
|
|
1893
|
-
formatConversation(history) {
|
|
1894
|
-
return history.map((turn) => ({
|
|
1895
|
-
role: turn.role,
|
|
1896
|
-
content: turn.content
|
|
1897
|
-
}));
|
|
1898
|
-
}
|
|
1899
|
-
/**
|
|
1900
|
-
* Parse an OpenAI SSE streaming response into an async iterable of
|
|
1901
|
-
* `TextChunk` and `ToolCall` objects.
|
|
1902
|
-
*
|
|
1903
|
-
* The OpenAI streaming endpoint sends each chunk as a JSON object
|
|
1904
|
-
* prefixed by `data: `. The final line is `data: [DONE]`.
|
|
1905
|
-
* Text content arrives in `choices[0].delta.content` and tool calls
|
|
1906
|
-
* arrive in `choices[0].delta.tool_calls`.
|
|
1907
|
-
*
|
|
1908
|
-
* This method also:
|
|
1909
|
-
* - Detects content filtering and throws `ContentFilterError`.
|
|
1910
|
-
* - Tracks token usage (accessible via `lastUsage` after iteration).
|
|
1911
|
-
*/
|
|
1912
|
-
async *parseResponse(stream) {
|
|
1913
|
-
const reader = stream.getReader();
|
|
1914
|
-
const decoder = new TextDecoder();
|
|
1915
|
-
let buffer = "";
|
|
1916
|
-
let doneEmitted = false;
|
|
1917
|
-
this._lastUsage = emptyUsage();
|
|
1918
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
1919
|
-
try {
|
|
1920
|
-
while (true) {
|
|
1921
|
-
const { done, value } = await reader.read();
|
|
1922
|
-
if (done) break;
|
|
1923
|
-
buffer += decoder.decode(value, { stream: true });
|
|
1924
|
-
const lines = buffer.split("\n");
|
|
1925
|
-
buffer = lines.pop() ?? "";
|
|
1926
|
-
for (const line of lines) {
|
|
1927
|
-
const trimmed = line.trim();
|
|
1928
|
-
if (!trimmed.startsWith("data:")) continue;
|
|
1929
|
-
const jsonStr = trimmed.slice(5).trim();
|
|
1930
|
-
if (jsonStr === "" || jsonStr === "[DONE]") {
|
|
1931
|
-
if (jsonStr === "[DONE]") {
|
|
1932
|
-
yield* this.flushPendingToolCalls(pendingToolCalls);
|
|
1933
|
-
if (!doneEmitted) {
|
|
1934
|
-
doneEmitted = true;
|
|
1935
|
-
yield { text: "", done: true };
|
|
1936
|
-
}
|
|
1937
|
-
}
|
|
1938
|
-
continue;
|
|
1939
|
-
}
|
|
1940
|
-
let parsed;
|
|
1941
|
-
try {
|
|
1942
|
-
parsed = JSON.parse(jsonStr);
|
|
1943
|
-
} catch {
|
|
1944
|
-
continue;
|
|
1945
|
-
}
|
|
1946
|
-
if (this.isContentFiltered(parsed)) {
|
|
1947
|
-
throw new ContentFilterError({
|
|
1948
|
-
code: ErrorCodes.CONTENT_FILTER_TRIGGERED,
|
|
1949
|
-
message: "Response was blocked by provider content safety filter.",
|
|
1950
|
-
provider: "openai",
|
|
1951
|
-
suggestion: "Rephrase your question or adjust safety settings."
|
|
1952
|
-
});
|
|
1953
|
-
}
|
|
1954
|
-
const chunkUsage = this.extractUsage(parsed);
|
|
1955
|
-
if (chunkUsage) {
|
|
1956
|
-
this._lastUsage = chunkUsage;
|
|
1957
|
-
}
|
|
1958
|
-
yield* this.extractChunks(parsed, pendingToolCalls, doneEmitted);
|
|
1959
|
-
if (!doneEmitted && this.lastExtractEmittedDone) {
|
|
1960
|
-
doneEmitted = true;
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
if (buffer.trim().startsWith("data:")) {
|
|
1965
|
-
const jsonStr = buffer.trim().slice(5).trim();
|
|
1966
|
-
if (jsonStr === "[DONE]") {
|
|
1967
|
-
yield* this.flushPendingToolCalls(pendingToolCalls);
|
|
1968
|
-
if (!doneEmitted) {
|
|
1969
|
-
doneEmitted = true;
|
|
1970
|
-
yield { text: "", done: true };
|
|
1971
|
-
}
|
|
1972
|
-
} else if (jsonStr !== "") {
|
|
1973
|
-
try {
|
|
1974
|
-
const parsed = JSON.parse(jsonStr);
|
|
1975
|
-
if (this.isContentFiltered(parsed)) {
|
|
1976
|
-
throw new ContentFilterError({
|
|
1977
|
-
code: ErrorCodes.CONTENT_FILTER_TRIGGERED,
|
|
1978
|
-
message: "Response was blocked by provider content safety filter.",
|
|
1979
|
-
provider: "openai",
|
|
1980
|
-
suggestion: "Rephrase your question or adjust safety settings."
|
|
1981
|
-
});
|
|
1982
|
-
}
|
|
1983
|
-
const chunkUsage = this.extractUsage(parsed);
|
|
1984
|
-
if (chunkUsage) {
|
|
1985
|
-
this._lastUsage = chunkUsage;
|
|
1986
|
-
}
|
|
1987
|
-
yield* this.extractChunks(parsed, pendingToolCalls, doneEmitted);
|
|
1988
|
-
if (!doneEmitted && this.lastExtractEmittedDone) {
|
|
1989
|
-
doneEmitted = true;
|
|
1990
|
-
}
|
|
1991
|
-
} catch (error) {
|
|
1992
|
-
if (error instanceof ContentFilterError) throw error;
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
yield* this.flushPendingToolCalls(pendingToolCalls);
|
|
1997
|
-
} finally {
|
|
1998
|
-
reader.releaseLock();
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
/**
|
|
2002
|
-
* Format a tool result so it can be sent back to OpenAI as a
|
|
2003
|
-
* `tool` role message with the `tool_call_id`.
|
|
2004
|
-
*/
|
|
2005
|
-
formatToolResult(callId, result) {
|
|
2006
|
-
return {
|
|
2007
|
-
role: "tool",
|
|
2008
|
-
tool_call_id: callId,
|
|
2009
|
-
content: typeof result === "string" ? result : JSON.stringify(result)
|
|
2010
|
-
};
|
|
2011
|
-
}
|
|
2012
|
-
// -----------------------------------------------------------------------
|
|
2013
|
-
// Streaming request
|
|
2014
|
-
// -----------------------------------------------------------------------
|
|
2015
|
-
/**
|
|
2016
|
-
* Build and execute a streaming request to the OpenAI Chat Completions API.
|
|
2017
|
-
* Returns the raw `ReadableStream` for the response body together with
|
|
2018
|
-
* the raw Response object.
|
|
2019
|
-
*/
|
|
2020
|
-
async streamRequest(params) {
|
|
2021
|
-
const contentsArray = params.contents;
|
|
2022
|
-
const messages = [
|
|
2023
|
-
{ role: "system", content: params.systemPrompt },
|
|
2024
|
-
...contentsArray
|
|
2025
|
-
];
|
|
2026
|
-
if (params.userMessage) {
|
|
2027
|
-
messages.push({ role: "user", content: params.userMessage });
|
|
2028
|
-
}
|
|
2029
|
-
const body = {
|
|
2030
|
-
model: this.model,
|
|
2031
|
-
messages,
|
|
2032
|
-
stream: true,
|
|
2033
|
-
temperature: 0.7,
|
|
2034
|
-
top_p: 0.95
|
|
2035
|
-
};
|
|
2036
|
-
if (params.tools) {
|
|
2037
|
-
body.tools = params.tools;
|
|
2038
|
-
}
|
|
2039
|
-
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2040
|
-
const controller = new AbortController();
|
|
2041
|
-
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
2042
|
-
if (params.signal) {
|
|
2043
|
-
params.signal.addEventListener(
|
|
2044
|
-
"abort",
|
|
2045
|
-
() => controller.abort(params.signal.reason),
|
|
2046
|
-
{ once: true }
|
|
2047
|
-
);
|
|
2048
|
-
}
|
|
2049
|
-
let response;
|
|
2050
|
-
try {
|
|
2051
|
-
response = await fetch(OPENAI_CHAT_URL, {
|
|
2052
|
-
method: "POST",
|
|
2053
|
-
headers: {
|
|
2054
|
-
"Content-Type": "application/json",
|
|
2055
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
2056
|
-
},
|
|
2057
|
-
body: JSON.stringify(body),
|
|
2058
|
-
signal: controller.signal
|
|
2059
|
-
});
|
|
2060
|
-
} catch (error) {
|
|
2061
|
-
clearTimeout(timeoutId);
|
|
2062
|
-
if (error instanceof DOMException && error.name === "AbortError") {
|
|
2063
|
-
if (params.signal?.aborted) {
|
|
2064
|
-
throw error;
|
|
2065
|
-
}
|
|
2066
|
-
throw new TimeoutError({
|
|
2067
|
-
code: ErrorCodes.TIMEOUT_LLM_RESPONSE,
|
|
2068
|
-
message: `OpenAI request timed out after ${timeoutMs}ms`,
|
|
2069
|
-
provider: "openai",
|
|
2070
|
-
recoverable: true,
|
|
2071
|
-
suggestion: "Try again or increase the timeout.",
|
|
2072
|
-
operationName: "openai.chatCompletions",
|
|
2073
|
-
timeoutMs
|
|
2074
|
-
});
|
|
2075
|
-
}
|
|
2076
|
-
throw new NetworkError({
|
|
2077
|
-
code: ErrorCodes.NETWORK_CONNECTION_LOST,
|
|
2078
|
-
message: `Failed to connect to OpenAI API: ${error.message}`,
|
|
2079
|
-
provider: "openai",
|
|
2080
|
-
suggestion: "Check your network connection and try again.",
|
|
2081
|
-
cause: error instanceof Error ? error : void 0
|
|
2082
|
-
});
|
|
2083
|
-
}
|
|
2084
|
-
clearTimeout(timeoutId);
|
|
2085
|
-
if (!response.ok) {
|
|
2086
|
-
await this.handleHttpError(response);
|
|
2087
|
-
}
|
|
2088
|
-
if (!response.body) {
|
|
2089
|
-
throw new NetworkError({
|
|
2090
|
-
code: ErrorCodes.NETWORK_CONNECTION_LOST,
|
|
2091
|
-
message: "OpenAI response body is null -- streaming unavailable.",
|
|
2092
|
-
provider: "openai",
|
|
2093
|
-
suggestion: "Retry the request."
|
|
2094
|
-
});
|
|
2095
|
-
}
|
|
2096
|
-
return { stream: response.body, response };
|
|
2097
|
-
}
|
|
2098
|
-
// -----------------------------------------------------------------------
|
|
2099
|
-
// Internal helpers
|
|
2100
|
-
// -----------------------------------------------------------------------
|
|
2101
|
-
/**
|
|
2102
|
-
* Extract `TextChunk` and accumulate `ToolCall` data from a single parsed
|
|
2103
|
-
* OpenAI SSE JSON object.
|
|
2104
|
-
*
|
|
2105
|
-
* OpenAI tool calls arrive incrementally: the first chunk for a tool call
|
|
2106
|
-
* carries the `id` and `function.name`, while subsequent chunks append to
|
|
2107
|
-
* `function.arguments`. We accumulate these in `pendingToolCalls` and only
|
|
2108
|
-
* yield complete `ToolCall` objects when the finish_reason is 'tool_calls'
|
|
2109
|
-
* or when flushed.
|
|
2110
|
-
*/
|
|
2111
|
-
*extractChunks(parsed, pendingToolCalls, doneEmitted) {
|
|
2112
|
-
this.lastExtractEmittedDone = false;
|
|
2113
|
-
const choices = parsed.choices;
|
|
2114
|
-
if (!choices || choices.length === 0) return;
|
|
2115
|
-
for (const choice of choices) {
|
|
2116
|
-
const delta = choice.delta;
|
|
2117
|
-
const finishReason = choice.finish_reason;
|
|
2118
|
-
if (delta) {
|
|
2119
|
-
if (typeof delta.content === "string" && delta.content !== "") {
|
|
2120
|
-
yield {
|
|
2121
|
-
text: delta.content,
|
|
2122
|
-
done: false
|
|
2123
|
-
};
|
|
2124
|
-
}
|
|
2125
|
-
const toolCallDeltas = delta.tool_calls;
|
|
2126
|
-
if (toolCallDeltas) {
|
|
2127
|
-
for (const tc of toolCallDeltas) {
|
|
2128
|
-
const existing = pendingToolCalls.get(tc.index);
|
|
2129
|
-
if (existing) {
|
|
2130
|
-
if (tc.function?.arguments) {
|
|
2131
|
-
existing.argumentsJson += tc.function.arguments;
|
|
2132
|
-
}
|
|
2133
|
-
} else {
|
|
2134
|
-
pendingToolCalls.set(tc.index, {
|
|
2135
|
-
id: tc.id ?? "",
|
|
2136
|
-
name: tc.function?.name ?? "",
|
|
2137
|
-
argumentsJson: tc.function?.arguments ?? ""
|
|
2138
|
-
});
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
if (finishReason === "tool_calls") {
|
|
2144
|
-
yield* this.flushPendingToolCalls(pendingToolCalls);
|
|
2145
|
-
}
|
|
2146
|
-
if (finishReason === "stop" && !doneEmitted && !this.lastExtractEmittedDone) {
|
|
2147
|
-
this.lastExtractEmittedDone = true;
|
|
2148
|
-
yield { text: "", done: true };
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
}
|
|
2152
|
-
/**
|
|
2153
|
-
* Flush all accumulated pending tool calls as complete `ToolCall` objects.
|
|
2154
|
-
*/
|
|
2155
|
-
*flushPendingToolCalls(pendingToolCalls) {
|
|
2156
|
-
const sorted = [...pendingToolCalls.entries()].sort(
|
|
2157
|
-
([a], [b]) => a - b
|
|
2158
|
-
);
|
|
2159
|
-
for (const [, tc] of sorted) {
|
|
2160
|
-
let args = {};
|
|
2161
|
-
try {
|
|
2162
|
-
args = JSON.parse(tc.argumentsJson);
|
|
2163
|
-
} catch (_e) {
|
|
2164
|
-
console.warn("[GuideKit:LLM] Failed to parse tool call arguments:", tc.argumentsJson);
|
|
2165
|
-
}
|
|
2166
|
-
yield {
|
|
2167
|
-
id: tc.id,
|
|
2168
|
-
name: tc.name,
|
|
2169
|
-
arguments: args
|
|
2170
|
-
};
|
|
2171
|
-
}
|
|
2172
|
-
pendingToolCalls.clear();
|
|
2173
|
-
}
|
|
2174
|
-
/**
|
|
2175
|
-
* Extract token usage from a parsed OpenAI response chunk.
|
|
2176
|
-
* Usage data typically appears in the final chunk when `stream_options`
|
|
2177
|
-
* includes `include_usage`, or in the non-streaming response.
|
|
2178
|
-
* Returns `null` if no usage data is present.
|
|
2179
|
-
*/
|
|
2180
|
-
extractUsage(parsed) {
|
|
2181
|
-
const usage = parsed.usage;
|
|
2182
|
-
if (!usage) return null;
|
|
2183
|
-
return {
|
|
2184
|
-
prompt: usage.prompt_tokens ?? 0,
|
|
2185
|
-
completion: usage.completion_tokens ?? 0,
|
|
2186
|
-
total: usage.total_tokens ?? 0
|
|
2187
|
-
};
|
|
2188
|
-
}
|
|
2189
|
-
/**
|
|
2190
|
-
* Check whether a parsed OpenAI chunk indicates the response was
|
|
2191
|
-
* blocked by a content filter.
|
|
2192
|
-
*
|
|
2193
|
-
* OpenAI signals content filtering through:
|
|
2194
|
-
* - `choices[].finish_reason === 'content_filter'`
|
|
2195
|
-
* - `choices[].content_filter_results` with `filtered: true`
|
|
2196
|
-
*/
|
|
2197
|
-
isContentFiltered(parsed) {
|
|
2198
|
-
const choices = parsed.choices;
|
|
2199
|
-
if (!choices || choices.length === 0) return false;
|
|
2200
|
-
return choices.some((choice) => {
|
|
2201
|
-
if (choice.finish_reason === "content_filter") return true;
|
|
2202
|
-
const filterResults = choice.content_filter_results;
|
|
2203
|
-
if (filterResults) {
|
|
2204
|
-
return Object.values(filterResults).some((r) => r.filtered === true);
|
|
2205
|
-
}
|
|
2206
|
-
return false;
|
|
2207
|
-
});
|
|
2208
|
-
}
|
|
2209
|
-
/**
|
|
2210
|
-
* Translate an HTTP error response from OpenAI into the appropriate
|
|
2211
|
-
* GuideKit error class.
|
|
2212
|
-
*/
|
|
2213
|
-
async handleHttpError(response) {
|
|
2214
|
-
let errorBody = "";
|
|
2215
|
-
try {
|
|
2216
|
-
errorBody = await response.text();
|
|
2217
|
-
} catch {
|
|
2218
|
-
}
|
|
2219
|
-
const status = response.status;
|
|
2220
|
-
if (status === 401 || status === 403) {
|
|
2221
|
-
throw new AuthenticationError({
|
|
2222
|
-
code: ErrorCodes.AUTH_INVALID_KEY,
|
|
2223
|
-
message: `OpenAI API authentication failed (${status}): ${errorBody}`,
|
|
2224
|
-
provider: "openai",
|
|
2225
|
-
suggestion: "Verify your OpenAI API key is correct and has not expired."
|
|
2226
|
-
});
|
|
2227
|
-
}
|
|
2228
|
-
if (status === 429) {
|
|
2229
|
-
const retryAfterHeader = response.headers.get("retry-after");
|
|
2230
|
-
const retryAfterMs = retryAfterHeader ? parseInt(retryAfterHeader, 10) * 1e3 : 6e4;
|
|
2231
|
-
throw new RateLimitError({
|
|
2232
|
-
code: ErrorCodes.RATE_LIMIT_PROVIDER,
|
|
2233
|
-
message: `OpenAI API rate limit exceeded (429): ${errorBody}`,
|
|
2234
|
-
provider: "openai",
|
|
2235
|
-
recoverable: true,
|
|
2236
|
-
suggestion: `Rate limited by OpenAI. Retry after ${Math.ceil(retryAfterMs / 1e3)}s.`,
|
|
2237
|
-
retryAfterMs
|
|
2238
|
-
});
|
|
2239
|
-
}
|
|
2240
|
-
if (status >= 500) {
|
|
2241
|
-
throw new NetworkError({
|
|
2242
|
-
code: ErrorCodes.NETWORK_CONNECTION_LOST,
|
|
2243
|
-
message: `OpenAI API server error (${status}): ${errorBody}`,
|
|
2244
|
-
provider: "openai",
|
|
2245
|
-
suggestion: "The OpenAI API is experiencing issues. Please try again later."
|
|
2246
|
-
});
|
|
2247
|
-
}
|
|
2248
|
-
throw new NetworkError({
|
|
2249
|
-
code: ErrorCodes.NETWORK_CONNECTION_LOST,
|
|
2250
|
-
message: `OpenAI API request failed (${status}): ${errorBody}`,
|
|
2251
|
-
provider: "openai",
|
|
2252
|
-
suggestion: "Check the request parameters and try again."
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
};
|
|
2256
|
-
|
|
2257
1842
|
// src/llm/index.ts
|
|
2258
1843
|
var DEFAULT_GEMINI_MODEL = "gemini-2.5-flash";
|
|
2259
|
-
var
|
|
1844
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
2260
1845
|
var GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models";
|
|
2261
1846
|
var DEFAULT_SAFETY_SETTINGS = [
|
|
2262
1847
|
{ category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_ONLY_HIGH" },
|
|
@@ -2264,7 +1849,7 @@ var DEFAULT_SAFETY_SETTINGS = [
|
|
|
2264
1849
|
{ category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold: "BLOCK_ONLY_HIGH" },
|
|
2265
1850
|
{ category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_ONLY_HIGH" }
|
|
2266
1851
|
];
|
|
2267
|
-
function
|
|
1852
|
+
function emptyUsage() {
|
|
2268
1853
|
return { prompt: 0, completion: 0, total: 0 };
|
|
2269
1854
|
}
|
|
2270
1855
|
var GeminiAdapter = class {
|
|
@@ -2275,7 +1860,7 @@ var GeminiAdapter = class {
|
|
|
2275
1860
|
* Updated as each SSE chunk is parsed; the final value reflects the
|
|
2276
1861
|
* cumulative usage metadata sent by Gemini (typically in the last chunk).
|
|
2277
1862
|
*/
|
|
2278
|
-
_lastUsage =
|
|
1863
|
+
_lastUsage = emptyUsage();
|
|
2279
1864
|
constructor(config) {
|
|
2280
1865
|
this.apiKey = config.apiKey;
|
|
2281
1866
|
this.model = config.model ?? DEFAULT_GEMINI_MODEL;
|
|
@@ -2333,7 +1918,7 @@ var GeminiAdapter = class {
|
|
|
2333
1918
|
const reader = stream.getReader();
|
|
2334
1919
|
const decoder = new TextDecoder();
|
|
2335
1920
|
let buffer = "";
|
|
2336
|
-
this._lastUsage =
|
|
1921
|
+
this._lastUsage = emptyUsage();
|
|
2337
1922
|
try {
|
|
2338
1923
|
while (true) {
|
|
2339
1924
|
const { done, value } = await reader.read();
|
|
@@ -2442,7 +2027,7 @@ var GeminiAdapter = class {
|
|
|
2442
2027
|
if (params.tools) {
|
|
2443
2028
|
body.tools = params.tools;
|
|
2444
2029
|
}
|
|
2445
|
-
const timeoutMs = params.timeoutMs ??
|
|
2030
|
+
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2446
2031
|
const controller = new AbortController();
|
|
2447
2032
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
2448
2033
|
if (params.signal) {
|
|
@@ -2717,7 +2302,7 @@ var LLMOrchestrator = class {
|
|
|
2717
2302
|
}
|
|
2718
2303
|
}
|
|
2719
2304
|
this.callbacks.onChunk?.({ text: "", done: true });
|
|
2720
|
-
let usage =
|
|
2305
|
+
let usage = emptyUsage();
|
|
2721
2306
|
if ("lastUsage" in adapter) {
|
|
2722
2307
|
usage = adapter.lastUsage;
|
|
2723
2308
|
}
|
|
@@ -2737,7 +2322,7 @@ var LLMOrchestrator = class {
|
|
|
2737
2322
|
*
|
|
2738
2323
|
* Custom adapters:
|
|
2739
2324
|
* - Pass `{ adapter: myAdapter }` to use any `LLMProviderAdapter`.
|
|
2740
|
-
* Example: `llm: { adapter:
|
|
2325
|
+
* Example: `llm: { adapter: myCustomAdapter }`
|
|
2741
2326
|
*/
|
|
2742
2327
|
createAdapter(config) {
|
|
2743
2328
|
if ("adapter" in config) {
|
|
@@ -9617,6 +9202,6 @@ var GuideKitCore = class {
|
|
|
9617
9202
|
}
|
|
9618
9203
|
};
|
|
9619
9204
|
|
|
9620
|
-
export { AuthenticationError, AwarenessSystem, BrowserSupportError, ConfigurationError, ConnectionManager, ContentFilterError, ContextManager, DOMScanner, ErrorCodes, EventBus, GeminiAdapter, GuideKitCore, GuideKitError, I18n, InitializationError, LLMOrchestrator, NavigationController, NetworkError,
|
|
9205
|
+
export { AuthenticationError, AwarenessSystem, BrowserSupportError, ConfigurationError, ConnectionManager, ContentFilterError, ContextManager, DOMScanner, ErrorCodes, EventBus, GeminiAdapter, GuideKitCore, GuideKitError, I18n, InitializationError, LLMOrchestrator, NavigationController, NetworkError, PermissionError, ProactiveTriggerEngine, RateLimitError, RateLimiter, ResourceExhaustedError, ResourceManager, SingletonGuard, TimeoutError, TokenManager, ToolExecutor, VisualGuidance, VoicePipeline, WebSpeechSTT, WebSpeechTTS, createEventBus, isGuideKitError };
|
|
9621
9206
|
//# sourceMappingURL=index.js.map
|
|
9622
9207
|
//# sourceMappingURL=index.js.map
|