@steipete/summarize 0.8.2 → 0.10.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/CHANGELOG.md +114 -1
- package/LICENSE +1 -1
- package/README.md +309 -182
- package/dist/cli.js +1 -1
- package/dist/esm/cache.js +72 -4
- package/dist/esm/cache.js.map +1 -1
- package/dist/esm/config.js +197 -1
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/content/asset.js +75 -2
- package/dist/esm/content/asset.js.map +1 -1
- package/dist/esm/daemon/agent.js +547 -0
- package/dist/esm/daemon/agent.js.map +1 -0
- package/dist/esm/daemon/chat.js +97 -0
- package/dist/esm/daemon/chat.js.map +1 -0
- package/dist/esm/daemon/cli.js +105 -10
- package/dist/esm/daemon/cli.js.map +1 -1
- package/dist/esm/daemon/env-snapshot.js +3 -0
- package/dist/esm/daemon/env-snapshot.js.map +1 -1
- package/dist/esm/daemon/flow-context.js +53 -28
- package/dist/esm/daemon/flow-context.js.map +1 -1
- package/dist/esm/daemon/launchd.js +27 -0
- package/dist/esm/daemon/launchd.js.map +1 -1
- package/dist/esm/daemon/process-registry.js +206 -0
- package/dist/esm/daemon/process-registry.js.map +1 -0
- package/dist/esm/daemon/schtasks.js +64 -0
- package/dist/esm/daemon/schtasks.js.map +1 -1
- package/dist/esm/daemon/server.js +1034 -52
- package/dist/esm/daemon/server.js.map +1 -1
- package/dist/esm/daemon/summarize.js +66 -18
- package/dist/esm/daemon/summarize.js.map +1 -1
- package/dist/esm/daemon/systemd.js +61 -0
- package/dist/esm/daemon/systemd.js.map +1 -1
- package/dist/esm/flags.js +24 -0
- package/dist/esm/flags.js.map +1 -1
- package/dist/esm/llm/attachments.js +2 -0
- package/dist/esm/llm/attachments.js.map +1 -0
- package/dist/esm/llm/errors.js +6 -0
- package/dist/esm/llm/errors.js.map +1 -0
- package/dist/esm/llm/generate-text.js +206 -356
- package/dist/esm/llm/generate-text.js.map +1 -1
- package/dist/esm/llm/html-to-markdown.js +1 -2
- package/dist/esm/llm/html-to-markdown.js.map +1 -1
- package/dist/esm/llm/prompt.js.map +1 -1
- package/dist/esm/llm/providers/anthropic.js +126 -0
- package/dist/esm/llm/providers/anthropic.js.map +1 -0
- package/dist/esm/llm/providers/google.js +78 -0
- package/dist/esm/llm/providers/google.js.map +1 -0
- package/dist/esm/llm/providers/models.js +111 -0
- package/dist/esm/llm/providers/models.js.map +1 -0
- package/dist/esm/llm/providers/openai.js +150 -0
- package/dist/esm/llm/providers/openai.js.map +1 -0
- package/dist/esm/llm/providers/shared.js +48 -0
- package/dist/esm/llm/providers/shared.js.map +1 -0
- package/dist/esm/llm/providers/types.js +2 -0
- package/dist/esm/llm/providers/types.js.map +1 -0
- package/dist/esm/llm/transcript-to-markdown.js +1 -2
- package/dist/esm/llm/transcript-to-markdown.js.map +1 -1
- package/dist/esm/llm/types.js +2 -0
- package/dist/esm/llm/types.js.map +1 -0
- package/dist/esm/llm/usage.js +69 -0
- package/dist/esm/llm/usage.js.map +1 -0
- package/dist/esm/logging/daemon.js +124 -0
- package/dist/esm/logging/daemon.js.map +1 -0
- package/dist/esm/logging/ring-file.js +66 -0
- package/dist/esm/logging/ring-file.js.map +1 -0
- package/dist/esm/media-cache.js +251 -0
- package/dist/esm/media-cache.js.map +1 -0
- package/dist/esm/model-auto.js +103 -5
- package/dist/esm/model-auto.js.map +1 -1
- package/dist/esm/processes.js +2 -0
- package/dist/esm/processes.js.map +1 -0
- package/dist/esm/refresh-free.js +3 -3
- package/dist/esm/refresh-free.js.map +1 -1
- package/dist/esm/run/attachments.js +8 -4
- package/dist/esm/run/attachments.js.map +1 -1
- package/dist/esm/run/bird.js +118 -5
- package/dist/esm/run/bird.js.map +1 -1
- package/dist/esm/run/cache-state.js +3 -2
- package/dist/esm/run/cache-state.js.map +1 -1
- package/dist/esm/run/cli-preflight.js +19 -1
- package/dist/esm/run/cli-preflight.js.map +1 -1
- package/dist/esm/run/constants.js +0 -7
- package/dist/esm/run/constants.js.map +1 -1
- package/dist/esm/run/finish-line.js +58 -11
- package/dist/esm/run/finish-line.js.map +1 -1
- package/dist/esm/run/flows/asset/extract.js +70 -0
- package/dist/esm/run/flows/asset/extract.js.map +1 -0
- package/dist/esm/run/flows/asset/input.js +209 -25
- package/dist/esm/run/flows/asset/input.js.map +1 -1
- package/dist/esm/run/flows/asset/media-policy.js +3 -0
- package/dist/esm/run/flows/asset/media-policy.js.map +1 -0
- package/dist/esm/run/flows/asset/media.js +224 -0
- package/dist/esm/run/flows/asset/media.js.map +1 -0
- package/dist/esm/run/flows/asset/output.js +98 -0
- package/dist/esm/run/flows/asset/output.js.map +1 -0
- package/dist/esm/run/flows/asset/preprocess.js +92 -16
- package/dist/esm/run/flows/asset/preprocess.js.map +1 -1
- package/dist/esm/run/flows/asset/summary.js +165 -11
- package/dist/esm/run/flows/asset/summary.js.map +1 -1
- package/dist/esm/run/flows/url/extract.js +6 -6
- package/dist/esm/run/flows/url/extract.js.map +1 -1
- package/dist/esm/run/flows/url/flow.js +338 -36
- package/dist/esm/run/flows/url/flow.js.map +1 -1
- package/dist/esm/run/flows/url/markdown.js +6 -1
- package/dist/esm/run/flows/url/markdown.js.map +1 -1
- package/dist/esm/run/flows/url/slides-output.js +485 -0
- package/dist/esm/run/flows/url/slides-output.js.map +1 -0
- package/dist/esm/run/flows/url/slides-text.js +628 -0
- package/dist/esm/run/flows/url/slides-text.js.map +1 -0
- package/dist/esm/run/flows/url/summary.js +358 -83
- package/dist/esm/run/flows/url/summary.js.map +1 -1
- package/dist/esm/run/help.js +94 -5
- package/dist/esm/run/help.js.map +1 -1
- package/dist/esm/run/logging.js +12 -4
- package/dist/esm/run/logging.js.map +1 -1
- package/dist/esm/run/media-cache-state.js +33 -0
- package/dist/esm/run/media-cache-state.js.map +1 -0
- package/dist/esm/run/progress.js +19 -1
- package/dist/esm/run/progress.js.map +1 -1
- package/dist/esm/run/run-context.js +19 -0
- package/dist/esm/run/run-context.js.map +1 -0
- package/dist/esm/run/run-output.js +1 -1
- package/dist/esm/run/run-output.js.map +1 -1
- package/dist/esm/run/run-settings.js +182 -0
- package/dist/esm/run/run-settings.js.map +1 -0
- package/dist/esm/run/runner.js +225 -32
- package/dist/esm/run/runner.js.map +1 -1
- package/dist/esm/run/slides-cli.js +225 -0
- package/dist/esm/run/slides-cli.js.map +1 -0
- package/dist/esm/run/slides-render.js +163 -0
- package/dist/esm/run/slides-render.js.map +1 -0
- package/dist/esm/run/stream-output.js +63 -0
- package/dist/esm/run/stream-output.js.map +1 -0
- package/dist/esm/run/streaming.js +16 -43
- package/dist/esm/run/streaming.js.map +1 -1
- package/dist/esm/run/summary-engine.js +59 -41
- package/dist/esm/run/summary-engine.js.map +1 -1
- package/dist/esm/run/transcriber-cli.js +148 -0
- package/dist/esm/run/transcriber-cli.js.map +1 -0
- package/dist/esm/shared/sse-events.js +26 -0
- package/dist/esm/shared/sse-events.js.map +1 -0
- package/dist/esm/shared/streaming-merge.js +44 -0
- package/dist/esm/shared/streaming-merge.js.map +1 -0
- package/dist/esm/slides/extract.js +1942 -0
- package/dist/esm/slides/extract.js.map +1 -0
- package/dist/esm/slides/index.js +4 -0
- package/dist/esm/slides/index.js.map +1 -0
- package/dist/esm/slides/settings.js +73 -0
- package/dist/esm/slides/settings.js.map +1 -0
- package/dist/esm/slides/store.js +111 -0
- package/dist/esm/slides/store.js.map +1 -0
- package/dist/esm/slides/types.js +2 -0
- package/dist/esm/slides/types.js.map +1 -0
- package/dist/esm/tty/osc-progress.js +21 -1
- package/dist/esm/tty/osc-progress.js.map +1 -1
- package/dist/esm/tty/progress/fetch-html.js +8 -4
- package/dist/esm/tty/progress/fetch-html.js.map +1 -1
- package/dist/esm/tty/progress/transcript.js +82 -31
- package/dist/esm/tty/progress/transcript.js.map +1 -1
- package/dist/esm/tty/spinner.js +2 -2
- package/dist/esm/tty/spinner.js.map +1 -1
- package/dist/esm/tty/theme.js +189 -0
- package/dist/esm/tty/theme.js.map +1 -0
- package/dist/esm/tty/website-progress.js +17 -13
- package/dist/esm/tty/website-progress.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/cache.d.ts +14 -2
- package/dist/types/config.d.ts +34 -0
- package/dist/types/daemon/agent.d.ts +25 -0
- package/dist/types/daemon/chat.d.ts +27 -0
- package/dist/types/daemon/env-snapshot.d.ts +1 -1
- package/dist/types/daemon/flow-context.d.ts +24 -3
- package/dist/types/daemon/launchd.d.ts +4 -0
- package/dist/types/daemon/process-registry.d.ts +73 -0
- package/dist/types/daemon/schtasks.d.ts +4 -0
- package/dist/types/daemon/server.d.ts +7 -1
- package/dist/types/daemon/summarize.d.ts +47 -5
- package/dist/types/daemon/systemd.d.ts +4 -0
- package/dist/types/flags.d.ts +1 -0
- package/dist/types/llm/attachments.d.ts +6 -0
- package/dist/types/llm/errors.d.ts +1 -0
- package/dist/types/llm/generate-text.d.ts +29 -13
- package/dist/types/llm/prompt.d.ts +7 -2
- package/dist/types/llm/providers/anthropic.d.ts +30 -0
- package/dist/types/llm/providers/google.d.ts +29 -0
- package/dist/types/llm/providers/models.d.ts +27 -0
- package/dist/types/llm/providers/openai.d.ts +38 -0
- package/dist/types/llm/providers/shared.d.ts +14 -0
- package/dist/types/llm/providers/types.d.ts +6 -0
- package/dist/types/llm/types.d.ts +5 -0
- package/dist/types/llm/usage.d.ts +5 -0
- package/dist/types/logging/daemon.d.ts +26 -0
- package/dist/types/logging/ring-file.d.ts +10 -0
- package/dist/types/media-cache.d.ts +22 -0
- package/dist/types/model-auto.d.ts +1 -0
- package/dist/types/processes.d.ts +1 -0
- package/dist/types/run/attachments.d.ts +9 -6
- package/dist/types/run/bird.d.ts +7 -0
- package/dist/types/run/constants.d.ts +0 -2
- package/dist/types/run/finish-line.d.ts +59 -1
- package/dist/types/run/flows/asset/extract.d.ts +18 -0
- package/dist/types/run/flows/asset/input.d.ts +12 -2
- package/dist/types/run/flows/asset/media-policy.d.ts +2 -0
- package/dist/types/run/flows/asset/media.d.ts +21 -0
- package/dist/types/run/flows/asset/output.d.ts +42 -0
- package/dist/types/run/flows/asset/preprocess.d.ts +22 -2
- package/dist/types/run/flows/asset/summary.d.ts +6 -0
- package/dist/types/run/flows/url/extract.d.ts +2 -1
- package/dist/types/run/flows/url/slides-output.d.ts +66 -0
- package/dist/types/run/flows/url/slides-text.d.ts +87 -0
- package/dist/types/run/flows/url/summary.d.ts +11 -3
- package/dist/types/run/flows/url/types.d.ts +29 -2
- package/dist/types/run/help.d.ts +3 -0
- package/dist/types/run/logging.d.ts +3 -2
- package/dist/types/run/media-cache-state.d.ts +7 -0
- package/dist/types/run/progress.d.ts +2 -1
- package/dist/types/run/run-context.d.ts +44 -0
- package/dist/types/run/run-settings.d.ts +62 -0
- package/dist/types/run/slides-cli.d.ts +9 -0
- package/dist/types/run/slides-render.d.ts +30 -0
- package/dist/types/run/stream-output.d.ts +12 -0
- package/dist/types/run/streaming.d.ts +10 -4
- package/dist/types/run/summary-engine.d.ts +15 -3
- package/dist/types/run/summary-llm.d.ts +2 -2
- package/dist/types/run/transcriber-cli.d.ts +8 -0
- package/dist/types/shared/sse-events.d.ts +64 -0
- package/dist/types/shared/streaming-merge.d.ts +4 -0
- package/dist/types/slides/extract.d.ts +42 -0
- package/dist/types/slides/index.d.ts +5 -0
- package/dist/types/slides/settings.d.ts +20 -0
- package/dist/types/slides/store.d.ts +15 -0
- package/dist/types/slides/types.d.ts +40 -0
- package/dist/types/tty/osc-progress.d.ts +2 -2
- package/dist/types/tty/progress/fetch-html.d.ts +3 -1
- package/dist/types/tty/progress/transcript.d.ts +3 -1
- package/dist/types/tty/spinner.d.ts +3 -1
- package/dist/types/tty/theme.d.ts +44 -0
- package/dist/types/tty/website-progress.d.ts +3 -1
- package/dist/types/version.d.ts +1 -1
- package/docs/README.md +13 -8
- package/docs/_config.yml +26 -0
- package/docs/_layouts/default.html +60 -0
- package/docs/agent.md +333 -0
- package/docs/assets/site.css +748 -0
- package/docs/assets/site.js +72 -0
- package/docs/assets/summarize-cli.png +0 -0
- package/docs/assets/summarize-extension.png +0 -0
- package/docs/assets/youtube-slides.png +0 -0
- package/docs/cache.md +29 -3
- package/docs/chrome-extension.md +85 -7
- package/docs/config.md +74 -2
- package/docs/extract-only.md +10 -2
- package/docs/index.html +205 -0
- package/docs/index.md +25 -0
- package/docs/language.md +1 -1
- package/docs/llm.md +17 -1
- package/docs/manual-tests.md +2 -0
- package/docs/media.md +37 -0
- package/docs/model-auto.md +2 -1
- package/docs/nvidia-onnx-transcription.md +55 -0
- package/docs/openai.md +5 -0
- package/docs/releasing.md +26 -0
- package/docs/site/assets/site.css +399 -228
- package/docs/site/assets/summarize-cli.png +0 -0
- package/docs/site/assets/summarize-extension.png +0 -0
- package/docs/site/docs/chrome-extension.html +89 -0
- package/docs/site/docs/config.html +1 -0
- package/docs/site/docs/extract-only.html +1 -0
- package/docs/site/docs/firecrawl.html +1 -0
- package/docs/site/docs/index.html +5 -0
- package/docs/site/docs/llm.html +1 -0
- package/docs/site/docs/openai.html +1 -0
- package/docs/site/docs/website.html +1 -0
- package/docs/site/docs/youtube.html +1 -0
- package/docs/site/index.html +148 -84
- package/docs/slides.md +74 -0
- package/docs/timestamps.md +103 -0
- package/docs/website.md +13 -0
- package/docs/youtube.md +16 -0
- package/package.json +22 -18
- package/dist/esm/daemon/request-settings.js +0 -91
- package/dist/esm/daemon/request-settings.js.map +0 -1
- package/dist/types/daemon/request-settings.d.ts +0 -27
|
@@ -1,265 +1,169 @@
|
|
|
1
|
-
import { completeSimple,
|
|
1
|
+
import { completeSimple, streamSimple } from '@mariozechner/pi-ai';
|
|
2
|
+
import { createUnsupportedFunctionalityError } from './errors.js';
|
|
2
3
|
import { parseGatewayStyleModelId } from './model-id.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return null;
|
|
15
|
-
return { type: errorType, message: errorMessage };
|
|
4
|
+
import { userTextAndImageMessage } from './prompt.js';
|
|
5
|
+
import { completeAnthropicDocument, completeAnthropicText, normalizeAnthropicModelAccessError, } from './providers/anthropic.js';
|
|
6
|
+
import { completeGoogleDocument, completeGoogleText } from './providers/google.js';
|
|
7
|
+
import { resolveAnthropicModel, resolveGoogleModel, resolveOpenAiModel, resolveXaiModel, resolveZaiModel, } from './providers/models.js';
|
|
8
|
+
import { completeOpenAiDocument, completeOpenAiText, resolveOpenAiClientConfig, } from './providers/openai.js';
|
|
9
|
+
import { extractText } from './providers/shared.js';
|
|
10
|
+
import { normalizeTokenUsage } from './usage.js';
|
|
11
|
+
function promptToContext(prompt) {
|
|
12
|
+
const attachments = prompt.attachments ?? [];
|
|
13
|
+
if (attachments.some((attachment) => attachment.kind === 'document')) {
|
|
14
|
+
throw new Error('Internal error: document prompt cannot be converted to context.');
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
return
|
|
16
|
+
if (attachments.length === 0) {
|
|
17
|
+
return {
|
|
18
|
+
systemPrompt: prompt.system,
|
|
19
|
+
messages: [{ role: 'user', content: prompt.userText, timestamp: Date.now() }],
|
|
20
|
+
};
|
|
19
21
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (!error || typeof error !== 'object')
|
|
23
|
-
return null;
|
|
24
|
-
const maybe = error;
|
|
25
|
-
const statusCode = typeof maybe.statusCode === 'number' ? maybe.statusCode : null;
|
|
26
|
-
const responseBody = typeof maybe.responseBody === 'string' ? maybe.responseBody : null;
|
|
27
|
-
const payload = responseBody ? parseAnthropicErrorPayload(responseBody) : null;
|
|
28
|
-
const payloadType = payload?.type ?? null;
|
|
29
|
-
const payloadMessage = payload?.message ?? null;
|
|
30
|
-
const message = typeof maybe.message === 'string' ? maybe.message : '';
|
|
31
|
-
const combinedMessage = (payloadMessage ?? message).trim();
|
|
32
|
-
const hasModelMessage = /^model:\s*\S+/i.test(combinedMessage);
|
|
33
|
-
const isAccessStatus = statusCode === 401 || statusCode === 403 || statusCode === 404;
|
|
34
|
-
const isAccessType = payloadType === 'not_found_error' ||
|
|
35
|
-
payloadType === 'permission_error' ||
|
|
36
|
-
payloadType === 'authentication_error';
|
|
37
|
-
if (!hasModelMessage && !isAccessStatus && !isAccessType)
|
|
38
|
-
return null;
|
|
39
|
-
const modelLabel = hasModelMessage ? combinedMessage.replace(/^model:\s*/i, '').trim() : modelId;
|
|
40
|
-
const hint = `Anthropic API rejected model "${modelLabel}". Your ANTHROPIC_API_KEY likely lacks access to this model or it is unavailable for your account. Try another anthropic/... model or request access.`;
|
|
41
|
-
return new Error(hint, { cause: error instanceof Error ? error : undefined });
|
|
42
|
-
}
|
|
43
|
-
function normalizeTokenUsage(raw) {
|
|
44
|
-
if (!raw || typeof raw !== 'object')
|
|
45
|
-
return null;
|
|
46
|
-
const usage = raw;
|
|
47
|
-
const promptTokens = typeof usage.input === 'number' && Number.isFinite(usage.input) ? usage.input : null;
|
|
48
|
-
const completionTokens = typeof usage.output === 'number' && Number.isFinite(usage.output) ? usage.output : null;
|
|
49
|
-
const totalTokens = typeof usage.totalTokens === 'number' && Number.isFinite(usage.totalTokens)
|
|
50
|
-
? usage.totalTokens
|
|
51
|
-
: null;
|
|
52
|
-
if (promptTokens === null && completionTokens === null && totalTokens === null)
|
|
53
|
-
return null;
|
|
54
|
-
return { promptTokens, completionTokens, totalTokens };
|
|
55
|
-
}
|
|
56
|
-
function resolveBaseUrlOverride(raw) {
|
|
57
|
-
const trimmed = typeof raw === 'string' ? raw.trim() : '';
|
|
58
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
59
|
-
}
|
|
60
|
-
function resolveOpenAiClientConfig({ apiKeys, forceOpenRouter, openaiBaseUrlOverride, forceChatCompletions, }) {
|
|
61
|
-
const baseUrlRaw = openaiBaseUrlOverride ??
|
|
62
|
-
(typeof process !== 'undefined' ? process.env.OPENAI_BASE_URL : undefined);
|
|
63
|
-
const baseUrl = typeof baseUrlRaw === 'string' && baseUrlRaw.trim().length > 0 ? baseUrlRaw.trim() : null;
|
|
64
|
-
const isOpenRouterViaBaseUrl = baseUrl ? /openrouter\.ai/i.test(baseUrl) : false;
|
|
65
|
-
const hasOpenRouterKey = apiKeys.openrouterApiKey != null;
|
|
66
|
-
const hasOpenAiKey = apiKeys.openaiApiKey != null;
|
|
67
|
-
const isOpenRouter = Boolean(forceOpenRouter) ||
|
|
68
|
-
isOpenRouterViaBaseUrl ||
|
|
69
|
-
(hasOpenRouterKey && !baseUrl && !hasOpenAiKey);
|
|
70
|
-
const apiKey = isOpenRouter
|
|
71
|
-
? (apiKeys.openrouterApiKey ?? apiKeys.openaiApiKey)
|
|
72
|
-
: apiKeys.openaiApiKey;
|
|
73
|
-
if (!apiKey) {
|
|
74
|
-
throw new Error(isOpenRouter
|
|
75
|
-
? 'Missing OPENROUTER_API_KEY (or OPENAI_API_KEY) for OpenRouter'
|
|
76
|
-
: 'Missing OPENAI_API_KEY for openai/... model');
|
|
22
|
+
if (attachments.length !== 1 || attachments[0]?.kind !== 'image') {
|
|
23
|
+
throw new Error('Internal error: only single image attachments are supported for prompts.');
|
|
77
24
|
}
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
})();
|
|
92
|
-
const useChatCompletions = Boolean(forceChatCompletions) || isOpenRouter || isCustomBaseURL;
|
|
93
|
-
return {
|
|
94
|
-
apiKey,
|
|
95
|
-
baseURL: baseURL ?? undefined,
|
|
96
|
-
useChatCompletions,
|
|
97
|
-
isOpenRouter,
|
|
98
|
-
};
|
|
25
|
+
const attachment = attachments[0];
|
|
26
|
+
const messages = [
|
|
27
|
+
userTextAndImageMessage({
|
|
28
|
+
text: prompt.userText,
|
|
29
|
+
imageBytes: attachment.bytes,
|
|
30
|
+
mimeType: attachment.mediaType,
|
|
31
|
+
}),
|
|
32
|
+
];
|
|
33
|
+
return { systemPrompt: prompt.system, messages };
|
|
99
34
|
}
|
|
100
|
-
function
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
35
|
+
function isRetryableTimeoutError(error) {
|
|
36
|
+
if (!error)
|
|
37
|
+
return false;
|
|
38
|
+
const message = typeof error === 'string'
|
|
39
|
+
? error
|
|
40
|
+
: error instanceof Error
|
|
41
|
+
? error.message
|
|
42
|
+
: typeof error.message === 'string'
|
|
43
|
+
? String(error.message)
|
|
44
|
+
: '';
|
|
45
|
+
return /timed out/i.test(message) || /empty summary/i.test(message);
|
|
107
46
|
}
|
|
108
|
-
function
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.join('');
|
|
113
|
-
return text.trim();
|
|
47
|
+
function computeRetryDelayMs(attempt) {
|
|
48
|
+
const base = 500;
|
|
49
|
+
const jitter = Math.floor(Math.random() * 200);
|
|
50
|
+
return Math.min(2000, base * (attempt + 1) + jitter);
|
|
114
51
|
}
|
|
115
|
-
function
|
|
116
|
-
|
|
117
|
-
if (msg.role === 'user' || msg.role === 'toolResult') {
|
|
118
|
-
if (Array.isArray(msg.content) && msg.content.some((c) => c.type === 'image'))
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return false;
|
|
52
|
+
function sleep(ms) {
|
|
53
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
123
54
|
}
|
|
124
|
-
function
|
|
125
|
-
|
|
126
|
-
return getModel(provider, modelId);
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
55
|
+
function isOpenaiGpt5Model(parsed) {
|
|
56
|
+
return parsed.provider === 'openai' && /^gpt-5([-.].+)?$/i.test(parsed.model);
|
|
131
57
|
}
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
baseUrl,
|
|
139
|
-
reasoning: false,
|
|
140
|
-
input: allowImages ? ['text', 'image'] : ['text'],
|
|
141
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
142
|
-
contextWindow: 128_000,
|
|
143
|
-
maxTokens: 16_384,
|
|
144
|
-
...(headers ? { headers } : {}),
|
|
145
|
-
};
|
|
58
|
+
function resolveEffectiveTemperature({ parsed, temperature, }) {
|
|
59
|
+
if (typeof temperature !== 'number')
|
|
60
|
+
return undefined;
|
|
61
|
+
if (isOpenaiGpt5Model(parsed))
|
|
62
|
+
return undefined;
|
|
63
|
+
return temperature;
|
|
146
64
|
}
|
|
147
|
-
function
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
65
|
+
export async function generateTextWithModelId({ modelId, apiKeys, prompt, temperature, maxOutputTokens, timeoutMs, fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, forceChatCompletions, retries = 0, onRetry, }) {
|
|
66
|
+
const parsed = parseGatewayStyleModelId(modelId);
|
|
67
|
+
const effectiveTemperature = resolveEffectiveTemperature({ parsed, temperature });
|
|
68
|
+
const attachments = prompt.attachments ?? [];
|
|
69
|
+
const documentAttachment = attachments.find((attachment) => attachment.kind === 'document') ?? null;
|
|
70
|
+
if (documentAttachment) {
|
|
71
|
+
if (attachments.length !== 1) {
|
|
72
|
+
throw new Error('Internal error: document attachments cannot be combined with other inputs.');
|
|
73
|
+
}
|
|
74
|
+
if (parsed.provider === 'anthropic') {
|
|
75
|
+
const apiKey = apiKeys.anthropicApiKey;
|
|
76
|
+
if (!apiKey)
|
|
77
|
+
throw new Error('Missing ANTHROPIC_API_KEY for anthropic/... model');
|
|
78
|
+
try {
|
|
79
|
+
const result = await completeAnthropicDocument({
|
|
80
|
+
modelId: parsed.model,
|
|
81
|
+
apiKey,
|
|
82
|
+
promptText: prompt.userText,
|
|
83
|
+
document: documentAttachment,
|
|
84
|
+
system: prompt.system,
|
|
85
|
+
maxOutputTokens,
|
|
86
|
+
timeoutMs,
|
|
87
|
+
fetchImpl,
|
|
88
|
+
anthropicBaseUrlOverride,
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
text: result.text,
|
|
92
|
+
canonicalModelId: parsed.canonical,
|
|
93
|
+
provider: parsed.provider,
|
|
94
|
+
usage: result.usage,
|
|
95
|
+
};
|
|
158
96
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
97
|
+
catch (error) {
|
|
98
|
+
const normalized = normalizeAnthropicModelAccessError(error, parsed.model);
|
|
99
|
+
if (normalized)
|
|
100
|
+
throw normalized;
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (parsed.provider === 'openai') {
|
|
105
|
+
const openaiConfig = resolveOpenAiClientConfig({
|
|
106
|
+
apiKeys: {
|
|
107
|
+
openaiApiKey: apiKeys.openaiApiKey,
|
|
108
|
+
openrouterApiKey: apiKeys.openrouterApiKey,
|
|
109
|
+
},
|
|
110
|
+
forceOpenRouter,
|
|
111
|
+
openaiBaseUrlOverride,
|
|
112
|
+
forceChatCompletions,
|
|
113
|
+
});
|
|
114
|
+
const result = await completeOpenAiDocument({
|
|
115
|
+
modelId: parsed.model,
|
|
116
|
+
openaiConfig,
|
|
117
|
+
promptText: prompt.userText,
|
|
118
|
+
document: documentAttachment,
|
|
119
|
+
maxOutputTokens,
|
|
120
|
+
temperature: effectiveTemperature,
|
|
121
|
+
timeoutMs,
|
|
122
|
+
fetchImpl,
|
|
123
|
+
});
|
|
185
124
|
return {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
api: 'openai-completions',
|
|
191
|
-
baseUrl: override,
|
|
192
|
-
allowImages,
|
|
193
|
-
})),
|
|
194
|
-
baseUrl: override,
|
|
125
|
+
text: result.text,
|
|
126
|
+
canonicalModelId: parsed.canonical,
|
|
127
|
+
provider: parsed.provider,
|
|
128
|
+
usage: result.usage,
|
|
195
129
|
};
|
|
196
130
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
131
|
+
if (parsed.provider === 'google') {
|
|
132
|
+
const apiKey = apiKeys.googleApiKey;
|
|
133
|
+
if (!apiKey)
|
|
134
|
+
throw new Error('Missing GEMINI_API_KEY (or GOOGLE_GENERATIVE_AI_API_KEY / GOOGLE_API_KEY) for google/... model');
|
|
135
|
+
const result = await completeGoogleDocument({
|
|
136
|
+
modelId: parsed.model,
|
|
137
|
+
apiKey,
|
|
138
|
+
promptText: prompt.userText,
|
|
139
|
+
document: documentAttachment,
|
|
140
|
+
maxOutputTokens,
|
|
141
|
+
temperature: effectiveTemperature,
|
|
142
|
+
timeoutMs,
|
|
143
|
+
fetchImpl,
|
|
144
|
+
googleBaseUrlOverride,
|
|
145
|
+
});
|
|
210
146
|
return {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
api: 'google-generative-ai',
|
|
216
|
-
baseUrl: override,
|
|
217
|
-
allowImages,
|
|
218
|
-
})),
|
|
219
|
-
baseUrl: override,
|
|
147
|
+
text: result.text,
|
|
148
|
+
canonicalModelId: parsed.canonical,
|
|
149
|
+
provider: parsed.provider,
|
|
150
|
+
usage: result.usage,
|
|
220
151
|
};
|
|
221
152
|
}
|
|
222
|
-
|
|
223
|
-
createSyntheticModel({
|
|
224
|
-
provider: 'google',
|
|
225
|
-
modelId,
|
|
226
|
-
api: 'google-generative-ai',
|
|
227
|
-
baseUrl: 'https://generativelanguage.googleapis.com/v1beta',
|
|
228
|
-
allowImages,
|
|
229
|
-
}));
|
|
153
|
+
throw createUnsupportedFunctionalityError(`document attachments are not supported for ${parsed.provider}/... models`);
|
|
230
154
|
}
|
|
231
|
-
const
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
baseUrl: override,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
return (base ??
|
|
247
|
-
createSyntheticModel({
|
|
248
|
-
provider: 'anthropic',
|
|
249
|
-
modelId,
|
|
250
|
-
api: 'anthropic-messages',
|
|
251
|
-
baseUrl: 'https://api.anthropic.com',
|
|
252
|
-
allowImages,
|
|
253
|
-
}));
|
|
254
|
-
}
|
|
255
|
-
export async function generateTextWithModelId({ modelId, apiKeys, system, prompt, temperature, maxOutputTokens, timeoutMs, fetchImpl: _fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, forceChatCompletions, retries = 0, onRetry, }) {
|
|
256
|
-
void _fetchImpl;
|
|
257
|
-
const parsed = parseGatewayStyleModelId(modelId);
|
|
258
|
-
const context = promptToContext({ system, prompt });
|
|
259
|
-
const isOpenaiGpt5 = parsed.provider === 'openai' && /^gpt-5([-.].+)?$/i.test(parsed.model);
|
|
260
|
-
const effectiveTemperature = typeof temperature === 'number' && !(isOpenaiGpt5 && temperature === 0)
|
|
261
|
-
? temperature
|
|
262
|
-
: undefined;
|
|
155
|
+
const context = promptToContext(prompt);
|
|
156
|
+
const openaiConfig = parsed.provider === 'openai'
|
|
157
|
+
? resolveOpenAiClientConfig({
|
|
158
|
+
apiKeys: {
|
|
159
|
+
openaiApiKey: apiKeys.openaiApiKey,
|
|
160
|
+
openrouterApiKey: apiKeys.openrouterApiKey,
|
|
161
|
+
},
|
|
162
|
+
forceOpenRouter,
|
|
163
|
+
openaiBaseUrlOverride,
|
|
164
|
+
forceChatCompletions,
|
|
165
|
+
})
|
|
166
|
+
: null;
|
|
263
167
|
const maxRetries = Math.max(0, retries);
|
|
264
168
|
let attempt = 0;
|
|
265
169
|
while (attempt <= maxRetries) {
|
|
@@ -270,10 +174,8 @@ export async function generateTextWithModelId({ modelId, apiKeys, system, prompt
|
|
|
270
174
|
const apiKey = apiKeys.xaiApiKey;
|
|
271
175
|
if (!apiKey)
|
|
272
176
|
throw new Error('Missing XAI_API_KEY for xai/... model');
|
|
273
|
-
const model =
|
|
177
|
+
const model = resolveXaiModel({
|
|
274
178
|
modelId: parsed.model,
|
|
275
|
-
parsedProvider: parsed.provider,
|
|
276
|
-
openaiConfig: null,
|
|
277
179
|
context,
|
|
278
180
|
xaiBaseUrlOverride,
|
|
279
181
|
});
|
|
@@ -299,76 +201,48 @@ export async function generateTextWithModelId({ modelId, apiKeys, system, prompt
|
|
|
299
201
|
const apiKey = apiKeys.googleApiKey;
|
|
300
202
|
if (!apiKey)
|
|
301
203
|
throw new Error('Missing GEMINI_API_KEY (or GOOGLE_GENERATIVE_AI_API_KEY / GOOGLE_API_KEY) for google/... model');
|
|
302
|
-
const
|
|
204
|
+
const result = await completeGoogleText({
|
|
303
205
|
modelId: parsed.model,
|
|
304
|
-
parsedProvider: parsed.provider,
|
|
305
|
-
openaiConfig: null,
|
|
306
|
-
context,
|
|
307
|
-
googleBaseUrlOverride,
|
|
308
|
-
});
|
|
309
|
-
const result = await completeSimple(model, context, {
|
|
310
|
-
...(typeof effectiveTemperature === 'number'
|
|
311
|
-
? { temperature: effectiveTemperature }
|
|
312
|
-
: {}),
|
|
313
|
-
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
314
206
|
apiKey,
|
|
207
|
+
context,
|
|
208
|
+
temperature: effectiveTemperature,
|
|
209
|
+
maxOutputTokens,
|
|
315
210
|
signal: controller.signal,
|
|
211
|
+
googleBaseUrlOverride,
|
|
316
212
|
});
|
|
317
|
-
const text = extractText(result);
|
|
318
|
-
if (!text)
|
|
319
|
-
throw new Error(`LLM returned an empty summary (model ${parsed.canonical}).`);
|
|
320
213
|
return {
|
|
321
|
-
text,
|
|
214
|
+
text: result.text,
|
|
322
215
|
canonicalModelId: parsed.canonical,
|
|
323
216
|
provider: parsed.provider,
|
|
324
|
-
usage:
|
|
217
|
+
usage: result.usage,
|
|
325
218
|
};
|
|
326
219
|
}
|
|
327
220
|
if (parsed.provider === 'anthropic') {
|
|
328
221
|
const apiKey = apiKeys.anthropicApiKey;
|
|
329
222
|
if (!apiKey)
|
|
330
223
|
throw new Error('Missing ANTHROPIC_API_KEY for anthropic/... model');
|
|
331
|
-
const
|
|
224
|
+
const result = await completeAnthropicText({
|
|
332
225
|
modelId: parsed.model,
|
|
333
|
-
parsedProvider: parsed.provider,
|
|
334
|
-
openaiConfig: null,
|
|
335
|
-
context,
|
|
336
|
-
anthropicBaseUrlOverride,
|
|
337
|
-
});
|
|
338
|
-
const result = await completeSimple(model, context, {
|
|
339
|
-
...(typeof effectiveTemperature === 'number'
|
|
340
|
-
? { temperature: effectiveTemperature }
|
|
341
|
-
: {}),
|
|
342
|
-
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
343
226
|
apiKey,
|
|
227
|
+
context,
|
|
228
|
+
temperature: effectiveTemperature,
|
|
229
|
+
maxOutputTokens,
|
|
344
230
|
signal: controller.signal,
|
|
231
|
+
anthropicBaseUrlOverride,
|
|
345
232
|
});
|
|
346
|
-
const text = extractText(result);
|
|
347
|
-
if (!text)
|
|
348
|
-
throw new Error(`LLM returned an empty summary (model ${parsed.canonical}).`);
|
|
349
233
|
return {
|
|
350
|
-
text,
|
|
234
|
+
text: result.text,
|
|
351
235
|
canonicalModelId: parsed.canonical,
|
|
352
236
|
provider: parsed.provider,
|
|
353
|
-
usage:
|
|
237
|
+
usage: result.usage,
|
|
354
238
|
};
|
|
355
239
|
}
|
|
356
|
-
const openaiConfig = parsed.provider === 'openai'
|
|
357
|
-
? resolveOpenAiClientConfig({
|
|
358
|
-
apiKeys,
|
|
359
|
-
forceOpenRouter,
|
|
360
|
-
openaiBaseUrlOverride,
|
|
361
|
-
forceChatCompletions,
|
|
362
|
-
})
|
|
363
|
-
: null;
|
|
364
240
|
if (parsed.provider === 'zai') {
|
|
365
241
|
const apiKey = apiKeys.openaiApiKey;
|
|
366
242
|
if (!apiKey)
|
|
367
243
|
throw new Error('Missing Z_AI_API_KEY for zai/... model');
|
|
368
|
-
const model =
|
|
244
|
+
const model = resolveZaiModel({
|
|
369
245
|
modelId: parsed.model,
|
|
370
|
-
parsedProvider: parsed.provider,
|
|
371
|
-
openaiConfig: null,
|
|
372
246
|
context,
|
|
373
247
|
openaiBaseUrlOverride,
|
|
374
248
|
});
|
|
@@ -390,30 +264,22 @@ export async function generateTextWithModelId({ modelId, apiKeys, system, prompt
|
|
|
390
264
|
usage: normalizeTokenUsage(result.usage),
|
|
391
265
|
};
|
|
392
266
|
}
|
|
393
|
-
|
|
267
|
+
if (!openaiConfig) {
|
|
268
|
+
throw new Error('Missing OPENAI_API_KEY for openai/... model');
|
|
269
|
+
}
|
|
270
|
+
const result = await completeOpenAiText({
|
|
394
271
|
modelId: parsed.model,
|
|
395
|
-
parsedProvider: parsed.provider,
|
|
396
272
|
openaiConfig,
|
|
397
273
|
context,
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
googleBaseUrlOverride,
|
|
401
|
-
xaiBaseUrlOverride,
|
|
402
|
-
});
|
|
403
|
-
const result = await completeSimple(model, context, {
|
|
404
|
-
...(typeof effectiveTemperature === 'number' ? { temperature: effectiveTemperature } : {}),
|
|
405
|
-
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
406
|
-
apiKey: openaiConfig?.apiKey ?? apiKeys.openaiApiKey ?? undefined,
|
|
274
|
+
temperature: effectiveTemperature,
|
|
275
|
+
maxOutputTokens,
|
|
407
276
|
signal: controller.signal,
|
|
408
277
|
});
|
|
409
|
-
const text = extractText(result);
|
|
410
|
-
if (!text)
|
|
411
|
-
throw new Error(`LLM returned an empty summary (model ${parsed.canonical}).`);
|
|
412
278
|
return {
|
|
413
|
-
text,
|
|
279
|
+
text: result.text,
|
|
414
280
|
canonicalModelId: parsed.canonical,
|
|
415
281
|
provider: parsed.provider,
|
|
416
|
-
usage:
|
|
282
|
+
usage: result.usage,
|
|
417
283
|
};
|
|
418
284
|
}
|
|
419
285
|
catch (error) {
|
|
@@ -440,30 +306,28 @@ export async function generateTextWithModelId({ modelId, apiKeys, system, prompt
|
|
|
440
306
|
}
|
|
441
307
|
throw new Error(`LLM request failed after ${maxRetries + 1} attempts.`);
|
|
442
308
|
}
|
|
443
|
-
function
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
function sleep(ms) {
|
|
461
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
309
|
+
export async function streamTextWithModelId({ modelId, apiKeys, prompt, temperature, maxOutputTokens, timeoutMs, fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, forceChatCompletions, }) {
|
|
310
|
+
const context = promptToContext(prompt);
|
|
311
|
+
return streamTextWithContext({
|
|
312
|
+
modelId,
|
|
313
|
+
apiKeys,
|
|
314
|
+
context,
|
|
315
|
+
temperature,
|
|
316
|
+
maxOutputTokens,
|
|
317
|
+
timeoutMs,
|
|
318
|
+
fetchImpl,
|
|
319
|
+
forceOpenRouter,
|
|
320
|
+
openaiBaseUrlOverride,
|
|
321
|
+
anthropicBaseUrlOverride,
|
|
322
|
+
googleBaseUrlOverride,
|
|
323
|
+
xaiBaseUrlOverride,
|
|
324
|
+
forceChatCompletions,
|
|
325
|
+
});
|
|
462
326
|
}
|
|
463
|
-
export async function
|
|
464
|
-
void _fetchImpl;
|
|
327
|
+
export async function streamTextWithContext({ modelId, apiKeys, context, temperature, maxOutputTokens, timeoutMs, fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, forceChatCompletions, }) {
|
|
465
328
|
const parsed = parseGatewayStyleModelId(modelId);
|
|
466
|
-
const
|
|
329
|
+
const effectiveTemperature = resolveEffectiveTemperature({ parsed, temperature });
|
|
330
|
+
void fetchImpl;
|
|
467
331
|
const controller = new AbortController();
|
|
468
332
|
let timeoutId = null;
|
|
469
333
|
const startedAtMs = Date.now();
|
|
@@ -539,15 +403,13 @@ export async function streamTextWithModelId({ modelId, apiKeys, system, prompt,
|
|
|
539
403
|
const apiKey = apiKeys.xaiApiKey;
|
|
540
404
|
if (!apiKey)
|
|
541
405
|
throw new Error('Missing XAI_API_KEY for xai/... model');
|
|
542
|
-
const model =
|
|
406
|
+
const model = resolveXaiModel({
|
|
543
407
|
modelId: parsed.model,
|
|
544
|
-
parsedProvider: parsed.provider,
|
|
545
|
-
openaiConfig: null,
|
|
546
408
|
context,
|
|
547
409
|
xaiBaseUrlOverride,
|
|
548
410
|
});
|
|
549
411
|
const stream = streamSimple(model, context, {
|
|
550
|
-
...(typeof
|
|
412
|
+
...(typeof effectiveTemperature === 'number' ? { temperature: effectiveTemperature } : {}),
|
|
551
413
|
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
552
414
|
apiKey,
|
|
553
415
|
signal: controller.signal,
|
|
@@ -579,15 +441,13 @@ export async function streamTextWithModelId({ modelId, apiKeys, system, prompt,
|
|
|
579
441
|
const apiKey = apiKeys.googleApiKey;
|
|
580
442
|
if (!apiKey)
|
|
581
443
|
throw new Error('Missing GEMINI_API_KEY (or GOOGLE_GENERATIVE_AI_API_KEY / GOOGLE_API_KEY) for google/... model');
|
|
582
|
-
const model =
|
|
444
|
+
const model = resolveGoogleModel({
|
|
583
445
|
modelId: parsed.model,
|
|
584
|
-
parsedProvider: parsed.provider,
|
|
585
|
-
openaiConfig: null,
|
|
586
446
|
context,
|
|
587
447
|
googleBaseUrlOverride,
|
|
588
448
|
});
|
|
589
449
|
const stream = streamSimple(model, context, {
|
|
590
|
-
...(typeof
|
|
450
|
+
...(typeof effectiveTemperature === 'number' ? { temperature: effectiveTemperature } : {}),
|
|
591
451
|
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
592
452
|
apiKey,
|
|
593
453
|
signal: controller.signal,
|
|
@@ -619,15 +479,13 @@ export async function streamTextWithModelId({ modelId, apiKeys, system, prompt,
|
|
|
619
479
|
const apiKey = apiKeys.anthropicApiKey;
|
|
620
480
|
if (!apiKey)
|
|
621
481
|
throw new Error('Missing ANTHROPIC_API_KEY for anthropic/... model');
|
|
622
|
-
const model =
|
|
482
|
+
const model = resolveAnthropicModel({
|
|
623
483
|
modelId: parsed.model,
|
|
624
|
-
parsedProvider: parsed.provider,
|
|
625
|
-
openaiConfig: null,
|
|
626
484
|
context,
|
|
627
485
|
anthropicBaseUrlOverride,
|
|
628
486
|
});
|
|
629
487
|
const stream = streamSimple(model, context, {
|
|
630
|
-
...(typeof
|
|
488
|
+
...(typeof effectiveTemperature === 'number' ? { temperature: effectiveTemperature } : {}),
|
|
631
489
|
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
632
490
|
apiKey,
|
|
633
491
|
signal: controller.signal,
|
|
@@ -660,15 +518,13 @@ export async function streamTextWithModelId({ modelId, apiKeys, system, prompt,
|
|
|
660
518
|
const apiKey = apiKeys.openaiApiKey;
|
|
661
519
|
if (!apiKey)
|
|
662
520
|
throw new Error('Missing Z_AI_API_KEY for zai/... model');
|
|
663
|
-
const model =
|
|
521
|
+
const model = resolveZaiModel({
|
|
664
522
|
modelId: parsed.model,
|
|
665
|
-
parsedProvider: parsed.provider,
|
|
666
|
-
openaiConfig: null,
|
|
667
523
|
context,
|
|
668
524
|
openaiBaseUrlOverride,
|
|
669
525
|
});
|
|
670
526
|
const stream = streamSimple(model, context, {
|
|
671
|
-
...(typeof
|
|
527
|
+
...(typeof effectiveTemperature === 'number' ? { temperature: effectiveTemperature } : {}),
|
|
672
528
|
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
673
529
|
apiKey,
|
|
674
530
|
signal: controller.signal,
|
|
@@ -697,23 +553,17 @@ export async function streamTextWithModelId({ modelId, apiKeys, system, prompt,
|
|
|
697
553
|
};
|
|
698
554
|
}
|
|
699
555
|
const openaiConfig = resolveOpenAiClientConfig({
|
|
700
|
-
apiKeys
|
|
556
|
+
apiKeys: {
|
|
557
|
+
openaiApiKey: apiKeys.openaiApiKey,
|
|
558
|
+
openrouterApiKey: apiKeys.openrouterApiKey,
|
|
559
|
+
},
|
|
701
560
|
forceOpenRouter,
|
|
702
561
|
openaiBaseUrlOverride,
|
|
703
562
|
forceChatCompletions,
|
|
704
563
|
});
|
|
705
|
-
const model =
|
|
706
|
-
modelId: parsed.model,
|
|
707
|
-
parsedProvider: parsed.provider,
|
|
708
|
-
openaiConfig,
|
|
709
|
-
context,
|
|
710
|
-
openaiBaseUrlOverride,
|
|
711
|
-
anthropicBaseUrlOverride,
|
|
712
|
-
googleBaseUrlOverride,
|
|
713
|
-
xaiBaseUrlOverride,
|
|
714
|
-
});
|
|
564
|
+
const model = resolveOpenAiModel({ modelId: parsed.model, context, openaiConfig });
|
|
715
565
|
const stream = streamSimple(model, context, {
|
|
716
|
-
...(typeof
|
|
566
|
+
...(typeof effectiveTemperature === 'number' ? { temperature: effectiveTemperature } : {}),
|
|
717
567
|
...(typeof maxOutputTokens === 'number' ? { maxTokens: maxOutputTokens } : {}),
|
|
718
568
|
apiKey: openaiConfig.apiKey,
|
|
719
569
|
signal: controller.signal,
|