@kenkaiiii/gg-core 5.23.3 → 5.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-7OICWYUV.js → chunk-6OH2XAFL.js} +69 -5
- package/dist/chunk-6OH2XAFL.js.map +1 -0
- package/dist/index.cjs +357 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +135 -2
- package/dist/index.d.ts +135 -2
- package/dist/index.js +281 -2
- package/dist/index.js.map +1 -1
- package/dist/model-registry.cjs +41 -3
- package/dist/model-registry.cjs.map +1 -1
- package/dist/model-registry.d.cts +10 -1
- package/dist/model-registry.d.ts +10 -1
- package/dist/model-registry.js +7 -1
- package/package.json +2 -2
- package/dist/chunk-7OICWYUV.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthStorage,
|
|
3
3
|
DEFAULT_MAX_VIDEO_BYTES,
|
|
4
|
+
LOCAL_AUTH_KEY_PREFIX,
|
|
4
5
|
MODELS,
|
|
5
6
|
MOONSHOT_OAUTH_KEY,
|
|
6
7
|
NotLoggedInError,
|
|
7
8
|
XIAOMI_CREDITS_KEY,
|
|
9
|
+
clearRuntimeModels,
|
|
8
10
|
closeLogger,
|
|
9
11
|
generatePKCE,
|
|
12
|
+
getAllModels,
|
|
10
13
|
getAuthStorageKey,
|
|
11
14
|
getAuthStorageKeys,
|
|
12
15
|
getClaudeCliUserAgent,
|
|
@@ -38,9 +41,10 @@ import {
|
|
|
38
41
|
refreshKimiToken,
|
|
39
42
|
refreshOpenAIToken,
|
|
40
43
|
registerLogCleanup,
|
|
44
|
+
registerRuntimeModels,
|
|
41
45
|
usesOpenAICodexTransport,
|
|
42
46
|
withFileLock
|
|
43
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-6OH2XAFL.js";
|
|
44
48
|
import {
|
|
45
49
|
getAppPaths
|
|
46
50
|
} from "./chunk-QNR6SNB2.js";
|
|
@@ -71,6 +75,7 @@ var ANTHROPIC_ADAPTIVE_THINKING_LEVELS = [
|
|
|
71
75
|
"max"
|
|
72
76
|
];
|
|
73
77
|
var MOONSHOT_K3_THINKING_LEVELS = ["low", "high", "max"];
|
|
78
|
+
var LOCAL_THINKING_LEVELS = ["low", "medium", "high", "max"];
|
|
74
79
|
function isOpenAIGptModel(provider, model) {
|
|
75
80
|
return provider === "openai" && model.startsWith("gpt-");
|
|
76
81
|
}
|
|
@@ -90,6 +95,12 @@ function isAnthropicAdaptiveModel(provider, model) {
|
|
|
90
95
|
return provider === "anthropic" && /opus-5|opus-4-8|opus-4-7|opus-4-6|sonnet-5|fable-5|mythos-5/.test(model);
|
|
91
96
|
}
|
|
92
97
|
function getSupportedThinkingLevels(provider, model) {
|
|
98
|
+
if (provider === "local") {
|
|
99
|
+
const info = getModel(model);
|
|
100
|
+
if (!info?.supportsThinking) return [];
|
|
101
|
+
const maxIndex2 = LOCAL_THINKING_LEVELS.indexOf(info.maxThinkingLevel);
|
|
102
|
+
return maxIndex2 === -1 ? LOCAL_THINKING_LEVELS.slice(0, 3) : LOCAL_THINKING_LEVELS.slice(0, maxIndex2 + 1);
|
|
103
|
+
}
|
|
93
104
|
const maxLevel = getMaxThinkingLevel(model);
|
|
94
105
|
if (isAnthropicAdaptiveModel(provider, model)) {
|
|
95
106
|
const levels2 = isAnthropicXhighModel(provider, model) ? ANTHROPIC_XHIGH_THINKING_LEVELS : ANTHROPIC_ADAPTIVE_THINKING_LEVELS;
|
|
@@ -119,7 +130,11 @@ function isThinkingLevelSupported(provider, model, level) {
|
|
|
119
130
|
}
|
|
120
131
|
function getNextThinkingLevel(provider, model, current) {
|
|
121
132
|
const supportedLevels = getSupportedThinkingLevels(provider, model);
|
|
122
|
-
const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model)
|
|
133
|
+
const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model) || // Local servers take a real effort level, not just on/off: Ollama accepts
|
|
134
|
+
// low/medium/high on `reasoning_effort` (verified against 0.32) and the
|
|
135
|
+
// other OpenAI-compatible servers use the same three. A model that can't
|
|
136
|
+
// reason at all already has no supported levels, so it never gets here.
|
|
137
|
+
provider === "local";
|
|
123
138
|
if (!shouldCycleLevels) {
|
|
124
139
|
return current ? void 0 : supportedLevels[0];
|
|
125
140
|
}
|
|
@@ -129,6 +144,253 @@ function getNextThinkingLevel(provider, model, current) {
|
|
|
129
144
|
return supportedLevels[index + 1];
|
|
130
145
|
}
|
|
131
146
|
|
|
147
|
+
// src/local-models.ts
|
|
148
|
+
var DEFAULT_LOCAL_ENDPOINTS = [
|
|
149
|
+
{ id: "ollama", label: "Ollama", baseUrl: "http://127.0.0.1:11434/v1", kind: "ollama" },
|
|
150
|
+
{ id: "lmstudio", label: "LM Studio", baseUrl: "http://127.0.0.1:1234/v1", kind: "lmstudio" },
|
|
151
|
+
{ id: "llamacpp", label: "llama.cpp", baseUrl: "http://127.0.0.1:8080/v1", kind: "llamacpp" },
|
|
152
|
+
{ id: "vllm", label: "vLLM", baseUrl: "http://127.0.0.1:8000/v1", kind: "vllm" }
|
|
153
|
+
];
|
|
154
|
+
var FALLBACK_CONTEXT_WINDOW = 8192;
|
|
155
|
+
var LOCAL_API_KEY_PLACEHOLDER = "local";
|
|
156
|
+
var DEFAULT_PROBE_TIMEOUT_MS = 1200;
|
|
157
|
+
var ENRICH_CONCURRENCY = 6;
|
|
158
|
+
var CACHE_TTL_MS = 3e4;
|
|
159
|
+
var NON_CHAT_ID_PATTERN = /(?:^|[-_/])(?:embed|embedding|rerank|reranker|bge|nomic-embed)/i;
|
|
160
|
+
var LOCAL_ID_PREFIX = "local/";
|
|
161
|
+
function formatLocalModelId(endpointId, rawId) {
|
|
162
|
+
return `${LOCAL_ID_PREFIX}${endpointId}/${rawId}`;
|
|
163
|
+
}
|
|
164
|
+
function parseLocalModelId(id) {
|
|
165
|
+
if (!id.startsWith(LOCAL_ID_PREFIX)) return void 0;
|
|
166
|
+
const rest = id.slice(LOCAL_ID_PREFIX.length);
|
|
167
|
+
const slash = rest.indexOf("/");
|
|
168
|
+
if (slash <= 0 || slash === rest.length - 1) return void 0;
|
|
169
|
+
return { endpointId: rest.slice(0, slash), rawId: rest.slice(slash + 1) };
|
|
170
|
+
}
|
|
171
|
+
function isLocalModelId(id) {
|
|
172
|
+
return parseLocalModelId(id) !== void 0;
|
|
173
|
+
}
|
|
174
|
+
function localAuthStorageKey(endpointId) {
|
|
175
|
+
return `local:${endpointId}`;
|
|
176
|
+
}
|
|
177
|
+
function endpointRoot(baseUrl) {
|
|
178
|
+
return baseUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
179
|
+
}
|
|
180
|
+
function authHeaders(endpoint) {
|
|
181
|
+
return {
|
|
182
|
+
Authorization: `Bearer ${endpoint.apiKey ?? LOCAL_API_KEY_PLACEHOLDER}`,
|
|
183
|
+
Accept: "application/json"
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async function fetchJson(url, endpoint, options) {
|
|
187
|
+
try {
|
|
188
|
+
const res = await fetchJsonOrThrow(url, endpoint, options);
|
|
189
|
+
return res;
|
|
190
|
+
} catch {
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async function fetchJsonOrThrow(url, endpoint, { timeoutMs, signal, method = "GET", body }) {
|
|
195
|
+
const controller = new AbortController();
|
|
196
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
197
|
+
const onAbort = () => controller.abort();
|
|
198
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
199
|
+
try {
|
|
200
|
+
const res = await fetch(url, {
|
|
201
|
+
method,
|
|
202
|
+
signal: controller.signal,
|
|
203
|
+
headers: body ? { ...authHeaders(endpoint), "Content-Type": "application/json" } : authHeaders(endpoint),
|
|
204
|
+
...body ? { body: JSON.stringify(body) } : {}
|
|
205
|
+
});
|
|
206
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
207
|
+
return await res.json();
|
|
208
|
+
} finally {
|
|
209
|
+
clearTimeout(timer);
|
|
210
|
+
signal?.removeEventListener("abort", onAbort);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function unreachableReason(endpoint, err) {
|
|
214
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
215
|
+
if (/abort/i.test(message)) return `No response from ${endpoint.baseUrl} (timed out)`;
|
|
216
|
+
if (/HTTP 401|HTTP 403/.test(message)) {
|
|
217
|
+
return `${endpoint.baseUrl} rejected the API key (HTTP ${message.includes("401") ? 401 : 403})`;
|
|
218
|
+
}
|
|
219
|
+
if (/HTTP \d+/.test(message)) return `${endpoint.baseUrl} returned ${message}`;
|
|
220
|
+
return `Not running at ${endpoint.baseUrl}`;
|
|
221
|
+
}
|
|
222
|
+
async function probeEndpoint(endpoint, { timeoutMs = DEFAULT_PROBE_TIMEOUT_MS, signal } = {}) {
|
|
223
|
+
const listUrl = `${endpoint.baseUrl.replace(/\/+$/, "")}/models`;
|
|
224
|
+
let list;
|
|
225
|
+
try {
|
|
226
|
+
list = await fetchJsonOrThrow(listUrl, endpoint, { timeoutMs, signal });
|
|
227
|
+
} catch (err) {
|
|
228
|
+
return { endpoint, reachable: false, reason: unreachableReason(endpoint, err), models: [] };
|
|
229
|
+
}
|
|
230
|
+
const entries = (list.data ?? []).filter(
|
|
231
|
+
(entry) => typeof entry.id === "string" && entry.id.length > 0 && !NON_CHAT_ID_PATTERN.test(entry.id)
|
|
232
|
+
);
|
|
233
|
+
const models = await enrich(endpoint, entries, { timeoutMs, signal });
|
|
234
|
+
log("INFO", "local-models", `Probed ${endpoint.label}`, {
|
|
235
|
+
baseUrl: endpoint.baseUrl,
|
|
236
|
+
models: String(models.length)
|
|
237
|
+
});
|
|
238
|
+
return { endpoint, reachable: true, models };
|
|
239
|
+
}
|
|
240
|
+
async function enrich(endpoint, entries, options) {
|
|
241
|
+
if (endpoint.kind === "lmstudio") return enrichLmStudio(endpoint, entries, options);
|
|
242
|
+
if (endpoint.kind === "ollama") return enrichOllama(endpoint, entries, options);
|
|
243
|
+
if (endpoint.kind === "llamacpp") return enrichLlamaCpp(endpoint, entries, options);
|
|
244
|
+
return entries.map((entry) => genericModel(endpoint, entry));
|
|
245
|
+
}
|
|
246
|
+
function genericModel(endpoint, entry) {
|
|
247
|
+
const declared = typeof entry.max_model_len === "number" ? entry.max_model_len : void 0;
|
|
248
|
+
return {
|
|
249
|
+
rawId: entry.id,
|
|
250
|
+
endpointId: endpoint.id,
|
|
251
|
+
contextWindow: declared ?? FALLBACK_CONTEXT_WINDOW,
|
|
252
|
+
contextWindowKnown: declared !== void 0,
|
|
253
|
+
supportsTools: true,
|
|
254
|
+
supportsImages: false,
|
|
255
|
+
supportsThinking: false
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
async function enrichOllama(endpoint, entries, options) {
|
|
259
|
+
const showUrl = `${endpointRoot(endpoint.baseUrl)}/api/show`;
|
|
260
|
+
const enriched = await mapLimited(entries, ENRICH_CONCURRENCY, async (entry) => {
|
|
261
|
+
const show = await fetchJson(showUrl, endpoint, {
|
|
262
|
+
...options,
|
|
263
|
+
method: "POST",
|
|
264
|
+
body: { model: entry.id }
|
|
265
|
+
});
|
|
266
|
+
if (!show) return genericModel(endpoint, entry);
|
|
267
|
+
const caps = show.capabilities ?? [];
|
|
268
|
+
if (caps.includes("embedding") && !caps.includes("completion")) return void 0;
|
|
269
|
+
const ctx = ollamaContextLength(show.model_info);
|
|
270
|
+
return {
|
|
271
|
+
rawId: entry.id,
|
|
272
|
+
endpointId: endpoint.id,
|
|
273
|
+
contextWindow: ctx ?? FALLBACK_CONTEXT_WINDOW,
|
|
274
|
+
contextWindowKnown: ctx !== void 0,
|
|
275
|
+
// Ollama reports capabilities honestly, so trust it here rather than
|
|
276
|
+
// using the optimistic generic default.
|
|
277
|
+
supportsTools: caps.includes("tools"),
|
|
278
|
+
supportsImages: caps.includes("vision"),
|
|
279
|
+
supportsThinking: caps.includes("thinking")
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
return enriched.filter((model) => model !== void 0);
|
|
283
|
+
}
|
|
284
|
+
function ollamaContextLength(info) {
|
|
285
|
+
if (!info) return void 0;
|
|
286
|
+
for (const [key, value] of Object.entries(info)) {
|
|
287
|
+
if (key.endsWith(".context_length") && typeof value === "number" && value > 0) return value;
|
|
288
|
+
}
|
|
289
|
+
return void 0;
|
|
290
|
+
}
|
|
291
|
+
async function enrichLmStudio(endpoint, entries, options) {
|
|
292
|
+
const detail = await fetchJson(
|
|
293
|
+
`${endpointRoot(endpoint.baseUrl)}/api/v0/models`,
|
|
294
|
+
endpoint,
|
|
295
|
+
options
|
|
296
|
+
);
|
|
297
|
+
if (!detail?.data) return entries.map((entry) => genericModel(endpoint, entry));
|
|
298
|
+
const byId = new Map(detail.data.filter((m) => m.id).map((m) => [m.id, m]));
|
|
299
|
+
const models = [];
|
|
300
|
+
for (const entry of entries) {
|
|
301
|
+
const info = byId.get(entry.id);
|
|
302
|
+
if (info && info.type !== "llm" && info.type !== "vlm") continue;
|
|
303
|
+
const ctx = info?.max_context_length;
|
|
304
|
+
models.push({
|
|
305
|
+
rawId: entry.id,
|
|
306
|
+
endpointId: endpoint.id,
|
|
307
|
+
contextWindow: typeof ctx === "number" && ctx > 0 ? ctx : FALLBACK_CONTEXT_WINDOW,
|
|
308
|
+
contextWindowKnown: typeof ctx === "number" && ctx > 0,
|
|
309
|
+
// LM Studio doesn't report tool support; it gates per-model at request time.
|
|
310
|
+
supportsTools: true,
|
|
311
|
+
supportsImages: info?.type === "vlm",
|
|
312
|
+
supportsThinking: false,
|
|
313
|
+
loaded: info?.state === "loaded"
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
return models;
|
|
317
|
+
}
|
|
318
|
+
async function enrichLlamaCpp(endpoint, entries, options) {
|
|
319
|
+
const props = await fetchJson(
|
|
320
|
+
`${endpointRoot(endpoint.baseUrl)}/props`,
|
|
321
|
+
endpoint,
|
|
322
|
+
options
|
|
323
|
+
);
|
|
324
|
+
const nCtx = props?.default_generation_settings?.n_ctx;
|
|
325
|
+
const known = typeof nCtx === "number" && nCtx > 0;
|
|
326
|
+
return entries.map((entry) => ({
|
|
327
|
+
...genericModel(endpoint, entry),
|
|
328
|
+
contextWindow: known ? nCtx : FALLBACK_CONTEXT_WINDOW,
|
|
329
|
+
contextWindowKnown: known
|
|
330
|
+
}));
|
|
331
|
+
}
|
|
332
|
+
async function mapLimited(items, limit, fn) {
|
|
333
|
+
const results = new Array(items.length);
|
|
334
|
+
let next = 0;
|
|
335
|
+
const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
336
|
+
while (next < items.length) {
|
|
337
|
+
const index = next++;
|
|
338
|
+
results[index] = await fn(items[index]);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
await Promise.all(workers);
|
|
342
|
+
return results;
|
|
343
|
+
}
|
|
344
|
+
function maxThinkingLevelFor(endpoint) {
|
|
345
|
+
return endpoint.kind === "ollama" ? "max" : "high";
|
|
346
|
+
}
|
|
347
|
+
function toModelInfo(model, endpoint) {
|
|
348
|
+
return {
|
|
349
|
+
id: formatLocalModelId(model.endpointId, model.rawId),
|
|
350
|
+
name: `${model.rawId} (${endpoint.label})`,
|
|
351
|
+
provider: "local",
|
|
352
|
+
contextWindow: model.contextWindow,
|
|
353
|
+
// Leave real headroom for the prompt on small local windows.
|
|
354
|
+
maxOutputTokens: Math.max(512, Math.min(4096, Math.floor(model.contextWindow / 4))),
|
|
355
|
+
supportsThinking: model.supportsThinking,
|
|
356
|
+
supportsImages: model.supportsImages,
|
|
357
|
+
supportsVideo: false,
|
|
358
|
+
costTier: "low",
|
|
359
|
+
maxThinkingLevel: maxThinkingLevelFor(endpoint),
|
|
360
|
+
authStorageKeys: [localAuthStorageKey(model.endpointId)]
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
var cache;
|
|
364
|
+
function cacheKey(endpoints) {
|
|
365
|
+
return endpoints.map((e) => `${e.id}@${e.baseUrl}`).join("|");
|
|
366
|
+
}
|
|
367
|
+
async function discoverLocalModels(endpoints = DEFAULT_LOCAL_ENDPOINTS, options = {}) {
|
|
368
|
+
const key = cacheKey(endpoints);
|
|
369
|
+
if (!options.force && cache && cache.key === key && Date.now() - cache.at < CACHE_TTL_MS) {
|
|
370
|
+
return cache.result;
|
|
371
|
+
}
|
|
372
|
+
const probes = await Promise.all(endpoints.map((endpoint) => probeEndpoint(endpoint, options)));
|
|
373
|
+
const models = probes.flatMap(
|
|
374
|
+
(probe) => probe.models.map((model) => toModelInfo(model, probe.endpoint))
|
|
375
|
+
);
|
|
376
|
+
const result = { probes, models };
|
|
377
|
+
cache = { key, at: Date.now(), result };
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
function clearLocalDiscoveryCache() {
|
|
381
|
+
cache = void 0;
|
|
382
|
+
}
|
|
383
|
+
function findProbedModel(probes, modelId) {
|
|
384
|
+
const parsed = parseLocalModelId(modelId);
|
|
385
|
+
if (!parsed) return void 0;
|
|
386
|
+
for (const probe of probes) {
|
|
387
|
+
if (probe.endpoint.id !== parsed.endpointId) continue;
|
|
388
|
+
const model = probe.models.find((m) => m.rawId === parsed.rawId);
|
|
389
|
+
if (model) return { model, endpoint: probe.endpoint };
|
|
390
|
+
}
|
|
391
|
+
return void 0;
|
|
392
|
+
}
|
|
393
|
+
|
|
132
394
|
// src/provider-usage.ts
|
|
133
395
|
var SubscriptionUsageError = class extends Error {
|
|
134
396
|
constructor(message, status, retryAfterMs2) {
|
|
@@ -845,19 +1107,30 @@ function createAutoUpdater(config) {
|
|
|
845
1107
|
}
|
|
846
1108
|
export {
|
|
847
1109
|
AuthStorage,
|
|
1110
|
+
DEFAULT_LOCAL_ENDPOINTS,
|
|
848
1111
|
DEFAULT_MAX_VIDEO_BYTES,
|
|
1112
|
+
FALLBACK_CONTEXT_WINDOW,
|
|
1113
|
+
LOCAL_API_KEY_PLACEHOLDER,
|
|
1114
|
+
LOCAL_AUTH_KEY_PREFIX,
|
|
849
1115
|
MODELS,
|
|
850
1116
|
MOONSHOT_OAUTH_KEY,
|
|
851
1117
|
NotLoggedInError,
|
|
852
1118
|
SubscriptionUsageError,
|
|
853
1119
|
TelegramBot,
|
|
854
1120
|
XIAOMI_CREDITS_KEY,
|
|
1121
|
+
clearLocalDiscoveryCache,
|
|
1122
|
+
clearRuntimeModels,
|
|
855
1123
|
closeLogger,
|
|
856
1124
|
createAutoUpdater,
|
|
857
1125
|
decodeOggOpus,
|
|
1126
|
+
discoverLocalModels,
|
|
858
1127
|
downmixToMono,
|
|
1128
|
+
endpointRoot,
|
|
859
1129
|
fetchSubscriptionUsage,
|
|
1130
|
+
findProbedModel,
|
|
1131
|
+
formatLocalModelId,
|
|
860
1132
|
generatePKCE,
|
|
1133
|
+
getAllModels,
|
|
861
1134
|
getAppPaths,
|
|
862
1135
|
getAuthStorageKey,
|
|
863
1136
|
getAuthStorageKeys,
|
|
@@ -877,25 +1150,31 @@ export {
|
|
|
877
1150
|
getToolResultCharLimit,
|
|
878
1151
|
getVideoByteLimit,
|
|
879
1152
|
isKimiCodingEndpoint,
|
|
1153
|
+
isLocalModelId,
|
|
880
1154
|
isLoggerOpen,
|
|
881
1155
|
isModelLoaded,
|
|
882
1156
|
isThinkingLevelSupported,
|
|
883
1157
|
kimiCodeBaseUrl,
|
|
884
1158
|
kimiCodingHeaders,
|
|
1159
|
+
localAuthStorageKey,
|
|
885
1160
|
log,
|
|
886
1161
|
loginAnthropic,
|
|
887
1162
|
loginGemini,
|
|
888
1163
|
loginKimi,
|
|
889
1164
|
loginOpenAI,
|
|
890
1165
|
openLog,
|
|
1166
|
+
parseLocalModelId,
|
|
1167
|
+
probeEndpoint,
|
|
891
1168
|
readStoredBaseUrlSync,
|
|
892
1169
|
refreshAnthropicToken,
|
|
893
1170
|
refreshGeminiToken,
|
|
894
1171
|
refreshKimiToken,
|
|
895
1172
|
refreshOpenAIToken,
|
|
896
1173
|
registerLogCleanup,
|
|
1174
|
+
registerRuntimeModels,
|
|
897
1175
|
resample,
|
|
898
1176
|
setProgressCallback,
|
|
1177
|
+
toModelInfo,
|
|
899
1178
|
transcribeVoice,
|
|
900
1179
|
usesOpenAICodexTransport,
|
|
901
1180
|
withFileLock
|