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