@umituz/web-ai 1.1.0 → 1.2.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/README.md +29 -3
- package/dist/{cancellation-error-_39nYWwz.d.cts → cancellation-error-BWb59Wkj.d.cts} +1 -1
- package/dist/{cancellation-error-hYcE9AS9.d.ts → cancellation-error-D9LETLCD.d.ts} +1 -1
- package/dist/chat/index.cjs +1 -0
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.js +1 -0
- package/dist/chat/index.js.map +1 -1
- package/dist/content/index.cjs +622 -8
- package/dist/content/index.cjs.map +1 -1
- package/dist/content/index.d.cts +2 -2
- package/dist/content/index.d.ts +2 -2
- package/dist/content/index.js +622 -8
- package/dist/content/index.js.map +1 -1
- package/dist/context-manager-CuZz0vnC.d.cts +104 -0
- package/dist/context-manager-CuZz0vnC.d.ts +104 -0
- package/dist/core/index.cjs +147 -10
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +91 -73
- package/dist/core/index.d.ts +91 -73
- package/dist/core/index.js +141 -11
- package/dist/core/index.js.map +1 -1
- package/dist/{create-ai-D-oEWzf9.d.ts → create-ai-Cq3HkJxd.d.ts} +61 -1
- package/dist/{create-ai-DRysRImc.d.cts → create-ai-DDyTVzef.d.cts} +61 -1
- package/dist/hooks/index.cjs +747 -15
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +57 -4
- package/dist/hooks/index.d.ts +57 -4
- package/dist/hooks/index.js +746 -16
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +1180 -242
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +1140 -243
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs +1212 -362
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.d.cts +422 -10
- package/dist/providers/index.d.ts +422 -10
- package/dist/providers/index.js +1179 -363
- package/dist/providers/index.js.map +1 -1
- package/dist/remote-chat-client-LrNlew4n.d.cts +70 -0
- package/dist/remote-chat-client-LrNlew4n.d.ts +70 -0
- package/dist/{requestQueue-D89wx91Q.d.cts → requestQueue--h2uZ-Q3.d.cts} +1 -1
- package/dist/{requestQueue-AP6n_bRH.d.ts → requestQueue-BGeCy4Fd.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/tool-call-accumulator-C7KhaXZA.d.cts +0 -69
- package/dist/tool-call-accumulator-C7KhaXZA.d.ts +0 -69
package/dist/index.cjs
CHANGED
|
@@ -305,6 +305,23 @@ function errorFromUnknown(err) {
|
|
|
305
305
|
return new AiError("upstream_error");
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
+
// src/core/errors/error-status.ts
|
|
309
|
+
var AI_ERROR_STATUS = {
|
|
310
|
+
invalid_key: 502,
|
|
311
|
+
missing_key: 503,
|
|
312
|
+
rate_limited: 429,
|
|
313
|
+
capacity: 503,
|
|
314
|
+
timeout: 504,
|
|
315
|
+
invalid_request: 400,
|
|
316
|
+
model_unavailable: 503,
|
|
317
|
+
upstream_error: 502,
|
|
318
|
+
network: 502,
|
|
319
|
+
cancelled: 400
|
|
320
|
+
};
|
|
321
|
+
function aiErrorStatus(code) {
|
|
322
|
+
return AI_ERROR_STATUS[code];
|
|
323
|
+
}
|
|
324
|
+
|
|
308
325
|
// src/core/executor/retry-executor.strategy.ts
|
|
309
326
|
var RetryExecutor = class {
|
|
310
327
|
constructor(retryManager2, options) {
|
|
@@ -1428,13 +1445,14 @@ function buildContext(history, systemPrompt, budget) {
|
|
|
1428
1445
|
const selected = [];
|
|
1429
1446
|
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
1430
1447
|
const message = history[i];
|
|
1448
|
+
if (!message) continue;
|
|
1431
1449
|
const cost = estimateMessageTokens(message);
|
|
1432
1450
|
if (used + cost > available && selected.length > 0) break;
|
|
1433
1451
|
used += cost;
|
|
1434
1452
|
selected.push(message);
|
|
1435
1453
|
}
|
|
1436
1454
|
selected.reverse();
|
|
1437
|
-
while (selected.length > 1 && (selected[0]
|
|
1455
|
+
while (selected.length > 1 && (selected[0]?.role === "assistant" || selected[0]?.role === "tool")) {
|
|
1438
1456
|
selected.shift();
|
|
1439
1457
|
}
|
|
1440
1458
|
return [{ role: "system", content: systemPrompt }, ...selected];
|
|
@@ -1637,7 +1655,10 @@ function diffLines(before, after) {
|
|
|
1637
1655
|
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
1638
1656
|
for (let i2 = m - 1; i2 >= 0; i2 -= 1) {
|
|
1639
1657
|
for (let j2 = n - 1; j2 >= 0; j2 -= 1) {
|
|
1640
|
-
|
|
1658
|
+
const row = dp[i2];
|
|
1659
|
+
if (row) {
|
|
1660
|
+
row[j2] = a[i2] === b[j2] ? (dp[i2 + 1]?.[j2 + 1] ?? 0) + 1 : Math.max(dp[i2 + 1]?.[j2] ?? 0, row[j2 + 1] ?? 0);
|
|
1661
|
+
}
|
|
1641
1662
|
}
|
|
1642
1663
|
}
|
|
1643
1664
|
const out = [];
|
|
@@ -1645,23 +1666,23 @@ function diffLines(before, after) {
|
|
|
1645
1666
|
let j = 0;
|
|
1646
1667
|
while (i < m && j < n) {
|
|
1647
1668
|
if (a[i] === b[j]) {
|
|
1648
|
-
out.push({ type: "same", text: a[i] });
|
|
1669
|
+
out.push({ type: "same", text: a[i] ?? "" });
|
|
1649
1670
|
i += 1;
|
|
1650
1671
|
j += 1;
|
|
1651
|
-
} else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
1652
|
-
out.push({ type: "remove", text: a[i] });
|
|
1672
|
+
} else if ((dp[i + 1]?.[j] ?? 0) >= (dp[i]?.[j + 1] ?? 0)) {
|
|
1673
|
+
out.push({ type: "remove", text: a[i] ?? "" });
|
|
1653
1674
|
i += 1;
|
|
1654
1675
|
} else {
|
|
1655
|
-
out.push({ type: "add", text: b[j] });
|
|
1676
|
+
out.push({ type: "add", text: b[j] ?? "" });
|
|
1656
1677
|
j += 1;
|
|
1657
1678
|
}
|
|
1658
1679
|
}
|
|
1659
1680
|
while (i < m) {
|
|
1660
|
-
out.push({ type: "remove", text: a[i] });
|
|
1681
|
+
out.push({ type: "remove", text: a[i] ?? "" });
|
|
1661
1682
|
i += 1;
|
|
1662
1683
|
}
|
|
1663
1684
|
while (j < n) {
|
|
1664
|
-
out.push({ type: "add", text: b[j] });
|
|
1685
|
+
out.push({ type: "add", text: b[j] ?? "" });
|
|
1665
1686
|
j += 1;
|
|
1666
1687
|
}
|
|
1667
1688
|
return out;
|
|
@@ -1776,14 +1797,14 @@ function dotProduct(a, b) {
|
|
|
1776
1797
|
const length = Math.min(a.length, b.length);
|
|
1777
1798
|
let sum = 0;
|
|
1778
1799
|
for (let i = 0; i < length; i += 1) {
|
|
1779
|
-
sum += a[i] * b[i];
|
|
1800
|
+
sum += (a[i] ?? 0) * (b[i] ?? 0);
|
|
1780
1801
|
}
|
|
1781
1802
|
return sum;
|
|
1782
1803
|
}
|
|
1783
1804
|
function magnitude(v) {
|
|
1784
1805
|
let sum = 0;
|
|
1785
1806
|
for (let i = 0; i < v.length; i += 1) {
|
|
1786
|
-
sum += v[i] * v[i];
|
|
1807
|
+
sum += (v[i] ?? 0) * (v[i] ?? 0);
|
|
1787
1808
|
}
|
|
1788
1809
|
return Math.sqrt(sum);
|
|
1789
1810
|
}
|
|
@@ -1928,6 +1949,115 @@ function validateToolArgs(toolKey, args, schemas) {
|
|
|
1928
1949
|
return { ok: false, error: `Invalid schema definition for tool: ${toolKey}` };
|
|
1929
1950
|
}
|
|
1930
1951
|
|
|
1952
|
+
// src/core/analytics/usage-series.ts
|
|
1953
|
+
function num(value) {
|
|
1954
|
+
const parsed = typeof value === "number" ? value : Number(value ?? 0);
|
|
1955
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
1956
|
+
}
|
|
1957
|
+
function utcDateKey(base, offsetDays) {
|
|
1958
|
+
const shifted = new Date(base.getTime() - offsetDays * 864e5);
|
|
1959
|
+
return shifted.toISOString().slice(0, 10);
|
|
1960
|
+
}
|
|
1961
|
+
function buildUsageDailySeries(days, usageRows, messageRows, today = /* @__PURE__ */ new Date()) {
|
|
1962
|
+
const usageByDate = new Map(usageRows.map((row) => [row.date, row]));
|
|
1963
|
+
const messageByDate = new Map(messageRows.map((row) => [row.date, row]));
|
|
1964
|
+
const series = [];
|
|
1965
|
+
for (let offset = days - 1; offset >= 0; offset -= 1) {
|
|
1966
|
+
const date = utcDateKey(today, offset);
|
|
1967
|
+
const usage = usageByDate.get(date);
|
|
1968
|
+
const message = messageByDate.get(date);
|
|
1969
|
+
series.push({
|
|
1970
|
+
date,
|
|
1971
|
+
requests: num(usage?.requests),
|
|
1972
|
+
attempts: num(message?.attempts),
|
|
1973
|
+
errors: num(message?.errors),
|
|
1974
|
+
inputTokens: num(usage?.inputTokens),
|
|
1975
|
+
outputTokens: num(usage?.outputTokens),
|
|
1976
|
+
reasoningTokens: num(usage?.reasoningTokens),
|
|
1977
|
+
costMicros: num(usage?.costMicros)
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
return series;
|
|
1981
|
+
}
|
|
1982
|
+
function usageWindowTotals(series, from, to) {
|
|
1983
|
+
const slice = series.slice(from, to);
|
|
1984
|
+
return slice.reduce(
|
|
1985
|
+
(acc, day) => ({
|
|
1986
|
+
requests: acc.requests + day.requests,
|
|
1987
|
+
attempts: acc.attempts + day.attempts,
|
|
1988
|
+
errors: acc.errors + day.errors,
|
|
1989
|
+
inputTokens: acc.inputTokens + day.inputTokens,
|
|
1990
|
+
outputTokens: acc.outputTokens + day.outputTokens,
|
|
1991
|
+
costMicros: acc.costMicros + day.costMicros
|
|
1992
|
+
}),
|
|
1993
|
+
{ requests: 0, attempts: 0, errors: 0, inputTokens: 0, outputTokens: 0, costMicros: 0 }
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
function usageTrendOf(current, previous) {
|
|
1997
|
+
return {
|
|
1998
|
+
current,
|
|
1999
|
+
previous,
|
|
2000
|
+
deltaPct: previous > 0 ? (current - previous) / previous * 100 : null
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
function errorRatePct(errors, attempts) {
|
|
2004
|
+
if (attempts <= 0) return 0;
|
|
2005
|
+
return errors / attempts * 100;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// src/core/remote/remote-chat-client.ts
|
|
2009
|
+
async function surfaceHttpError(response, callbacks) {
|
|
2010
|
+
const payload = await response.json().catch(() => null);
|
|
2011
|
+
callbacks.onError?.(payload?.code ?? "request_failed", payload?.error ?? "Request failed");
|
|
2012
|
+
}
|
|
2013
|
+
function createRemoteChatClient(options) {
|
|
2014
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
2015
|
+
const { urls } = options;
|
|
2016
|
+
return {
|
|
2017
|
+
streamChat(conversationId, body, callbacks) {
|
|
2018
|
+
const controller = new AbortController();
|
|
2019
|
+
const promise = (async () => {
|
|
2020
|
+
const response = await doFetch(urls.stream(conversationId), {
|
|
2021
|
+
method: "POST",
|
|
2022
|
+
headers: { "content-type": "application/json" },
|
|
2023
|
+
body: JSON.stringify(body),
|
|
2024
|
+
signal: controller.signal
|
|
2025
|
+
});
|
|
2026
|
+
if (!response.ok) {
|
|
2027
|
+
await surfaceHttpError(response, callbacks);
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
if (!response.body) {
|
|
2031
|
+
callbacks.onError?.("request_failed", "The server returned an empty stream.");
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
await readSseResponse(response, callbacks);
|
|
2035
|
+
})();
|
|
2036
|
+
return {
|
|
2037
|
+
promise,
|
|
2038
|
+
abort: () => controller.abort()
|
|
2039
|
+
};
|
|
2040
|
+
},
|
|
2041
|
+
async resolveToolCall(conversationId, toolCallId, approved, callbacks) {
|
|
2042
|
+
const response = await doFetch(urls.resolveToolCall(conversationId, toolCallId), {
|
|
2043
|
+
method: "POST",
|
|
2044
|
+
headers: { "content-type": "application/json" },
|
|
2045
|
+
body: JSON.stringify({ approved })
|
|
2046
|
+
});
|
|
2047
|
+
if (!response.ok) {
|
|
2048
|
+
await surfaceHttpError(response, callbacks);
|
|
2049
|
+
return false;
|
|
2050
|
+
}
|
|
2051
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
2052
|
+
if (!contentType.includes("text/event-stream") || !response.body) {
|
|
2053
|
+
return false;
|
|
2054
|
+
}
|
|
2055
|
+
await readSseResponse(response, callbacks);
|
|
2056
|
+
return true;
|
|
2057
|
+
}
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
|
|
1931
2061
|
// src/providers/base/provider.types.ts
|
|
1932
2062
|
function isTextProvider(provider) {
|
|
1933
2063
|
return provider.capabilities.includes("text");
|
|
@@ -2658,7 +2788,7 @@ var AnthropicProvider = class {
|
|
|
2658
2788
|
);
|
|
2659
2789
|
}
|
|
2660
2790
|
const structuredPrompt = new StructuredPromptBuilder(
|
|
2661
|
-
messages[lastUserIndex]
|
|
2791
|
+
messages[lastUserIndex]?.content ?? ""
|
|
2662
2792
|
).withSchema(request.schema).build();
|
|
2663
2793
|
messages[lastUserIndex] = { role: "user", content: structuredPrompt };
|
|
2664
2794
|
const wireRequest = new AnthropicRequestBuilder(model).withRequest({ ...request, messages }).withEffort(this.config.effort).build();
|
|
@@ -2738,7 +2868,8 @@ function mapAnthropicUsage(usage) {
|
|
|
2738
2868
|
}
|
|
2739
2869
|
function findLastIndex(items, predicate) {
|
|
2740
2870
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
2741
|
-
|
|
2871
|
+
const item = items[i];
|
|
2872
|
+
if (item !== void 0 && predicate(item)) return i;
|
|
2742
2873
|
}
|
|
2743
2874
|
return -1;
|
|
2744
2875
|
}
|
|
@@ -3238,7 +3369,7 @@ var GroqProvider = class {
|
|
|
3238
3369
|
);
|
|
3239
3370
|
}
|
|
3240
3371
|
const structuredPrompt = new StructuredPromptBuilder(
|
|
3241
|
-
messages[lastUserIndex]
|
|
3372
|
+
messages[lastUserIndex]?.content ?? ""
|
|
3242
3373
|
).withSchema(request.schema).build();
|
|
3243
3374
|
messages[lastUserIndex] = { role: "user", content: structuredPrompt };
|
|
3244
3375
|
const wireRequest = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig(this.generationConfig(request, STRUCTURED_TEMPERATURE)).withJsonResponse(true).build();
|
|
@@ -3335,7 +3466,8 @@ function createGroqProvider(config) {
|
|
|
3335
3466
|
}
|
|
3336
3467
|
function findLastIndex2(items, predicate) {
|
|
3337
3468
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
3338
|
-
|
|
3469
|
+
const item = items[i];
|
|
3470
|
+
if (item !== void 0 && predicate(item)) return i;
|
|
3339
3471
|
}
|
|
3340
3472
|
return -1;
|
|
3341
3473
|
}
|
|
@@ -3485,7 +3617,7 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
3485
3617
|
}
|
|
3486
3618
|
messages[lastUserIndex] = {
|
|
3487
3619
|
role: "user",
|
|
3488
|
-
content: new StructuredPromptBuilder(messages[lastUserIndex]
|
|
3620
|
+
content: new StructuredPromptBuilder(messages[lastUserIndex]?.content ?? "").withSchema(request.schema).build()
|
|
3489
3621
|
};
|
|
3490
3622
|
const result = await this.generate({ ...request, messages, temperature: 0.1 });
|
|
3491
3623
|
return { value: this.jsonParser.parse(result.text), result };
|
|
@@ -3591,7 +3723,8 @@ function mapGeminiFinishReason(reason) {
|
|
|
3591
3723
|
}
|
|
3592
3724
|
function findLastIndex3(items, predicate) {
|
|
3593
3725
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
3594
|
-
|
|
3726
|
+
const item = items[i];
|
|
3727
|
+
if (item !== void 0 && predicate(item)) return i;
|
|
3595
3728
|
}
|
|
3596
3729
|
return -1;
|
|
3597
3730
|
}
|
|
@@ -4809,98 +4942,636 @@ function createPrunaProvider(config) {
|
|
|
4809
4942
|
return new PrunaProvider(config);
|
|
4810
4943
|
}
|
|
4811
4944
|
|
|
4812
|
-
// src/providers/
|
|
4813
|
-
function
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
fallbackEnabled: config.fallbackEnabled,
|
|
4817
|
-
defaultTier: config.defaultTier
|
|
4818
|
-
});
|
|
4819
|
-
if (config.anthropic?.apiKey) {
|
|
4820
|
-
factory.register(new AnthropicProvider(config.anthropic));
|
|
4945
|
+
// src/providers/adapters/openai-compatible.adapter.ts
|
|
4946
|
+
function toWireMessage(message) {
|
|
4947
|
+
if (message.role === "tool") {
|
|
4948
|
+
return { role: "tool", content: message.content, tool_call_id: message.toolCallId ?? "" };
|
|
4821
4949
|
}
|
|
4822
|
-
if (
|
|
4823
|
-
|
|
4950
|
+
if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
|
|
4951
|
+
return {
|
|
4952
|
+
role: "assistant",
|
|
4953
|
+
content: message.content,
|
|
4954
|
+
tool_calls: message.toolCalls.map((call) => ({
|
|
4955
|
+
id: call.id,
|
|
4956
|
+
type: "function",
|
|
4957
|
+
function: { name: call.name, arguments: call.arguments }
|
|
4958
|
+
}))
|
|
4959
|
+
};
|
|
4824
4960
|
}
|
|
4825
|
-
if (
|
|
4826
|
-
|
|
4961
|
+
if (message.role === "user") return { role: "user", content: message.content };
|
|
4962
|
+
return { role: message.role, content: message.content };
|
|
4963
|
+
}
|
|
4964
|
+
function mergeImages(messages, images) {
|
|
4965
|
+
if (images.length === 0) return [...messages];
|
|
4966
|
+
const parts = images.map((image) => ({
|
|
4967
|
+
type: "image_url",
|
|
4968
|
+
image_url: { url: `data:${image.mimeType};base64,${image.dataBase64}` }
|
|
4969
|
+
}));
|
|
4970
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
4971
|
+
const message = messages[index];
|
|
4972
|
+
if (!message || message.role !== "user") continue;
|
|
4973
|
+
const textParts = typeof message.content === "string" ? message.content.length > 0 ? [{ type: "text", text: message.content }] : [] : message.content;
|
|
4974
|
+
return [
|
|
4975
|
+
...messages.slice(0, index),
|
|
4976
|
+
{ role: "user", content: [...textParts, ...parts] },
|
|
4977
|
+
...messages.slice(index + 1)
|
|
4978
|
+
];
|
|
4827
4979
|
}
|
|
4828
|
-
|
|
4829
|
-
|
|
4980
|
+
return [...messages, { role: "user", content: [...parts] }];
|
|
4981
|
+
}
|
|
4982
|
+
async function extractErrorDetail(response) {
|
|
4983
|
+
try {
|
|
4984
|
+
const body = await response.json();
|
|
4985
|
+
return body.error;
|
|
4986
|
+
} catch {
|
|
4987
|
+
return void 0;
|
|
4830
4988
|
}
|
|
4831
|
-
|
|
4832
|
-
|
|
4989
|
+
}
|
|
4990
|
+
async function* parseSseEvent2(rawEvent, toolCallAccumulator) {
|
|
4991
|
+
for (const line of rawEvent.split("\n")) {
|
|
4992
|
+
if (!line.startsWith("data:")) continue;
|
|
4993
|
+
const payload = line.slice(5).trim();
|
|
4994
|
+
if (payload.length === 0 || payload === "[DONE]") continue;
|
|
4995
|
+
let chunk;
|
|
4996
|
+
try {
|
|
4997
|
+
chunk = JSON.parse(payload);
|
|
4998
|
+
} catch {
|
|
4999
|
+
continue;
|
|
5000
|
+
}
|
|
5001
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
5002
|
+
if (delta?.reasoning) {
|
|
5003
|
+
yield { type: "delta", channel: "reasoning", text: delta.reasoning };
|
|
5004
|
+
}
|
|
5005
|
+
if (delta?.content) {
|
|
5006
|
+
yield { type: "delta", channel: "answer", text: delta.content };
|
|
5007
|
+
}
|
|
5008
|
+
if (delta?.tool_calls) {
|
|
5009
|
+
for (const toolCallDelta of delta.tool_calls) toolCallAccumulator.push(toolCallDelta);
|
|
5010
|
+
}
|
|
5011
|
+
if (chunk.usage) {
|
|
5012
|
+
yield {
|
|
5013
|
+
type: "usage",
|
|
5014
|
+
usage: {
|
|
5015
|
+
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
5016
|
+
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
5017
|
+
reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens
|
|
5018
|
+
}
|
|
5019
|
+
};
|
|
5020
|
+
}
|
|
4833
5021
|
}
|
|
4834
|
-
return factory;
|
|
4835
5022
|
}
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
});
|
|
4842
|
-
var createAssistantMessage = (content) => ({
|
|
4843
|
-
role: "assistant",
|
|
4844
|
-
content
|
|
4845
|
-
});
|
|
4846
|
-
var createSystemMessage = (content) => ({
|
|
4847
|
-
role: "system",
|
|
4848
|
-
content
|
|
4849
|
-
});
|
|
4850
|
-
var createMessage = (role, content) => ({
|
|
4851
|
-
role,
|
|
4852
|
-
content
|
|
4853
|
-
});
|
|
4854
|
-
var promptToMessages = (prompt) => [
|
|
4855
|
-
createUserMessage(prompt)
|
|
4856
|
-
];
|
|
4857
|
-
var extractTextFromMessages = (messages) => messages.map((m) => m.content).join("\n\n");
|
|
4858
|
-
var formatMessagesForDisplay = (messages) => messages.map((m) => `[${m.role.toUpperCase()}]: ${m.content}`).join("\n\n---\n\n");
|
|
4859
|
-
|
|
4860
|
-
// src/providers/groq/groq-structured-json.ts
|
|
4861
|
-
async function requestStructuredJson(client, request) {
|
|
4862
|
-
const chatRequest = {
|
|
4863
|
-
model: request.model,
|
|
4864
|
-
messages: [createUserMessage(request.instructions)],
|
|
4865
|
-
temperature: request.temperature,
|
|
4866
|
-
max_tokens: request.maxTokens,
|
|
4867
|
-
response_format: { type: "json_object" },
|
|
4868
|
-
...request.reasoningEffort !== void 0 ? { reasoning_effort: request.reasoningEffort } : {}
|
|
4869
|
-
};
|
|
4870
|
-
const response = await client.postChatCompletion(chatRequest);
|
|
4871
|
-
const content = response.choices[0]?.message?.content ?? "";
|
|
4872
|
-
const candidate = extractJsonCandidate(content);
|
|
5023
|
+
async function* parseSseStream(body) {
|
|
5024
|
+
const reader = body.getReader();
|
|
5025
|
+
const decoder = new TextDecoder();
|
|
5026
|
+
const toolCallAccumulator = new ToolCallAccumulator();
|
|
5027
|
+
let buffer = "";
|
|
4873
5028
|
try {
|
|
4874
|
-
|
|
5029
|
+
while (true) {
|
|
5030
|
+
const { done, value } = await reader.read();
|
|
5031
|
+
if (done) break;
|
|
5032
|
+
buffer += decoder.decode(value, { stream: true });
|
|
5033
|
+
let separator = buffer.indexOf("\n\n");
|
|
5034
|
+
while (separator !== -1) {
|
|
5035
|
+
const rawEvent = buffer.slice(0, separator);
|
|
5036
|
+
buffer = buffer.slice(separator + 2);
|
|
5037
|
+
separator = buffer.indexOf("\n\n");
|
|
5038
|
+
yield* parseSseEvent2(rawEvent, toolCallAccumulator);
|
|
5039
|
+
}
|
|
5040
|
+
}
|
|
4875
5041
|
} catch (err) {
|
|
4876
|
-
throw
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
5042
|
+
throw errorFromUnknown(err);
|
|
5043
|
+
} finally {
|
|
5044
|
+
reader.releaseLock();
|
|
5045
|
+
}
|
|
5046
|
+
const calls = toolCallAccumulator.finish();
|
|
5047
|
+
if (calls.length > 0) yield { type: "tool_calls", calls };
|
|
5048
|
+
}
|
|
5049
|
+
function createOpenAiCompatibleAdapter(config) {
|
|
5050
|
+
if (!config.baseUrl && !config.endpointUrl) {
|
|
5051
|
+
throw new Error("createOpenAiCompatibleAdapter requires baseUrl or endpointUrl");
|
|
4881
5052
|
}
|
|
5053
|
+
const endpoint = config.endpointUrl ?? `${config.baseUrl}/chat/completions`;
|
|
5054
|
+
return {
|
|
5055
|
+
async *stream(req) {
|
|
5056
|
+
const timeout = AbortSignal.timeout(config.timeoutMs);
|
|
5057
|
+
const signal = req.signal ? AbortSignal.any([req.signal, timeout]) : timeout;
|
|
5058
|
+
let response;
|
|
5059
|
+
try {
|
|
5060
|
+
response = await fetch(endpoint, {
|
|
5061
|
+
method: "POST",
|
|
5062
|
+
headers: {
|
|
5063
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
5064
|
+
"Content-Type": "application/json"
|
|
5065
|
+
},
|
|
5066
|
+
body: JSON.stringify({
|
|
5067
|
+
model: req.externalModelId,
|
|
5068
|
+
messages: mergeImages(req.messages.map(toWireMessage), req.images ?? []),
|
|
5069
|
+
temperature: req.temperature,
|
|
5070
|
+
max_completion_tokens: req.maxOutputTokens,
|
|
5071
|
+
top_p: req.topP,
|
|
5072
|
+
stream: true,
|
|
5073
|
+
stream_options: { include_usage: true },
|
|
5074
|
+
...req.tools && req.tools.length > 0 ? {
|
|
5075
|
+
tools: req.tools.map((tool) => ({ type: "function", function: tool })),
|
|
5076
|
+
tool_choice: "auto"
|
|
5077
|
+
} : {}
|
|
5078
|
+
}),
|
|
5079
|
+
signal
|
|
5080
|
+
});
|
|
5081
|
+
} catch (err) {
|
|
5082
|
+
throw errorFromUnknown(err);
|
|
5083
|
+
}
|
|
5084
|
+
if (!response.ok || !response.body) {
|
|
5085
|
+
const detail = await extractErrorDetail(response);
|
|
5086
|
+
throw errorFromStatus(response.status, detail?.message, detail);
|
|
5087
|
+
}
|
|
5088
|
+
yield* parseSseStream(response.body);
|
|
5089
|
+
}
|
|
5090
|
+
};
|
|
4882
5091
|
}
|
|
4883
5092
|
|
|
4884
|
-
// src/providers/
|
|
4885
|
-
var
|
|
4886
|
-
var
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
this.
|
|
4890
|
-
|
|
5093
|
+
// src/providers/openai-compatible/openai-compatible.provider.ts
|
|
5094
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
5095
|
+
var STRUCTURED_TEMPERATURE2 = 0.1;
|
|
5096
|
+
var OpenAiCompatibleProvider = class {
|
|
5097
|
+
constructor(config) {
|
|
5098
|
+
this.config = config;
|
|
5099
|
+
if (!config.baseUrl && !config.endpointUrl) {
|
|
5100
|
+
throw new AIError(
|
|
5101
|
+
"MISSING_CONFIG" /* MISSING_CONFIG */,
|
|
5102
|
+
"OpenAiCompatibleProvider requires baseUrl or endpointUrl"
|
|
5103
|
+
);
|
|
5104
|
+
}
|
|
5105
|
+
this.adapter = createOpenAiCompatibleAdapter({
|
|
5106
|
+
baseUrl: config.baseUrl,
|
|
5107
|
+
endpointUrl: config.endpointUrl,
|
|
5108
|
+
apiKey: config.apiKey,
|
|
5109
|
+
timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
5110
|
+
});
|
|
5111
|
+
this.tiers = mergeTierOverrides(
|
|
5112
|
+
config.model ? { fast: config.model, balanced: config.model, powerful: config.model } : {},
|
|
5113
|
+
config.models
|
|
5114
|
+
);
|
|
4891
5115
|
}
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
id = "groq-text-generation";
|
|
4896
|
-
name = "Groq Text Generation";
|
|
5116
|
+
config;
|
|
5117
|
+
id = "openai-compatible";
|
|
5118
|
+
name = "OpenAI-compatible";
|
|
4897
5119
|
capabilities = ["text"];
|
|
5120
|
+
adapter;
|
|
5121
|
+
tiers;
|
|
4898
5122
|
jsonParser = new JsonResponseParser();
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
5123
|
+
resolveModel(tier) {
|
|
5124
|
+
return resolveModel(this.tiers, tier, this.id);
|
|
5125
|
+
}
|
|
5126
|
+
async healthCheck() {
|
|
5127
|
+
return this.config.apiKey && (this.config.baseUrl || this.config.endpointUrl) ? "healthy" : "unavailable";
|
|
5128
|
+
}
|
|
5129
|
+
async estimateCost() {
|
|
5130
|
+
return 0;
|
|
5131
|
+
}
|
|
5132
|
+
async generate(request) {
|
|
5133
|
+
const model = this.modelFor(request);
|
|
5134
|
+
const outcome = await this.consume(this.toAdapterRequest(model, request));
|
|
5135
|
+
if (outcome.text.length === 0) {
|
|
5136
|
+
throw this.noContentError(model);
|
|
5137
|
+
}
|
|
5138
|
+
return {
|
|
5139
|
+
text: outcome.text,
|
|
5140
|
+
usage: outcome.usage,
|
|
5141
|
+
model,
|
|
5142
|
+
providerId: this.id,
|
|
5143
|
+
finishReason: "stop"
|
|
5144
|
+
};
|
|
5145
|
+
}
|
|
5146
|
+
async generateStructured(request) {
|
|
5147
|
+
const model = this.modelFor(request);
|
|
5148
|
+
const messages = this.toWireMessages(request.messages, request.systemPrompt);
|
|
5149
|
+
const lastUserIndex = findLastIndex4(messages, (m) => m.role === "user");
|
|
5150
|
+
if (lastUserIndex === -1) {
|
|
5151
|
+
throw new AIError(
|
|
5152
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
5153
|
+
"generateStructured requires at least one user message"
|
|
5154
|
+
);
|
|
5155
|
+
}
|
|
5156
|
+
const structuredPrompt = new StructuredPromptBuilder(
|
|
5157
|
+
messages[lastUserIndex]?.content ?? ""
|
|
5158
|
+
).withSchema(request.schema).build();
|
|
5159
|
+
messages[lastUserIndex] = { role: "user", content: structuredPrompt };
|
|
5160
|
+
const outcome = await this.consume({
|
|
5161
|
+
externalModelId: model,
|
|
5162
|
+
messages,
|
|
5163
|
+
temperature: STRUCTURED_TEMPERATURE2,
|
|
5164
|
+
signal: request.signal
|
|
5165
|
+
});
|
|
5166
|
+
if (outcome.text.length === 0) {
|
|
5167
|
+
throw this.noContentError(model);
|
|
5168
|
+
}
|
|
5169
|
+
return {
|
|
5170
|
+
value: this.jsonParser.parse(outcome.text),
|
|
5171
|
+
result: {
|
|
5172
|
+
text: outcome.text,
|
|
5173
|
+
usage: outcome.usage,
|
|
5174
|
+
model,
|
|
5175
|
+
providerId: this.id,
|
|
5176
|
+
finishReason: "stop"
|
|
5177
|
+
}
|
|
5178
|
+
};
|
|
5179
|
+
}
|
|
5180
|
+
async stream(request, callbacks) {
|
|
5181
|
+
const model = this.modelFor(request);
|
|
5182
|
+
try {
|
|
5183
|
+
const outcome = await this.consume(this.toAdapterRequest(model, request), (text) => {
|
|
5184
|
+
callbacks.onChunk?.(text);
|
|
5185
|
+
});
|
|
5186
|
+
if (outcome.text.length === 0) {
|
|
5187
|
+
throw this.noContentError(model);
|
|
5188
|
+
}
|
|
5189
|
+
const result = {
|
|
5190
|
+
text: outcome.text,
|
|
5191
|
+
usage: outcome.usage,
|
|
5192
|
+
model,
|
|
5193
|
+
providerId: this.id,
|
|
5194
|
+
finishReason: "stop"
|
|
5195
|
+
};
|
|
5196
|
+
callbacks.onComplete?.(result);
|
|
5197
|
+
return result;
|
|
5198
|
+
} catch (error) {
|
|
5199
|
+
callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
5200
|
+
throw error;
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
5203
|
+
/* ---------- internals ---------- */
|
|
5204
|
+
/** Drain one adapter stream to its end. `onChunk`, when given, sees answer
|
|
5205
|
+
* deltas as they arrive — the streaming surface is this same drain. */
|
|
5206
|
+
async consume(req, onChunk) {
|
|
5207
|
+
let text = "";
|
|
5208
|
+
let usage;
|
|
5209
|
+
for await (const event of this.adapter.stream(req)) {
|
|
5210
|
+
if (event.type === "delta" && event.channel === "answer") {
|
|
5211
|
+
text += event.text;
|
|
5212
|
+
onChunk?.(event.text);
|
|
5213
|
+
} else if (event.type === "usage") {
|
|
5214
|
+
usage = event.usage;
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
return { text, usage };
|
|
5218
|
+
}
|
|
5219
|
+
modelFor(request) {
|
|
5220
|
+
return request.model ?? this.resolveModel(request.tier ?? "balanced");
|
|
5221
|
+
}
|
|
5222
|
+
noContentError(model) {
|
|
5223
|
+
return new AIError(
|
|
5224
|
+
"SERVER_ERROR" /* SERVER_ERROR */,
|
|
5225
|
+
"No content generated from the OpenAI-compatible endpoint",
|
|
5226
|
+
void 0,
|
|
5227
|
+
{ model }
|
|
5228
|
+
);
|
|
5229
|
+
}
|
|
5230
|
+
toAdapterRequest(model, request) {
|
|
5231
|
+
return {
|
|
5232
|
+
externalModelId: model,
|
|
5233
|
+
messages: this.toWireMessages(request.messages, request.systemPrompt),
|
|
5234
|
+
...request.temperature !== void 0 ? { temperature: request.temperature } : {},
|
|
5235
|
+
...request.maxTokens !== void 0 ? { maxOutputTokens: request.maxTokens } : {},
|
|
5236
|
+
...request.topP !== void 0 ? { topP: request.topP } : {},
|
|
5237
|
+
...request.signal ? { signal: request.signal } : {}
|
|
5238
|
+
};
|
|
5239
|
+
}
|
|
5240
|
+
/** Neutral messages onto the adapter's shape; systemPrompt becomes the
|
|
5241
|
+
* leading system message (in-band, the OpenAI way). */
|
|
5242
|
+
toWireMessages(messages, systemPrompt) {
|
|
5243
|
+
const wire = [];
|
|
5244
|
+
if (systemPrompt && systemPrompt.length > 0) {
|
|
5245
|
+
wire.push({ role: "system", content: systemPrompt });
|
|
5246
|
+
}
|
|
5247
|
+
for (const message of messages) {
|
|
5248
|
+
wire.push({ role: message.role, content: message.content });
|
|
5249
|
+
}
|
|
5250
|
+
return wire;
|
|
5251
|
+
}
|
|
5252
|
+
};
|
|
5253
|
+
function createOpenAiCompatibleProvider(config) {
|
|
5254
|
+
return new OpenAiCompatibleProvider(config);
|
|
5255
|
+
}
|
|
5256
|
+
function findLastIndex4(items, predicate) {
|
|
5257
|
+
for (let index = items.length - 1; index >= 0; index -= 1) {
|
|
5258
|
+
if (predicate(items[index])) return index;
|
|
5259
|
+
}
|
|
5260
|
+
return -1;
|
|
5261
|
+
}
|
|
5262
|
+
|
|
5263
|
+
// src/providers/workers-ai/workers-ai.entities.ts
|
|
5264
|
+
var WorkersAIError = class extends Error {
|
|
5265
|
+
status;
|
|
5266
|
+
constructor(message, status) {
|
|
5267
|
+
super(message);
|
|
5268
|
+
this.name = "WorkersAIError";
|
|
5269
|
+
this.status = status;
|
|
5270
|
+
}
|
|
5271
|
+
};
|
|
5272
|
+
|
|
5273
|
+
// src/providers/workers-ai/workers-ai.text.ts
|
|
5274
|
+
var WORKERS_AI_LLM_MODEL = "@cf/meta/llama-3.3-70b-instruct-fp8-fast";
|
|
5275
|
+
var WORKERS_AI_TEXT_TIMEOUT_MS = 25e3;
|
|
5276
|
+
function workersAIConfigured(env) {
|
|
5277
|
+
return typeof env.AI?.run === "function";
|
|
5278
|
+
}
|
|
5279
|
+
function requireAi(env) {
|
|
5280
|
+
const ai = env.AI;
|
|
5281
|
+
if (!ai || typeof ai.run !== "function") throw new WorkersAIError("Workers AI is not configured");
|
|
5282
|
+
return ai;
|
|
5283
|
+
}
|
|
5284
|
+
async function runWorkersAIText(env, messages, opts = {}) {
|
|
5285
|
+
const ai = requireAi(env);
|
|
5286
|
+
const model = opts.model ?? WORKERS_AI_LLM_MODEL;
|
|
5287
|
+
let result;
|
|
5288
|
+
try {
|
|
5289
|
+
result = await Promise.race([
|
|
5290
|
+
ai.run(model, {
|
|
5291
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
5292
|
+
max_tokens: opts.maxTokens ?? 900,
|
|
5293
|
+
temperature: opts.temperature ?? 0.7
|
|
5294
|
+
}),
|
|
5295
|
+
new Promise(
|
|
5296
|
+
(_, reject) => setTimeout(() => reject(new WorkersAIError("Workers AI timed out")), WORKERS_AI_TEXT_TIMEOUT_MS)
|
|
5297
|
+
)
|
|
5298
|
+
]);
|
|
5299
|
+
} catch (err) {
|
|
5300
|
+
throw err instanceof WorkersAIError ? err : new WorkersAIError(err instanceof Error ? err.message : "Workers AI request failed");
|
|
5301
|
+
}
|
|
5302
|
+
const response = result ?? {};
|
|
5303
|
+
let text = response.response;
|
|
5304
|
+
if (typeof text !== "string" || text.length === 0) {
|
|
5305
|
+
text = response.choices?.[0]?.message?.content;
|
|
5306
|
+
}
|
|
5307
|
+
if (typeof text !== "string" || text.length === 0) {
|
|
5308
|
+
throw new WorkersAIError("Workers AI returned no text");
|
|
5309
|
+
}
|
|
5310
|
+
return text;
|
|
5311
|
+
}
|
|
5312
|
+
async function* streamWorkersAIText(env, messages, opts = {}) {
|
|
5313
|
+
const ai = requireAi(env);
|
|
5314
|
+
const model = opts.model ?? WORKERS_AI_LLM_MODEL;
|
|
5315
|
+
let body;
|
|
5316
|
+
try {
|
|
5317
|
+
body = await Promise.race([
|
|
5318
|
+
ai.run(model, {
|
|
5319
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
5320
|
+
stream: true,
|
|
5321
|
+
max_tokens: opts.maxTokens ?? 600,
|
|
5322
|
+
temperature: opts.temperature ?? 0.7
|
|
5323
|
+
}),
|
|
5324
|
+
new Promise(
|
|
5325
|
+
(_, reject) => setTimeout(() => reject(new WorkersAIError("Workers AI timed out")), WORKERS_AI_TEXT_TIMEOUT_MS)
|
|
5326
|
+
)
|
|
5327
|
+
]);
|
|
5328
|
+
} catch (err) {
|
|
5329
|
+
throw err instanceof WorkersAIError ? err : new WorkersAIError(err instanceof Error ? err.message : "Workers AI request failed");
|
|
5330
|
+
}
|
|
5331
|
+
const stream = body;
|
|
5332
|
+
const getReader = typeof stream === "object" && stream !== null && "getReader" in stream && typeof stream.getReader === "function" ? stream.getReader : void 0;
|
|
5333
|
+
if (!getReader) throw new WorkersAIError("Workers AI stream was not readable");
|
|
5334
|
+
const reader = getReader.call(stream);
|
|
5335
|
+
const decoder = new TextDecoder();
|
|
5336
|
+
let buffer = "";
|
|
5337
|
+
try {
|
|
5338
|
+
for (; ; ) {
|
|
5339
|
+
const { done, value } = await reader.read();
|
|
5340
|
+
if (done) break;
|
|
5341
|
+
buffer += decoder.decode(value, { stream: true });
|
|
5342
|
+
let newlineAt;
|
|
5343
|
+
while ((newlineAt = buffer.indexOf("\n")) !== -1) {
|
|
5344
|
+
let line = buffer.slice(0, newlineAt);
|
|
5345
|
+
buffer = buffer.slice(newlineAt + 1);
|
|
5346
|
+
if (line.endsWith("\r")) line = line.slice(0, -1);
|
|
5347
|
+
if (line.startsWith(":") || line.trim() === "") continue;
|
|
5348
|
+
if (!line.startsWith("data: ")) continue;
|
|
5349
|
+
const payload = line.slice(6).trim();
|
|
5350
|
+
if (payload === "[DONE]") return;
|
|
5351
|
+
try {
|
|
5352
|
+
const parsed = JSON.parse(payload);
|
|
5353
|
+
if (typeof parsed.response === "string" && parsed.response.length > 0) yield parsed.response;
|
|
5354
|
+
} catch {
|
|
5355
|
+
buffer = `${line}
|
|
5356
|
+
${buffer}`;
|
|
5357
|
+
break;
|
|
5358
|
+
}
|
|
5359
|
+
}
|
|
5360
|
+
}
|
|
5361
|
+
} finally {
|
|
5362
|
+
reader.releaseLock();
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5365
|
+
|
|
5366
|
+
// src/providers/workers-ai/workers-ai.provider.ts
|
|
5367
|
+
var WORKERS_AI_TIERS = {
|
|
5368
|
+
fast: "@cf/meta/llama-3.1-8b-instruct-fp8-fast",
|
|
5369
|
+
balanced: WORKERS_AI_LLM_MODEL,
|
|
5370
|
+
powerful: WORKERS_AI_LLM_MODEL
|
|
5371
|
+
};
|
|
5372
|
+
var WorkersAIProvider = class {
|
|
5373
|
+
id = "workers-ai";
|
|
5374
|
+
name = "Cloudflare Workers AI";
|
|
5375
|
+
capabilities = ["text"];
|
|
5376
|
+
binding;
|
|
5377
|
+
tiers;
|
|
5378
|
+
jsonParser = new JsonResponseParser();
|
|
5379
|
+
constructor(config) {
|
|
5380
|
+
this.binding = config.binding;
|
|
5381
|
+
this.tiers = mergeTierOverrides(WORKERS_AI_TIERS, config.models);
|
|
5382
|
+
}
|
|
5383
|
+
resolveModel(tier) {
|
|
5384
|
+
return resolveModel(this.tiers, tier, this.id);
|
|
5385
|
+
}
|
|
5386
|
+
async healthCheck() {
|
|
5387
|
+
return typeof this.binding?.run === "function" ? "healthy" : "unavailable";
|
|
5388
|
+
}
|
|
5389
|
+
/** Workers AI is allocation-priced (neurons per deployment), not per
|
|
5390
|
+
* request — there is no per-call cost to estimate. */
|
|
5391
|
+
async estimateCost(_request) {
|
|
5392
|
+
return 0;
|
|
5393
|
+
}
|
|
5394
|
+
async generate(request) {
|
|
5395
|
+
const model = request.model ?? this.resolveModel(request.tier ?? "balanced");
|
|
5396
|
+
const messages = withSystemPrompt(request);
|
|
5397
|
+
try {
|
|
5398
|
+
const text = await runWorkersAIText(
|
|
5399
|
+
{ AI: this.binding },
|
|
5400
|
+
messages,
|
|
5401
|
+
{
|
|
5402
|
+
model,
|
|
5403
|
+
maxTokens: request.maxTokens,
|
|
5404
|
+
temperature: request.temperature
|
|
5405
|
+
}
|
|
5406
|
+
);
|
|
5407
|
+
return { text, model, providerId: this.id, finishReason: "stop" };
|
|
5408
|
+
} catch (error) {
|
|
5409
|
+
throw toAIError(error);
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
async generateStructured(request) {
|
|
5413
|
+
const messages = [...request.messages];
|
|
5414
|
+
const lastUserIndex = findLastIndex5(messages, (m) => m.role === "user");
|
|
5415
|
+
if (lastUserIndex === -1) {
|
|
5416
|
+
throw new AIError("UNKNOWN_ERROR" /* UNKNOWN_ERROR */, "generateStructured requires at least one user message");
|
|
5417
|
+
}
|
|
5418
|
+
messages[lastUserIndex] = {
|
|
5419
|
+
role: "user",
|
|
5420
|
+
content: new StructuredPromptBuilder(messages[lastUserIndex]?.content ?? "").withSchema(request.schema).build()
|
|
5421
|
+
};
|
|
5422
|
+
const result = await this.generate({ ...request, messages, temperature: 0.1 });
|
|
5423
|
+
return { value: this.jsonParser.parse(result.text), result };
|
|
5424
|
+
}
|
|
5425
|
+
async stream(request, callbacks) {
|
|
5426
|
+
const model = request.model ?? this.resolveModel(request.tier ?? "balanced");
|
|
5427
|
+
const messages = withSystemPrompt(request);
|
|
5428
|
+
let text = "";
|
|
5429
|
+
try {
|
|
5430
|
+
for await (const chunk of streamWorkersAIText({ AI: this.binding }, messages, {
|
|
5431
|
+
model,
|
|
5432
|
+
maxTokens: request.maxTokens,
|
|
5433
|
+
temperature: request.temperature
|
|
5434
|
+
})) {
|
|
5435
|
+
text += chunk;
|
|
5436
|
+
callbacks.onChunk?.(chunk);
|
|
5437
|
+
}
|
|
5438
|
+
} catch (error) {
|
|
5439
|
+
const aiError = toAIError(error);
|
|
5440
|
+
callbacks.onError?.(aiError);
|
|
5441
|
+
throw aiError;
|
|
5442
|
+
}
|
|
5443
|
+
const result = { text, model, providerId: this.id, finishReason: "stop" };
|
|
5444
|
+
callbacks.onComplete?.(result);
|
|
5445
|
+
return result;
|
|
5446
|
+
}
|
|
5447
|
+
};
|
|
5448
|
+
function withSystemPrompt(request) {
|
|
5449
|
+
if (request.systemPrompt && request.systemPrompt.length > 0) {
|
|
5450
|
+
return [
|
|
5451
|
+
{ role: "system", content: request.systemPrompt },
|
|
5452
|
+
...request.messages.filter((m) => m.role !== "system")
|
|
5453
|
+
];
|
|
5454
|
+
}
|
|
5455
|
+
return request.messages;
|
|
5456
|
+
}
|
|
5457
|
+
function toAIError(error) {
|
|
5458
|
+
if (error instanceof AIError) return error;
|
|
5459
|
+
const message = error instanceof Error ? error.message : "Workers AI request failed";
|
|
5460
|
+
const type = error instanceof WorkersAIError && error.message.includes("not configured") ? "INVALID_API_KEY" /* INVALID_API_KEY */ : "SERVER_ERROR" /* SERVER_ERROR */;
|
|
5461
|
+
return new AIError(type, message, error instanceof Error ? error : void 0);
|
|
5462
|
+
}
|
|
5463
|
+
function findLastIndex5(items, predicate) {
|
|
5464
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
5465
|
+
const item = items[i];
|
|
5466
|
+
if (item !== void 0 && predicate(item)) return i;
|
|
5467
|
+
}
|
|
5468
|
+
return -1;
|
|
5469
|
+
}
|
|
5470
|
+
function createWorkersAIProvider(config) {
|
|
5471
|
+
return new WorkersAIProvider(config);
|
|
5472
|
+
}
|
|
5473
|
+
|
|
5474
|
+
// src/providers/factory/create-ai.ts
|
|
5475
|
+
function createAI(config = {}) {
|
|
5476
|
+
const factory = new ProviderFactory({
|
|
5477
|
+
priority: config.priority,
|
|
5478
|
+
fallbackEnabled: config.fallbackEnabled,
|
|
5479
|
+
defaultTier: config.defaultTier
|
|
5480
|
+
});
|
|
5481
|
+
if (config.anthropic?.apiKey) {
|
|
5482
|
+
factory.register(new AnthropicProvider(config.anthropic));
|
|
5483
|
+
}
|
|
5484
|
+
if (config.groq?.apiKey) {
|
|
5485
|
+
factory.register(new GroqProvider(config.groq));
|
|
5486
|
+
}
|
|
5487
|
+
if (config.gemini?.apiKey) {
|
|
5488
|
+
factory.register(new GeminiProvider({ ...config.gemini, enabled: true }));
|
|
5489
|
+
}
|
|
5490
|
+
if (config.fal?.apiKey) {
|
|
5491
|
+
factory.register(new FalProvider({ ...config.fal, enabled: true }));
|
|
5492
|
+
}
|
|
5493
|
+
if (config.pruna?.apiKey) {
|
|
5494
|
+
factory.register(new PrunaProvider({ ...config.pruna, enabled: true }));
|
|
5495
|
+
}
|
|
5496
|
+
const openaiCompatible = config.openaiCompatible;
|
|
5497
|
+
if (openaiCompatible?.apiKey && (openaiCompatible.baseUrl || openaiCompatible.endpointUrl)) {
|
|
5498
|
+
factory.register(
|
|
5499
|
+
new OpenAiCompatibleProvider({ ...openaiCompatible, apiKey: openaiCompatible.apiKey })
|
|
5500
|
+
);
|
|
5501
|
+
}
|
|
5502
|
+
if (config.workersAI?.binding) {
|
|
5503
|
+
factory.register(new WorkersAIProvider(config.workersAI));
|
|
5504
|
+
}
|
|
5505
|
+
return factory;
|
|
5506
|
+
}
|
|
5507
|
+
|
|
5508
|
+
// src/providers/groq/groq-messages.ts
|
|
5509
|
+
var createUserMessage = (content) => ({
|
|
5510
|
+
role: "user",
|
|
5511
|
+
content
|
|
5512
|
+
});
|
|
5513
|
+
var createAssistantMessage = (content) => ({
|
|
5514
|
+
role: "assistant",
|
|
5515
|
+
content
|
|
5516
|
+
});
|
|
5517
|
+
var createSystemMessage = (content) => ({
|
|
5518
|
+
role: "system",
|
|
5519
|
+
content
|
|
5520
|
+
});
|
|
5521
|
+
var createMessage = (role, content) => ({
|
|
5522
|
+
role,
|
|
5523
|
+
content
|
|
5524
|
+
});
|
|
5525
|
+
var promptToMessages = (prompt) => [
|
|
5526
|
+
createUserMessage(prompt)
|
|
5527
|
+
];
|
|
5528
|
+
var extractTextFromMessages = (messages) => messages.map((m) => m.content).join("\n\n");
|
|
5529
|
+
var formatMessagesForDisplay = (messages) => messages.map((m) => `[${m.role.toUpperCase()}]: ${m.content}`).join("\n\n---\n\n");
|
|
5530
|
+
|
|
5531
|
+
// src/providers/groq/groq-structured-json.ts
|
|
5532
|
+
async function requestStructuredJson(client, request) {
|
|
5533
|
+
const chatRequest = {
|
|
5534
|
+
model: request.model,
|
|
5535
|
+
messages: [createUserMessage(request.instructions)],
|
|
5536
|
+
temperature: request.temperature,
|
|
5537
|
+
max_tokens: request.maxTokens,
|
|
5538
|
+
response_format: { type: "json_object" },
|
|
5539
|
+
...request.reasoningEffort !== void 0 ? { reasoning_effort: request.reasoningEffort } : {}
|
|
5540
|
+
};
|
|
5541
|
+
const response = await client.postChatCompletion(chatRequest);
|
|
5542
|
+
const content = response.choices[0]?.message?.content ?? "";
|
|
5543
|
+
const candidate = extractJsonCandidate(content);
|
|
5544
|
+
try {
|
|
5545
|
+
return JSON.parse(candidate);
|
|
5546
|
+
} catch (err) {
|
|
5547
|
+
throw new GroqError(
|
|
5548
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
5549
|
+
"model response contained no parsable json object",
|
|
5550
|
+
err instanceof Error ? err : void 0
|
|
5551
|
+
);
|
|
5552
|
+
}
|
|
5553
|
+
}
|
|
5554
|
+
|
|
5555
|
+
// src/providers/groq/text-generation.service.ts
|
|
5556
|
+
var STRUCTURED_OUTPUT_TEMPERATURE = 0.1;
|
|
5557
|
+
var TextGenerationService = class {
|
|
5558
|
+
constructor(httpClient, cache = new CacheManager(), defaultModel = DEFAULT_MODELS.TEXT) {
|
|
5559
|
+
this.httpClient = httpClient;
|
|
5560
|
+
this.cache = cache;
|
|
5561
|
+
this.defaultModel = defaultModel;
|
|
5562
|
+
}
|
|
5563
|
+
httpClient;
|
|
5564
|
+
cache;
|
|
5565
|
+
defaultModel;
|
|
5566
|
+
id = "groq-text-generation";
|
|
5567
|
+
name = "Groq Text Generation";
|
|
5568
|
+
capabilities = ["text"];
|
|
5569
|
+
jsonParser = new JsonResponseParser();
|
|
5570
|
+
generateCompletion(prompt, options = {}) {
|
|
5571
|
+
const model = options.model ?? this.defaultModel;
|
|
5572
|
+
return this.executeWithCache(
|
|
5573
|
+
{
|
|
5574
|
+
type: CACHE_KEY_TYPE_COMPLETION,
|
|
4904
5575
|
model,
|
|
4905
5576
|
prompt,
|
|
4906
5577
|
config: options.generationConfig
|
|
@@ -5200,6 +5871,7 @@ var ChatService = class {
|
|
|
5200
5871
|
if (messages.length === 0) return null;
|
|
5201
5872
|
const last = messages[messages.length - 1];
|
|
5202
5873
|
const first = messages[0];
|
|
5874
|
+
if (!last || !first) return null;
|
|
5203
5875
|
const companionId = String(first.metadata?.["companionId"] ?? "unknown");
|
|
5204
5876
|
const companionName = String(first.metadata?.["companionName"] ?? "Unknown");
|
|
5205
5877
|
return {
|
|
@@ -5343,6 +6015,211 @@ function resetProvider() {
|
|
|
5343
6015
|
container = null;
|
|
5344
6016
|
}
|
|
5345
6017
|
|
|
6018
|
+
// src/providers/workers-ai/workers-ai.speech.ts
|
|
6019
|
+
var WORKERS_AI_SPEECH_TIMEOUT_MS = 45e3;
|
|
6020
|
+
async function readAll(stream) {
|
|
6021
|
+
const reader = stream.getReader();
|
|
6022
|
+
const chunks = [];
|
|
6023
|
+
try {
|
|
6024
|
+
for (; ; ) {
|
|
6025
|
+
const { done, value } = await reader.read();
|
|
6026
|
+
if (done) break;
|
|
6027
|
+
if (value) chunks.push(value);
|
|
6028
|
+
}
|
|
6029
|
+
} finally {
|
|
6030
|
+
reader.releaseLock();
|
|
6031
|
+
}
|
|
6032
|
+
const combined = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
|
|
6033
|
+
let offset = 0;
|
|
6034
|
+
for (const chunk of chunks) {
|
|
6035
|
+
combined.set(chunk, offset);
|
|
6036
|
+
offset += chunk.length;
|
|
6037
|
+
}
|
|
6038
|
+
return combined;
|
|
6039
|
+
}
|
|
6040
|
+
function base64ToBytes2(base64) {
|
|
6041
|
+
const binary = atob(base64);
|
|
6042
|
+
const bytes = new Uint8Array(binary.length);
|
|
6043
|
+
for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
|
|
6044
|
+
return bytes;
|
|
6045
|
+
}
|
|
6046
|
+
async function speakWithWorkersAI(env, engine, text) {
|
|
6047
|
+
const ai = env.AI;
|
|
6048
|
+
if (!ai || typeof ai.run !== "function") throw new WorkersAIError("Workers AI is not configured");
|
|
6049
|
+
const input = engine.langParam ? { prompt: text, lang: engine.langParam } : { text };
|
|
6050
|
+
let result;
|
|
6051
|
+
try {
|
|
6052
|
+
result = await Promise.race([
|
|
6053
|
+
ai.run(engine.model, input),
|
|
6054
|
+
new Promise(
|
|
6055
|
+
(_, reject) => setTimeout(() => reject(new WorkersAIError("The speech engine timed out")), WORKERS_AI_SPEECH_TIMEOUT_MS)
|
|
6056
|
+
)
|
|
6057
|
+
]);
|
|
6058
|
+
} catch (err) {
|
|
6059
|
+
throw err instanceof WorkersAIError ? err : new WorkersAIError(err instanceof Error ? err.message : "Workers AI speech request failed");
|
|
6060
|
+
}
|
|
6061
|
+
if (result instanceof ReadableStream) {
|
|
6062
|
+
const bytes = await readAll(result);
|
|
6063
|
+
if (bytes.length === 0) throw new WorkersAIError("The speech engine returned no audio");
|
|
6064
|
+
return { bytes };
|
|
6065
|
+
}
|
|
6066
|
+
const audio = result ?? {};
|
|
6067
|
+
if (typeof audio.audio === "string" && audio.audio.length > 0) {
|
|
6068
|
+
return { bytes: base64ToBytes2(audio.audio) };
|
|
6069
|
+
}
|
|
6070
|
+
throw new WorkersAIError("The speech engine returned no audio");
|
|
6071
|
+
}
|
|
6072
|
+
|
|
6073
|
+
// src/providers/fal/queue/fal-queue.entities.ts
|
|
6074
|
+
var FalQueueError = class extends Error {
|
|
6075
|
+
status;
|
|
6076
|
+
constructor(message, status) {
|
|
6077
|
+
super(message);
|
|
6078
|
+
this.name = "FalQueueError";
|
|
6079
|
+
this.status = status;
|
|
6080
|
+
}
|
|
6081
|
+
};
|
|
6082
|
+
var FAL_ASPECT_IMAGE_SIZES = {
|
|
6083
|
+
"1:1": "square_hd",
|
|
6084
|
+
"16:9": "landscape_16_9",
|
|
6085
|
+
"9:16": "portrait_16_9"
|
|
6086
|
+
};
|
|
6087
|
+
|
|
6088
|
+
// src/providers/fal/queue/fal-queue.client.ts
|
|
6089
|
+
var FAL_QUEUE_BASE = "https://queue.fal.run";
|
|
6090
|
+
var FAL_SUBMIT_TIMEOUT_MS = 15e3;
|
|
6091
|
+
var FAL_POLL_TIMEOUT_MS = 1e4;
|
|
6092
|
+
function falQueueConfigured(env) {
|
|
6093
|
+
return Boolean(env.FAL_KEY);
|
|
6094
|
+
}
|
|
6095
|
+
async function falFetch(env, url, timeoutMs, body) {
|
|
6096
|
+
if (!falQueueConfigured(env)) throw new FalQueueError("fal.ai is not configured");
|
|
6097
|
+
const request = async () => fetch(url, {
|
|
6098
|
+
method: body !== void 0 ? "POST" : "GET",
|
|
6099
|
+
headers: {
|
|
6100
|
+
Authorization: `Key ${env.FAL_KEY}`,
|
|
6101
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
6102
|
+
},
|
|
6103
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
6104
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
6105
|
+
});
|
|
6106
|
+
let res;
|
|
6107
|
+
try {
|
|
6108
|
+
res = await request();
|
|
6109
|
+
if (res.status >= 500) res = await request();
|
|
6110
|
+
} catch (err) {
|
|
6111
|
+
throw new FalQueueError(err instanceof Error ? err.message : "fal.ai request failed");
|
|
6112
|
+
}
|
|
6113
|
+
if (!res.ok) {
|
|
6114
|
+
const text = await res.text().catch(() => "");
|
|
6115
|
+
throw new FalQueueError(`fal ${res.status}: ${text.slice(0, 200)}`, res.status);
|
|
6116
|
+
}
|
|
6117
|
+
return await res.json();
|
|
6118
|
+
}
|
|
6119
|
+
function createFalQueue(env) {
|
|
6120
|
+
return {
|
|
6121
|
+
async submit(model, input) {
|
|
6122
|
+
const res = await falFetch(env, `${FAL_QUEUE_BASE}/${model}`, FAL_SUBMIT_TIMEOUT_MS, input);
|
|
6123
|
+
return { requestId: res.request_id, statusUrl: res.status_url, responseUrl: res.response_url };
|
|
6124
|
+
},
|
|
6125
|
+
async checkStatus(statusUrl) {
|
|
6126
|
+
const res = await falFetch(env, statusUrl, FAL_POLL_TIMEOUT_MS);
|
|
6127
|
+
return {
|
|
6128
|
+
status: res.status,
|
|
6129
|
+
queuePosition: res.queue_position,
|
|
6130
|
+
logs: res.logs?.map((l) => l.message ?? "").filter(Boolean)
|
|
6131
|
+
};
|
|
6132
|
+
},
|
|
6133
|
+
fetchResult(responseUrl) {
|
|
6134
|
+
return falFetch(env, responseUrl, FAL_POLL_TIMEOUT_MS);
|
|
6135
|
+
}
|
|
6136
|
+
};
|
|
6137
|
+
}
|
|
6138
|
+
|
|
6139
|
+
// src/providers/fal/queue/fal-wire.ts
|
|
6140
|
+
function buildFalImageInput(model, input) {
|
|
6141
|
+
const base = { prompt: input.prompt, num_images: input.numImages };
|
|
6142
|
+
if (model.includes("flux")) {
|
|
6143
|
+
const imageSize = input.aspectRatio ? FAL_ASPECT_IMAGE_SIZES[input.aspectRatio] : void 0;
|
|
6144
|
+
if (imageSize) base.image_size = imageSize;
|
|
6145
|
+
}
|
|
6146
|
+
return base;
|
|
6147
|
+
}
|
|
6148
|
+
function parseFalImageOutput(raw) {
|
|
6149
|
+
const obj = raw ?? {};
|
|
6150
|
+
const entries = Array.isArray(obj.images) ? obj.images : obj.image && typeof obj.image === "object" ? [obj.image] : [];
|
|
6151
|
+
const imageUrls = entries.map((e) => typeof e.url === "string" ? e.url : "").filter((url) => url.length > 0);
|
|
6152
|
+
const first = entries.find((e) => typeof e.width === "number" || typeof e.height === "number");
|
|
6153
|
+
return {
|
|
6154
|
+
imageUrls,
|
|
6155
|
+
...typeof obj.seed === "number" ? { seed: obj.seed } : {},
|
|
6156
|
+
...typeof first?.width === "number" ? { width: first.width } : {},
|
|
6157
|
+
...typeof first?.height === "number" ? { height: first.height } : {}
|
|
6158
|
+
};
|
|
6159
|
+
}
|
|
6160
|
+
function buildFalVideoInput(spec, input) {
|
|
6161
|
+
const base = { prompt: input.prompt };
|
|
6162
|
+
if (spec.durationFormat !== "none" && typeof input.durationSeconds === "number") {
|
|
6163
|
+
base.duration = spec.durationFormat === "s-suffix" ? `${input.durationSeconds}s` : String(input.durationSeconds);
|
|
6164
|
+
}
|
|
6165
|
+
if (spec.aspectRatios && input.aspectRatio) base.aspect_ratio = input.aspectRatio;
|
|
6166
|
+
if (spec.resolutions && input.resolution) base.resolution = input.resolution;
|
|
6167
|
+
if (input.imageUrl) base.image_url = input.imageUrl;
|
|
6168
|
+
if (spec.supportsNegativePrompt && input.negativePrompt) base.negative_prompt = input.negativePrompt;
|
|
6169
|
+
if (spec.generateAudio) base.generate_audio = true;
|
|
6170
|
+
return base;
|
|
6171
|
+
}
|
|
6172
|
+
function parseFalVideoOutput(raw) {
|
|
6173
|
+
const obj = raw ?? {};
|
|
6174
|
+
const video = obj.video && typeof obj.video === "object" ? obj.video : void 0;
|
|
6175
|
+
if (!video || typeof video.url !== "string" || video.url.length === 0) return null;
|
|
6176
|
+
return {
|
|
6177
|
+
videoUrl: video.url,
|
|
6178
|
+
...typeof video.content_type === "string" ? { contentType: video.content_type } : {},
|
|
6179
|
+
...typeof video.file_size === "number" ? { fileSize: video.file_size } : {}
|
|
6180
|
+
};
|
|
6181
|
+
}
|
|
6182
|
+
function buildFalTagPrompt(prompt) {
|
|
6183
|
+
return prompt.toLowerCase().split(/[,\s]+/).filter((word) => word.length > 3).slice(0, 5).join(", ");
|
|
6184
|
+
}
|
|
6185
|
+
function buildFalAudioLyrics(input) {
|
|
6186
|
+
if (input.instrumental) return "[inst]";
|
|
6187
|
+
const lyrics = input.lyrics?.trim();
|
|
6188
|
+
if (!lyrics) return void 0;
|
|
6189
|
+
if (lyrics.includes("[verse]") || lyrics.includes("[chorus]")) return lyrics;
|
|
6190
|
+
return `[verse]
|
|
6191
|
+
${lyrics}
|
|
6192
|
+
[/verse]`;
|
|
6193
|
+
}
|
|
6194
|
+
function buildFalAudioInput(spec, input) {
|
|
6195
|
+
const tags = buildFalTagPrompt(input.prompt);
|
|
6196
|
+
const base = { prompt: tags, duration: input.durationSeconds };
|
|
6197
|
+
if (spec.supportsLyrics) {
|
|
6198
|
+
const lyrics = buildFalAudioLyrics(input);
|
|
6199
|
+
if (lyrics) base.lyrics = lyrics;
|
|
6200
|
+
}
|
|
6201
|
+
if (spec.supportsInstrumental && input.instrumental !== void 0) {
|
|
6202
|
+
base.instrumental = input.instrumental;
|
|
6203
|
+
}
|
|
6204
|
+
return base;
|
|
6205
|
+
}
|
|
6206
|
+
function parseFalAudioOutput(raw) {
|
|
6207
|
+
const obj = raw ?? {};
|
|
6208
|
+
const nested = (key) => {
|
|
6209
|
+
const value = obj[key];
|
|
6210
|
+
if (!value || typeof value !== "object") return void 0;
|
|
6211
|
+
const url = value.url;
|
|
6212
|
+
return typeof url === "string" && url.length > 0 ? url : void 0;
|
|
6213
|
+
};
|
|
6214
|
+
const flat = (key) => {
|
|
6215
|
+
const value = obj[key];
|
|
6216
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
6217
|
+
};
|
|
6218
|
+
const audioUrl = nested("audio_url") ?? nested("audio_file") ?? nested("audio") ?? flat("audio_url") ?? flat("audio");
|
|
6219
|
+
if (!audioUrl) return null;
|
|
6220
|
+
return { audioUrl };
|
|
6221
|
+
}
|
|
6222
|
+
|
|
5346
6223
|
// src/providers/embeddings/openai-embeddings.ts
|
|
5347
6224
|
var DEFAULT_EMBED_TIMEOUT_MS = 6e4;
|
|
5348
6225
|
function createOpenAiEmbeddingsAdapter(config) {
|
|
@@ -5530,150 +6407,6 @@ function createOpenAiImageAdapter(config) {
|
|
|
5530
6407
|
};
|
|
5531
6408
|
}
|
|
5532
6409
|
|
|
5533
|
-
// src/providers/adapters/openai-compatible.adapter.ts
|
|
5534
|
-
function toWireMessage(message) {
|
|
5535
|
-
if (message.role === "tool") {
|
|
5536
|
-
return { role: "tool", content: message.content, tool_call_id: message.toolCallId ?? "" };
|
|
5537
|
-
}
|
|
5538
|
-
if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
|
|
5539
|
-
return {
|
|
5540
|
-
role: "assistant",
|
|
5541
|
-
content: message.content,
|
|
5542
|
-
tool_calls: message.toolCalls.map((call) => ({
|
|
5543
|
-
id: call.id,
|
|
5544
|
-
type: "function",
|
|
5545
|
-
function: { name: call.name, arguments: call.arguments }
|
|
5546
|
-
}))
|
|
5547
|
-
};
|
|
5548
|
-
}
|
|
5549
|
-
if (message.role === "user") return { role: "user", content: message.content };
|
|
5550
|
-
return { role: message.role, content: message.content };
|
|
5551
|
-
}
|
|
5552
|
-
function mergeImages(messages, images) {
|
|
5553
|
-
if (images.length === 0) return [...messages];
|
|
5554
|
-
const parts = images.map((image) => ({
|
|
5555
|
-
type: "image_url",
|
|
5556
|
-
image_url: { url: `data:${image.mimeType};base64,${image.dataBase64}` }
|
|
5557
|
-
}));
|
|
5558
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
5559
|
-
const message = messages[index];
|
|
5560
|
-
if (message.role !== "user") continue;
|
|
5561
|
-
const textParts = typeof message.content === "string" ? message.content.length > 0 ? [{ type: "text", text: message.content }] : [] : message.content;
|
|
5562
|
-
return [
|
|
5563
|
-
...messages.slice(0, index),
|
|
5564
|
-
{ role: "user", content: [...textParts, ...parts] },
|
|
5565
|
-
...messages.slice(index + 1)
|
|
5566
|
-
];
|
|
5567
|
-
}
|
|
5568
|
-
return [...messages, { role: "user", content: [...parts] }];
|
|
5569
|
-
}
|
|
5570
|
-
async function extractErrorDetail(response) {
|
|
5571
|
-
try {
|
|
5572
|
-
const body = await response.json();
|
|
5573
|
-
return body.error;
|
|
5574
|
-
} catch {
|
|
5575
|
-
return void 0;
|
|
5576
|
-
}
|
|
5577
|
-
}
|
|
5578
|
-
async function* parseSseEvent2(rawEvent, toolCallAccumulator) {
|
|
5579
|
-
for (const line of rawEvent.split("\n")) {
|
|
5580
|
-
if (!line.startsWith("data:")) continue;
|
|
5581
|
-
const payload = line.slice(5).trim();
|
|
5582
|
-
if (payload.length === 0 || payload === "[DONE]") continue;
|
|
5583
|
-
let chunk;
|
|
5584
|
-
try {
|
|
5585
|
-
chunk = JSON.parse(payload);
|
|
5586
|
-
} catch {
|
|
5587
|
-
continue;
|
|
5588
|
-
}
|
|
5589
|
-
const delta = chunk.choices?.[0]?.delta;
|
|
5590
|
-
if (delta?.reasoning) {
|
|
5591
|
-
yield { type: "delta", channel: "reasoning", text: delta.reasoning };
|
|
5592
|
-
}
|
|
5593
|
-
if (delta?.content) {
|
|
5594
|
-
yield { type: "delta", channel: "answer", text: delta.content };
|
|
5595
|
-
}
|
|
5596
|
-
if (delta?.tool_calls) {
|
|
5597
|
-
for (const toolCallDelta of delta.tool_calls) toolCallAccumulator.push(toolCallDelta);
|
|
5598
|
-
}
|
|
5599
|
-
if (chunk.usage) {
|
|
5600
|
-
yield {
|
|
5601
|
-
type: "usage",
|
|
5602
|
-
usage: {
|
|
5603
|
-
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
5604
|
-
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
5605
|
-
reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens
|
|
5606
|
-
}
|
|
5607
|
-
};
|
|
5608
|
-
}
|
|
5609
|
-
}
|
|
5610
|
-
}
|
|
5611
|
-
async function* parseSseStream(body) {
|
|
5612
|
-
const reader = body.getReader();
|
|
5613
|
-
const decoder = new TextDecoder();
|
|
5614
|
-
const toolCallAccumulator = new ToolCallAccumulator();
|
|
5615
|
-
let buffer = "";
|
|
5616
|
-
try {
|
|
5617
|
-
while (true) {
|
|
5618
|
-
const { done, value } = await reader.read();
|
|
5619
|
-
if (done) break;
|
|
5620
|
-
buffer += decoder.decode(value, { stream: true });
|
|
5621
|
-
let separator = buffer.indexOf("\n\n");
|
|
5622
|
-
while (separator !== -1) {
|
|
5623
|
-
const rawEvent = buffer.slice(0, separator);
|
|
5624
|
-
buffer = buffer.slice(separator + 2);
|
|
5625
|
-
separator = buffer.indexOf("\n\n");
|
|
5626
|
-
yield* parseSseEvent2(rawEvent, toolCallAccumulator);
|
|
5627
|
-
}
|
|
5628
|
-
}
|
|
5629
|
-
} catch (err) {
|
|
5630
|
-
throw errorFromUnknown(err);
|
|
5631
|
-
} finally {
|
|
5632
|
-
reader.releaseLock();
|
|
5633
|
-
}
|
|
5634
|
-
const calls = toolCallAccumulator.finish();
|
|
5635
|
-
if (calls.length > 0) yield { type: "tool_calls", calls };
|
|
5636
|
-
}
|
|
5637
|
-
function createOpenAiCompatibleAdapter(config) {
|
|
5638
|
-
return {
|
|
5639
|
-
async *stream(req) {
|
|
5640
|
-
const timeout = AbortSignal.timeout(config.timeoutMs);
|
|
5641
|
-
const signal = req.signal ? AbortSignal.any([req.signal, timeout]) : timeout;
|
|
5642
|
-
let response;
|
|
5643
|
-
try {
|
|
5644
|
-
response = await fetch(`${config.baseUrl}/chat/completions`, {
|
|
5645
|
-
method: "POST",
|
|
5646
|
-
headers: {
|
|
5647
|
-
Authorization: `Bearer ${config.apiKey}`,
|
|
5648
|
-
"Content-Type": "application/json"
|
|
5649
|
-
},
|
|
5650
|
-
body: JSON.stringify({
|
|
5651
|
-
model: req.externalModelId,
|
|
5652
|
-
messages: mergeImages(req.messages.map(toWireMessage), req.images ?? []),
|
|
5653
|
-
temperature: req.temperature,
|
|
5654
|
-
max_completion_tokens: req.maxOutputTokens,
|
|
5655
|
-
top_p: req.topP,
|
|
5656
|
-
stream: true,
|
|
5657
|
-
stream_options: { include_usage: true },
|
|
5658
|
-
...req.tools && req.tools.length > 0 ? {
|
|
5659
|
-
tools: req.tools.map((tool) => ({ type: "function", function: tool })),
|
|
5660
|
-
tool_choice: "auto"
|
|
5661
|
-
} : {}
|
|
5662
|
-
}),
|
|
5663
|
-
signal
|
|
5664
|
-
});
|
|
5665
|
-
} catch (err) {
|
|
5666
|
-
throw errorFromUnknown(err);
|
|
5667
|
-
}
|
|
5668
|
-
if (!response.ok || !response.body) {
|
|
5669
|
-
const detail = await extractErrorDetail(response);
|
|
5670
|
-
throw errorFromStatus(response.status, detail?.message, detail);
|
|
5671
|
-
}
|
|
5672
|
-
yield* parseSseStream(response.body);
|
|
5673
|
-
}
|
|
5674
|
-
};
|
|
5675
|
-
}
|
|
5676
|
-
|
|
5677
6410
|
// src/providers/adapters/anthropic.adapter.ts
|
|
5678
6411
|
var ANTHROPIC_VERSION = "2023-06-01";
|
|
5679
6412
|
var ERROR_TYPE_TO_CODE = {
|
|
@@ -5694,7 +6427,7 @@ function mergeImages2(messages, images) {
|
|
|
5694
6427
|
}));
|
|
5695
6428
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
5696
6429
|
const message = messages[index];
|
|
5697
|
-
if (message.role !== "user") continue;
|
|
6430
|
+
if (!message || message.role !== "user") continue;
|
|
5698
6431
|
const textBlocks = typeof message.content === "string" ? message.content.length > 0 ? [{ type: "text", text: message.content }] : [] : message.content;
|
|
5699
6432
|
return [
|
|
5700
6433
|
...messages.slice(0, index),
|
|
@@ -5810,7 +6543,7 @@ function createAnthropicAdapter(config) {
|
|
|
5810
6543
|
model: req.externalModelId,
|
|
5811
6544
|
messages,
|
|
5812
6545
|
...system.length > 0 ? { system } : {},
|
|
5813
|
-
max_tokens: req.maxOutputTokens,
|
|
6546
|
+
max_tokens: req.maxOutputTokens ?? 4096,
|
|
5814
6547
|
stream: true
|
|
5815
6548
|
}),
|
|
5816
6549
|
signal
|
|
@@ -5827,6 +6560,170 @@ function createAnthropicAdapter(config) {
|
|
|
5827
6560
|
};
|
|
5828
6561
|
}
|
|
5829
6562
|
|
|
6563
|
+
// src/providers/adapters/adapter-resolver.ts
|
|
6564
|
+
var ADAPTER_TIMEOUT_MS = 6e4;
|
|
6565
|
+
var ADAPTER_MEDIA_TIMEOUT_MS = 12e4;
|
|
6566
|
+
function resolveApiKey(env, apiKeyEnv) {
|
|
6567
|
+
const value = env[apiKeyEnv];
|
|
6568
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
6569
|
+
throw new AiError("missing_key");
|
|
6570
|
+
}
|
|
6571
|
+
return value.trim();
|
|
6572
|
+
}
|
|
6573
|
+
function apiKeyAvailable(env, apiKeyEnv) {
|
|
6574
|
+
try {
|
|
6575
|
+
resolveApiKey(env, apiKeyEnv);
|
|
6576
|
+
return true;
|
|
6577
|
+
} catch {
|
|
6578
|
+
return false;
|
|
6579
|
+
}
|
|
6580
|
+
}
|
|
6581
|
+
function normalizeBaseUrl(url) {
|
|
6582
|
+
return url.replace(/\/$/, "");
|
|
6583
|
+
}
|
|
6584
|
+
function openAiApiKey(binding, capability) {
|
|
6585
|
+
if (binding.adapter !== "openai-compatible") {
|
|
6586
|
+
throw new AiError(
|
|
6587
|
+
"model_unavailable",
|
|
6588
|
+
`Adapter kind does not support ${capability}: ${binding.adapter}`
|
|
6589
|
+
);
|
|
6590
|
+
}
|
|
6591
|
+
return binding.apiKey;
|
|
6592
|
+
}
|
|
6593
|
+
function chatAdapterFor(binding, timing = {}) {
|
|
6594
|
+
const timeoutMs = timing.timeoutMs ?? ADAPTER_TIMEOUT_MS;
|
|
6595
|
+
if (binding.adapter === "openai-compatible") {
|
|
6596
|
+
return createOpenAiCompatibleAdapter({
|
|
6597
|
+
baseUrl: normalizeBaseUrl(binding.baseUrl),
|
|
6598
|
+
apiKey: binding.apiKey,
|
|
6599
|
+
timeoutMs
|
|
6600
|
+
});
|
|
6601
|
+
}
|
|
6602
|
+
if (binding.adapter === "anthropic") {
|
|
6603
|
+
return createAnthropicAdapter({
|
|
6604
|
+
baseUrl: normalizeBaseUrl(binding.baseUrl),
|
|
6605
|
+
apiKey: binding.apiKey,
|
|
6606
|
+
timeoutMs
|
|
6607
|
+
});
|
|
6608
|
+
}
|
|
6609
|
+
throw new AiError("model_unavailable", `Unsupported adapter kind: ${binding.adapter}`);
|
|
6610
|
+
}
|
|
6611
|
+
function imageAdapterFor(binding, timing = {}) {
|
|
6612
|
+
return createOpenAiImageAdapter({
|
|
6613
|
+
baseUrl: normalizeBaseUrl(binding.baseUrl),
|
|
6614
|
+
apiKey: openAiApiKey(binding, "images"),
|
|
6615
|
+
timeoutMs: timing.mediaTimeoutMs ?? ADAPTER_MEDIA_TIMEOUT_MS
|
|
6616
|
+
});
|
|
6617
|
+
}
|
|
6618
|
+
function embeddingsAdapterFor(binding, timing = {}) {
|
|
6619
|
+
return createOpenAiEmbeddingsAdapter({
|
|
6620
|
+
baseUrl: normalizeBaseUrl(binding.baseUrl),
|
|
6621
|
+
apiKey: openAiApiKey(binding, "embeddings"),
|
|
6622
|
+
timeoutMs: timing.timeoutMs ?? ADAPTER_TIMEOUT_MS
|
|
6623
|
+
});
|
|
6624
|
+
}
|
|
6625
|
+
function audioTranscriptionAdapterFor(binding, timing = {}) {
|
|
6626
|
+
return createOpenAiAudioTranscriptionAdapter({
|
|
6627
|
+
baseUrl: normalizeBaseUrl(binding.baseUrl),
|
|
6628
|
+
apiKey: openAiApiKey(binding, "audio transcription"),
|
|
6629
|
+
timeoutMs: timing.timeoutMs ?? ADAPTER_TIMEOUT_MS
|
|
6630
|
+
});
|
|
6631
|
+
}
|
|
6632
|
+
function speechAdapterFor(binding, timing = {}) {
|
|
6633
|
+
return createOpenAiSpeechAdapter({
|
|
6634
|
+
baseUrl: normalizeBaseUrl(binding.baseUrl),
|
|
6635
|
+
apiKey: openAiApiKey(binding, "speech synthesis"),
|
|
6636
|
+
timeoutMs: timing.mediaTimeoutMs ?? ADAPTER_MEDIA_TIMEOUT_MS
|
|
6637
|
+
});
|
|
6638
|
+
}
|
|
6639
|
+
function createAdapterResolver(env, timing = {}) {
|
|
6640
|
+
const toProviderBinding = (binding) => ({
|
|
6641
|
+
adapter: binding.adapter,
|
|
6642
|
+
baseUrl: binding.baseUrl,
|
|
6643
|
+
apiKey: resolveApiKey(env, binding.apiKeyEnv)
|
|
6644
|
+
});
|
|
6645
|
+
return {
|
|
6646
|
+
chat: (binding) => chatAdapterFor(toProviderBinding(binding), timing),
|
|
6647
|
+
image: (binding) => imageAdapterFor(toProviderBinding(binding), timing),
|
|
6648
|
+
embeddings: (binding) => embeddingsAdapterFor(toProviderBinding(binding), timing),
|
|
6649
|
+
audioTranscription: (binding) => audioTranscriptionAdapterFor(toProviderBinding(binding), timing),
|
|
6650
|
+
speech: (binding) => speechAdapterFor(toProviderBinding(binding), timing),
|
|
6651
|
+
available: (binding) => apiKeyAvailable(env, binding.apiKeyEnv)
|
|
6652
|
+
};
|
|
6653
|
+
}
|
|
6654
|
+
|
|
6655
|
+
// src/providers/execution/run-conversation.ts
|
|
6656
|
+
async function* runConversation(input) {
|
|
6657
|
+
const tools = input.tools && input.tools.length > 0 ? { tools: input.tools } : {};
|
|
6658
|
+
const images = input.images && input.images.length > 0 ? { images: input.images } : {};
|
|
6659
|
+
for (const [index, attempt] of input.attempts.entries()) {
|
|
6660
|
+
let answer = "";
|
|
6661
|
+
let reasoning = "";
|
|
6662
|
+
let usage = null;
|
|
6663
|
+
let toolCalls = [];
|
|
6664
|
+
const startedAt = Date.now();
|
|
6665
|
+
const context = buildContext(input.history, input.systemPrompt, {
|
|
6666
|
+
contextWindow: attempt.model.contextWindow,
|
|
6667
|
+
// No explicit output reservation → keep the whole window for input.
|
|
6668
|
+
maxOutputTokens: attempt.settings.maxOutputTokens ?? 0
|
|
6669
|
+
});
|
|
6670
|
+
yield { type: "attempt", index };
|
|
6671
|
+
try {
|
|
6672
|
+
for await (const event of attempt.adapter.stream({
|
|
6673
|
+
externalModelId: attempt.model.externalModelId,
|
|
6674
|
+
messages: context,
|
|
6675
|
+
temperature: attempt.settings.temperature,
|
|
6676
|
+
maxOutputTokens: attempt.settings.maxOutputTokens,
|
|
6677
|
+
topP: attempt.settings.topP,
|
|
6678
|
+
...tools,
|
|
6679
|
+
...images,
|
|
6680
|
+
signal: input.signal
|
|
6681
|
+
})) {
|
|
6682
|
+
if (event.type === "delta") {
|
|
6683
|
+
if (event.channel === "reasoning") reasoning += event.text;
|
|
6684
|
+
else answer += event.text;
|
|
6685
|
+
yield { type: "delta", channel: event.channel, text: event.text };
|
|
6686
|
+
} else if (event.type === "tool_calls") {
|
|
6687
|
+
toolCalls = [...event.calls];
|
|
6688
|
+
} else {
|
|
6689
|
+
usage = event.usage;
|
|
6690
|
+
}
|
|
6691
|
+
}
|
|
6692
|
+
} catch (err) {
|
|
6693
|
+
const result2 = {
|
|
6694
|
+
answer,
|
|
6695
|
+
reasoning,
|
|
6696
|
+
usage,
|
|
6697
|
+
toolCalls,
|
|
6698
|
+
durationMs: Date.now() - startedAt
|
|
6699
|
+
};
|
|
6700
|
+
if (input.signal?.aborted === true) {
|
|
6701
|
+
yield { type: "stopped", result: result2 };
|
|
6702
|
+
return;
|
|
6703
|
+
}
|
|
6704
|
+
if (index + 1 < input.attempts.length && canFailover(err, answer.length + reasoning.length)) {
|
|
6705
|
+
continue;
|
|
6706
|
+
}
|
|
6707
|
+
const aiError = err instanceof AiError ? err : errorFromUnknown(err);
|
|
6708
|
+
yield { type: "failed", code: aiError.code, message: aiError.userMessage, result: result2 };
|
|
6709
|
+
return;
|
|
6710
|
+
}
|
|
6711
|
+
const result = {
|
|
6712
|
+
answer,
|
|
6713
|
+
reasoning,
|
|
6714
|
+
usage,
|
|
6715
|
+
toolCalls,
|
|
6716
|
+
durationMs: Date.now() - startedAt
|
|
6717
|
+
};
|
|
6718
|
+
if (toolCalls.length > 0 && input.tools && input.tools.length > 0) {
|
|
6719
|
+
yield { type: "tool_calls", result };
|
|
6720
|
+
return;
|
|
6721
|
+
}
|
|
6722
|
+
yield { type: "done", result };
|
|
6723
|
+
return;
|
|
6724
|
+
}
|
|
6725
|
+
}
|
|
6726
|
+
|
|
5830
6727
|
// src/content/domain/calculations/ContentCreditCost.ts
|
|
5831
6728
|
var CREDIT_COSTS = {
|
|
5832
6729
|
"text-to-image": { standard: 1, hd: 2, "4k": 4 },
|
|
@@ -6461,7 +7358,7 @@ async function batchRequest(requests, options = {}) {
|
|
|
6461
7358
|
errors.push(result.reason);
|
|
6462
7359
|
if (stopOnError) {
|
|
6463
7360
|
throw new Error(
|
|
6464
|
-
`Batch request failed: ${errors[0]
|
|
7361
|
+
`Batch request failed: ${errors[0]?.message}`
|
|
6465
7362
|
);
|
|
6466
7363
|
}
|
|
6467
7364
|
}
|
|
@@ -6923,7 +7820,7 @@ function safeJSONParse(text, fallback, onError) {
|
|
|
6923
7820
|
}
|
|
6924
7821
|
if (error instanceof SyntaxError) {
|
|
6925
7822
|
const positionMatch = error.message.match(/position (\d+)/);
|
|
6926
|
-
const position = positionMatch ? parseInt(positionMatch[1], 10) : -1;
|
|
7823
|
+
const position = positionMatch ? parseInt(positionMatch[1] ?? "", 10) : -1;
|
|
6927
7824
|
if (position > 0) {
|
|
6928
7825
|
const context = text.substring(Math.max(0, position - 50), position + 50);
|
|
6929
7826
|
onError?.(`JSON parse error at position ${position}: "${context}"`);
|
|
@@ -7422,9 +8319,12 @@ function buildVideoRequest(data) {
|
|
|
7422
8319
|
}
|
|
7423
8320
|
|
|
7424
8321
|
exports.ABTestService = ABTestService;
|
|
8322
|
+
exports.ADAPTER_MEDIA_TIMEOUT_MS = ADAPTER_MEDIA_TIMEOUT_MS;
|
|
8323
|
+
exports.ADAPTER_TIMEOUT_MS = ADAPTER_TIMEOUT_MS;
|
|
7425
8324
|
exports.AIContentService = AIContentService;
|
|
7426
8325
|
exports.AIError = AIError;
|
|
7427
8326
|
exports.AIErrorType = AIErrorType;
|
|
8327
|
+
exports.AI_ERROR_STATUS = AI_ERROR_STATUS;
|
|
7428
8328
|
exports.ANTHROPIC_API_VERSION = ANTHROPIC_API_VERSION;
|
|
7429
8329
|
exports.ANTHROPIC_DEFAULT_MAX_TOKENS = ANTHROPIC_DEFAULT_MAX_TOKENS;
|
|
7430
8330
|
exports.ANTHROPIC_MODELS = ANTHROPIC_MODELS;
|
|
@@ -7470,7 +8370,9 @@ exports.DEFAULT_RETRY_MAX_DELAY_MS = DEFAULT_RETRY_MAX_DELAY_MS;
|
|
|
7470
8370
|
exports.DEFAULT_TASK_POLICIES = DEFAULT_TASK_POLICIES;
|
|
7471
8371
|
exports.DebounceManager = DebounceManager;
|
|
7472
8372
|
exports.DedupeExecutor = DedupeExecutor;
|
|
8373
|
+
exports.FAL_ASPECT_IMAGE_SIZES = FAL_ASPECT_IMAGE_SIZES;
|
|
7473
8374
|
exports.FalProvider = FalProvider;
|
|
8375
|
+
exports.FalQueueError = FalQueueError;
|
|
7474
8376
|
exports.GEMINI_TIERS = GEMINI_TIERS;
|
|
7475
8377
|
exports.GENERATION_BOUNDS = GENERATION_BOUNDS;
|
|
7476
8378
|
exports.GENERATION_COSTS = CREDIT_COSTS;
|
|
@@ -7501,6 +8403,7 @@ exports.MEMORY_TOTAL_LIMIT = MEMORY_TOTAL_LIMIT;
|
|
|
7501
8403
|
exports.MICROS_PER_UNIT = MICROS_PER_UNIT;
|
|
7502
8404
|
exports.MOTION_OPTIONS = MOTION_OPTIONS;
|
|
7503
8405
|
exports.MediaGenerationService = MediaGenerationService;
|
|
8406
|
+
exports.OpenAiCompatibleProvider = OpenAiCompatibleProvider;
|
|
7504
8407
|
exports.PromptBuilder = PromptBuilder;
|
|
7505
8408
|
exports.ProviderError = ProviderError;
|
|
7506
8409
|
exports.ProviderFactory = ProviderFactory;
|
|
@@ -7549,21 +8452,34 @@ exports.VIDEO_QUALITY_VALUES = VIDEO_QUALITY_VALUES;
|
|
|
7549
8452
|
exports.VIDEO_WIZARD_STEPS = VIDEO_WIZARD_STEPS;
|
|
7550
8453
|
exports.ValidationError = ValidationError2;
|
|
7551
8454
|
exports.VideoScriptService = VideoScriptService;
|
|
8455
|
+
exports.WORKERS_AI_LLM_MODEL = WORKERS_AI_LLM_MODEL;
|
|
8456
|
+
exports.WORKERS_AI_TIERS = WORKERS_AI_TIERS;
|
|
8457
|
+
exports.WorkersAIError = WorkersAIError;
|
|
8458
|
+
exports.WorkersAIProvider = WorkersAIProvider;
|
|
7552
8459
|
exports.accumulateReport = accumulateReport;
|
|
7553
8460
|
exports.aiErrorMessage = aiErrorMessage;
|
|
8461
|
+
exports.aiErrorStatus = aiErrorStatus;
|
|
8462
|
+
exports.apiKeyAvailable = apiKeyAvailable;
|
|
7554
8463
|
exports.asObjectArray = asObjectArray;
|
|
7555
8464
|
exports.asRecord = asRecord;
|
|
7556
8465
|
exports.asStringArray = asStringArray;
|
|
7557
8466
|
exports.asTrimmedOptionalString = asTrimmedOptionalString;
|
|
8467
|
+
exports.audioTranscriptionAdapterFor = audioTranscriptionAdapterFor;
|
|
7558
8468
|
exports.batchEmbed = batchEmbed;
|
|
7559
8469
|
exports.batchRequest = batchRequest;
|
|
7560
8470
|
exports.buildCacheKey = buildCacheKey;
|
|
7561
8471
|
exports.buildContentRequest = buildContentRequest;
|
|
7562
8472
|
exports.buildContext = buildContext;
|
|
8473
|
+
exports.buildFalAudioInput = buildFalAudioInput;
|
|
8474
|
+
exports.buildFalAudioLyrics = buildFalAudioLyrics;
|
|
8475
|
+
exports.buildFalImageInput = buildFalImageInput;
|
|
8476
|
+
exports.buildFalTagPrompt = buildFalTagPrompt;
|
|
8477
|
+
exports.buildFalVideoInput = buildFalVideoInput;
|
|
7563
8478
|
exports.buildHttpStatusFallback = buildHttpStatusFallback;
|
|
7564
8479
|
exports.buildImageRequest = buildImageRequest;
|
|
7565
8480
|
exports.buildResearchMessages = buildResearchMessages;
|
|
7566
8481
|
exports.buildSystemPrompt = buildSystemPrompt;
|
|
8482
|
+
exports.buildUsageDailySeries = buildUsageDailySeries;
|
|
7567
8483
|
exports.buildUsageData = buildUsageData;
|
|
7568
8484
|
exports.buildVideoRequest = buildVideoRequest;
|
|
7569
8485
|
exports.cacheManager = cacheManager;
|
|
@@ -7574,6 +8490,7 @@ exports.calculateTrailingDelay = calculateTrailingDelay;
|
|
|
7574
8490
|
exports.canFailover = canFailover;
|
|
7575
8491
|
exports.canStartTask = canStartTask;
|
|
7576
8492
|
exports.capText = capText;
|
|
8493
|
+
exports.chatAdapterFor = chatAdapterFor;
|
|
7577
8494
|
exports.chatIdGenerator = chatIdGenerator;
|
|
7578
8495
|
exports.chunkText = chunkText;
|
|
7579
8496
|
exports.clampScore = clampScore;
|
|
@@ -7585,22 +8502,27 @@ exports.consumeGroqStream = consumeGroqStream;
|
|
|
7585
8502
|
exports.cosineSimilarity = cosineSimilarity;
|
|
7586
8503
|
exports.countChanges = countChanges;
|
|
7587
8504
|
exports.createAI = createAI;
|
|
8505
|
+
exports.createAdapterResolver = createAdapterResolver;
|
|
7588
8506
|
exports.createAnthropicAdapter = createAnthropicAdapter;
|
|
7589
8507
|
exports.createAssistantMessage = createAssistantMessage;
|
|
7590
8508
|
exports.createFalProvider = createFalProvider;
|
|
8509
|
+
exports.createFalQueue = createFalQueue;
|
|
7591
8510
|
exports.createGeminiProvider = createGeminiProvider;
|
|
7592
8511
|
exports.createGroqProvider = createGroqProvider;
|
|
7593
8512
|
exports.createMessage = createMessage;
|
|
7594
8513
|
exports.createOpenAiAudioTranscriptionAdapter = createOpenAiAudioTranscriptionAdapter;
|
|
7595
8514
|
exports.createOpenAiCompatibleAdapter = createOpenAiCompatibleAdapter;
|
|
8515
|
+
exports.createOpenAiCompatibleProvider = createOpenAiCompatibleProvider;
|
|
7596
8516
|
exports.createOpenAiEmbeddingsAdapter = createOpenAiEmbeddingsAdapter;
|
|
7597
8517
|
exports.createOpenAiImageAdapter = createOpenAiImageAdapter;
|
|
7598
8518
|
exports.createOpenAiSpeechAdapter = createOpenAiSpeechAdapter;
|
|
7599
8519
|
exports.createProviderFactory = createProviderFactory;
|
|
7600
8520
|
exports.createPrunaProvider = createPrunaProvider;
|
|
8521
|
+
exports.createRemoteChatClient = createRemoteChatClient;
|
|
7601
8522
|
exports.createSseResponse = createSseResponse;
|
|
7602
8523
|
exports.createSystemMessage = createSystemMessage;
|
|
7603
8524
|
exports.createUserMessage = createUserMessage;
|
|
8525
|
+
exports.createWorkersAIProvider = createWorkersAIProvider;
|
|
7604
8526
|
exports.debounce = debounce;
|
|
7605
8527
|
exports.debounceManager = debounceManager;
|
|
7606
8528
|
exports.defaultEffortForModel = defaultEffortForModel;
|
|
@@ -7609,8 +8531,10 @@ exports.deriveSnippetTitle = deriveSnippetTitle;
|
|
|
7609
8531
|
exports.describeAIErrorType = describeAIErrorType;
|
|
7610
8532
|
exports.diffLines = diffLines;
|
|
7611
8533
|
exports.dotProduct = dotProduct;
|
|
8534
|
+
exports.embeddingsAdapterFor = embeddingsAdapterFor;
|
|
7612
8535
|
exports.errorFromStatus = errorFromStatus;
|
|
7613
8536
|
exports.errorFromUnknown = errorFromUnknown;
|
|
8537
|
+
exports.errorRatePct = errorRatePct;
|
|
7614
8538
|
exports.estimateMessageTokens = estimateMessageTokens;
|
|
7615
8539
|
exports.estimateTokens = estimateTokens;
|
|
7616
8540
|
exports.extractContentFromSsePayload = extractContentFromSsePayload;
|
|
@@ -7626,6 +8550,7 @@ exports.extractText = extractText;
|
|
|
7626
8550
|
exports.extractTextFromMessages = extractTextFromMessages;
|
|
7627
8551
|
exports.extractTokenUsage = extractTokenUsage;
|
|
7628
8552
|
exports.failoverCandidate = failoverCandidate;
|
|
8553
|
+
exports.falQueueConfigured = falQueueConfigured;
|
|
7629
8554
|
exports.findTopKSimilar = findTopKSimilar;
|
|
7630
8555
|
exports.formatCost = formatCost;
|
|
7631
8556
|
exports.formatErrorForLogging = formatErrorForLogging;
|
|
@@ -7638,6 +8563,7 @@ exports.generateWithPruna = generateWithPruna;
|
|
|
7638
8563
|
exports.getDimensionsForAspectRatio = getDimensionsForAspectRatio;
|
|
7639
8564
|
exports.getProvider = getProvider;
|
|
7640
8565
|
exports.getRecommendedQuality = getRecommendedQuality;
|
|
8566
|
+
exports.imageAdapterFor = imageAdapterFor;
|
|
7641
8567
|
exports.isAuthErrorType = isAuthErrorType;
|
|
7642
8568
|
exports.isMediaProvider = isMediaProvider;
|
|
7643
8569
|
exports.isRetryableErrorType = isRetryableErrorType;
|
|
@@ -7660,6 +8586,9 @@ exports.normalizeSources = normalizeSources;
|
|
|
7660
8586
|
exports.normalizeSseChunk = normalizeSseChunk;
|
|
7661
8587
|
exports.oneOfCatalog = oneOfCatalog;
|
|
7662
8588
|
exports.parseAIResponse = parseAIResponse;
|
|
8589
|
+
exports.parseFalAudioOutput = parseFalAudioOutput;
|
|
8590
|
+
exports.parseFalImageOutput = parseFalImageOutput;
|
|
8591
|
+
exports.parseFalVideoOutput = parseFalVideoOutput;
|
|
7663
8592
|
exports.parseSseEvent = parseSseEvent;
|
|
7664
8593
|
exports.planTaskFailure = planTaskFailure;
|
|
7665
8594
|
exports.pollForResult = pollForResult;
|
|
@@ -7671,25 +8600,34 @@ exports.requestDeduplicator = requestDeduplicator;
|
|
|
7671
8600
|
exports.requestQueue = requestQueue;
|
|
7672
8601
|
exports.requestStructuredJson = requestStructuredJson;
|
|
7673
8602
|
exports.resetProvider = resetProvider;
|
|
8603
|
+
exports.resolveApiKey = resolveApiKey;
|
|
7674
8604
|
exports.resolveModel = resolveModel;
|
|
7675
8605
|
exports.resolveUserFriendlyErrorMessage = resolveUserFriendlyErrorMessage;
|
|
7676
8606
|
exports.resolveUserFriendlyMessage = resolveUserFriendlyMessage;
|
|
7677
8607
|
exports.retryManager = retryManager;
|
|
8608
|
+
exports.runConversation = runConversation;
|
|
8609
|
+
exports.runWorkersAIText = runWorkersAIText;
|
|
7678
8610
|
exports.safeJSONParse = safeJSONParse;
|
|
7679
8611
|
exports.searchWeb = searchWeb;
|
|
7680
8612
|
exports.selectLeastRecentlyUsedKey = selectLeastRecentlyUsedKey;
|
|
7681
8613
|
exports.selectMemories = selectMemories;
|
|
7682
8614
|
exports.shouldCallOnLeadingEdge = shouldCallOnLeadingEdge;
|
|
8615
|
+
exports.speakWithWorkersAI = speakWithWorkersAI;
|
|
8616
|
+
exports.speechAdapterFor = speechAdapterFor;
|
|
7683
8617
|
exports.splitMarkdown = splitMarkdown;
|
|
7684
8618
|
exports.splitSseLines = splitSseLines;
|
|
7685
8619
|
exports.sseStreamResponse = sseStreamResponse;
|
|
8620
|
+
exports.streamWorkersAIText = streamWorkersAIText;
|
|
7686
8621
|
exports.submitPrediction = submitPrediction;
|
|
7687
8622
|
exports.throttle = throttle;
|
|
7688
8623
|
exports.throttleManager = throttleManager;
|
|
7689
8624
|
exports.toGroqMessages = toGroqMessages;
|
|
7690
8625
|
exports.uploadImage = uploadImage;
|
|
8626
|
+
exports.usageTrendOf = usageTrendOf;
|
|
8627
|
+
exports.usageWindowTotals = usageWindowTotals;
|
|
7691
8628
|
exports.validateApiKey = validateApiKey;
|
|
7692
8629
|
exports.validateToolArgs = validateToolArgs;
|
|
7693
8630
|
exports.withRetry = withRetry;
|
|
8631
|
+
exports.workersAIConfigured = workersAIConfigured;
|
|
7694
8632
|
//# sourceMappingURL=index.cjs.map
|
|
7695
8633
|
//# sourceMappingURL=index.cjs.map
|