dsh-codearts 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/INSTALL.en.md +24 -0
- package/INSTALL.md +22 -0
- package/lib/bin.mjs +2 -2
- package/lib/client/index.js +52 -52
- package/lib/estimate-BePoD-Np.mjs +113 -0
- package/lib/index.d.mts +754 -1
- package/lib/index.mjs +9 -7
- package/lib/models-CgKCibpk.mjs +377 -0
- package/lib/openai-completions-Cn5ZQvOO.mjs +19392 -0
- package/lib/rolldown-runtime-B4iAMlE-.mjs +35 -0
- package/lib/{usage-5YK7bW-e.mjs → usage-B0NfG8vZ.mjs} +1 -12
- package/package.json +1 -4
package/lib/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { A as filterEnabledModels, C as rateLimitFrame, D as FALLBACK_CODEARTS_MODELS, E as CodeArtsCatalog, F as MANUAL_ACCOUNT_ID, I as codeartsAccountsPath, L as codeartsAuthPath, M as isBenefitModel, N as CodeArtsAccountStore, O as clearBenefitBlocked, P as CodeArtsCredentialStore, R as startLogin, S as prepareChatBody, T as upstreamErrorMessage, _ as isQueueableRate, a as SNAP_HOST, b as maxTokensCeilingFor, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isParamInvalidFrame, h as isConcurrencyCap, i as refreshCatalog, j as isBenefitBlocked, k as creditRatioLabel, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isTpmLimit, w as signedGet, x as pickDailyWelfareCampaign, y as isWelfareClaimedStatus } from "./usage-
|
|
1
|
+
import { A as filterEnabledModels, C as rateLimitFrame, D as FALLBACK_CODEARTS_MODELS, E as CodeArtsCatalog, F as MANUAL_ACCOUNT_ID, I as codeartsAccountsPath, L as codeartsAuthPath, M as isBenefitModel, N as CodeArtsAccountStore, O as clearBenefitBlocked, P as CodeArtsCredentialStore, R as startLogin, S as prepareChatBody, T as upstreamErrorMessage, _ as isQueueableRate, a as SNAP_HOST, b as maxTokensCeilingFor, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isParamInvalidFrame, h as isConcurrencyCap, i as refreshCatalog, j as isBenefitBlocked, k as creditRatioLabel, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isTpmLimit, w as signedGet, x as pickDailyWelfareCampaign, y as isWelfareClaimedStatus } from "./usage-B0NfG8vZ.mjs";
|
|
2
|
+
import { i as lazyApi, r as createProvider } from "./models-CgKCibpk.mjs";
|
|
2
3
|
import z from "@deepseek-ai/schemastery";
|
|
3
4
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
4
5
|
import { createServer } from "node:http";
|
|
5
|
-
import { createProvider } from "@earendil-works/pi-ai";
|
|
6
|
-
import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
|
|
7
6
|
import { resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
8
7
|
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
9
8
|
import * as settingsModule from "@deepseek-ai/dsh-settings";
|
|
@@ -545,6 +544,9 @@ var CodeArtsCreditCache = class {
|
|
|
545
544
|
}
|
|
546
545
|
};
|
|
547
546
|
//#endregion
|
|
547
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.lazy.js
|
|
548
|
+
const openAICompletionsApi = () => lazyApi(() => import("./openai-completions-Cn5ZQvOO.mjs"));
|
|
549
|
+
//#endregion
|
|
548
550
|
//#region src/adapter.ts
|
|
549
551
|
/**
|
|
550
552
|
* The `codearts` pi-ai provider.
|
|
@@ -734,8 +736,8 @@ var CodeArtsPiAiAdapter = class extends PiAiAdapter {
|
|
|
734
736
|
* 用户只看得到一句「本轮运行失败」。
|
|
735
737
|
*
|
|
736
738
|
* 什么时候会拿到旧的那份:profile 顶层被别的插件 hoist 了一个低版本,而本插件的依赖
|
|
737
|
-
* 没落地到自己的 `node_modules`。1.1.
|
|
738
|
-
*
|
|
739
|
+
* 没落地到自己的 `node_modules`。1.1.4 起 pi-ai 直接打包进 `lib/`(不再经 npm 解析),
|
|
740
|
+
* 版本漂移在结构上不可能了;这里仍探测一次,把「产物损坏/不兼容」明说,而不是让
|
|
739
741
|
* 每条消息各自崩在一个看不懂的 TypeError 上。
|
|
740
742
|
*
|
|
741
743
|
* 探测用能力而不是版本号:不依赖 package.json 能不能读到,也对未来的版本漂移免疫。
|
|
@@ -751,10 +753,10 @@ function probePiAiCompat() {
|
|
|
751
753
|
return probe;
|
|
752
754
|
}
|
|
753
755
|
async function runProbe() {
|
|
754
|
-
const hint = `需要 @earendil-works/pi-ai >= ${MIN_PI_AI_VERSION}
|
|
756
|
+
const hint = `需要 @earendil-works/pi-ai >= ${MIN_PI_AI_VERSION} 的行为;1.1.4 起它已打进插件产物,探测失败说明产物损坏或被改动,请重装 dsh-codearts`;
|
|
755
757
|
let estimate;
|
|
756
758
|
try {
|
|
757
|
-
({estimateMessageTokens: estimate} = await import("
|
|
759
|
+
({estimateMessageTokens: estimate} = await import("./estimate-BePoD-Np.mjs").then((n) => n.n));
|
|
758
760
|
} catch (error) {
|
|
759
761
|
return `pi-ai 不兼容:读不到 @earendil-works/pi-ai/utils/estimate(${messageOf(error)})。${hint}`;
|
|
760
762
|
}
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/utils/event-stream.js
|
|
2
|
+
var FifoQueue = class {
|
|
3
|
+
incoming = [];
|
|
4
|
+
outgoing = [];
|
|
5
|
+
get length() {
|
|
6
|
+
return this.incoming.length + this.outgoing.length;
|
|
7
|
+
}
|
|
8
|
+
enqueue(value) {
|
|
9
|
+
this.incoming.push(value);
|
|
10
|
+
}
|
|
11
|
+
dequeue() {
|
|
12
|
+
if (this.outgoing.length === 0) while (this.incoming.length > 0) this.outgoing.push(this.incoming.pop());
|
|
13
|
+
return this.outgoing.pop();
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var EventStream = class {
|
|
17
|
+
queue = new FifoQueue();
|
|
18
|
+
waiting = new FifoQueue();
|
|
19
|
+
done = false;
|
|
20
|
+
finalResultPromise;
|
|
21
|
+
resolveFinalResult;
|
|
22
|
+
isComplete;
|
|
23
|
+
extractResult;
|
|
24
|
+
constructor(isComplete, extractResult) {
|
|
25
|
+
this.isComplete = isComplete;
|
|
26
|
+
this.extractResult = extractResult;
|
|
27
|
+
this.finalResultPromise = new Promise((resolve) => {
|
|
28
|
+
this.resolveFinalResult = resolve;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
push(event) {
|
|
32
|
+
if (this.done) return;
|
|
33
|
+
if (this.isComplete(event)) {
|
|
34
|
+
this.done = true;
|
|
35
|
+
this.resolveFinalResult(this.extractResult(event));
|
|
36
|
+
}
|
|
37
|
+
const waiter = this.waiting.dequeue();
|
|
38
|
+
if (waiter) waiter({
|
|
39
|
+
value: event,
|
|
40
|
+
done: false
|
|
41
|
+
});
|
|
42
|
+
else this.queue.enqueue(event);
|
|
43
|
+
}
|
|
44
|
+
end(result) {
|
|
45
|
+
this.done = true;
|
|
46
|
+
if (result !== void 0) this.resolveFinalResult(result);
|
|
47
|
+
while (this.waiting.length > 0) this.waiting.dequeue()({
|
|
48
|
+
value: void 0,
|
|
49
|
+
done: true
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async *[Symbol.asyncIterator]() {
|
|
53
|
+
while (true) if (this.queue.length > 0) yield this.queue.dequeue();
|
|
54
|
+
else if (this.done) return;
|
|
55
|
+
else {
|
|
56
|
+
const result = await new Promise((resolve) => this.waiting.enqueue(resolve));
|
|
57
|
+
if (result.done) return;
|
|
58
|
+
yield result.value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
result() {
|
|
62
|
+
return this.finalResultPromise;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Event stream of one assistant response. It also times the response: the final message (`done` or `error` event, or
|
|
67
|
+
* the result passed to `end()`) gets `durationMs`, measured with a monotonic clock from the stream's creation, unless
|
|
68
|
+
* the message already has one or its `timestamp` predates the stream. A stream that forwards a response which started
|
|
69
|
+
* elsewhere, such as a deferred result fetched later, therefore leaves it untimed.
|
|
70
|
+
*/
|
|
71
|
+
var AssistantMessageEventStream = class extends EventStream {
|
|
72
|
+
#startedAt = Date.now();
|
|
73
|
+
#startedAtMonotonic = performance.now();
|
|
74
|
+
constructor() {
|
|
75
|
+
super((event) => event.type === "done" || event.type === "error", (event) => {
|
|
76
|
+
if (event.type === "done") return event.message;
|
|
77
|
+
else if (event.type === "error") return event.error;
|
|
78
|
+
throw new Error("Unexpected event type for final result");
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
push(event) {
|
|
82
|
+
if (event.type === "done") this.#time(event.message);
|
|
83
|
+
else if (event.type === "error") this.#time(event.error);
|
|
84
|
+
super.push(event);
|
|
85
|
+
}
|
|
86
|
+
end(result) {
|
|
87
|
+
if (result !== void 0) this.#time(result);
|
|
88
|
+
super.end(result);
|
|
89
|
+
}
|
|
90
|
+
#time(message) {
|
|
91
|
+
if (this.done || message.durationMs !== void 0 || message.timestamp < this.#startedAt) return;
|
|
92
|
+
message.durationMs = Math.max(0, Math.round(performance.now() - this.#startedAtMonotonic));
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/api/lazy.js
|
|
97
|
+
function createSetupErrorMessage(model, error, timestamp) {
|
|
98
|
+
return {
|
|
99
|
+
role: "assistant",
|
|
100
|
+
content: [],
|
|
101
|
+
api: model.api,
|
|
102
|
+
provider: model.provider,
|
|
103
|
+
model: model.id,
|
|
104
|
+
usage: {
|
|
105
|
+
input: 0,
|
|
106
|
+
output: 0,
|
|
107
|
+
cacheRead: 0,
|
|
108
|
+
cacheWrite: 0,
|
|
109
|
+
totalTokens: 0,
|
|
110
|
+
cost: {
|
|
111
|
+
input: 0,
|
|
112
|
+
output: 0,
|
|
113
|
+
cacheRead: 0,
|
|
114
|
+
cacheWrite: 0,
|
|
115
|
+
total: 0
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
stopReason: "error",
|
|
119
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
120
|
+
timestamp
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function hasResult(source) {
|
|
124
|
+
return typeof source.result === "function";
|
|
125
|
+
}
|
|
126
|
+
async function forwardStream(target, source) {
|
|
127
|
+
for await (const event of source) target.push(event);
|
|
128
|
+
target.end(hasResult(source) ? await source.result() : void 0);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Returns a stream synchronously while running async setup (auth resolution,
|
|
132
|
+
* lazy module loading) behind it. Setup failures terminate the stream with an
|
|
133
|
+
* error event.
|
|
134
|
+
*/
|
|
135
|
+
function lazyStream(model, setup) {
|
|
136
|
+
const startedAt = Date.now();
|
|
137
|
+
const outer = new AssistantMessageEventStream();
|
|
138
|
+
setup().then((inner) => forwardStream(outer, inner)).catch((error) => {
|
|
139
|
+
const message = createSetupErrorMessage(model, error, startedAt);
|
|
140
|
+
outer.push({
|
|
141
|
+
type: "error",
|
|
142
|
+
reason: "error",
|
|
143
|
+
error: message
|
|
144
|
+
});
|
|
145
|
+
outer.end(message);
|
|
146
|
+
});
|
|
147
|
+
return outer;
|
|
148
|
+
}
|
|
149
|
+
function lazyApi(load, capabilities) {
|
|
150
|
+
const api = {
|
|
151
|
+
stream: (model, context, options) => lazyStream(model, async () => (await load()).stream(model, context, options)),
|
|
152
|
+
streamSimple: (model, context, options) => lazyStream(model, async () => (await load()).streamSimple(model, context, options))
|
|
153
|
+
};
|
|
154
|
+
if (capabilities?.fetchDeferred) api.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
|
|
155
|
+
const implementation = await load();
|
|
156
|
+
if (!implementation.fetchDeferred) throw new Error("API does not support deferred responses");
|
|
157
|
+
return implementation.fetchDeferred(model, handle, options);
|
|
158
|
+
});
|
|
159
|
+
if (capabilities?.cancelDeferred) api.cancelDeferred = async (model, handle, options) => {
|
|
160
|
+
const implementation = await load();
|
|
161
|
+
if (!implementation.cancelDeferred) throw new Error("API cannot cancel deferred responses");
|
|
162
|
+
await implementation.cancelDeferred(model, handle, options);
|
|
163
|
+
};
|
|
164
|
+
return api;
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/utils/diagnostics.js
|
|
168
|
+
function formatThrownValue(value) {
|
|
169
|
+
if (value instanceof Error) return value.message || value.name;
|
|
170
|
+
if (typeof value === "string") return value;
|
|
171
|
+
return String(value);
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/utils/models-error.js
|
|
175
|
+
var ModelsError = class extends Error {
|
|
176
|
+
code;
|
|
177
|
+
constructor(code, message, options) {
|
|
178
|
+
super(withCauseDetail(message, options?.cause), options);
|
|
179
|
+
this.name = "ModelsError";
|
|
180
|
+
this.code = code;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
/** Callers surface `error.message` only, so keep the underlying reason in it. */
|
|
184
|
+
function withCauseDetail(message, cause) {
|
|
185
|
+
if (cause === void 0 || cause === null) return message;
|
|
186
|
+
const detail = formatThrownValue(cause).trim();
|
|
187
|
+
if (!detail || message.includes(detail)) return message;
|
|
188
|
+
return `${message}: ${detail}`;
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/utils/model-operations.js
|
|
192
|
+
/** The type of a model. Models without `type` are chat models. */
|
|
193
|
+
function getModelType(model) {
|
|
194
|
+
return model.type ?? "chat";
|
|
195
|
+
}
|
|
196
|
+
/** Runtime-checked model type narrowing, including legacy chat models without `type`. */
|
|
197
|
+
function isModelType(model, type) {
|
|
198
|
+
return getModelType(model) === type;
|
|
199
|
+
}
|
|
200
|
+
function imageErrorResult(model, error, aborted = false) {
|
|
201
|
+
return {
|
|
202
|
+
api: model.api,
|
|
203
|
+
provider: model.provider,
|
|
204
|
+
model: model.id,
|
|
205
|
+
output: [],
|
|
206
|
+
stopReason: aborted ? "aborted" : "error",
|
|
207
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
208
|
+
timestamp: Date.now()
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function classifierErrorResult(model, error, aborted = false) {
|
|
212
|
+
return {
|
|
213
|
+
api: model.api,
|
|
214
|
+
provider: model.provider,
|
|
215
|
+
model: model.id,
|
|
216
|
+
answers: {},
|
|
217
|
+
stopReason: aborted ? "aborted" : "error",
|
|
218
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
219
|
+
timestamp: Date.now()
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/models.js
|
|
224
|
+
const KNOWN_MODEL_TYPES = {
|
|
225
|
+
chat: true,
|
|
226
|
+
image: true,
|
|
227
|
+
classifier: true
|
|
228
|
+
};
|
|
229
|
+
/** Models from stores and remote sources may have types that only newer versions know. */
|
|
230
|
+
function hasKnownModelType(model) {
|
|
231
|
+
return Object.hasOwn(KNOWN_MODEL_TYPES, getModelType(model));
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Builds a provider from parts. Built-in provider factories and models.json
|
|
235
|
+
* custom providers both go through this. A single `api` streams all chat
|
|
236
|
+
* models; an `api` map dispatches on `model.api`, and a model whose api has
|
|
237
|
+
* no entry produces a stream error. One-shot operation maps dispatch on
|
|
238
|
+
* `model.api` the same way. At least one concrete implementation across
|
|
239
|
+
* `api`/`images`/`classifiers` is required; empty maps are rejected.
|
|
240
|
+
*/
|
|
241
|
+
function createProvider(input) {
|
|
242
|
+
const single = input.api && typeof input.api.stream === "function" ? input.api : void 0;
|
|
243
|
+
const byApi = single || !input.api ? void 0 : input.api;
|
|
244
|
+
const images = input.images;
|
|
245
|
+
const classifiers = input.classifiers;
|
|
246
|
+
const streams = single ? [single] : Object.values(byApi ?? {}).filter((entry) => entry !== void 0);
|
|
247
|
+
const imageImplementations = Object.values(images ?? {}).filter((entry) => entry !== void 0);
|
|
248
|
+
const classifierImplementations = Object.values(classifiers ?? {}).filter((entry) => entry !== void 0);
|
|
249
|
+
if (streams.length === 0 && imageImplementations.length === 0 && classifierImplementations.length === 0) throw new Error(`Provider ${input.id}: at least one of "api", "images", or "classifiers" is required.`);
|
|
250
|
+
const baselineModels = input.models;
|
|
251
|
+
let dynamicModels = [];
|
|
252
|
+
const fetchModels = input.fetchModels;
|
|
253
|
+
const currentModels = () => {
|
|
254
|
+
const merged = [...baselineModels];
|
|
255
|
+
for (const model of dynamicModels) {
|
|
256
|
+
const index = merged.findIndex((entry) => getModelType(entry) === getModelType(model) && entry.id === model.id);
|
|
257
|
+
if (index >= 0) merged[index] = model;
|
|
258
|
+
else merged.push(model);
|
|
259
|
+
}
|
|
260
|
+
return merged;
|
|
261
|
+
};
|
|
262
|
+
const apiFor = (model) => single ?? byApi?.[model.api];
|
|
263
|
+
const dispatch = (model, run) => {
|
|
264
|
+
const streams = apiFor(model);
|
|
265
|
+
if (!streams) return lazyStream(model, async () => {
|
|
266
|
+
throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
|
|
267
|
+
});
|
|
268
|
+
return run(streams);
|
|
269
|
+
};
|
|
270
|
+
const provider = {
|
|
271
|
+
id: input.id,
|
|
272
|
+
name: input.name ?? input.id,
|
|
273
|
+
baseUrl: input.baseUrl,
|
|
274
|
+
headers: input.headers,
|
|
275
|
+
auth: input.auth,
|
|
276
|
+
getModels: () => currentModels().filter((model) => isModelType(model, "chat")),
|
|
277
|
+
getAllModels: currentModels,
|
|
278
|
+
refreshModels: fetchModels ? async (context) => {
|
|
279
|
+
if (context.stored) {
|
|
280
|
+
const restored = context.stored.models.filter((model) => model.provider === input.id).map((model) => model);
|
|
281
|
+
if (!await context.publish({ update: () => {
|
|
282
|
+
dynamicModels = restored;
|
|
283
|
+
} })) return;
|
|
284
|
+
}
|
|
285
|
+
if (!context.allowNetwork || context.signal.aborted) return;
|
|
286
|
+
const fetched = await fetchModels(context);
|
|
287
|
+
if (context.signal.aborted) return;
|
|
288
|
+
const refreshed = fetched.filter(hasKnownModelType);
|
|
289
|
+
await context.publish({
|
|
290
|
+
persist: {
|
|
291
|
+
models: refreshed,
|
|
292
|
+
checkedAt: Date.now()
|
|
293
|
+
},
|
|
294
|
+
update: () => {
|
|
295
|
+
dynamicModels = refreshed;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
} : void 0,
|
|
299
|
+
filterModels: input.filterModels,
|
|
300
|
+
filterAllModels: input.filterAllModels,
|
|
301
|
+
stream: (model, context, options) => dispatch(model, (streams) => streams.stream(model, context, options)),
|
|
302
|
+
streamSimple: (model, context, options) => dispatch(model, (streams) => streams.streamSimple(model, context, options))
|
|
303
|
+
};
|
|
304
|
+
if (streams.some((entry) => entry.fetchDeferred !== void 0)) provider.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
|
|
305
|
+
const implementation = apiFor(model);
|
|
306
|
+
if (!implementation?.fetchDeferred) throw new ModelsError("provider", `Provider ${input.id} does not support deferred responses for "${model.api}"`);
|
|
307
|
+
return implementation.fetchDeferred(model, handle, options);
|
|
308
|
+
});
|
|
309
|
+
if (streams.some((entry) => entry.cancelDeferred !== void 0)) provider.cancelDeferred = async (model, handle, options) => {
|
|
310
|
+
const implementation = apiFor(model);
|
|
311
|
+
if (!implementation?.cancelDeferred) throw new ModelsError("provider", `Provider ${input.id} cannot cancel deferred responses for "${model.api}"`);
|
|
312
|
+
await implementation.cancelDeferred(model, handle, options);
|
|
313
|
+
};
|
|
314
|
+
if (images && imageImplementations.length > 0) provider.generateImages = async (model, context, options) => {
|
|
315
|
+
const implementation = images[model.api];
|
|
316
|
+
if (!implementation) return imageErrorResult(model, new ModelsError("provider", `Provider ${input.id} has no image generation implementation for "${model.api}"`));
|
|
317
|
+
return implementation.generateImages(model, context, options);
|
|
318
|
+
};
|
|
319
|
+
if (classifiers && classifierImplementations.length > 0) provider.classify = async (model, context, options) => {
|
|
320
|
+
const implementation = classifiers[model.api];
|
|
321
|
+
if (!implementation) return classifierErrorResult(model, new ModelsError("provider", `Provider ${input.id} has no classifier implementation for "${model.api}"`));
|
|
322
|
+
return implementation.classify(model, context, options);
|
|
323
|
+
};
|
|
324
|
+
return provider;
|
|
325
|
+
}
|
|
326
|
+
function calculateCost(model, usage) {
|
|
327
|
+
const inputTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
328
|
+
let rates = model.cost;
|
|
329
|
+
let matchedThreshold = -1;
|
|
330
|
+
for (const tier of model.cost.tiers ?? []) if (inputTokens > tier.inputTokensAbove && tier.inputTokensAbove > matchedThreshold) {
|
|
331
|
+
rates = tier;
|
|
332
|
+
matchedThreshold = tier.inputTokensAbove;
|
|
333
|
+
}
|
|
334
|
+
const longWrite = usage.cacheWrite1h ?? 0;
|
|
335
|
+
const shortWrite = usage.cacheWrite - longWrite;
|
|
336
|
+
usage.cost.input = rates.input / 1e6 * usage.input;
|
|
337
|
+
usage.cost.output = rates.output / 1e6 * usage.output;
|
|
338
|
+
usage.cost.cacheRead = rates.cacheRead / 1e6 * usage.cacheRead;
|
|
339
|
+
usage.cost.cacheWrite = (rates.cacheWrite * shortWrite + rates.input * 2 * longWrite) / 1e6;
|
|
340
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
341
|
+
return usage.cost;
|
|
342
|
+
}
|
|
343
|
+
const EXTENDED_THINKING_LEVELS = [
|
|
344
|
+
"off",
|
|
345
|
+
"minimal",
|
|
346
|
+
"low",
|
|
347
|
+
"medium",
|
|
348
|
+
"high",
|
|
349
|
+
"xhigh",
|
|
350
|
+
"max"
|
|
351
|
+
];
|
|
352
|
+
function getSupportedThinkingLevels(model) {
|
|
353
|
+
if (!model.reasoning) return ["off"];
|
|
354
|
+
return EXTENDED_THINKING_LEVELS.filter((level) => {
|
|
355
|
+
const mapped = model.thinkingLevelMap?.[level];
|
|
356
|
+
if (mapped === null) return false;
|
|
357
|
+
if (level === "xhigh" || level === "max") return mapped !== void 0;
|
|
358
|
+
return true;
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function clampThinkingLevel(model, level) {
|
|
362
|
+
const availableLevels = getSupportedThinkingLevels(model);
|
|
363
|
+
if (availableLevels.includes(level)) return level;
|
|
364
|
+
const requestedIndex = EXTENDED_THINKING_LEVELS.indexOf(level);
|
|
365
|
+
if (requestedIndex === -1) return availableLevels[0] ?? "off";
|
|
366
|
+
for (let i = requestedIndex; i < EXTENDED_THINKING_LEVELS.length; i++) {
|
|
367
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
368
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
369
|
+
}
|
|
370
|
+
for (let i = requestedIndex - 1; i >= 0; i--) {
|
|
371
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
372
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
373
|
+
}
|
|
374
|
+
return availableLevels[0] ?? "off";
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
377
|
+
export { AssistantMessageEventStream as a, lazyApi as i, clampThinkingLevel as n, createProvider as r, calculateCost as t };
|