dsh-plugin-subscription-oauth 0.8.12 → 0.8.14
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/lib/auth/provider-controller.d.ts +2 -0
- package/lib/auth/provider-controller.js +14 -10
- package/lib/auth/registry.d.ts +5 -1
- package/lib/auth/registry.js +5 -0
- package/lib/auth/rpc.js +9 -0
- package/lib/client.js.map +1 -1
- package/lib/protocol.d.ts +16 -1
- package/lib/protocol.js +1 -0
- package/lib/providers/ark-provider.js +4 -0
- package/lib/providers/ark.d.ts +4 -0
- package/lib/providers/ark.js +16 -2
- package/lib/providers/glm-provider.js +4 -0
- package/lib/providers/glm.d.ts +4 -0
- package/lib/providers/glm.js +16 -2
- package/lib/providers/grok.d.ts +10 -0
- package/lib/providers/grok.js +45 -5
- package/lib/providers/kimi-provider.js +9 -0
- package/lib/providers/kimi.d.ts +8 -0
- package/lib/providers/kimi.js +32 -2
- package/package.json +1 -1
package/lib/protocol.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
/** Prefix of every RPC method this plugin serves. */
|
|
13
13
|
export declare const RPC_PREFIX = "subscription-oauth.";
|
|
14
14
|
/** Endpoints the Settings page may call. */
|
|
15
|
-
export declare const RPC_ENDPOINTS: readonly ["status", "login", "cancel", "logout", "setDefault", "refresh", "discover", "setModelVisible", "setModelOrder", "addModel", "removeModel", "usage", "reload", "deepseek-balance", "ccswitch-balance"];
|
|
15
|
+
export declare const RPC_ENDPOINTS: readonly ["status", "login", "cancel", "logout", "setDefault", "refresh", "discover", "setModelVisible", "setModelOrder", "addModel", "removeModel", "usage", "reload", "deepseek-balance", "ccswitch-balance", "model-variants"];
|
|
16
16
|
/** One endpoint name. */
|
|
17
17
|
export type RpcEndpoint = typeof RPC_ENDPOINTS[number];
|
|
18
18
|
/** Client → host envelope. */
|
|
@@ -120,6 +120,8 @@ export interface ModelSummary {
|
|
|
120
120
|
* hidden or moved; the page renders it without those controls.
|
|
121
121
|
*/
|
|
122
122
|
pinned?: boolean;
|
|
123
|
+
/** Fast/lightspeed variant wire id, when the provider reported one for this base. */
|
|
124
|
+
fastVariant?: string;
|
|
123
125
|
}
|
|
124
126
|
/** One metered allowance of a subscription plan. */
|
|
125
127
|
export interface UsageWindow {
|
|
@@ -321,6 +323,10 @@ export interface RpcMap {
|
|
|
321
323
|
payload: CcSwitchBalanceRequest;
|
|
322
324
|
value: CcSwitchBalanceResult;
|
|
323
325
|
};
|
|
326
|
+
'model-variants': {
|
|
327
|
+
payload: DiscoverRequest;
|
|
328
|
+
value: ModelVariantsResult;
|
|
329
|
+
};
|
|
324
330
|
}
|
|
325
331
|
/** One currency's wallet balance, as the platform reports it. */
|
|
326
332
|
export interface WalletBalance {
|
|
@@ -347,6 +353,15 @@ export type BalanceResult =
|
|
|
347
353
|
| {
|
|
348
354
|
ok: false;
|
|
349
355
|
};
|
|
356
|
+
/** One model's fast and image variants, as discovery reported them. */
|
|
357
|
+
export interface ModelVariants {
|
|
358
|
+
/** Fast/lightspeed variant wire id, when the provider reported one. */
|
|
359
|
+
fast?: string;
|
|
360
|
+
/** Image-generation model wire id, when the provider reported one. */
|
|
361
|
+
image?: string;
|
|
362
|
+
}
|
|
363
|
+
/** Result of `model-variants`: the variants for one model id. */
|
|
364
|
+
export type ModelVariantsResult = ModelVariants | undefined;
|
|
350
365
|
/** Payload of `deepseek-balance`. */
|
|
351
366
|
export interface DeepSeekBalanceRequest {
|
|
352
367
|
/** Client metadata the host's account service expects. */
|
package/lib/protocol.js
CHANGED
|
@@ -170,5 +170,9 @@ export function createArkProvider(options) {
|
|
|
170
170
|
removeModel: (id) => controller.removeModel(id),
|
|
171
171
|
usage: (force) => controller.usage(force),
|
|
172
172
|
reload: () => controller.reload(),
|
|
173
|
+
modelVariants: (id) => {
|
|
174
|
+
const image = adapter.imageModelId();
|
|
175
|
+
return image === undefined ? undefined : { image };
|
|
176
|
+
},
|
|
173
177
|
};
|
|
174
178
|
}
|
package/lib/providers/ark.d.ts
CHANGED
|
@@ -100,10 +100,14 @@ export interface ArkAdapterOptions {
|
|
|
100
100
|
export declare class ArkAdapter extends LlmAdapter {
|
|
101
101
|
private readonly options;
|
|
102
102
|
private live;
|
|
103
|
+
/** Image-generation model id, when discovery reported one. */
|
|
104
|
+
private imageModel;
|
|
103
105
|
constructor(options: ArkAdapterOptions);
|
|
104
106
|
providerInfo(provider: string): LlmProviderInfo;
|
|
105
107
|
providerRetryPolicy(): undefined;
|
|
106
108
|
listModels(_provider: string): Promise<readonly LlmModelInfo[]>;
|
|
109
|
+
/** The image-generation model id, when discovery reported one. */
|
|
110
|
+
imageModelId(): string | undefined;
|
|
107
111
|
resolveModel(_provider: string, model: string): Promise<LlmResolvedModelInfo>;
|
|
108
112
|
stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
109
113
|
/** Translate an auth failure into the message a user can act on. */
|
package/lib/providers/ark.js
CHANGED
|
@@ -23,6 +23,9 @@ import { proxiedFetch } from '../http.js';
|
|
|
23
23
|
import { findEntry, resolveCatalog } from './catalog.js';
|
|
24
24
|
import { streamProviderResponses, accountPoolHooks } from './responses-stream.js';
|
|
25
25
|
import { toResponsesInput, toResponsesTools } from '../translate/responses.js';
|
|
26
|
+
import { isImageModel } from './grok.js';
|
|
27
|
+
/** Model ids that are clearly not chat models. */
|
|
28
|
+
const NON_CHAT_ID = /(?:^|[-_/])(?:image|video|imagine|embed|embedding|whisper|tts|vision-only)/i;
|
|
26
29
|
/** Provider route this module serves. */
|
|
27
30
|
export const ARK_PROVIDER_ID = 'ark';
|
|
28
31
|
/** Display name for the picker group and the Settings card. */
|
|
@@ -113,6 +116,8 @@ function extraEntry(id) {
|
|
|
113
116
|
export class ArkAdapter extends LlmAdapter {
|
|
114
117
|
options;
|
|
115
118
|
live;
|
|
119
|
+
/** Image-generation model id, when discovery reported one. */
|
|
120
|
+
imageModel;
|
|
116
121
|
constructor(options) {
|
|
117
122
|
super();
|
|
118
123
|
this.options = options;
|
|
@@ -129,7 +134,9 @@ export class ArkAdapter extends LlmAdapter {
|
|
|
129
134
|
if (await this.options.tokens.session() === undefined)
|
|
130
135
|
return [];
|
|
131
136
|
const hidden = await this.hidden();
|
|
132
|
-
|
|
137
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
138
|
+
const imageless = this.catalog().filter((entry) => !isImageModel(entry.id));
|
|
139
|
+
return resolveCatalog(imageless, [], hidden).entries.map((entry) => ({
|
|
133
140
|
provider: ARK_PROVIDER_ID,
|
|
134
141
|
id: entry.id,
|
|
135
142
|
name: entry.name,
|
|
@@ -137,6 +144,10 @@ export class ArkAdapter extends LlmAdapter {
|
|
|
137
144
|
...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
|
|
138
145
|
}));
|
|
139
146
|
}
|
|
147
|
+
/** The image-generation model id, when discovery reported one. */
|
|
148
|
+
imageModelId() {
|
|
149
|
+
return this.imageModel;
|
|
150
|
+
}
|
|
140
151
|
async resolveModel(_provider, model) {
|
|
141
152
|
const entry = findEntry(this.catalog(), model);
|
|
142
153
|
if (entry === undefined) {
|
|
@@ -246,9 +257,12 @@ export class ArkAdapter extends LlmAdapter {
|
|
|
246
257
|
return undefined;
|
|
247
258
|
}
|
|
248
259
|
const body = await response.json();
|
|
249
|
-
const
|
|
260
|
+
const allIds = (body.data ?? [])
|
|
250
261
|
.map((entry) => (typeof entry?.id === 'string' ? entry.id.trim() : ''))
|
|
251
262
|
.filter((id) => id !== '');
|
|
263
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
264
|
+
this.imageModel = allIds.find((id) => isImageModel(id));
|
|
265
|
+
const ids = allIds.filter((id) => !NON_CHAT_ID.test(id));
|
|
252
266
|
return ids.length === 0 ? undefined : ids;
|
|
253
267
|
}
|
|
254
268
|
catch (error) {
|
|
@@ -166,5 +166,9 @@ export function createGlmProvider(options) {
|
|
|
166
166
|
removeModel: (id) => controller.removeModel(id),
|
|
167
167
|
usage: (force) => controller.usage(force),
|
|
168
168
|
reload: () => controller.reload(),
|
|
169
|
+
modelVariants: (id) => {
|
|
170
|
+
const image = adapter.imageModelId();
|
|
171
|
+
return image === undefined ? undefined : { image };
|
|
172
|
+
},
|
|
169
173
|
};
|
|
170
174
|
}
|
package/lib/providers/glm.d.ts
CHANGED
|
@@ -120,6 +120,8 @@ export declare class GlmAdapter extends LlmAdapter {
|
|
|
120
120
|
private readonly options;
|
|
121
121
|
/** Live catalog ids, once discovery succeeded this session. */
|
|
122
122
|
private live;
|
|
123
|
+
/** Image-generation model id, when discovery reported one. */
|
|
124
|
+
private imageModel;
|
|
123
125
|
constructor(options: GlmAdapterOptions);
|
|
124
126
|
providerInfo(provider: string): LlmProviderInfo;
|
|
125
127
|
providerRetryPolicy(): undefined;
|
|
@@ -134,6 +136,8 @@ export declare class GlmAdapter extends LlmAdapter {
|
|
|
134
136
|
private shippedCatalog;
|
|
135
137
|
/** Ids the user published by hand that this route does not already serve. */
|
|
136
138
|
private addedEntries;
|
|
139
|
+
/** The image-generation model id, when discovery reported one. */
|
|
140
|
+
imageModelId(): string | undefined;
|
|
137
141
|
/** The ids the picker must currently omit. */
|
|
138
142
|
private hidden;
|
|
139
143
|
/**
|
package/lib/providers/glm.js
CHANGED
|
@@ -15,6 +15,9 @@ import { proxiedFetch } from '../http.js';
|
|
|
15
15
|
import { findEntry, resolveCatalog } from './catalog.js';
|
|
16
16
|
import { streamProviderResponses, accountPoolHooks } from './responses-stream.js';
|
|
17
17
|
import { toResponsesInput, toResponsesTools } from '../translate/responses.js';
|
|
18
|
+
import { isImageModel } from './grok.js';
|
|
19
|
+
/** Model ids that are clearly not chat models. */
|
|
20
|
+
const NON_CHAT_ID = /(?:^|[-_/])(?:image|video|imagine|embed|embedding|whisper|tts|vision-only)/i;
|
|
18
21
|
/** Provider route this module serves. */
|
|
19
22
|
export const GLM_PROVIDER_ID = 'glm';
|
|
20
23
|
/** Display name for the picker group and the Settings card. */
|
|
@@ -220,6 +223,8 @@ export class GlmAdapter extends LlmAdapter {
|
|
|
220
223
|
options;
|
|
221
224
|
/** Live catalog ids, once discovery succeeded this session. */
|
|
222
225
|
live;
|
|
226
|
+
/** Image-generation model id, when discovery reported one. */
|
|
227
|
+
imageModel;
|
|
223
228
|
constructor(options) {
|
|
224
229
|
super();
|
|
225
230
|
this.options = options;
|
|
@@ -238,7 +243,9 @@ export class GlmAdapter extends LlmAdapter {
|
|
|
238
243
|
if (await this.options.tokens.session() === undefined)
|
|
239
244
|
return [];
|
|
240
245
|
const hidden = await this.hidden();
|
|
241
|
-
|
|
246
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
247
|
+
const imageless = this.catalog().filter((entry) => !isImageModel(entry.id));
|
|
248
|
+
return resolveCatalog(imageless, [], hidden).entries.map((entry) => ({
|
|
242
249
|
provider: GLM_PROVIDER_ID,
|
|
243
250
|
id: entry.id,
|
|
244
251
|
name: entry.name,
|
|
@@ -326,6 +333,10 @@ export class GlmAdapter extends LlmAdapter {
|
|
|
326
333
|
.filter((id) => findEntry(own, id) === undefined)
|
|
327
334
|
.map((id) => extraEntry(id));
|
|
328
335
|
}
|
|
336
|
+
/** The image-generation model id, when discovery reported one. */
|
|
337
|
+
imageModelId() {
|
|
338
|
+
return this.imageModel;
|
|
339
|
+
}
|
|
329
340
|
/** The ids the picker must currently omit. */
|
|
330
341
|
async hidden() {
|
|
331
342
|
if (this.options.hiddenModels === undefined)
|
|
@@ -367,9 +378,12 @@ export class GlmAdapter extends LlmAdapter {
|
|
|
367
378
|
return undefined;
|
|
368
379
|
}
|
|
369
380
|
const body = await response.json();
|
|
370
|
-
const
|
|
381
|
+
const allIds = (body.data ?? [])
|
|
371
382
|
.map((entry) => (typeof entry?.id === 'string' ? entry.id.trim() : ''))
|
|
372
383
|
.filter((id) => id !== '');
|
|
384
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
385
|
+
this.imageModel = allIds.find((id) => isImageModel(id));
|
|
386
|
+
const ids = allIds.filter((id) => !NON_CHAT_ID.test(id));
|
|
373
387
|
return ids.length === 0 ? undefined : ids;
|
|
374
388
|
}
|
|
375
389
|
catch (error) {
|
package/lib/providers/grok.d.ts
CHANGED
|
@@ -112,6 +112,8 @@ interface GrokCliMetadata {
|
|
|
112
112
|
reasoningEfforts?: readonly string[];
|
|
113
113
|
defaultEffort?: string;
|
|
114
114
|
}
|
|
115
|
+
/** True when a model id names an image-generation model. */
|
|
116
|
+
export declare function isImageModel(id: string): boolean;
|
|
115
117
|
/** True when a model id names a fast/lightspeed variant of a base model. */
|
|
116
118
|
export declare function isFastVariant(id: string): boolean;
|
|
117
119
|
/** The base model id a fast variant belongs to (`grok-4.7-fast` → `grok-4.7`). */
|
|
@@ -150,6 +152,10 @@ export declare class GrokAdapter extends LlmAdapter {
|
|
|
150
152
|
private discovered;
|
|
151
153
|
/** Capability metadata from the CLI catalog, keyed by model id. */
|
|
152
154
|
private readonly metadata;
|
|
155
|
+
/** Fast-variant wire id per base model, for the picker's quick-mode button. */
|
|
156
|
+
private readonly fastVariants;
|
|
157
|
+
/** Image-generation model id, when discovery reported one. */
|
|
158
|
+
private imageModel;
|
|
153
159
|
/** Ids the user added by hand, cached so the sync catalog can name them. */
|
|
154
160
|
private userAddedIds;
|
|
155
161
|
constructor(options: GrokAdapterOptions);
|
|
@@ -182,6 +188,10 @@ export declare class GrokAdapter extends LlmAdapter {
|
|
|
182
188
|
private addedEntries;
|
|
183
189
|
/** Record the live catalog for the picker. */
|
|
184
190
|
discover(ids: readonly string[], metadata?: ReadonlyMap<string, GrokCliMetadata>): void;
|
|
191
|
+
/** The fast/lightspeed variant wire id for a base model, when discovery reported one. */
|
|
192
|
+
fastVariant(baseId: string): string | undefined;
|
|
193
|
+
/** The image-generation model id, when discovery reported one. */
|
|
194
|
+
imageModelId(): string | undefined;
|
|
185
195
|
/** The curated catalog, for the Settings page's model list. */
|
|
186
196
|
catalogEntries(): readonly CatalogEntry[];
|
|
187
197
|
/** What this route itself serves, without the ids added by hand. */
|
package/lib/providers/grok.js
CHANGED
|
@@ -262,6 +262,12 @@ export async function refreshGrokToken(input) {
|
|
|
262
262
|
}
|
|
263
263
|
/** Model ids that are clearly not chat models. */
|
|
264
264
|
const NON_CHAT_ID = /(?:^|[-_/])(?:image|video|imagine|embed|embedding|whisper|tts|vision-only)/i;
|
|
265
|
+
/** Model ids that are image-generation models, matched per provider's naming. */
|
|
266
|
+
const IMAGE_MODEL = /(?:^|[-_/])(?:image|imagine|draw|pic|photo)(?:[-_/]|$)/i;
|
|
267
|
+
/** True when a model id names an image-generation model. */
|
|
268
|
+
export function isImageModel(id) {
|
|
269
|
+
return IMAGE_MODEL.test(id);
|
|
270
|
+
}
|
|
265
271
|
/** Model ids that are the fast/lightspeed variant of a base model, matched per base. */
|
|
266
272
|
const FAST_VARIANT = /(?:^|[-_])(?:fast|lightspeed|turbo|quick)$/i;
|
|
267
273
|
/** True when a model id names a fast/lightspeed variant of a base model. */
|
|
@@ -279,6 +285,10 @@ export class GrokAdapter extends LlmAdapter {
|
|
|
279
285
|
discovered;
|
|
280
286
|
/** Capability metadata from the CLI catalog, keyed by model id. */
|
|
281
287
|
metadata = new Map();
|
|
288
|
+
/** Fast-variant wire id per base model, for the picker's quick-mode button. */
|
|
289
|
+
fastVariants = new Map();
|
|
290
|
+
/** Image-generation model id, when discovery reported one. */
|
|
291
|
+
imageModel;
|
|
282
292
|
/** Ids the user added by hand, cached so the sync catalog can name them. */
|
|
283
293
|
userAddedIds = [];
|
|
284
294
|
constructor(options) {
|
|
@@ -299,7 +309,9 @@ export class GrokAdapter extends LlmAdapter {
|
|
|
299
309
|
return [];
|
|
300
310
|
await this.syncUserModels();
|
|
301
311
|
const hidden = await this.hidden();
|
|
302
|
-
|
|
312
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
313
|
+
const imageless = this.catalog().filter((entry) => !isImageModel(entry.id));
|
|
314
|
+
return resolveCatalog(imageless, [], hidden).entries.map((entry) => ({
|
|
303
315
|
provider: GROK_PROVIDER_ID,
|
|
304
316
|
id: entry.id,
|
|
305
317
|
name: entry.name,
|
|
@@ -445,6 +457,14 @@ export class GrokAdapter extends LlmAdapter {
|
|
|
445
457
|
for (const [id, meta] of metadata)
|
|
446
458
|
this.metadata.set(id, meta);
|
|
447
459
|
}
|
|
460
|
+
/** The fast/lightspeed variant wire id for a base model, when discovery reported one. */
|
|
461
|
+
fastVariant(baseId) {
|
|
462
|
+
return this.fastVariants.get(baseId);
|
|
463
|
+
}
|
|
464
|
+
/** The image-generation model id, when discovery reported one. */
|
|
465
|
+
imageModelId() {
|
|
466
|
+
return this.imageModel;
|
|
467
|
+
}
|
|
448
468
|
/** The curated catalog, for the Settings page's model list. */
|
|
449
469
|
catalogEntries() {
|
|
450
470
|
return this.catalog();
|
|
@@ -524,18 +544,29 @@ export class GrokAdapter extends LlmAdapter {
|
|
|
524
544
|
return undefined;
|
|
525
545
|
}
|
|
526
546
|
const payload = await response.json();
|
|
547
|
+
const allIds = (payload.data ?? [])
|
|
548
|
+
.map((entry) => entry.id)
|
|
549
|
+
.filter((id) => typeof id === 'string' && id.length > 0);
|
|
550
|
+
// Image models are not chat models; they are picked by an agent, not the picker.
|
|
551
|
+
this.imageModel = allIds.find((id) => isImageModel(id));
|
|
552
|
+
const rawIds = allIds.filter((id) => !NON_CHAT_ID.test(id));
|
|
527
553
|
// Fast/lightspeed variants ride with their base model: they share the base's
|
|
528
554
|
// visibility switch and are reached by a picker button, not a separate row.
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
555
|
+
this.fastVariants.clear();
|
|
556
|
+
for (const id of rawIds) {
|
|
557
|
+
if (!isFastVariant(id))
|
|
558
|
+
continue;
|
|
559
|
+
const base = baseModelOf(id);
|
|
560
|
+
if (!this.fastVariants.has(base))
|
|
561
|
+
this.fastVariants.set(base, id);
|
|
562
|
+
}
|
|
563
|
+
const ids = rawIds
|
|
532
564
|
.map((id) => (isFastVariant(id) ? baseModelOf(id) : id))
|
|
533
565
|
.filter((id, index, list) => list.indexOf(id) === index);
|
|
534
566
|
if (ids.length === 0) {
|
|
535
567
|
this.options.onWarn?.('xAI model discovery returned an empty catalog; using the built-in catalog');
|
|
536
568
|
return undefined;
|
|
537
569
|
}
|
|
538
|
-
// Keep the fast-variant ids discoverable for the picker button, keyed by their base.
|
|
539
570
|
const metadata = await this.fetchCliMetadata(fetchFn, signal);
|
|
540
571
|
for (const [id, meta] of metadata)
|
|
541
572
|
this.metadata.set(id, meta);
|
|
@@ -698,6 +729,7 @@ export function createGrokProvider(options) {
|
|
|
698
729
|
{ key: 'credentialFile', value: options.credentialFile },
|
|
699
730
|
],
|
|
700
731
|
applyDiscovery: (ids) => { adapter.discover(ids); },
|
|
732
|
+
fastVariant: (baseId) => adapter.fastVariant(baseId),
|
|
701
733
|
};
|
|
702
734
|
const controller = new ProviderController({
|
|
703
735
|
spec,
|
|
@@ -726,5 +758,13 @@ export function createGrokProvider(options) {
|
|
|
726
758
|
removeModel: (id) => controller.removeModel(id),
|
|
727
759
|
usage: (force) => controller.usage(force),
|
|
728
760
|
reload: () => controller.reload(),
|
|
761
|
+
modelVariants: (id) => {
|
|
762
|
+
const fast = adapter.fastVariant(id);
|
|
763
|
+
const image = adapter.imageModelId();
|
|
764
|
+
return {
|
|
765
|
+
...fast === undefined ? {} : { fast },
|
|
766
|
+
...image === undefined ? {} : { image },
|
|
767
|
+
};
|
|
768
|
+
},
|
|
729
769
|
};
|
|
730
770
|
}
|
|
@@ -119,6 +119,7 @@ export function createKimiProvider(options) {
|
|
|
119
119
|
{ key: 'credentialFile', value: options.credentialFile },
|
|
120
120
|
],
|
|
121
121
|
applyDiscovery: (ids) => { adapter.discover(ids); },
|
|
122
|
+
fastVariant: (baseId) => adapter.fastVariant(baseId),
|
|
122
123
|
};
|
|
123
124
|
const controller = new ProviderController({
|
|
124
125
|
spec,
|
|
@@ -149,5 +150,13 @@ export function createKimiProvider(options) {
|
|
|
149
150
|
removeModel: (id) => controller.removeModel(id),
|
|
150
151
|
usage: (force) => controller.usage(force),
|
|
151
152
|
reload: () => controller.reload(),
|
|
153
|
+
modelVariants: (id) => {
|
|
154
|
+
const fast = adapter.fastVariant(id);
|
|
155
|
+
const image = adapter.imageModelId();
|
|
156
|
+
return {
|
|
157
|
+
...fast === undefined ? {} : { fast },
|
|
158
|
+
...image === undefined ? {} : { image },
|
|
159
|
+
};
|
|
160
|
+
},
|
|
152
161
|
};
|
|
153
162
|
}
|
package/lib/providers/kimi.d.ts
CHANGED
|
@@ -102,6 +102,10 @@ export declare class KimiAdapter extends LlmAdapter {
|
|
|
102
102
|
private readonly options;
|
|
103
103
|
/** Live catalog ids seen this session, used to accept renamed models. */
|
|
104
104
|
private discovered;
|
|
105
|
+
/** Image-generation model id, when discovery reported one. */
|
|
106
|
+
private imageModel;
|
|
107
|
+
/** Fast-variant wire id per base model, for the picker's quick-mode button. */
|
|
108
|
+
private readonly fastVariants;
|
|
105
109
|
/** Ids the user added by hand, cached so the sync catalog can name them. */
|
|
106
110
|
private userAddedIds;
|
|
107
111
|
/** Tools already reported as flattened, so each is stated once. */
|
|
@@ -116,6 +120,10 @@ export declare class KimiAdapter extends LlmAdapter {
|
|
|
116
120
|
providerInfo(provider: string): LlmProviderInfo;
|
|
117
121
|
providerRetryPolicy(): undefined;
|
|
118
122
|
listModels(_provider: string): Promise<readonly LlmModelInfo[]>;
|
|
123
|
+
/** The image-generation model id, when discovery reported one. */
|
|
124
|
+
imageModelId(): string | undefined;
|
|
125
|
+
/** The fast/lightspeed variant wire id for a base model, when discovery reported one. */
|
|
126
|
+
fastVariant(baseId: string): string | undefined;
|
|
119
127
|
/** The ids the picker must currently omit. */
|
|
120
128
|
private hidden;
|
|
121
129
|
resolveModel(_provider: string, model: string): Promise<LlmResolvedModelInfo>;
|
package/lib/providers/kimi.js
CHANGED
|
@@ -15,6 +15,9 @@ import { streamProviderResponses, accountPoolHooks } from './responses-stream.js
|
|
|
15
15
|
import { fallbackEntry, findEntry, resolveCatalog } from './catalog.js';
|
|
16
16
|
import { streamResponses, toResponsesInput, toResponsesTools } from '../translate/responses.js';
|
|
17
17
|
import { prepareMoonshotTool } from '../translate/moonshot-schema.js';
|
|
18
|
+
import { isImageModel, isFastVariant, baseModelOf } from './grok.js';
|
|
19
|
+
/** Model ids that are clearly not chat models. */
|
|
20
|
+
const NON_CHAT_ID = /(?:^|[-_/])(?:image|video|imagine|embed|embedding|whisper|tts|vision-only)/i;
|
|
18
21
|
/**
|
|
19
22
|
* Coerce one decoded credential entry into a Kimi session.
|
|
20
23
|
* @param value - decoded JSON value for one account.
|
|
@@ -129,6 +132,10 @@ export class KimiAdapter extends LlmAdapter {
|
|
|
129
132
|
options;
|
|
130
133
|
/** Live catalog ids seen this session, used to accept renamed models. */
|
|
131
134
|
discovered;
|
|
135
|
+
/** Image-generation model id, when discovery reported one. */
|
|
136
|
+
imageModel;
|
|
137
|
+
/** Fast-variant wire id per base model, for the picker's quick-mode button. */
|
|
138
|
+
fastVariants = new Map();
|
|
132
139
|
/** Ids the user added by hand, cached so the sync catalog can name them. */
|
|
133
140
|
userAddedIds = [];
|
|
134
141
|
/** Tools already reported as flattened, so each is stated once. */
|
|
@@ -171,7 +178,9 @@ export class KimiAdapter extends LlmAdapter {
|
|
|
171
178
|
return [];
|
|
172
179
|
await this.syncUserModels();
|
|
173
180
|
const hidden = await this.hidden();
|
|
174
|
-
|
|
181
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
182
|
+
const imageless = this.catalog().filter((entry) => !isImageModel(entry.id));
|
|
183
|
+
return resolveCatalog(imageless, [], hidden).entries.map((entry) => ({
|
|
175
184
|
provider: KIMI_PROVIDER_ID,
|
|
176
185
|
id: entry.id,
|
|
177
186
|
name: entry.name,
|
|
@@ -179,6 +188,14 @@ export class KimiAdapter extends LlmAdapter {
|
|
|
179
188
|
...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
|
|
180
189
|
}));
|
|
181
190
|
}
|
|
191
|
+
/** The image-generation model id, when discovery reported one. */
|
|
192
|
+
imageModelId() {
|
|
193
|
+
return this.imageModel;
|
|
194
|
+
}
|
|
195
|
+
/** The fast/lightspeed variant wire id for a base model, when discovery reported one. */
|
|
196
|
+
fastVariant(baseId) {
|
|
197
|
+
return this.fastVariants.get(baseId);
|
|
198
|
+
}
|
|
182
199
|
/** The ids the picker must currently omit. */
|
|
183
200
|
async hidden() {
|
|
184
201
|
if (this.options.hiddenModels === undefined)
|
|
@@ -414,9 +431,22 @@ export class KimiAdapter extends LlmAdapter {
|
|
|
414
431
|
return undefined;
|
|
415
432
|
}
|
|
416
433
|
const payload = await response.json();
|
|
417
|
-
const
|
|
434
|
+
const allIds = (payload.data ?? [])
|
|
418
435
|
.map((entry) => entry.id)
|
|
419
436
|
.filter((id) => typeof id === 'string' && id.length > 0);
|
|
437
|
+
// Image models are never picker rows: they are agent-called, always on.
|
|
438
|
+
this.imageModel = allIds.find((id) => isImageModel(id));
|
|
439
|
+
// Fast/lightspeed variants ride with their base model: they share the base's
|
|
440
|
+
// visibility switch and are reached by a picker button, not a separate row.
|
|
441
|
+
this.fastVariants.clear();
|
|
442
|
+
for (const id of allIds) {
|
|
443
|
+
if (!isFastVariant(id))
|
|
444
|
+
continue;
|
|
445
|
+
const base = baseModelOf(id);
|
|
446
|
+
if (!this.fastVariants.has(base))
|
|
447
|
+
this.fastVariants.set(base, id);
|
|
448
|
+
}
|
|
449
|
+
const ids = allIds.filter((id) => !NON_CHAT_ID.test(id));
|
|
420
450
|
if (ids.length === 0) {
|
|
421
451
|
this.options.onWarn?.('Kimi model discovery returned an empty catalog; using the built-in catalog');
|
|
422
452
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-subscription-oauth",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.14",
|
|
4
4
|
"description": "Use subscription accounts as DeepSeek Harness LLM providers — Kimi Code (OAuth device flow), Grok / X Premium (OIDC + PKCE), Google Antigravity (Google OAuth + Cloud Code Assist) and GLM / BigModel (ZCode's browser sign-in) — with per-model visibility, drag-to-reorder Auto fallback and plan quotas from the web Settings page",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "EricFL1998",
|