@morlay/dsh-llm-openai-compatible 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-CYd_pegB.d.mts +62 -0
- package/dist/index.d.mts +3 -63
- package/dist/index.mjs +2 -402
- package/dist/invariant.d.mts +7 -0
- package/dist/invariant.mjs +8 -0
- package/dist/translate-BzOJ1xx-.mjs +401 -0
- package/dist/wire.d.mts +37 -0
- package/dist/wire.mjs +2 -0
- package/package.json +5 -2
- package/src/invariant.ts +13 -0
- package/src/wire.ts +4 -0
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { GenerateOptions, LlmAdapter, LlmModelInfo, LlmProviderInfo, LlmResolvedModelInfo, ModelModality, ResolvedRetryPolicy, StreamChunk } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import { CredentialRef } from "@deepseek-ai/dsh-credentials";
|
|
3
|
+
import { LanguageModelV4Usage } from "@ai-sdk/provider";
|
|
4
|
+
import { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
5
|
+
//#region src/adapter.d.ts
|
|
6
|
+
declare const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300000;
|
|
7
|
+
declare const DEFAULT_CONTEXT_WINDOW = 262144;
|
|
8
|
+
declare const DEFAULT_MAX_TOKENS = 32768;
|
|
9
|
+
declare const DEFAULT_MAX_REQUEST_IMAGE_BYTES: number;
|
|
10
|
+
type ReasoningEffort = "off" | "low" | "high" | "max";
|
|
11
|
+
interface ResolvedModelProfile {
|
|
12
|
+
id: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
contextWindow?: number;
|
|
16
|
+
maxTokens?: number;
|
|
17
|
+
inputModalities: readonly ModelModality[];
|
|
18
|
+
reasoningEfforts?: false | Partial<Record<ReasoningEffort, string | null>>;
|
|
19
|
+
}
|
|
20
|
+
interface ResolvedProviderProfile {
|
|
21
|
+
provider: string;
|
|
22
|
+
displayName: string;
|
|
23
|
+
apiKeyEnv?: CredentialRef;
|
|
24
|
+
baseURL: string;
|
|
25
|
+
headers?: Readonly<Record<string, string>>;
|
|
26
|
+
temperature?: number;
|
|
27
|
+
topP?: number;
|
|
28
|
+
topK?: number;
|
|
29
|
+
presencePenalty?: number;
|
|
30
|
+
frequencyPenalty?: number;
|
|
31
|
+
seed?: number;
|
|
32
|
+
reasoning?: ReasoningEffort;
|
|
33
|
+
models: readonly ResolvedModelProfile[];
|
|
34
|
+
defaultContextWindow: number;
|
|
35
|
+
defaultMaxTokens: number;
|
|
36
|
+
maxRequestImageBytes: number;
|
|
37
|
+
streamIdleTimeoutMs: number;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
retryPolicy: ResolvedRetryPolicy;
|
|
40
|
+
}
|
|
41
|
+
interface OpenAICompatibleAdapterOptions {
|
|
42
|
+
profiles: () => ReadonlyMap<string, ResolvedProviderProfile>;
|
|
43
|
+
resolveApiKey: (provider: string, profile: ResolvedProviderProfile) => Promise<string | undefined>;
|
|
44
|
+
resolveUserId: () => string;
|
|
45
|
+
resolveAttachments?: () => AttachmentStore | undefined;
|
|
46
|
+
}
|
|
47
|
+
declare class OpenAICompatibleAdapter extends LlmAdapter {
|
|
48
|
+
private readonly config;
|
|
49
|
+
private readonly sdkProviders;
|
|
50
|
+
constructor(config: OpenAICompatibleAdapterOptions);
|
|
51
|
+
private profileOf;
|
|
52
|
+
private modelOf;
|
|
53
|
+
private sdkModel;
|
|
54
|
+
providerInfo(provider: string): LlmProviderInfo;
|
|
55
|
+
providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined;
|
|
56
|
+
listModels(provider: string): Promise<readonly LlmModelInfo[]>;
|
|
57
|
+
resolveModel(provider: string, model: string, _signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
|
|
58
|
+
stream(options: GenerateOptions): AsyncGenerator<StreamChunk>;
|
|
59
|
+
private normalizeTransportError;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { OpenAICompatibleAdapter as a, ResolvedModelProfile as c, DEFAULT_STREAM_IDLE_TIMEOUT_MS as i, ResolvedProviderProfile as l, DEFAULT_MAX_REQUEST_IMAGE_BYTES as n, OpenAICompatibleAdapterOptions as o, DEFAULT_MAX_TOKENS as r, ReasoningEffort as s, DEFAULT_CONTEXT_WINDOW as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,66 +1,7 @@
|
|
|
1
|
+
import { a as OpenAICompatibleAdapter, c as ResolvedModelProfile, i as DEFAULT_STREAM_IDLE_TIMEOUT_MS, l as ResolvedProviderProfile, n as DEFAULT_MAX_REQUEST_IMAGE_BYTES, o as OpenAICompatibleAdapterOptions, r as DEFAULT_MAX_TOKENS, s as ReasoningEffort, t as DEFAULT_CONTEXT_WINDOW } from "./adapter-CYd_pegB.mjs";
|
|
1
2
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import {
|
|
3
|
-
import { CredentialRef } from "@deepseek-ai/dsh-credentials";
|
|
4
|
-
import "@ai-sdk/provider";
|
|
5
|
-
import { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
3
|
+
import { ModelModality, RetryPolicyConfig } from "@deepseek-ai/dsh-llm";
|
|
6
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
7
|
-
//#region src/adapter.d.ts
|
|
8
|
-
declare const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300000;
|
|
9
|
-
declare const DEFAULT_CONTEXT_WINDOW = 262144;
|
|
10
|
-
declare const DEFAULT_MAX_TOKENS = 32768;
|
|
11
|
-
declare const DEFAULT_MAX_REQUEST_IMAGE_BYTES: number;
|
|
12
|
-
type ReasoningEffort = "off" | "low" | "high" | "max";
|
|
13
|
-
interface ResolvedModelProfile {
|
|
14
|
-
id: string;
|
|
15
|
-
name?: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
contextWindow?: number;
|
|
18
|
-
maxTokens?: number;
|
|
19
|
-
inputModalities: readonly ModelModality[];
|
|
20
|
-
reasoningEfforts?: false | Partial<Record<ReasoningEffort, string | null>>;
|
|
21
|
-
}
|
|
22
|
-
interface ResolvedProviderProfile {
|
|
23
|
-
provider: string;
|
|
24
|
-
displayName: string;
|
|
25
|
-
apiKeyEnv?: CredentialRef;
|
|
26
|
-
baseURL: string;
|
|
27
|
-
headers?: Readonly<Record<string, string>>;
|
|
28
|
-
temperature?: number;
|
|
29
|
-
topP?: number;
|
|
30
|
-
topK?: number;
|
|
31
|
-
presencePenalty?: number;
|
|
32
|
-
frequencyPenalty?: number;
|
|
33
|
-
seed?: number;
|
|
34
|
-
reasoning?: ReasoningEffort;
|
|
35
|
-
models: readonly ResolvedModelProfile[];
|
|
36
|
-
defaultContextWindow: number;
|
|
37
|
-
defaultMaxTokens: number;
|
|
38
|
-
maxRequestImageBytes: number;
|
|
39
|
-
streamIdleTimeoutMs: number;
|
|
40
|
-
timeoutMs?: number;
|
|
41
|
-
retryPolicy: ResolvedRetryPolicy;
|
|
42
|
-
}
|
|
43
|
-
interface OpenAICompatibleAdapterOptions {
|
|
44
|
-
profiles: () => ReadonlyMap<string, ResolvedProviderProfile>;
|
|
45
|
-
resolveApiKey: (provider: string, profile: ResolvedProviderProfile) => Promise<string | undefined>;
|
|
46
|
-
resolveUserId: () => string;
|
|
47
|
-
resolveAttachments?: () => AttachmentStore | undefined;
|
|
48
|
-
}
|
|
49
|
-
declare class OpenAICompatibleAdapter extends LlmAdapter {
|
|
50
|
-
private readonly config;
|
|
51
|
-
private readonly sdkProviders;
|
|
52
|
-
constructor(config: OpenAICompatibleAdapterOptions);
|
|
53
|
-
private profileOf;
|
|
54
|
-
private modelOf;
|
|
55
|
-
private sdkModel;
|
|
56
|
-
providerInfo(provider: string): LlmProviderInfo;
|
|
57
|
-
providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined;
|
|
58
|
-
listModels(provider: string): Promise<readonly LlmModelInfo[]>;
|
|
59
|
-
resolveModel(provider: string, model: string, _signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
|
|
60
|
-
stream(options: GenerateOptions): AsyncGenerator<StreamChunk>;
|
|
61
|
-
private normalizeTransportError;
|
|
62
|
-
}
|
|
63
|
-
//#endregion
|
|
64
5
|
//#region src/index.d.ts
|
|
65
6
|
declare const name = "llm-openai-compatible";
|
|
66
7
|
declare const inject: string[];
|
|
@@ -105,5 +46,4 @@ declare function resolveProfiles(providers: Readonly<Record<string, ProviderProf
|
|
|
105
46
|
declare function assertServiceable(config: Config): void;
|
|
106
47
|
declare function apply(ctx: Context, config: Config): void;
|
|
107
48
|
//#endregion
|
|
108
|
-
export { Config, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_MAX_TOKENS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, MODEL_MODALITIES, ModelProfileSource, NS, OpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, ProviderProfileSource, REASONING_LEVELS, type ReasoningEffort, type ResolvedModelProfile, type ResolvedProviderProfile, apply, assertServiceable, inject, name, resolveAdapterOptions, resolveProfiles };
|
|
109
|
-
//# sourceMappingURL=index.d.mts.map
|
|
49
|
+
export { Config, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_MAX_TOKENS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, MODEL_MODALITIES, ModelProfileSource, NS, OpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, ProviderProfileSource, REASONING_LEVELS, type ReasoningEffort, type ResolvedModelProfile, type ResolvedProviderProfile, apply, assertServiceable, inject, name, resolveAdapterOptions, resolveProfiles };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { a as serializeCallOptions, o as serializeCallOptionsWithImages, r as translate } from "./translate-BzOJ1xx-.mjs";
|
|
1
2
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import { CONTEXT_WINDOW_EXCEEDED_CODE,
|
|
3
|
+
import { CONTEXT_WINDOW_EXCEEDED_CODE, LlmAdapter, LlmError, ProviderRequestId, QUOTA_EXCEEDED_CODE, ReasoningEffortId, RetryPolicySchema, assertUsableApiKey, attributionHeaders, contentHasImage, isContextWindowExceededError, isQuotaExceededError, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
3
4
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
4
5
|
import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
|
|
5
6
|
import { deepEqualJson } from "@deepseek-ai/dsh-util-values";
|
|
@@ -7,405 +8,6 @@ import { MAX_TIMER_DELAY_MS, deadline, idleWatchdog, timeoutOf } from "@deepseek
|
|
|
7
8
|
import { getOrCreateAnonymousUserId } from "@deepseek-ai/dsh-anonymous-user-id";
|
|
8
9
|
import { APICallError } from "@ai-sdk/provider";
|
|
9
10
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
10
|
-
import { AttachmentError } from "@deepseek-ai/dsh-attachment";
|
|
11
|
-
import { Buffer } from "node:buffer";
|
|
12
|
-
//#region src/serialize.ts
|
|
13
|
-
const TOOL_RESULT_IMAGE_TEXT = "Attached image(s) from tool result:";
|
|
14
|
-
function resolveReasoningWire(model, effort) {
|
|
15
|
-
if (effort === void 0) return void 0;
|
|
16
|
-
const declaration = model?.reasoningEfforts;
|
|
17
|
-
if (declaration === void 0 || declaration === false) {
|
|
18
|
-
const subject = model === void 0 ? "unlisted model" : `model "${model.id}"`;
|
|
19
|
-
throw new LlmError(`OpenAI-compatible ${subject} declares no reasoning efforts, so "${effort}" cannot be selected`, "UNSUPPORTED_REASONING_EFFORT");
|
|
20
|
-
}
|
|
21
|
-
const wire = declaration[effort];
|
|
22
|
-
if (wire === void 0) throw new LlmError(`OpenAI-compatible model "${model.id}" does not support reasoning effort "${effort}"`, "UNSUPPORTED_REASONING_EFFORT");
|
|
23
|
-
if (wire === null) return void 0;
|
|
24
|
-
return wire;
|
|
25
|
-
}
|
|
26
|
-
function flattenText(blocks) {
|
|
27
|
-
return blocks.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
28
|
-
}
|
|
29
|
-
function assertTextOnly(blocks) {
|
|
30
|
-
if (contentHasImage(blocks)) throw new LlmError("The OpenAI-compatible chat-completions adapter does not support image content in this message.", "UNSUPPORTED_CONTENT");
|
|
31
|
-
}
|
|
32
|
-
function assertSupportedImageRoles(messages) {
|
|
33
|
-
for (const message of messages) if (message.role !== "user" && contentHasImage(message.content)) throw new LlmError(`The OpenAI-compatible chat-completions adapter cannot represent image content in a ${message.role} message.`, "UNSUPPORTED_CONTENT");
|
|
34
|
-
}
|
|
35
|
-
async function imagePart(block, attachments, signal) {
|
|
36
|
-
try {
|
|
37
|
-
const stored = await attachments.readImage(block.attachment, signal);
|
|
38
|
-
return {
|
|
39
|
-
type: "file",
|
|
40
|
-
mediaType: stored.ref.mediaType,
|
|
41
|
-
data: {
|
|
42
|
-
type: "url",
|
|
43
|
-
url: new URL(`data:${stored.ref.mediaType};base64,${Buffer.from(stored.data).toString("base64")}`)
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
} catch (error) {
|
|
47
|
-
if (error instanceof AttachmentError) throw new LlmError(error.message, error.code, { cause: error });
|
|
48
|
-
throw error;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function assistantParts(message, toolNames) {
|
|
52
|
-
const parts = [];
|
|
53
|
-
for (const block of message.content) switch (block.type) {
|
|
54
|
-
case "text":
|
|
55
|
-
if (block.text.length > 0) parts.push({
|
|
56
|
-
type: "text",
|
|
57
|
-
text: block.text
|
|
58
|
-
});
|
|
59
|
-
break;
|
|
60
|
-
case "reasoning":
|
|
61
|
-
if (block.text.length > 0) parts.push({
|
|
62
|
-
type: "reasoning",
|
|
63
|
-
text: block.text
|
|
64
|
-
});
|
|
65
|
-
break;
|
|
66
|
-
case "tool-call": {
|
|
67
|
-
let input;
|
|
68
|
-
try {
|
|
69
|
-
input = JSON.parse(block.arguments);
|
|
70
|
-
} catch {
|
|
71
|
-
throw new LlmError(`assistant tool call "${block.id}" carries malformed JSON arguments`, "MALFORMED_RESPONSE");
|
|
72
|
-
}
|
|
73
|
-
parts.push({
|
|
74
|
-
type: "tool-call",
|
|
75
|
-
toolCallId: block.id,
|
|
76
|
-
toolName: block.name,
|
|
77
|
-
input
|
|
78
|
-
});
|
|
79
|
-
toolNames.set(block.id, block.name);
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return parts;
|
|
84
|
-
}
|
|
85
|
-
async function userParts(blocks, resolveImage, signal) {
|
|
86
|
-
const parts = [];
|
|
87
|
-
for (const block of blocks) switch (block.type) {
|
|
88
|
-
case "text":
|
|
89
|
-
if (block.text.length > 0) parts.push({
|
|
90
|
-
type: "text",
|
|
91
|
-
text: block.text
|
|
92
|
-
});
|
|
93
|
-
break;
|
|
94
|
-
case "image":
|
|
95
|
-
if (resolveImage === void 0) throw new LlmError("The OpenAI-compatible chat-completions adapter does not support image content in this message.", "UNSUPPORTED_CONTENT");
|
|
96
|
-
parts.push(await resolveImage(block, signal));
|
|
97
|
-
break;
|
|
98
|
-
case "tool-result": parts.push(...await userParts(block.content, resolveImage, signal));
|
|
99
|
-
}
|
|
100
|
-
return parts;
|
|
101
|
-
}
|
|
102
|
-
async function serializePrompt(messages, resolveImage, signal) {
|
|
103
|
-
if (resolveImage === void 0) for (const message of messages) assertTextOnly(message.content);
|
|
104
|
-
else assertSupportedImageRoles(messages);
|
|
105
|
-
const prompt = [];
|
|
106
|
-
const toolNames = /* @__PURE__ */ new Map();
|
|
107
|
-
let pendingToolImages = [];
|
|
108
|
-
const flushToolImages = () => {
|
|
109
|
-
if (pendingToolImages.length === 0) return;
|
|
110
|
-
prompt.push({
|
|
111
|
-
role: "user",
|
|
112
|
-
content: [{
|
|
113
|
-
type: "text",
|
|
114
|
-
text: TOOL_RESULT_IMAGE_TEXT
|
|
115
|
-
}, ...pendingToolImages]
|
|
116
|
-
});
|
|
117
|
-
pendingToolImages = [];
|
|
118
|
-
};
|
|
119
|
-
for (const message of messages) {
|
|
120
|
-
if (message.role === "system") {
|
|
121
|
-
flushToolImages();
|
|
122
|
-
prompt.push({
|
|
123
|
-
role: "system",
|
|
124
|
-
content: flattenText(message.content)
|
|
125
|
-
});
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (message.role === "assistant") {
|
|
129
|
-
flushToolImages();
|
|
130
|
-
const parts = assistantParts(message, toolNames);
|
|
131
|
-
if (parts.length > 0) prompt.push({
|
|
132
|
-
role: "assistant",
|
|
133
|
-
content: parts
|
|
134
|
-
});
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
const regular = message.content.filter((block) => block.type !== "tool-result");
|
|
138
|
-
const toolResults = message.content.filter((block) => block.type === "tool-result");
|
|
139
|
-
const content = await userParts(regular, resolveImage, signal);
|
|
140
|
-
if (content.length > 0 || toolResults.length === 0) {
|
|
141
|
-
flushToolImages();
|
|
142
|
-
prompt.push({
|
|
143
|
-
role: "user",
|
|
144
|
-
content
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
for (const result of toolResults) {
|
|
148
|
-
const images = [];
|
|
149
|
-
if (resolveImage !== void 0) {
|
|
150
|
-
for (const block of result.content) if (block.type === "image") images.push(await resolveImage(block, signal));
|
|
151
|
-
}
|
|
152
|
-
prompt.push({
|
|
153
|
-
role: "tool",
|
|
154
|
-
content: [{
|
|
155
|
-
type: "tool-result",
|
|
156
|
-
toolCallId: result.toolCallId,
|
|
157
|
-
toolName: toolNames.get(result.toolCallId) ?? "",
|
|
158
|
-
output: {
|
|
159
|
-
type: "text",
|
|
160
|
-
value: flattenText(result.content) || (images.length > 0 ? "(see attached image)" : "(no output)")
|
|
161
|
-
}
|
|
162
|
-
}]
|
|
163
|
-
});
|
|
164
|
-
pendingToolImages.push(...images);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
flushToolImages();
|
|
168
|
-
return prompt;
|
|
169
|
-
}
|
|
170
|
-
function serializeTools(options) {
|
|
171
|
-
const tools = options.tools?.map((tool) => ({
|
|
172
|
-
type: "function",
|
|
173
|
-
name: tool.name,
|
|
174
|
-
description: tool.description,
|
|
175
|
-
inputSchema: tool.parameters
|
|
176
|
-
}));
|
|
177
|
-
return tools !== void 0 && tools.length > 0 ? tools : void 0;
|
|
178
|
-
}
|
|
179
|
-
function callOptionsWithPrompt(options, profile, model, prompt) {
|
|
180
|
-
const tools = serializeTools(options);
|
|
181
|
-
const temperature = options.temperature ?? profile.temperature;
|
|
182
|
-
const maxOutputTokens = options.maxTokens ?? model?.maxTokens ?? profile.defaultMaxTokens;
|
|
183
|
-
const reasoningEffort = resolveReasoningWire(model, options.reasoningEffort === void 0 ? profile.reasoning : options.reasoningEffort);
|
|
184
|
-
const providerOptions = { "openai-compatible": {
|
|
185
|
-
...reasoningEffort === void 0 ? {} : { reasoningEffort },
|
|
186
|
-
...profile.topK === void 0 ? {} : { top_k: profile.topK }
|
|
187
|
-
} };
|
|
188
|
-
return {
|
|
189
|
-
prompt,
|
|
190
|
-
...temperature !== void 0 ? { temperature } : {},
|
|
191
|
-
...profile.topP !== void 0 ? { topP: profile.topP } : {},
|
|
192
|
-
...profile.presencePenalty !== void 0 ? { presencePenalty: profile.presencePenalty } : {},
|
|
193
|
-
...profile.frequencyPenalty !== void 0 ? { frequencyPenalty: profile.frequencyPenalty } : {},
|
|
194
|
-
...profile.seed !== void 0 ? { seed: profile.seed } : {},
|
|
195
|
-
...maxOutputTokens !== void 0 ? { maxOutputTokens } : {},
|
|
196
|
-
...options.stop !== void 0 ? { stopSequences: options.stop } : {},
|
|
197
|
-
...tools !== void 0 ? { tools } : {},
|
|
198
|
-
...Object.keys(providerOptions["openai-compatible"] ?? {}).length > 0 ? { providerOptions } : {}
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
async function serializeCallOptions(options, profile, model) {
|
|
202
|
-
const system = options.system === void 0 ? [] : [{
|
|
203
|
-
role: "system",
|
|
204
|
-
content: options.system
|
|
205
|
-
}];
|
|
206
|
-
const prompt = await serializePrompt(options.messages, void 0);
|
|
207
|
-
return callOptionsWithPrompt(options, profile, model, [...system, ...prompt]);
|
|
208
|
-
}
|
|
209
|
-
async function serializeCallOptionsWithImages(options, profile, model, images) {
|
|
210
|
-
const requestMessages = offloadRequestImagesWithPolicy(options.messages, {
|
|
211
|
-
representation: "raw",
|
|
212
|
-
maxBytes: images.maxRequestImageBytes,
|
|
213
|
-
placeholder: (ref) => textOnlyImageText(ref)
|
|
214
|
-
});
|
|
215
|
-
const resolveImage = (block, signal) => imagePart(block, images.attachments, signal);
|
|
216
|
-
const system = options.system === void 0 ? [] : [{
|
|
217
|
-
role: "system",
|
|
218
|
-
content: options.system
|
|
219
|
-
}];
|
|
220
|
-
const prompt = await serializePrompt(requestMessages, resolveImage, images.signal);
|
|
221
|
-
return callOptionsWithPrompt(options, profile, model, [...system, ...prompt]);
|
|
222
|
-
}
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region src/translate.ts
|
|
225
|
-
function mapFinishReason(reason) {
|
|
226
|
-
switch (reason.unified) {
|
|
227
|
-
case "stop": return { kind: "stop" };
|
|
228
|
-
case "tool-calls": return { kind: "tool-calls" };
|
|
229
|
-
case "length": return { kind: "max-tokens" };
|
|
230
|
-
default: return {
|
|
231
|
-
kind: "error",
|
|
232
|
-
failure: {
|
|
233
|
-
message: `model stopped: ${reason.raw ?? reason.unified}`,
|
|
234
|
-
code: (reason.raw ?? reason.unified).toUpperCase()
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
function mapUsage(usage) {
|
|
240
|
-
const cacheRead = usage.inputTokens.cacheRead;
|
|
241
|
-
const reasoning = usage.outputTokens.reasoning;
|
|
242
|
-
return {
|
|
243
|
-
inputTokens: usage.inputTokens.noCache ?? usage.inputTokens.total ?? 0,
|
|
244
|
-
outputTokens: usage.outputTokens.total ?? 0,
|
|
245
|
-
...cacheRead !== void 0 && cacheRead > 0 ? { cacheReadTokens: cacheRead } : {},
|
|
246
|
-
...reasoning !== void 0 && reasoning > 0 ? { reasoningTokens: reasoning } : {}
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
function closeBlock(block) {
|
|
250
|
-
switch (block.kind) {
|
|
251
|
-
case "text": return {
|
|
252
|
-
type: "text",
|
|
253
|
-
text: block.text
|
|
254
|
-
};
|
|
255
|
-
case "reasoning": return {
|
|
256
|
-
type: "reasoning",
|
|
257
|
-
text: block.text
|
|
258
|
-
};
|
|
259
|
-
case "tool-call": return {
|
|
260
|
-
type: "tool-call",
|
|
261
|
-
id: ToolCallId(block.callId ?? ""),
|
|
262
|
-
name: block.name ?? "",
|
|
263
|
-
arguments: block.text
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
async function* translate(stream) {
|
|
268
|
-
let nextIndex = 0;
|
|
269
|
-
const textBlocks = /* @__PURE__ */ new Map();
|
|
270
|
-
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
271
|
-
const toolBlocks = /* @__PURE__ */ new Map();
|
|
272
|
-
const toolQueue = [];
|
|
273
|
-
const order = [];
|
|
274
|
-
let pendingUsage;
|
|
275
|
-
let pendingFinish;
|
|
276
|
-
const open = (kind) => {
|
|
277
|
-
const block = {
|
|
278
|
-
index: nextIndex++,
|
|
279
|
-
kind,
|
|
280
|
-
text: ""
|
|
281
|
-
};
|
|
282
|
-
order.push(block);
|
|
283
|
-
return block;
|
|
284
|
-
};
|
|
285
|
-
for await (const part of stream) switch (part.type) {
|
|
286
|
-
case "stream-start":
|
|
287
|
-
case "response-metadata":
|
|
288
|
-
case "raw": break;
|
|
289
|
-
case "text-start": {
|
|
290
|
-
const block = open("text");
|
|
291
|
-
textBlocks.set(part.id, block);
|
|
292
|
-
yield {
|
|
293
|
-
type: "block-start",
|
|
294
|
-
index: block.index,
|
|
295
|
-
blockType: "text"
|
|
296
|
-
};
|
|
297
|
-
break;
|
|
298
|
-
}
|
|
299
|
-
case "text-delta": {
|
|
300
|
-
const block = textBlocks.get(part.id);
|
|
301
|
-
if (block === void 0) break;
|
|
302
|
-
block.text += part.delta;
|
|
303
|
-
yield {
|
|
304
|
-
type: "text-delta",
|
|
305
|
-
index: block.index,
|
|
306
|
-
text: part.delta
|
|
307
|
-
};
|
|
308
|
-
break;
|
|
309
|
-
}
|
|
310
|
-
case "text-end": break;
|
|
311
|
-
case "reasoning-start": {
|
|
312
|
-
const block = open("reasoning");
|
|
313
|
-
reasoningBlocks.set(part.id, block);
|
|
314
|
-
yield {
|
|
315
|
-
type: "block-start",
|
|
316
|
-
index: block.index,
|
|
317
|
-
blockType: "reasoning"
|
|
318
|
-
};
|
|
319
|
-
break;
|
|
320
|
-
}
|
|
321
|
-
case "reasoning-delta": {
|
|
322
|
-
const block = reasoningBlocks.get(part.id);
|
|
323
|
-
if (block === void 0) break;
|
|
324
|
-
block.text += part.delta;
|
|
325
|
-
yield {
|
|
326
|
-
type: "reasoning-delta",
|
|
327
|
-
index: block.index,
|
|
328
|
-
text: part.delta
|
|
329
|
-
};
|
|
330
|
-
break;
|
|
331
|
-
}
|
|
332
|
-
case "reasoning-end": break;
|
|
333
|
-
case "tool-input-start": {
|
|
334
|
-
const block = open("tool-call");
|
|
335
|
-
if (part.toolName !== void 0) block.name = part.toolName;
|
|
336
|
-
toolBlocks.set(part.id, block);
|
|
337
|
-
toolQueue.push(block);
|
|
338
|
-
yield {
|
|
339
|
-
type: "block-start",
|
|
340
|
-
index: block.index,
|
|
341
|
-
blockType: "tool-call"
|
|
342
|
-
};
|
|
343
|
-
break;
|
|
344
|
-
}
|
|
345
|
-
case "tool-input-delta": {
|
|
346
|
-
const block = toolBlocks.get(part.id);
|
|
347
|
-
if (block === void 0) break;
|
|
348
|
-
block.text += part.delta;
|
|
349
|
-
yield {
|
|
350
|
-
type: "tool-call-delta",
|
|
351
|
-
index: block.index,
|
|
352
|
-
id: ToolCallId(block.callId ?? part.id),
|
|
353
|
-
...block.name !== void 0 ? { name: block.name } : {},
|
|
354
|
-
argumentsDelta: part.delta
|
|
355
|
-
};
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
case "tool-input-end": break;
|
|
359
|
-
case "tool-call":
|
|
360
|
-
applyToolCall(part, toolQueue);
|
|
361
|
-
break;
|
|
362
|
-
case "tool-result":
|
|
363
|
-
case "tool-approval-request":
|
|
364
|
-
case "custom":
|
|
365
|
-
case "file":
|
|
366
|
-
case "reasoning-file":
|
|
367
|
-
case "source": break;
|
|
368
|
-
case "finish":
|
|
369
|
-
pendingUsage = mapUsage(part.usage);
|
|
370
|
-
pendingFinish = mapFinishReason(part.finishReason);
|
|
371
|
-
for (const block of order) yield {
|
|
372
|
-
type: "block-end",
|
|
373
|
-
index: block.index,
|
|
374
|
-
block: closeBlock(block)
|
|
375
|
-
};
|
|
376
|
-
if (pendingUsage !== void 0) yield {
|
|
377
|
-
type: "usage",
|
|
378
|
-
usage: pendingUsage
|
|
379
|
-
};
|
|
380
|
-
const reason = pendingFinish ?? { kind: "stop" };
|
|
381
|
-
yield {
|
|
382
|
-
type: "finish",
|
|
383
|
-
reason: reason.kind === "stop" && order.length === 0 ? {
|
|
384
|
-
kind: "error",
|
|
385
|
-
failure: {
|
|
386
|
-
message: "model returned a completed response with no content",
|
|
387
|
-
code: EMPTY_RESPONSE_CODE
|
|
388
|
-
}
|
|
389
|
-
} : reason
|
|
390
|
-
};
|
|
391
|
-
return;
|
|
392
|
-
case "error": {
|
|
393
|
-
const error = part.error;
|
|
394
|
-
const cause = error instanceof Error ? error : void 0;
|
|
395
|
-
const message = cause?.message ?? (typeof error === "string" ? error : "provider stream error");
|
|
396
|
-
throw new LlmError(`OpenAI-compatible stream failed: ${message}`, "TRANSPORT", { cause });
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
throw new LlmError("AI SDK stream ended without a finish part", "STREAM_CLOSED");
|
|
400
|
-
}
|
|
401
|
-
function applyToolCall(part, toolQueue) {
|
|
402
|
-
const block = toolQueue.shift();
|
|
403
|
-
if (block === void 0) return;
|
|
404
|
-
block.callId = part.toolCallId;
|
|
405
|
-
block.name = part.toolName;
|
|
406
|
-
block.text = part.input;
|
|
407
|
-
}
|
|
408
|
-
//#endregion
|
|
409
11
|
//#region src/adapter.ts
|
|
410
12
|
const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
|
|
411
13
|
const DEFAULT_CONTEXT_WINDOW = 262144;
|
|
@@ -891,5 +493,3 @@ function apply(ctx, config) {
|
|
|
891
493
|
}
|
|
892
494
|
//#endregion
|
|
893
495
|
export { Config, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_MAX_TOKENS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, MODEL_MODALITIES, NS, OpenAICompatibleAdapter, REASONING_LEVELS, apply, assertServiceable, inject, name, resolveAdapterOptions, resolveProfiles };
|
|
894
|
-
|
|
895
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
//#region src/invariant.d.ts
|
|
3
|
+
declare const name = "llm-openai-compatible-invariant";
|
|
4
|
+
declare const inject: string[];
|
|
5
|
+
declare const apply: (ctx: Context) => Promise<() => void>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/invariant.ts
|
|
2
|
+
const PACKAGE_NAME = "@morlay/dsh-llm-openai-compatible";
|
|
3
|
+
const name = "llm-openai-compatible-invariant";
|
|
4
|
+
const inject = ["invariants"];
|
|
5
|
+
const install = () => {};
|
|
6
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
7
|
+
//#endregion
|
|
8
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { EMPTY_RESPONSE_CODE, LlmError, ToolCallId, contentHasImage, offloadRequestImagesWithPolicy, textOnlyImageText } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import { AttachmentError } from "@deepseek-ai/dsh-attachment";
|
|
3
|
+
import { Buffer } from "node:buffer";
|
|
4
|
+
//#region src/serialize.ts
|
|
5
|
+
const TOOL_RESULT_IMAGE_TEXT = "Attached image(s) from tool result:";
|
|
6
|
+
function resolveReasoningWire(model, effort) {
|
|
7
|
+
if (effort === void 0) return void 0;
|
|
8
|
+
const declaration = model?.reasoningEfforts;
|
|
9
|
+
if (declaration === void 0 || declaration === false) {
|
|
10
|
+
const subject = model === void 0 ? "unlisted model" : `model "${model.id}"`;
|
|
11
|
+
throw new LlmError(`OpenAI-compatible ${subject} declares no reasoning efforts, so "${effort}" cannot be selected`, "UNSUPPORTED_REASONING_EFFORT");
|
|
12
|
+
}
|
|
13
|
+
const wire = declaration[effort];
|
|
14
|
+
if (wire === void 0) throw new LlmError(`OpenAI-compatible model "${model.id}" does not support reasoning effort "${effort}"`, "UNSUPPORTED_REASONING_EFFORT");
|
|
15
|
+
if (wire === null) return void 0;
|
|
16
|
+
return wire;
|
|
17
|
+
}
|
|
18
|
+
function flattenText(blocks) {
|
|
19
|
+
return blocks.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
20
|
+
}
|
|
21
|
+
function assertTextOnly(blocks) {
|
|
22
|
+
if (contentHasImage(blocks)) throw new LlmError("The OpenAI-compatible chat-completions adapter does not support image content in this message.", "UNSUPPORTED_CONTENT");
|
|
23
|
+
}
|
|
24
|
+
function assertSupportedImageRoles(messages) {
|
|
25
|
+
for (const message of messages) if (message.role !== "user" && contentHasImage(message.content)) throw new LlmError(`The OpenAI-compatible chat-completions adapter cannot represent image content in a ${message.role} message.`, "UNSUPPORTED_CONTENT");
|
|
26
|
+
}
|
|
27
|
+
async function imagePart(block, attachments, signal) {
|
|
28
|
+
try {
|
|
29
|
+
const stored = await attachments.readImage(block.attachment, signal);
|
|
30
|
+
return {
|
|
31
|
+
type: "file",
|
|
32
|
+
mediaType: stored.ref.mediaType,
|
|
33
|
+
data: {
|
|
34
|
+
type: "url",
|
|
35
|
+
url: new URL(`data:${stored.ref.mediaType};base64,${Buffer.from(stored.data).toString("base64")}`)
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (error instanceof AttachmentError) throw new LlmError(error.message, error.code, { cause: error });
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function assistantParts(message, toolNames) {
|
|
44
|
+
const parts = [];
|
|
45
|
+
for (const block of message.content) switch (block.type) {
|
|
46
|
+
case "text":
|
|
47
|
+
if (block.text.length > 0) parts.push({
|
|
48
|
+
type: "text",
|
|
49
|
+
text: block.text
|
|
50
|
+
});
|
|
51
|
+
break;
|
|
52
|
+
case "reasoning":
|
|
53
|
+
if (block.text.length > 0) parts.push({
|
|
54
|
+
type: "reasoning",
|
|
55
|
+
text: block.text
|
|
56
|
+
});
|
|
57
|
+
break;
|
|
58
|
+
case "tool-call": {
|
|
59
|
+
let input;
|
|
60
|
+
try {
|
|
61
|
+
input = JSON.parse(block.arguments);
|
|
62
|
+
} catch {
|
|
63
|
+
throw new LlmError(`assistant tool call "${block.id}" carries malformed JSON arguments`, "MALFORMED_RESPONSE");
|
|
64
|
+
}
|
|
65
|
+
parts.push({
|
|
66
|
+
type: "tool-call",
|
|
67
|
+
toolCallId: block.id,
|
|
68
|
+
toolName: block.name,
|
|
69
|
+
input
|
|
70
|
+
});
|
|
71
|
+
toolNames.set(block.id, block.name);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return parts;
|
|
76
|
+
}
|
|
77
|
+
async function userParts(blocks, resolveImage, signal) {
|
|
78
|
+
const parts = [];
|
|
79
|
+
for (const block of blocks) switch (block.type) {
|
|
80
|
+
case "text":
|
|
81
|
+
if (block.text.length > 0) parts.push({
|
|
82
|
+
type: "text",
|
|
83
|
+
text: block.text
|
|
84
|
+
});
|
|
85
|
+
break;
|
|
86
|
+
case "image":
|
|
87
|
+
if (resolveImage === void 0) throw new LlmError("The OpenAI-compatible chat-completions adapter does not support image content in this message.", "UNSUPPORTED_CONTENT");
|
|
88
|
+
parts.push(await resolveImage(block, signal));
|
|
89
|
+
break;
|
|
90
|
+
case "tool-result": parts.push(...await userParts(block.content, resolveImage, signal));
|
|
91
|
+
}
|
|
92
|
+
return parts;
|
|
93
|
+
}
|
|
94
|
+
async function serializePrompt(messages, resolveImage, signal) {
|
|
95
|
+
if (resolveImage === void 0) for (const message of messages) assertTextOnly(message.content);
|
|
96
|
+
else assertSupportedImageRoles(messages);
|
|
97
|
+
const prompt = [];
|
|
98
|
+
const toolNames = /* @__PURE__ */ new Map();
|
|
99
|
+
let pendingToolImages = [];
|
|
100
|
+
const flushToolImages = () => {
|
|
101
|
+
if (pendingToolImages.length === 0) return;
|
|
102
|
+
prompt.push({
|
|
103
|
+
role: "user",
|
|
104
|
+
content: [{
|
|
105
|
+
type: "text",
|
|
106
|
+
text: TOOL_RESULT_IMAGE_TEXT
|
|
107
|
+
}, ...pendingToolImages]
|
|
108
|
+
});
|
|
109
|
+
pendingToolImages = [];
|
|
110
|
+
};
|
|
111
|
+
for (const message of messages) {
|
|
112
|
+
if (message.role === "system") {
|
|
113
|
+
flushToolImages();
|
|
114
|
+
prompt.push({
|
|
115
|
+
role: "system",
|
|
116
|
+
content: flattenText(message.content)
|
|
117
|
+
});
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (message.role === "assistant") {
|
|
121
|
+
flushToolImages();
|
|
122
|
+
const parts = assistantParts(message, toolNames);
|
|
123
|
+
if (parts.length > 0) prompt.push({
|
|
124
|
+
role: "assistant",
|
|
125
|
+
content: parts
|
|
126
|
+
});
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const regular = message.content.filter((block) => block.type !== "tool-result");
|
|
130
|
+
const toolResults = message.content.filter((block) => block.type === "tool-result");
|
|
131
|
+
const content = await userParts(regular, resolveImage, signal);
|
|
132
|
+
if (content.length > 0 || toolResults.length === 0) {
|
|
133
|
+
flushToolImages();
|
|
134
|
+
prompt.push({
|
|
135
|
+
role: "user",
|
|
136
|
+
content
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
for (const result of toolResults) {
|
|
140
|
+
const images = [];
|
|
141
|
+
if (resolveImage !== void 0) {
|
|
142
|
+
for (const block of result.content) if (block.type === "image") images.push(await resolveImage(block, signal));
|
|
143
|
+
}
|
|
144
|
+
prompt.push({
|
|
145
|
+
role: "tool",
|
|
146
|
+
content: [{
|
|
147
|
+
type: "tool-result",
|
|
148
|
+
toolCallId: result.toolCallId,
|
|
149
|
+
toolName: toolNames.get(result.toolCallId) ?? "",
|
|
150
|
+
output: {
|
|
151
|
+
type: "text",
|
|
152
|
+
value: flattenText(result.content) || (images.length > 0 ? "(see attached image)" : "(no output)")
|
|
153
|
+
}
|
|
154
|
+
}]
|
|
155
|
+
});
|
|
156
|
+
pendingToolImages.push(...images);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
flushToolImages();
|
|
160
|
+
return prompt;
|
|
161
|
+
}
|
|
162
|
+
function serializeTools(options) {
|
|
163
|
+
const tools = options.tools?.map((tool) => ({
|
|
164
|
+
type: "function",
|
|
165
|
+
name: tool.name,
|
|
166
|
+
description: tool.description,
|
|
167
|
+
inputSchema: tool.parameters
|
|
168
|
+
}));
|
|
169
|
+
return tools !== void 0 && tools.length > 0 ? tools : void 0;
|
|
170
|
+
}
|
|
171
|
+
function callOptionsWithPrompt(options, profile, model, prompt) {
|
|
172
|
+
const tools = serializeTools(options);
|
|
173
|
+
const temperature = options.temperature ?? profile.temperature;
|
|
174
|
+
const maxOutputTokens = options.maxTokens ?? model?.maxTokens ?? profile.defaultMaxTokens;
|
|
175
|
+
const reasoningEffort = resolveReasoningWire(model, options.reasoningEffort === void 0 ? profile.reasoning : options.reasoningEffort);
|
|
176
|
+
const providerOptions = { "openai-compatible": {
|
|
177
|
+
...reasoningEffort === void 0 ? {} : { reasoningEffort },
|
|
178
|
+
...profile.topK === void 0 ? {} : { top_k: profile.topK }
|
|
179
|
+
} };
|
|
180
|
+
return {
|
|
181
|
+
prompt,
|
|
182
|
+
...temperature !== void 0 ? { temperature } : {},
|
|
183
|
+
...profile.topP !== void 0 ? { topP: profile.topP } : {},
|
|
184
|
+
...profile.presencePenalty !== void 0 ? { presencePenalty: profile.presencePenalty } : {},
|
|
185
|
+
...profile.frequencyPenalty !== void 0 ? { frequencyPenalty: profile.frequencyPenalty } : {},
|
|
186
|
+
...profile.seed !== void 0 ? { seed: profile.seed } : {},
|
|
187
|
+
...maxOutputTokens !== void 0 ? { maxOutputTokens } : {},
|
|
188
|
+
...options.stop !== void 0 ? { stopSequences: options.stop } : {},
|
|
189
|
+
...tools !== void 0 ? { tools } : {},
|
|
190
|
+
...Object.keys(providerOptions["openai-compatible"] ?? {}).length > 0 ? { providerOptions } : {}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
async function serializeCallOptions(options, profile, model) {
|
|
194
|
+
const system = options.system === void 0 ? [] : [{
|
|
195
|
+
role: "system",
|
|
196
|
+
content: options.system
|
|
197
|
+
}];
|
|
198
|
+
const prompt = await serializePrompt(options.messages, void 0);
|
|
199
|
+
return callOptionsWithPrompt(options, profile, model, [...system, ...prompt]);
|
|
200
|
+
}
|
|
201
|
+
async function serializeCallOptionsWithImages(options, profile, model, images) {
|
|
202
|
+
const requestMessages = offloadRequestImagesWithPolicy(options.messages, {
|
|
203
|
+
representation: "raw",
|
|
204
|
+
maxBytes: images.maxRequestImageBytes,
|
|
205
|
+
placeholder: (ref) => textOnlyImageText(ref)
|
|
206
|
+
});
|
|
207
|
+
const resolveImage = (block, signal) => imagePart(block, images.attachments, signal);
|
|
208
|
+
const system = options.system === void 0 ? [] : [{
|
|
209
|
+
role: "system",
|
|
210
|
+
content: options.system
|
|
211
|
+
}];
|
|
212
|
+
const prompt = await serializePrompt(requestMessages, resolveImage, images.signal);
|
|
213
|
+
return callOptionsWithPrompt(options, profile, model, [...system, ...prompt]);
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/translate.ts
|
|
217
|
+
function mapFinishReason(reason) {
|
|
218
|
+
switch (reason.unified) {
|
|
219
|
+
case "stop": return { kind: "stop" };
|
|
220
|
+
case "tool-calls": return { kind: "tool-calls" };
|
|
221
|
+
case "length": return { kind: "max-tokens" };
|
|
222
|
+
default: return {
|
|
223
|
+
kind: "error",
|
|
224
|
+
failure: {
|
|
225
|
+
message: `model stopped: ${reason.raw ?? reason.unified}`,
|
|
226
|
+
code: (reason.raw ?? reason.unified).toUpperCase()
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function mapUsage(usage) {
|
|
232
|
+
const cacheRead = usage.inputTokens.cacheRead;
|
|
233
|
+
const reasoning = usage.outputTokens.reasoning;
|
|
234
|
+
return {
|
|
235
|
+
inputTokens: usage.inputTokens.noCache ?? usage.inputTokens.total ?? 0,
|
|
236
|
+
outputTokens: usage.outputTokens.total ?? 0,
|
|
237
|
+
...cacheRead !== void 0 && cacheRead > 0 ? { cacheReadTokens: cacheRead } : {},
|
|
238
|
+
...reasoning !== void 0 && reasoning > 0 ? { reasoningTokens: reasoning } : {}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function closeBlock(block) {
|
|
242
|
+
switch (block.kind) {
|
|
243
|
+
case "text": return {
|
|
244
|
+
type: "text",
|
|
245
|
+
text: block.text
|
|
246
|
+
};
|
|
247
|
+
case "reasoning": return {
|
|
248
|
+
type: "reasoning",
|
|
249
|
+
text: block.text
|
|
250
|
+
};
|
|
251
|
+
case "tool-call": return {
|
|
252
|
+
type: "tool-call",
|
|
253
|
+
id: ToolCallId(block.callId ?? ""),
|
|
254
|
+
name: block.name ?? "",
|
|
255
|
+
arguments: block.text
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function* translate(stream) {
|
|
260
|
+
let nextIndex = 0;
|
|
261
|
+
const textBlocks = /* @__PURE__ */ new Map();
|
|
262
|
+
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
263
|
+
const toolBlocks = /* @__PURE__ */ new Map();
|
|
264
|
+
const toolQueue = [];
|
|
265
|
+
const order = [];
|
|
266
|
+
let pendingUsage;
|
|
267
|
+
let pendingFinish;
|
|
268
|
+
const open = (kind) => {
|
|
269
|
+
const block = {
|
|
270
|
+
index: nextIndex++,
|
|
271
|
+
kind,
|
|
272
|
+
text: ""
|
|
273
|
+
};
|
|
274
|
+
order.push(block);
|
|
275
|
+
return block;
|
|
276
|
+
};
|
|
277
|
+
for await (const part of stream) switch (part.type) {
|
|
278
|
+
case "stream-start":
|
|
279
|
+
case "response-metadata":
|
|
280
|
+
case "raw": break;
|
|
281
|
+
case "text-start": {
|
|
282
|
+
const block = open("text");
|
|
283
|
+
textBlocks.set(part.id, block);
|
|
284
|
+
yield {
|
|
285
|
+
type: "block-start",
|
|
286
|
+
index: block.index,
|
|
287
|
+
blockType: "text"
|
|
288
|
+
};
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case "text-delta": {
|
|
292
|
+
const block = textBlocks.get(part.id);
|
|
293
|
+
if (block === void 0) break;
|
|
294
|
+
block.text += part.delta;
|
|
295
|
+
yield {
|
|
296
|
+
type: "text-delta",
|
|
297
|
+
index: block.index,
|
|
298
|
+
text: part.delta
|
|
299
|
+
};
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case "text-end": break;
|
|
303
|
+
case "reasoning-start": {
|
|
304
|
+
const block = open("reasoning");
|
|
305
|
+
reasoningBlocks.set(part.id, block);
|
|
306
|
+
yield {
|
|
307
|
+
type: "block-start",
|
|
308
|
+
index: block.index,
|
|
309
|
+
blockType: "reasoning"
|
|
310
|
+
};
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
case "reasoning-delta": {
|
|
314
|
+
const block = reasoningBlocks.get(part.id);
|
|
315
|
+
if (block === void 0) break;
|
|
316
|
+
block.text += part.delta;
|
|
317
|
+
yield {
|
|
318
|
+
type: "reasoning-delta",
|
|
319
|
+
index: block.index,
|
|
320
|
+
text: part.delta
|
|
321
|
+
};
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
case "reasoning-end": break;
|
|
325
|
+
case "tool-input-start": {
|
|
326
|
+
const block = open("tool-call");
|
|
327
|
+
if (part.toolName !== void 0) block.name = part.toolName;
|
|
328
|
+
toolBlocks.set(part.id, block);
|
|
329
|
+
toolQueue.push(block);
|
|
330
|
+
yield {
|
|
331
|
+
type: "block-start",
|
|
332
|
+
index: block.index,
|
|
333
|
+
blockType: "tool-call"
|
|
334
|
+
};
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
case "tool-input-delta": {
|
|
338
|
+
const block = toolBlocks.get(part.id);
|
|
339
|
+
if (block === void 0) break;
|
|
340
|
+
block.text += part.delta;
|
|
341
|
+
yield {
|
|
342
|
+
type: "tool-call-delta",
|
|
343
|
+
index: block.index,
|
|
344
|
+
id: ToolCallId(block.callId ?? part.id),
|
|
345
|
+
...block.name !== void 0 ? { name: block.name } : {},
|
|
346
|
+
argumentsDelta: part.delta
|
|
347
|
+
};
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case "tool-input-end": break;
|
|
351
|
+
case "tool-call":
|
|
352
|
+
applyToolCall(part, toolQueue);
|
|
353
|
+
break;
|
|
354
|
+
case "tool-result":
|
|
355
|
+
case "tool-approval-request":
|
|
356
|
+
case "custom":
|
|
357
|
+
case "file":
|
|
358
|
+
case "reasoning-file":
|
|
359
|
+
case "source": break;
|
|
360
|
+
case "finish":
|
|
361
|
+
pendingUsage = mapUsage(part.usage);
|
|
362
|
+
pendingFinish = mapFinishReason(part.finishReason);
|
|
363
|
+
for (const block of order) yield {
|
|
364
|
+
type: "block-end",
|
|
365
|
+
index: block.index,
|
|
366
|
+
block: closeBlock(block)
|
|
367
|
+
};
|
|
368
|
+
if (pendingUsage !== void 0) yield {
|
|
369
|
+
type: "usage",
|
|
370
|
+
usage: pendingUsage
|
|
371
|
+
};
|
|
372
|
+
const reason = pendingFinish ?? { kind: "stop" };
|
|
373
|
+
yield {
|
|
374
|
+
type: "finish",
|
|
375
|
+
reason: reason.kind === "stop" && order.length === 0 ? {
|
|
376
|
+
kind: "error",
|
|
377
|
+
failure: {
|
|
378
|
+
message: "model returned a completed response with no content",
|
|
379
|
+
code: EMPTY_RESPONSE_CODE
|
|
380
|
+
}
|
|
381
|
+
} : reason
|
|
382
|
+
};
|
|
383
|
+
return;
|
|
384
|
+
case "error": {
|
|
385
|
+
const error = part.error;
|
|
386
|
+
const cause = error instanceof Error ? error : void 0;
|
|
387
|
+
const message = cause?.message ?? (typeof error === "string" ? error : "provider stream error");
|
|
388
|
+
throw new LlmError(`OpenAI-compatible stream failed: ${message}`, "TRANSPORT", { cause });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
throw new LlmError("AI SDK stream ended without a finish part", "STREAM_CLOSED");
|
|
392
|
+
}
|
|
393
|
+
function applyToolCall(part, toolQueue) {
|
|
394
|
+
const block = toolQueue.shift();
|
|
395
|
+
if (block === void 0) return;
|
|
396
|
+
block.callId = part.toolCallId;
|
|
397
|
+
block.name = part.toolName;
|
|
398
|
+
block.text = part.input;
|
|
399
|
+
}
|
|
400
|
+
//#endregion
|
|
401
|
+
export { serializeCallOptions as a, resolveReasoningWire as i, mapUsage as n, serializeCallOptionsWithImages as o, translate as r, mapFinishReason as t };
|
package/dist/wire.d.mts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { c as ResolvedModelProfile, l as ResolvedProviderProfile } from "./adapter-CYd_pegB.mjs";
|
|
2
|
+
import { FinishReason, GenerateOptions, StreamChunk, TokenUsage } from "@deepseek-ai/dsh-llm";
|
|
3
|
+
import { LanguageModelV4FinishReason, LanguageModelV4FunctionTool, LanguageModelV4Prompt, LanguageModelV4StreamPart, LanguageModelV4Usage, SharedV4ProviderOptions } from "@ai-sdk/provider";
|
|
4
|
+
import { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
5
|
+
//#region src/serialize.d.ts
|
|
6
|
+
type OpenAICompatibleProviderOptions = SharedV4ProviderOptions & {
|
|
7
|
+
"openai-compatible"?: {
|
|
8
|
+
reasoningEffort?: string;
|
|
9
|
+
top_k?: number;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
interface OpenAICompatibleCallOptions {
|
|
13
|
+
prompt: LanguageModelV4Prompt;
|
|
14
|
+
maxOutputTokens?: number;
|
|
15
|
+
temperature?: number;
|
|
16
|
+
topP?: number;
|
|
17
|
+
presencePenalty?: number;
|
|
18
|
+
frequencyPenalty?: number;
|
|
19
|
+
seed?: number;
|
|
20
|
+
stopSequences?: string[];
|
|
21
|
+
tools?: LanguageModelV4FunctionTool[];
|
|
22
|
+
providerOptions?: OpenAICompatibleProviderOptions;
|
|
23
|
+
}
|
|
24
|
+
declare function resolveReasoningWire(model: ResolvedModelProfile | undefined, effort: ResolvedProviderProfile["reasoning"] | undefined): string | undefined;
|
|
25
|
+
declare function serializeCallOptions(options: GenerateOptions, profile: ResolvedProviderProfile, model: ResolvedModelProfile | undefined): Promise<OpenAICompatibleCallOptions>;
|
|
26
|
+
declare function serializeCallOptionsWithImages(options: GenerateOptions, profile: ResolvedProviderProfile, model: ResolvedModelProfile | undefined, images: {
|
|
27
|
+
attachments: AttachmentStore;
|
|
28
|
+
maxRequestImageBytes: number;
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
}): Promise<OpenAICompatibleCallOptions>;
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/translate.d.ts
|
|
33
|
+
declare function mapFinishReason(reason: LanguageModelV4FinishReason): FinishReason;
|
|
34
|
+
declare function mapUsage(usage: LanguageModelV4Usage): TokenUsage;
|
|
35
|
+
declare function translate(stream: ReadableStream<LanguageModelV4StreamPart>): AsyncGenerator<StreamChunk, void>;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { OpenAICompatibleCallOptions, OpenAICompatibleProviderOptions, mapFinishReason, mapUsage, resolveReasoningWire, serializeCallOptions, serializeCallOptionsWithImages, translate };
|
package/dist/wire.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as serializeCallOptions, i as resolveReasoningWire, n as mapUsage, o as serializeCallOptionsWithImages, r as translate, t as mapFinishReason } from "./translate-BzOJ1xx-.mjs";
|
|
2
|
+
export { mapFinishReason, mapUsage, resolveReasoningWire, serializeCallOptions, serializeCallOptionsWithImages, translate };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morlay/dsh-llm-openai-compatible",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "OpenAI-compatible LLM adapter plugin for DeepSeek Harness with configurable default sampling parameters (temperature / topP / topK / penalties / seed) over a providers dict.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "https://github.com/morlay/
|
|
16
|
+
"url": "https://github.com/morlay/better-session.git"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist",
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"type": "module",
|
|
25
25
|
"exports": {
|
|
26
26
|
".": "./dist/index.mjs",
|
|
27
|
+
"./invariant": "./dist/invariant.mjs",
|
|
28
|
+
"./wire": "./dist/wire.mjs",
|
|
27
29
|
"./package.json": "./package.json",
|
|
28
30
|
"./cordis.patch.yml": "./cordis.patch.yml"
|
|
29
31
|
},
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
"@deepseek-ai/dsh-anonymous-user-id": "^0.1.2-rc.1",
|
|
38
40
|
"@deepseek-ai/dsh-attachment": "^0.1.2-rc.1",
|
|
39
41
|
"@deepseek-ai/dsh-credentials": "^0.1.2-rc.1",
|
|
42
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-rc.1",
|
|
40
43
|
"@deepseek-ai/dsh-launch-environment": "^0.1.2-rc.1",
|
|
41
44
|
"@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
|
|
42
45
|
"@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
|
package/src/invariant.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { InvariantInstaller } from "@deepseek-ai/dsh-invariants";
|
|
3
|
+
|
|
4
|
+
const PACKAGE_NAME = "@morlay/dsh-llm-openai-compatible";
|
|
5
|
+
|
|
6
|
+
export const name = "llm-openai-compatible-invariant";
|
|
7
|
+
|
|
8
|
+
export const inject = ["invariants"];
|
|
9
|
+
|
|
10
|
+
const install: InvariantInstaller = () => {};
|
|
11
|
+
|
|
12
|
+
export const apply = (ctx: Context): Promise<() => void> =>
|
|
13
|
+
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
package/src/wire.ts
ADDED
package/dist/index.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapter.ts","../src/index.ts"],"mappings":";;;;;;;cA8Ba;cAEA;cAEA;cAEA;KAQD;UAEK;EACf;EACA;EACA;EACA;EACA;EACA,0BAA0B;EAE1B,2BAA2B,QAAQ,OAAO;;UAG3B;EACf;EACA;EAEA,YAAY;EAEZ;EACA,UAAU,SAAS;EAEnB;EACA;EACA;EACA;EACA;EACA;EAEA,YAAY;EAEZ,iBAAiB;EACjB;EACA;EAEA;EACA;EAEA;EACA,aAAa;;UAGE;EACf,gBAAgB,oBAAoB;EAEpC,gBACE,kBACA,SAAS,4BACN;EAEL;EAEA,2BAA2B;;cA8GhB,gCAAgC;mBAC1B;mBACA;EAEjB,YAAY,QAAQ;UAKZ;UAUA;UAOA;EAqBR,aAAa,mBAAmB;EAOhC,oBAAoB,mBAAmB;EAIvC,WAAW,mBAAmB,iBAAiB;EAK/C,aACE,kBACA,eACA,UAAU,cACT,QAAQ;EAeJ,OAAO,SAAS,kBAAkB,eAAe;UAmHhD;;;;cC9WG;cACA;cACA;cAEA;cAEA;UAEI;EACf;EACA;EACA;EACA;EACA;EACA,kBAAkB;EAClB,2BAA2B,QAAQ,OAAO;;UAG3B;EACf;EAEA;EAEA;EAEA,UAAU;EAEV;EACA;EACA;EACA;EACA;EACA;EAEA,YAAY;EAEZ,SAAS;EACT;EACA;EACA;EACA;EAEA;EACA,cAAc;;UAGC;EACf,YAAY,eAAe;;cAsChB,QAAQ,EAAE;iBAkHP,sBACd,kBACA,QAAQ,wBACP;iBAwGa,gBACd,WAAW,SAAS,eAAe,sCAClC,YAAY;iBAYC,kBAAkB,QAAQ;iBA2C1B,MAAM,KAAK,SAAS,QAAQ"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/serialize.ts","../src/translate.ts","../src/adapter.ts","../src/index.ts"],"sourcesContent":["import {\n LlmError,\n contentHasImage,\n offloadRequestImagesWithPolicy,\n textOnlyImageText,\n} from \"@deepseek-ai/dsh-llm\";\nimport type { ContentBlock, GenerateOptions, Message } from \"@deepseek-ai/dsh-llm\";\nimport { AttachmentError } from \"@deepseek-ai/dsh-attachment\";\nimport type { AttachmentStore } from \"@deepseek-ai/dsh-attachment\";\nimport type {\n JSONSchema7,\n LanguageModelV4FunctionTool,\n LanguageModelV4Prompt,\n SharedV4ProviderOptions,\n} from \"@ai-sdk/provider\";\nimport { Buffer } from \"node:buffer\";\nimport type { ReasoningEffort, ResolvedModelProfile, ResolvedProviderProfile } from \"./adapter.ts\";\n\nconst TOOL_RESULT_IMAGE_TEXT = \"Attached image(s) from tool result:\";\n\ntype UserContentPart = Extract<LanguageModelV4Prompt[number], { role: \"user\" }>[\"content\"][number];\n\nexport type OpenAICompatibleProviderOptions = SharedV4ProviderOptions & {\n \"openai-compatible\"?: {\n reasoningEffort?: string;\n\n top_k?: number;\n };\n};\n\nexport interface OpenAICompatibleCallOptions {\n prompt: LanguageModelV4Prompt;\n maxOutputTokens?: number;\n temperature?: number;\n topP?: number;\n presencePenalty?: number;\n frequencyPenalty?: number;\n seed?: number;\n stopSequences?: string[];\n tools?: LanguageModelV4FunctionTool[];\n providerOptions?: OpenAICompatibleProviderOptions;\n}\n\nexport function resolveReasoningWire(\n model: ResolvedModelProfile | undefined,\n effort: ResolvedProviderProfile[\"reasoning\"] | undefined,\n): string | undefined {\n if (effort === void 0) return void 0;\n const declaration = model?.reasoningEfforts;\n if (declaration === void 0 || declaration === false) {\n const subject = model === void 0 ? \"unlisted model\" : `model \"${model.id}\"`;\n throw new LlmError(\n `OpenAI-compatible ${subject} declares no reasoning efforts, so \"${effort}\" cannot be selected`,\n \"UNSUPPORTED_REASONING_EFFORT\",\n );\n }\n const wire = declaration[effort];\n if (wire === void 0) {\n throw new LlmError(\n `OpenAI-compatible model \"${model.id}\" does not support reasoning effort \"${effort}\"`,\n \"UNSUPPORTED_REASONING_EFFORT\",\n );\n }\n if (wire === null) return void 0;\n return wire;\n}\n\nfunction flattenText(blocks: readonly ContentBlock[]): string {\n return blocks\n .filter((block) => block.type === \"text\")\n .map((block) => block.text)\n .join(\"\");\n}\n\nfunction assertTextOnly(blocks: readonly ContentBlock[]): void {\n if (contentHasImage(blocks)) {\n throw new LlmError(\n \"The OpenAI-compatible chat-completions adapter does not support image content in this message.\",\n \"UNSUPPORTED_CONTENT\",\n );\n }\n}\n\nfunction assertSupportedImageRoles(messages: readonly Message[]): void {\n for (const message of messages) {\n if (message.role !== \"user\" && contentHasImage(message.content)) {\n throw new LlmError(\n `The OpenAI-compatible chat-completions adapter cannot represent image content in a ${message.role} message.`,\n \"UNSUPPORTED_CONTENT\",\n );\n }\n }\n}\n\nasync function imagePart(\n block: Extract<ContentBlock, { type: \"image\" }>,\n attachments: AttachmentStore,\n signal?: AbortSignal,\n): Promise<UserContentPart> {\n try {\n const stored = await attachments.readImage(block.attachment, signal);\n return {\n type: \"file\",\n mediaType: stored.ref.mediaType,\n data: {\n type: \"url\",\n url: new URL(\n `data:${stored.ref.mediaType};base64,${Buffer.from(stored.data).toString(\"base64\")}`,\n ),\n },\n };\n } catch (error) {\n if (error instanceof AttachmentError)\n throw new LlmError(error.message, error.code, { cause: error });\n throw error;\n }\n}\n\nfunction assistantParts(\n message: Message,\n toolNames: Map<string, string>,\n): Extract<LanguageModelV4Prompt[number], { role: \"assistant\" }>[\"content\"] {\n const parts: Extract<LanguageModelV4Prompt[number], { role: \"assistant\" }>[\"content\"] = [];\n for (const block of message.content) {\n switch (block.type) {\n case \"text\":\n if (block.text.length > 0) parts.push({ type: \"text\", text: block.text });\n break;\n case \"reasoning\":\n if (block.text.length > 0) parts.push({ type: \"reasoning\", text: block.text });\n break;\n case \"tool-call\": {\n let input: unknown;\n try {\n input = JSON.parse(block.arguments) as unknown;\n } catch {\n throw new LlmError(\n `assistant tool call \"${block.id}\" carries malformed JSON arguments`,\n \"MALFORMED_RESPONSE\",\n );\n }\n parts.push({ type: \"tool-call\", toolCallId: block.id, toolName: block.name, input });\n toolNames.set(block.id, block.name);\n break;\n }\n default:\n break;\n }\n }\n return parts;\n}\n\nasync function userParts(\n blocks: readonly ContentBlock[],\n resolveImage:\n | ((\n block: Extract<ContentBlock, { type: \"image\" }>,\n signal?: AbortSignal,\n ) => Promise<UserContentPart>)\n | undefined,\n signal?: AbortSignal,\n): Promise<UserContentPart[]> {\n const parts: UserContentPart[] = [];\n for (const block of blocks) {\n switch (block.type) {\n case \"text\":\n if (block.text.length > 0) parts.push({ type: \"text\", text: block.text });\n break;\n case \"image\":\n if (resolveImage === void 0)\n throw new LlmError(\n \"The OpenAI-compatible chat-completions adapter does not support image content in this message.\",\n \"UNSUPPORTED_CONTENT\",\n );\n parts.push(await resolveImage(block, signal));\n break;\n case \"tool-result\":\n parts.push(...(await userParts(block.content, resolveImage, signal)));\n break;\n default:\n break;\n }\n }\n return parts;\n}\n\nasync function serializePrompt(\n messages: readonly Message[],\n resolveImage:\n | ((\n block: Extract<ContentBlock, { type: \"image\" }>,\n signal?: AbortSignal,\n ) => Promise<UserContentPart>)\n | undefined,\n signal?: AbortSignal,\n): Promise<LanguageModelV4Prompt> {\n if (resolveImage === void 0) {\n for (const message of messages) assertTextOnly(message.content);\n } else {\n assertSupportedImageRoles(messages);\n }\n const prompt: LanguageModelV4Prompt = [];\n const toolNames = new Map<string, string>();\n let pendingToolImages: UserContentPart[] = [];\n const flushToolImages = () => {\n if (pendingToolImages.length === 0) return;\n prompt.push({\n role: \"user\",\n content: [{ type: \"text\", text: TOOL_RESULT_IMAGE_TEXT }, ...pendingToolImages],\n });\n pendingToolImages = [];\n };\n for (const message of messages) {\n if (message.role === \"system\") {\n flushToolImages();\n prompt.push({ role: \"system\", content: flattenText(message.content) });\n continue;\n }\n if (message.role === \"assistant\") {\n flushToolImages();\n const parts = assistantParts(message, toolNames);\n if (parts.length > 0) prompt.push({ role: \"assistant\", content: parts });\n continue;\n }\n const regular = message.content.filter((block) => block.type !== \"tool-result\");\n const toolResults = message.content.filter((block) => block.type === \"tool-result\");\n const content = await userParts(regular, resolveImage, signal);\n if (content.length > 0 || toolResults.length === 0) {\n flushToolImages();\n prompt.push({ role: \"user\", content });\n }\n for (const result of toolResults) {\n const images: UserContentPart[] = [];\n if (resolveImage !== void 0) {\n for (const block of result.content) {\n if (block.type === \"image\") images.push(await resolveImage(block, signal));\n }\n }\n prompt.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: result.toolCallId,\n toolName: toolNames.get(result.toolCallId) ?? \"\",\n output: {\n type: \"text\",\n value:\n flattenText(result.content) ||\n (images.length > 0 ? \"(see attached image)\" : \"(no output)\"),\n },\n },\n ],\n });\n pendingToolImages.push(...images);\n }\n }\n flushToolImages();\n return prompt;\n}\n\nfunction serializeTools(options: GenerateOptions): LanguageModelV4FunctionTool[] | undefined {\n const tools = options.tools?.map((tool): LanguageModelV4FunctionTool => ({\n type: \"function\",\n name: tool.name,\n description: tool.description,\n inputSchema: tool.parameters as JSONSchema7,\n }));\n return tools !== void 0 && tools.length > 0 ? tools : void 0;\n}\n\nfunction callOptionsWithPrompt(\n options: GenerateOptions,\n profile: ResolvedProviderProfile,\n model: ResolvedModelProfile | undefined,\n prompt: LanguageModelV4Prompt,\n): OpenAICompatibleCallOptions {\n const tools = serializeTools(options);\n const temperature = options.temperature ?? profile.temperature;\n const maxOutputTokens = options.maxTokens ?? model?.maxTokens ?? profile.defaultMaxTokens;\n const requestedEffort: ReasoningEffort | undefined =\n options.reasoningEffort === void 0\n ? profile.reasoning\n : (options.reasoningEffort as unknown as ReasoningEffort);\n const reasoningEffort = resolveReasoningWire(model, requestedEffort);\n const providerOptions: OpenAICompatibleProviderOptions = {\n \"openai-compatible\": {\n ...(reasoningEffort === void 0 ? {} : { reasoningEffort }),\n ...(profile.topK === void 0 ? {} : { top_k: profile.topK }),\n },\n };\n return {\n prompt,\n ...(temperature !== void 0 ? { temperature } : {}),\n ...(profile.topP !== void 0 ? { topP: profile.topP } : {}),\n ...(profile.presencePenalty !== void 0 ? { presencePenalty: profile.presencePenalty } : {}),\n ...(profile.frequencyPenalty !== void 0 ? { frequencyPenalty: profile.frequencyPenalty } : {}),\n ...(profile.seed !== void 0 ? { seed: profile.seed } : {}),\n ...(maxOutputTokens !== void 0 ? { maxOutputTokens } : {}),\n ...(options.stop !== void 0 ? { stopSequences: options.stop } : {}),\n ...(tools !== void 0 ? { tools } : {}),\n ...(Object.keys(providerOptions[\"openai-compatible\"] ?? {}).length > 0\n ? { providerOptions }\n : {}),\n };\n}\n\nexport async function serializeCallOptions(\n options: GenerateOptions,\n profile: ResolvedProviderProfile,\n model: ResolvedModelProfile | undefined,\n): Promise<OpenAICompatibleCallOptions> {\n const system =\n options.system === void 0 ? [] : [{ role: \"system\" as const, content: options.system }];\n const prompt = await serializePrompt(options.messages, void 0);\n return callOptionsWithPrompt(options, profile, model, [...system, ...prompt]);\n}\n\nexport async function serializeCallOptionsWithImages(\n options: GenerateOptions,\n profile: ResolvedProviderProfile,\n model: ResolvedModelProfile | undefined,\n images: { attachments: AttachmentStore; maxRequestImageBytes: number; signal?: AbortSignal },\n): Promise<OpenAICompatibleCallOptions> {\n const requestMessages = offloadRequestImagesWithPolicy(options.messages, {\n representation: \"raw\",\n maxBytes: images.maxRequestImageBytes,\n placeholder: (ref) => textOnlyImageText(ref),\n });\n const resolveImage = (block: Extract<ContentBlock, { type: \"image\" }>, signal?: AbortSignal) =>\n imagePart(block, images.attachments, signal);\n const system =\n options.system === void 0 ? [] : [{ role: \"system\" as const, content: options.system }];\n const prompt = await serializePrompt(requestMessages, resolveImage, images.signal);\n return callOptionsWithPrompt(options, profile, model, [...system, ...prompt]);\n}\n","import { EMPTY_RESPONSE_CODE, ToolCallId, LlmError } from \"@deepseek-ai/dsh-llm\";\nimport type { FinishReason, StreamChunk, TokenUsage } from \"@deepseek-ai/dsh-llm\";\nimport type {\n LanguageModelV4FinishReason,\n LanguageModelV4StreamPart,\n LanguageModelV4ToolCall,\n LanguageModelV4Usage,\n} from \"@ai-sdk/provider\";\n\nexport function mapFinishReason(reason: LanguageModelV4FinishReason): FinishReason {\n switch (reason.unified) {\n case \"stop\":\n return { kind: \"stop\" };\n case \"tool-calls\":\n return { kind: \"tool-calls\" };\n case \"length\":\n return { kind: \"max-tokens\" };\n default:\n return {\n kind: \"error\",\n failure: {\n message: `model stopped: ${reason.raw ?? reason.unified}`,\n code: (reason.raw ?? reason.unified).toUpperCase(),\n },\n };\n }\n}\n\nexport function mapUsage(usage: LanguageModelV4Usage): TokenUsage {\n const cacheRead = usage.inputTokens.cacheRead;\n const reasoning = usage.outputTokens.reasoning;\n return {\n inputTokens: usage.inputTokens.noCache ?? usage.inputTokens.total ?? 0,\n outputTokens: usage.outputTokens.total ?? 0,\n ...(cacheRead !== void 0 && cacheRead > 0 ? { cacheReadTokens: cacheRead } : {}),\n ...(reasoning !== void 0 && reasoning > 0 ? { reasoningTokens: reasoning } : {}),\n };\n}\n\ninterface OpenBlock {\n index: number;\n kind: \"text\" | \"reasoning\" | \"tool-call\";\n text: string;\n callId?: string;\n name?: string;\n}\n\nfunction closeBlock(block: OpenBlock): Extract<StreamChunk, { type: \"block-end\" }>[\"block\"] {\n switch (block.kind) {\n case \"text\":\n return { type: \"text\", text: block.text };\n case \"reasoning\":\n return { type: \"reasoning\", text: block.text };\n case \"tool-call\":\n return {\n type: \"tool-call\",\n id: ToolCallId(block.callId ?? \"\"),\n name: block.name ?? \"\",\n arguments: block.text,\n };\n }\n}\n\nexport async function* translate(\n stream: ReadableStream<LanguageModelV4StreamPart>,\n): AsyncGenerator<StreamChunk, void> {\n let nextIndex = 0;\n const textBlocks = new Map<string, OpenBlock>();\n const reasoningBlocks = new Map<string, OpenBlock>();\n const toolBlocks = new Map<string, OpenBlock>();\n const toolQueue: OpenBlock[] = [];\n const order: OpenBlock[] = [];\n let pendingUsage: TokenUsage | undefined;\n let pendingFinish: FinishReason | undefined;\n\n const open = (kind: OpenBlock[\"kind\"]): OpenBlock => {\n const block: OpenBlock = { index: nextIndex++, kind, text: \"\" };\n order.push(block);\n return block;\n };\n\n for await (const part of stream) {\n switch (part.type) {\n case \"stream-start\":\n case \"response-metadata\":\n case \"raw\":\n break;\n case \"text-start\": {\n const block = open(\"text\");\n textBlocks.set(part.id, block);\n yield { type: \"block-start\", index: block.index, blockType: \"text\" };\n break;\n }\n case \"text-delta\": {\n const block = textBlocks.get(part.id);\n if (block === void 0) break;\n block.text += part.delta;\n yield { type: \"text-delta\", index: block.index, text: part.delta };\n break;\n }\n case \"text-end\":\n break;\n case \"reasoning-start\": {\n const block = open(\"reasoning\");\n reasoningBlocks.set(part.id, block);\n yield { type: \"block-start\", index: block.index, blockType: \"reasoning\" };\n break;\n }\n case \"reasoning-delta\": {\n const block = reasoningBlocks.get(part.id);\n if (block === void 0) break;\n block.text += part.delta;\n yield { type: \"reasoning-delta\", index: block.index, text: part.delta };\n break;\n }\n case \"reasoning-end\":\n break;\n case \"tool-input-start\": {\n const block = open(\"tool-call\");\n if (part.toolName !== void 0) block.name = part.toolName;\n toolBlocks.set(part.id, block);\n toolQueue.push(block);\n yield { type: \"block-start\", index: block.index, blockType: \"tool-call\" };\n break;\n }\n case \"tool-input-delta\": {\n const block = toolBlocks.get(part.id);\n if (block === void 0) break;\n block.text += part.delta;\n yield {\n type: \"tool-call-delta\",\n index: block.index,\n id: ToolCallId(block.callId ?? part.id),\n ...(block.name !== void 0 ? { name: block.name } : {}),\n argumentsDelta: part.delta,\n };\n break;\n }\n case \"tool-input-end\":\n break;\n case \"tool-call\": {\n applyToolCall(part, toolQueue);\n break;\n }\n case \"tool-result\":\n case \"tool-approval-request\":\n case \"custom\":\n case \"file\":\n case \"reasoning-file\":\n case \"source\":\n // Provider-executed tools and generated files are not part of this\n // adapter's client-executed tool loop; nothing to emit.\n break;\n case \"finish\":\n pendingUsage = mapUsage(part.usage);\n pendingFinish = mapFinishReason(part.finishReason);\n for (const block of order)\n yield { type: \"block-end\", index: block.index, block: closeBlock(block) };\n if (pendingUsage !== void 0) yield { type: \"usage\", usage: pendingUsage };\n const reason = pendingFinish ?? { kind: \"stop\" as const };\n yield {\n type: \"finish\",\n reason:\n reason.kind === \"stop\" && order.length === 0\n ? {\n kind: \"error\",\n failure: {\n message: \"model returned a completed response with no content\",\n code: EMPTY_RESPONSE_CODE,\n },\n }\n : reason,\n };\n return;\n case \"error\": {\n const error = part.error;\n const cause = error instanceof Error ? error : void 0;\n const message =\n cause?.message ?? (typeof error === \"string\" ? error : \"provider stream error\");\n throw new LlmError(`OpenAI-compatible stream failed: ${message}`, \"TRANSPORT\", { cause });\n }\n }\n }\n throw new LlmError(\"AI SDK stream ended without a finish part\", \"STREAM_CLOSED\");\n}\n\nfunction applyToolCall(part: LanguageModelV4ToolCall, toolQueue: OpenBlock[]): void {\n const block = toolQueue.shift();\n if (block === void 0) return;\n block.callId = part.toolCallId;\n block.name = part.toolName;\n // The provider emits the complete arguments on this part; the buffered\n // deltas were a partial view.\n block.text = part.input;\n}\n","import {\n CONTEXT_WINDOW_EXCEEDED_CODE,\n QUOTA_EXCEEDED_CODE,\n LlmAdapter,\n LlmError,\n ProviderRequestId,\n ReasoningEffortId,\n attributionHeaders,\n contentHasImage,\n isContextWindowExceededError,\n isQuotaExceededError,\n} from \"@deepseek-ai/dsh-llm\";\nimport type {\n GenerateOptions,\n LlmModelInfo,\n LlmProviderInfo,\n LlmResolvedModelInfo,\n ModelModality,\n ResolvedRetryPolicy,\n StreamChunk,\n} from \"@deepseek-ai/dsh-llm\";\nimport type { AttachmentStore } from \"@deepseek-ai/dsh-attachment\";\nimport type { CredentialRef } from \"@deepseek-ai/dsh-credentials\";\nimport { deadline, idleWatchdog, timeoutOf } from \"@deepseek-ai/dsh-timeout\";\nimport { APICallError } from \"@ai-sdk/provider\";\nimport type { LanguageModelV4, LanguageModelV4Usage } from \"@ai-sdk/provider\";\nimport { createOpenAICompatible } from \"@ai-sdk/openai-compatible\";\nimport { serializeCallOptions, serializeCallOptionsWithImages } from \"./serialize.ts\";\nimport { translate } from \"./translate.ts\";\n\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000;\n\nexport const DEFAULT_CONTEXT_WINDOW = 262_144;\n\nexport const DEFAULT_MAX_TOKENS = 32_768;\n\nexport const DEFAULT_MAX_REQUEST_IMAGE_BYTES = 20 * 1024 * 1024;\n\nexport const STREAM_IDLE_TIMEOUT_CODE = \"LLM_STREAM_IDLE_TIMEOUT\";\n\nexport const REQUEST_TIMEOUT_CODE = \"LLM_REQUEST_TIMEOUT\";\n\nexport const PROVIDER_OPTIONS_KEY = \"openai-compatible\";\n\nexport type ReasoningEffort = \"off\" | \"low\" | \"high\" | \"max\";\n\nexport interface ResolvedModelProfile {\n id: string;\n name?: string;\n description?: string;\n contextWindow?: number;\n maxTokens?: number;\n inputModalities: readonly ModelModality[];\n\n reasoningEfforts?: false | Partial<Record<ReasoningEffort, string | null>>;\n}\n\nexport interface ResolvedProviderProfile {\n provider: string;\n displayName: string;\n\n apiKeyEnv?: CredentialRef;\n\n baseURL: string;\n headers?: Readonly<Record<string, string>>;\n // === sampling defaults (request-level values win) ===\n temperature?: number;\n topP?: number;\n topK?: number;\n presencePenalty?: number;\n frequencyPenalty?: number;\n seed?: number;\n\n reasoning?: ReasoningEffort;\n // === model catalog ===\n models: readonly ResolvedModelProfile[];\n defaultContextWindow: number;\n defaultMaxTokens: number;\n // === transport ===\n maxRequestImageBytes: number;\n streamIdleTimeoutMs: number;\n\n timeoutMs?: number;\n retryPolicy: ResolvedRetryPolicy;\n}\n\nexport interface OpenAICompatibleAdapterOptions {\n profiles: () => ReadonlyMap<string, ResolvedProviderProfile>;\n\n resolveApiKey: (\n provider: string,\n profile: ResolvedProviderProfile,\n ) => Promise<string | undefined>;\n\n resolveUserId: () => string;\n\n resolveAttachments?: () => AttachmentStore | undefined;\n}\n\ninterface WireUsageLike {\n prompt_tokens?: number | null | undefined;\n completion_tokens?: number | null | undefined;\n prompt_tokens_details?: { cached_tokens?: number | null | undefined } | null | undefined;\n\n prompt_cache_hit_tokens?: number | null | undefined;\n completion_tokens_details?: { reasoning_tokens?: number | null | undefined } | null | undefined;\n}\n\nexport function convertUsage(usage: WireUsageLike | null | undefined): LanguageModelV4Usage {\n if (usage == null) {\n return {\n inputTokens: { total: 0, noCache: 0, cacheRead: void 0, cacheWrite: void 0 },\n outputTokens: { total: 0, text: void 0, reasoning: void 0 },\n };\n }\n const promptTokens = usage.prompt_tokens ?? 0;\n const completionTokens = usage.completion_tokens ?? 0;\n const cacheRead =\n usage.prompt_tokens_details?.cached_tokens ?? usage.prompt_cache_hit_tokens ?? 0;\n const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0;\n return {\n inputTokens: {\n total: promptTokens,\n noCache: Math.max(0, promptTokens - cacheRead),\n cacheRead,\n cacheWrite: void 0,\n },\n outputTokens: {\n total: completionTokens,\n text: Math.max(0, completionTokens - reasoningTokens),\n reasoning: reasoningTokens,\n },\n };\n}\n\nfunction modelInfo(profile: ResolvedProviderProfile, model: ResolvedModelProfile): LlmModelInfo {\n return {\n provider: profile.provider,\n id: model.id,\n name: model.name ?? model.id,\n ...(model.description === void 0 ? {} : { description: model.description }),\n inputModalities: [...model.inputModalities],\n };\n}\n\nfunction reasoningInfo(\n model: ResolvedModelProfile | undefined,\n defaultEffort: ReasoningEffort | undefined,\n): Pick<LlmResolvedModelInfo, \"reasoning\"> {\n const declaration = model?.reasoningEfforts;\n if (declaration === void 0 || declaration === false) return {};\n const entries = Object.entries(declaration) as [ReasoningEffort, string | null | undefined][];\n const efforts = entries.map(([id]) => ({\n id: ReasoningEffortId(id),\n name: `${id.charAt(0).toUpperCase()}${id.slice(1)}`,\n }));\n return {\n reasoning: {\n efforts,\n // A configured default the model does not declare is silently dropped\n // here (describing a model must never throw); the request path still\n // refuses it, which is where a bad deployment default belongs.\n ...(defaultEffort !== void 0 && declaration[defaultEffort] !== void 0\n ? { defaultEffort: ReasoningEffortId(defaultEffort) }\n : {}),\n },\n };\n}\n\nexport function httpErrorCode(\n status: number,\n error?: { code?: unknown; type?: unknown; message?: unknown },\n): string {\n if (status === 401 || status === 403) return \"AUTH\";\n if (status === 413) return \"INVALID_REQUEST\";\n const detail = [error?.code, error?.type, error?.message].filter(Boolean).join(\" \");\n if (isQuotaExceededError(detail)) return QUOTA_EXCEEDED_CODE;\n if (status === 429) return \"RATE_LIMIT\";\n if (status === 400) {\n if (isContextWindowExceededError(detail)) return CONTEXT_WINDOW_EXCEEDED_CODE;\n return \"INVALID_REQUEST\";\n }\n if (status >= 500) return \"SERVER\";\n return `HTTP_${status}`;\n}\n\nfunction providerErrorBody(\n error: APICallError,\n): { code?: unknown; type?: unknown; message?: unknown } | undefined {\n if (error.responseBody === void 0) return void 0;\n try {\n const parsed = JSON.parse(error.responseBody) as {\n error?: { code?: unknown; type?: unknown; message?: unknown };\n };\n return parsed.error;\n } catch {\n return void 0;\n }\n}\n\nfunction requestId(headers: Record<string, string> | undefined): ProviderRequestId | undefined {\n if (headers === void 0) return void 0;\n const value = headers[\"x-request-id\"] ?? headers[\"x-openai-compatible-request-id\"];\n return value === void 0 || value.length === 0 ? void 0 : ProviderRequestId(value);\n}\n\nexport class OpenAICompatibleAdapter extends LlmAdapter {\n private readonly config: OpenAICompatibleAdapterOptions;\n private readonly sdkProviders = new Map<ResolvedProviderProfile, Map<string, LanguageModelV4>>();\n\n constructor(config: OpenAICompatibleAdapterOptions) {\n super();\n this.config = config;\n }\n\n private profileOf(provider: string): ResolvedProviderProfile {\n const profile = this.config.profiles().get(provider);\n if (profile === void 0)\n throw new LlmError(\n `OpenAI-compatible adapter does not own provider \"${provider}\"`,\n \"NO_ADAPTER\",\n );\n return profile;\n }\n\n private modelOf(\n profile: ResolvedProviderProfile,\n model: string,\n ): ResolvedModelProfile | undefined {\n return profile.models.find((entry) => entry.id === model);\n }\n\n private sdkModel(profile: ResolvedProviderProfile, modelId: string): LanguageModelV4 {\n let byModel = this.sdkProviders.get(profile);\n if (byModel === void 0) {\n byModel = new Map();\n this.sdkProviders.set(profile, byModel);\n }\n let model = byModel.get(modelId);\n if (model === void 0) {\n const provider = createOpenAICompatible({\n name: PROVIDER_OPTIONS_KEY,\n baseURL: profile.baseURL,\n headers: { ...profile.headers, ...attributionHeaders() },\n includeUsage: true,\n convertUsage,\n });\n model = provider.chatModel(modelId);\n byModel.set(modelId, model);\n }\n return model;\n }\n\n providerInfo(provider: string): LlmProviderInfo {\n return {\n id: provider,\n name: this.config.profiles().get(provider)?.displayName ?? provider,\n };\n }\n\n providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.config.profiles().get(provider)?.retryPolicy;\n }\n\n listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const profile = this.profileOf(provider);\n return Promise.resolve(profile.models.map((model) => modelInfo(profile, model)));\n }\n\n resolveModel(\n provider: string,\n model: string,\n _signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n const profile = this.profileOf(provider);\n const configured = this.modelOf(profile, model);\n const contextWindow = configured?.contextWindow ?? profile.defaultContextWindow;\n const maxTokens = configured?.maxTokens ?? profile.defaultMaxTokens;\n return Promise.resolve({\n ...(configured === void 0\n ? { provider, id: model, name: model, inputModalities: [\"text\" as const] }\n : modelInfo(profile, configured)),\n context: { contextWindow },\n ...(maxTokens !== void 0 ? { defaultMaxTokens: maxTokens } : {}),\n ...reasoningInfo(configured, profile.reasoning),\n });\n }\n\n async *stream(options: GenerateOptions): AsyncGenerator<StreamChunk> {\n const profile = this.profileOf(options.provider);\n const model = this.modelOf(profile, options.model);\n const hasImages = options.messages.some((message) => contentHasImage(message.content));\n let attachments: AttachmentStore | undefined;\n if (hasImages) {\n if (model?.inputModalities.includes(\"image\") !== true) {\n throw new LlmError(\n `OpenAI-compatible model \"${options.model}\" does not accept image input.`,\n \"UNSUPPORTED_CONTENT\",\n );\n }\n attachments = this.config.resolveAttachments?.();\n if (attachments === void 0)\n throw new LlmError(\n \"OpenAI-compatible image conversion requires the durable attachment service.\",\n \"UNSUPPORTED_CONTENT\",\n );\n }\n const apiKey = await this.config.resolveApiKey(options.provider, profile);\n const userId = this.config.resolveUserId();\n const consumer = new AbortController();\n const upstream =\n options.signal === void 0\n ? consumer.signal\n : AbortSignal.any([options.signal, consumer.signal]);\n const overall =\n profile.timeoutMs === void 0\n ? void 0\n : deadline(upstream, profile.timeoutMs, REQUEST_TIMEOUT_CODE);\n const watchdog = idleWatchdog(\n overall?.signal ?? upstream,\n profile.streamIdleTimeoutMs,\n STREAM_IDLE_TIMEOUT_CODE,\n );\n try {\n const callOptions =\n attachments === void 0\n ? await serializeCallOptions(options, profile, model)\n : await serializeCallOptionsWithImages(options, profile, model, {\n attachments,\n maxRequestImageBytes: profile.maxRequestImageBytes,\n signal: watchdog.signal,\n });\n const sdkModel = this.sdkModel(profile, options.model);\n let result;\n try {\n result = await sdkModel.doStream({\n ...callOptions,\n abortSignal: watchdog.signal,\n headers: {\n ...(apiKey === void 0 ? {} : { authorization: `Bearer ${apiKey}` }),\n \"x-openai-compatible-harness-user-id\": String(userId),\n ...(options.sessionId !== void 0\n ? { \"x-openai-compatible-harness-session-id\": String(options.sessionId) }\n : {}),\n ...(options.purpose === \"compaction\"\n ? { \"x-openai-compatible-harness-compact\": \"1\" }\n : {}),\n },\n });\n } catch (error) {\n throw this.normalizeTransportError(error, profile);\n }\n const iterator = translate(result.stream)[Symbol.asyncIterator]();\n let exhausted = false;\n try {\n while (true) {\n const next = await watchdog.next(iterator);\n if (next.done) {\n exhausted = true;\n return;\n }\n yield next.value;\n }\n } catch (error) {\n if (timeoutOf(watchdog.signal, STREAM_IDLE_TIMEOUT_CODE) !== void 0) {\n throw new LlmError(\n `OpenAI-compatible stream idle timeout after ${profile.streamIdleTimeoutMs}ms`,\n \"TIMEOUT\",\n { cause: error },\n );\n }\n if (\n profile.timeoutMs !== void 0 &&\n timeoutOf(watchdog.signal, REQUEST_TIMEOUT_CODE) !== void 0\n ) {\n throw new LlmError(\n `OpenAI-compatible request timeout after ${profile.timeoutMs}ms`,\n \"TIMEOUT\",\n { cause: error },\n );\n }\n if (options.signal?.aborted)\n throw new LlmError(\"OpenAI-compatible request aborted by caller\", \"ABORTED\", {\n cause: error,\n });\n if (error instanceof LlmError) throw error;\n throw this.normalizeTransportError(error, profile);\n } finally {\n consumer.abort(\"OpenAI-compatible stream consumer stopped\");\n if (!exhausted) {\n try {\n await iterator.return(void 0);\n } catch {\n // The transport already aborted; teardown is best-effort.\n }\n }\n }\n } finally {\n watchdog[Symbol.dispose]();\n overall?.[Symbol.dispose]();\n }\n }\n\n private normalizeTransportError(error: unknown, profile: ResolvedProviderProfile): LlmError {\n if (error instanceof LlmError) return error;\n if (APICallError.isInstance(error)) {\n const providerError = providerErrorBody(error);\n const message =\n typeof providerError?.message === \"string\" ? providerError.message : error.message;\n const id = requestId(error.responseHeaders);\n return new LlmError(message, httpErrorCode(error.statusCode ?? 0, providerError), {\n ...(error.statusCode === void 0 ? {} : { status: error.statusCode }),\n ...(id === void 0 ? {} : { requestId: id }),\n cause: error,\n });\n }\n if (error instanceof Error) {\n return new LlmError(\n `OpenAI-compatible API request to ${profile.baseURL} failed`,\n \"TRANSPORT\",\n { cause: error },\n );\n }\n return new LlmError(`OpenAI-compatible API request to ${profile.baseURL} failed`, \"TRANSPORT\");\n }\n}\n","import type { Context } from \"@deepseek-ai/cordis\";\nimport z from \"@deepseek-ai/schemastery\";\nimport {\n LlmError,\n RetryPolicySchema,\n assertUsableApiKey,\n resolveRetryPolicy,\n} from \"@deepseek-ai/dsh-llm\";\nimport type { ModelModality, RetryPolicyConfig } from \"@deepseek-ai/dsh-llm\";\nimport { credentialRef } from \"@deepseek-ai/dsh-credentials\";\nimport { launchEnvironmentOf } from \"@deepseek-ai/dsh-launch-environment\";\nimport { deepEqualJson } from \"@deepseek-ai/dsh-util-values\";\nimport { MAX_TIMER_DELAY_MS } from \"@deepseek-ai/dsh-timeout\";\nimport { getOrCreateAnonymousUserId } from \"@deepseek-ai/dsh-anonymous-user-id\";\nimport {\n DEFAULT_CONTEXT_WINDOW,\n DEFAULT_MAX_REQUEST_IMAGE_BYTES,\n DEFAULT_MAX_TOKENS,\n DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n OpenAICompatibleAdapter,\n} from \"./adapter.ts\";\nimport type { ReasoningEffort, ResolvedModelProfile, ResolvedProviderProfile } from \"./adapter.ts\";\n\nexport { OpenAICompatibleAdapter } from \"./adapter.ts\";\nexport type {\n OpenAICompatibleAdapterOptions,\n ReasoningEffort,\n ResolvedModelProfile,\n ResolvedProviderProfile,\n} from \"./adapter.ts\";\nexport {\n DEFAULT_CONTEXT_WINDOW,\n DEFAULT_MAX_REQUEST_IMAGE_BYTES,\n DEFAULT_MAX_TOKENS,\n DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n} from \"./adapter.ts\";\n\nexport const name = \"llm-openai-compatible\";\nexport const inject = [\"llm\"];\nexport const NS = \"llm-openai-compatible\";\n\nexport const REASONING_LEVELS = [\"off\", \"low\", \"high\", \"max\"] as const;\n\nexport const MODEL_MODALITIES = [\"text\", \"image\"] as const;\n\nexport interface ModelProfileSource {\n id: string;\n name?: string;\n description?: string;\n contextWindow?: number;\n maxTokens?: number;\n inputModalities?: ModelModality[];\n reasoningEfforts?: false | Partial<Record<ReasoningEffort, string | null>>;\n}\n\nexport interface ProviderProfileSource {\n apiKeyEnv?: string;\n\n displayName?: string;\n\n baseURL: string;\n\n headers?: Record<string, string>;\n // === sampling defaults (request-level values win) ===\n temperature?: number;\n topP?: number;\n topK?: number;\n presencePenalty?: number;\n frequencyPenalty?: number;\n seed?: number;\n\n reasoning?: ReasoningEffort;\n\n models?: ModelProfileSource[];\n defaultContextWindow?: number;\n defaultMaxTokens?: number;\n maxRequestImageBytes?: number;\n streamIdleTimeoutMs?: number;\n\n timeoutMs?: number;\n retryPolicy?: RetryPolicyConfig;\n}\n\nexport interface Config {\n providers?: Record<string, ProviderProfileSource>;\n}\n\nconst modelSchema = z.object({\n id: z.string().required(),\n name: z.string(),\n description: z.string(),\n contextWindow: z.number().step(1).min(1),\n maxTokens: z.number().step(1).min(1),\n inputModalities: z.array(z.union(MODEL_MODALITIES)).min(1).default([\"text\"]),\n reasoningEfforts: z.union([z.const(false), z.dict(z.union([z.string(), z.const(null)]))]),\n});\n\nconst providerSchema = z.object({\n apiKeyEnv: z.string().role(\"credential-ref\"),\n displayName: z.string(),\n baseURL: z.string().required(),\n headers: z.dict(z.string()),\n temperature: z.number().min(0).max(2),\n topP: z.number().min(0).max(1),\n topK: z.number().step(1).min(1),\n presencePenalty: z.number().min(-2).max(2),\n frequencyPenalty: z.number().min(-2).max(2),\n seed: z.number().step(1).min(1),\n reasoning: z.union(REASONING_LEVELS),\n models: z.array(modelSchema),\n defaultContextWindow: z.number().step(1).min(1).default(DEFAULT_CONTEXT_WINDOW),\n defaultMaxTokens: z.number().step(1).min(1).default(DEFAULT_MAX_TOKENS),\n maxRequestImageBytes: z.number().step(1).min(1).default(DEFAULT_MAX_REQUEST_IMAGE_BYTES),\n streamIdleTimeoutMs: z\n .number()\n .min(Number.MIN_VALUE)\n .max(MAX_TIMER_DELAY_MS)\n .default(DEFAULT_STREAM_IDLE_TIMEOUT_MS),\n timeoutMs: z.number().min(Number.MIN_VALUE).max(MAX_TIMER_DELAY_MS),\n retryPolicy: RetryPolicySchema,\n});\n\nexport const Config: z<Config> = z.object({\n providers: z.dict(providerSchema).default({}),\n});\n\nfunction isReasoningEffort(value: string): value is ReasoningEffort {\n return (REASONING_LEVELS as readonly string[]).includes(value);\n}\n\nfunction resolveReasoningEfforts(\n provider: string,\n modelId: string,\n value: ModelProfileSource[\"reasoningEfforts\"],\n): Pick<ResolvedModelProfile, \"reasoningEfforts\"> {\n if (value === void 0) return {};\n if (value === false) return { reasoningEfforts: false };\n const declaration: Partial<Record<ReasoningEffort, string | null>> = {};\n for (const [effort, wire] of Object.entries(value)) {\n if (!isReasoningEffort(effort)) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" model \"${modelId}\" declares unknown reasoning effort \"${effort}\"`,\n );\n }\n if (effort === \"off\") {\n if (wire !== null) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" model \"${modelId}\" reasoning effort \"off\" must leave an empty wire spelling (null) to omit reasoning_effort`,\n );\n }\n declaration.off = null;\n continue;\n }\n if (wire === null || wire.length === 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" model \"${modelId}\" reasoning effort \"${effort}\" needs a non-empty wire spelling`,\n );\n }\n declaration[effort] = wire;\n }\n return { reasoningEfforts: declaration };\n}\n\nfunction resolveModels(\n provider: string,\n models: readonly ModelProfileSource[] | undefined,\n): readonly ResolvedModelProfile[] {\n if (models === void 0) return [];\n const seen = new Set<string>();\n return models.map((model) => {\n if (model.id.length === 0)\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model ids must be non-empty`,\n );\n if (model.name !== void 0 && model.name.length === 0)\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model \"${model.id}\" has an empty name`,\n );\n if (\n model.contextWindow !== void 0 &&\n (!Number.isInteger(model.contextWindow) || model.contextWindow <= 0)\n ) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model \"${model.id}\" contextWindow must be a positive integer`,\n );\n }\n if (\n model.maxTokens !== void 0 &&\n (!Number.isInteger(model.maxTokens) || model.maxTokens <= 0)\n ) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model \"${model.id}\" maxTokens must be a positive integer`,\n );\n }\n const inputModalities = model.inputModalities ?? [\"text\"];\n if (inputModalities.length === 0)\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model \"${model.id}\" inputModalities must not be empty`,\n );\n if (\n inputModalities.some(\n (modality) => !(MODEL_MODALITIES as readonly string[]).includes(modality),\n )\n ) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model \"${model.id}\" inputModalities must contain only \"text\" and \"image\"`,\n );\n }\n if (new Set(inputModalities).size !== inputModalities.length) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" catalog model \"${model.id}\" inputModalities must not contain duplicates`,\n );\n }\n if (seen.has(model.id))\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" has duplicate catalog model \"${model.id}\"`,\n );\n seen.add(model.id);\n return {\n id: model.id,\n ...(model.name === void 0 ? {} : { name: model.name }),\n ...(model.description === void 0 ? {} : { description: model.description }),\n ...(model.contextWindow === void 0 ? {} : { contextWindow: model.contextWindow }),\n ...(model.maxTokens === void 0 ? {} : { maxTokens: model.maxTokens }),\n inputModalities: [...inputModalities],\n ...resolveReasoningEfforts(provider, model.id, model.reasoningEfforts),\n };\n });\n}\n\nfunction bounded(value: number | undefined, lo: number, hi: number): number | undefined {\n if (value === void 0) return void 0;\n if (!Number.isFinite(value) || value < lo || value > hi) return void 0;\n return value;\n}\n\nexport function resolveAdapterOptions(\n provider: string,\n source: ProviderProfileSource,\n): ResolvedProviderProfile {\n if (provider.length === 0)\n throw new Error(\"llm-openai-compatible: provider names must be non-empty\");\n if (source.baseURL === void 0 || source.baseURL.length === 0) {\n throw new Error(`llm-openai-compatible: provider \"${provider}\" requires a non-empty baseURL`);\n }\n if (source.displayName !== void 0 && source.displayName.length === 0) {\n throw new Error(`llm-openai-compatible: provider \"${provider}\" has an empty displayName`);\n }\n const streamIdleTimeoutMs = source.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;\n if (\n !Number.isFinite(streamIdleTimeoutMs) ||\n streamIdleTimeoutMs <= 0 ||\n streamIdleTimeoutMs > MAX_TIMER_DELAY_MS\n ) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" streamIdleTimeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`,\n );\n }\n const maxRequestImageBytes = source.maxRequestImageBytes ?? DEFAULT_MAX_REQUEST_IMAGE_BYTES;\n if (!Number.isSafeInteger(maxRequestImageBytes) || maxRequestImageBytes <= 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" maxRequestImageBytes must be a positive safe integer`,\n );\n }\n const defaultContextWindow = source.defaultContextWindow ?? DEFAULT_CONTEXT_WINDOW;\n if (!Number.isInteger(defaultContextWindow) || defaultContextWindow <= 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" defaultContextWindow must be a positive integer`,\n );\n }\n const defaultMaxTokens = source.defaultMaxTokens ?? DEFAULT_MAX_TOKENS;\n if (!Number.isSafeInteger(defaultMaxTokens) || defaultMaxTokens <= 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" defaultMaxTokens must be a positive safe integer`,\n );\n }\n const timeoutMs = bounded(source.timeoutMs, Number.MIN_VALUE, MAX_TIMER_DELAY_MS);\n if (source.timeoutMs !== void 0 && timeoutMs === void 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" timeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`,\n );\n }\n if (bounded(source.temperature, 0, 2) === void 0 && source.temperature !== void 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" temperature must be a finite number within 0..2`,\n );\n }\n if (bounded(source.topP, 0, 1) === void 0 && source.topP !== void 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" topP must be a finite number within 0..1`,\n );\n }\n if (source.topK !== void 0 && (!Number.isInteger(source.topK) || source.topK <= 0)) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" topK must be a positive integer`,\n );\n }\n if (bounded(source.presencePenalty, -2, 2) === void 0 && source.presencePenalty !== void 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" presencePenalty must be a finite number within -2..2`,\n );\n }\n if (bounded(source.frequencyPenalty, -2, 2) === void 0 && source.frequencyPenalty !== void 0) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" frequencyPenalty must be a finite number within -2..2`,\n );\n }\n if (source.seed !== void 0 && (!Number.isInteger(source.seed) || source.seed <= 0)) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" seed must be a positive integer`,\n );\n }\n if (source.reasoning !== void 0 && !isReasoningEffort(source.reasoning)) {\n throw new Error(\n `llm-openai-compatible: provider \"${provider}\" reasoning must be one of ${REASONING_LEVELS.join(\", \")}`,\n );\n }\n return {\n provider,\n displayName: source.displayName ?? provider,\n ...(source.apiKeyEnv === void 0 ? {} : { apiKeyEnv: credentialRef(source.apiKeyEnv) }),\n baseURL: source.baseURL,\n ...(source.headers === void 0 ? {} : { headers: { ...source.headers } }),\n ...(source.temperature === void 0 ? {} : { temperature: source.temperature }),\n ...(source.topP === void 0 ? {} : { topP: source.topP }),\n ...(source.topK === void 0 ? {} : { topK: source.topK }),\n ...(source.presencePenalty === void 0 ? {} : { presencePenalty: source.presencePenalty }),\n ...(source.frequencyPenalty === void 0 ? {} : { frequencyPenalty: source.frequencyPenalty }),\n ...(source.seed === void 0 ? {} : { seed: source.seed }),\n ...(source.reasoning === void 0 ? {} : { reasoning: source.reasoning }),\n models: resolveModels(provider, source.models),\n defaultContextWindow,\n defaultMaxTokens,\n maxRequestImageBytes,\n streamIdleTimeoutMs,\n ...(timeoutMs === void 0 ? {} : { timeoutMs }),\n retryPolicy: resolveRetryPolicy(\n source.retryPolicy,\n `llm-openai-compatible: provider \"${provider}\" retryPolicy`,\n ),\n };\n}\n\nexport function resolveProfiles(\n providers: Readonly<Record<string, ProviderProfileSource>> | undefined,\n): Map<string, ResolvedProviderProfile> {\n if (Array.isArray(providers))\n throw new Error(\n \"llm-openai-compatible: providers is now a dict keyed by provider route, not an array of profiles\",\n );\n const resolved = new Map<string, ResolvedProviderProfile>();\n for (const [provider, source] of Object.entries(providers ?? {})) {\n resolved.set(provider, resolveAdapterOptions(provider, source));\n }\n return resolved;\n}\n\nexport function assertServiceable(config: Config): void {\n resolveProfiles(config.providers);\n}\n\nfunction registrationFacts(profiles: ReadonlyMap<string, ResolvedProviderProfile>): unknown[] {\n return [...profiles.entries()]\n .map(([provider, profile]) => ({\n provider,\n displayName: profile.displayName,\n retryPolicy: profile.retryPolicy,\n }))\n .sort((left, right) => left.provider.localeCompare(right.provider));\n}\n\nfunction directoryEntries(profiles: ReadonlyMap<string, ResolvedProviderProfile>): {\n provider: string;\n displayName: string;\n settingsNs: typeof NS;\n settingsPath: readonly string[];\n declared: boolean;\n}[] {\n const entries = new Map<\n string,\n {\n provider: string;\n displayName: string;\n settingsNs: typeof NS;\n settingsPath: readonly string[];\n declared: boolean;\n }\n >();\n for (const [provider, profile] of profiles) {\n entries.set(provider, {\n provider,\n displayName: profile.displayName,\n settingsNs: NS,\n settingsPath: [\"providers\", provider],\n declared: true,\n });\n }\n return [...entries.values()];\n}\n\nexport function apply(ctx: Context, config: Config): void {\n let current = () => config;\n let lastRaw: Config | undefined;\n let memoized: Map<string, ResolvedProviderProfile> | undefined;\n\n const profiles = (): ReadonlyMap<string, ResolvedProviderProfile> => {\n const raw = current();\n if (raw === lastRaw && memoized !== void 0) return memoized;\n const next = resolveProfiles(raw.providers);\n lastRaw = raw;\n memoized = next;\n return next;\n };\n profiles();\n const resolveApiKey = async (\n provider: string,\n profile: ResolvedProviderProfile,\n ): Promise<string | undefined> => {\n const ref = profile.apiKeyEnv;\n if (ref === void 0) return void 0;\n const credentials = ctx.get(\"credentials\");\n if (credentials !== void 0) {\n const hit = await credentials.resolve(ref);\n if (hit !== void 0) return assertUsableApiKey(hit.value, \"llm-openai-compatible\", ref);\n } else {\n const ambient = launchEnvironmentOf(ctx).get(ref);\n if (ambient !== void 0 && ambient.value.length > 0)\n return assertUsableApiKey(ambient.value, \"llm-openai-compatible\", ref);\n }\n throw new LlmError(\n `llm-openai-compatible: no credential for provider route \"${provider}\"; its profile resolves ${ref}, which is not set — store ${ref} through the credentials service (the web Models page writes it), or export ${ref} in the launching environment`,\n \"MISSING_CREDENTIAL\",\n );\n };\n let userId: string | undefined;\n const resolveUserId = () => (userId ??= getOrCreateAnonymousUserId());\n const adapter = new OpenAICompatibleAdapter({\n profiles,\n resolveApiKey,\n resolveUserId,\n resolveAttachments: () => ctx.get(\"attachments\"),\n });\n let directory: ReturnType<typeof ctx.llm.registerConfigurableProviders> | undefined;\n let directoryFacts: unknown[] | undefined;\n const ensureDirectory = () => {\n const entries = directoryEntries(profiles());\n if (deepEqualJson(entries, directoryFacts)) return;\n if (directory === void 0) directory = ctx.llm.registerConfigurableProviders(entries);\n else directory.replace(entries);\n directoryFacts = entries;\n };\n ensureDirectory();\n let registration: ReturnType<typeof ctx.llm.registerAdapter> | undefined;\n let registeredFacts: unknown[] | undefined;\n const ensureRegistrationFacts = () => {\n const facts = registrationFacts(profiles());\n if (deepEqualJson(facts, registeredFacts)) return;\n const routes = [...profiles().keys()];\n if (registration === void 0) {\n if (routes.length === 0) {\n registeredFacts = facts;\n return;\n }\n registration = ctx.llm.registerAdapter(routes, adapter);\n } else {\n registration.replace(routes);\n }\n registeredFacts = facts;\n };\n ensureRegistrationFacts();\n ctx.inject([\"settings\"], (settingsCtx) => {\n settingsCtx.settings.installSection(ctx, NS, Config, config, {\n validate: assertServiceable,\n setSource: (source) => {\n current = source;\n },\n onChange: () => {\n try {\n ensureRegistrationFacts();\n } catch (error) {\n ctx.logger.error(\n \"llm-openai-compatible: keeping the previously registered routes after a refused update\",\n );\n ctx.logger.error(error);\n }\n try {\n ensureDirectory();\n } catch (error) {\n ctx.logger.error(\n \"llm-openai-compatible: keeping the previous configurable-provider directory after a refused update\",\n );\n ctx.logger.error(error);\n }\n },\n });\n });\n}\n"],"mappings":"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"}
|