dsh-plugin-subscription-oauth 0.8.16 → 0.8.17

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.
@@ -57,6 +57,10 @@ const EFFORT_LABELS = {
57
57
  low: { name: 'Low', description: 'Short chain of thought' },
58
58
  medium: { name: 'Medium', description: 'Balanced thinking budget' },
59
59
  high: { name: 'High', description: 'Deep chain of thought' },
60
+ // Not a thinking budget: this rung is the model's fast variant, which the composer's
61
+ // quick-mode button selects. It rides the effort channel so the row keeps its own id —
62
+ // a swapped model id would leave the picker with no way back to the standard model.
63
+ fast: { name: 'Fast', description: 'Lightspeed variant of this model' },
60
64
  };
61
65
  /**
62
66
  * Curated catalog entries.
@@ -123,13 +127,19 @@ function effortInfo(effort) {
123
127
  const label = EFFORT_LABELS[effort] ?? { name: effort, description: '' };
124
128
  return { id: ReasoningEffortId(effort), name: label.name, description: label.description };
125
129
  }
126
- /** The reasoning block for a catalog entry, or undefined when it supports none. */
127
- function reasoningInfo(entry) {
130
+ /**
131
+ * The reasoning block for a catalog entry, or undefined when it supports none.
132
+ *
133
+ * @param entry - the catalog row.
134
+ * @param fast - add the `fast` rung when this row has a fast variant.
135
+ */
136
+ function reasoningInfo(entry, fast = false) {
128
137
  const efforts = entry.reasoningEfforts;
129
- if (efforts === undefined || efforts.length === 0)
138
+ const ids = fast ? [...efforts ?? [], 'fast'] : efforts;
139
+ if (ids === undefined || ids.length === 0)
130
140
  return undefined;
131
141
  return {
132
- efforts: efforts.map(effortInfo),
142
+ efforts: ids.map(effortInfo),
133
143
  ...entry.defaultEffort === undefined ? {} : { defaultEffort: ReasoningEffortId(entry.defaultEffort) },
134
144
  };
135
145
  }
@@ -446,24 +456,18 @@ export class GrokAdapter extends LlmAdapter {
446
456
  return [];
447
457
  await this.syncUserModels();
448
458
  const hidden = await this.hidden();
449
- // The host validates a GUI selection against the exact ids `listModels` returns
450
- // and refuses an unknown one with `session/model-unavailable`, and its picker
451
- // lists every returned id as its own row. So a fast variant is published under
452
- // its base id: selecting it names the variant the request must send, and the
453
- // base's own id is withheld so the variant does not appear twice.
459
+ // One row per model, always under the model's own id: the host validates every GUI
460
+ // selection against this list, so publishing only the fast variant would leave the
461
+ // picker with no way back to the standard model. Fast mode is the row's `fast`
462
+ // reasoning rung instead (see `stream`).
454
463
  const imageless = this.catalog().filter((entry) => !isImageModel(entry.id));
455
- const listed = resolveCatalog(imageless, [], hidden).entries.map((entry) => {
456
- const fast = this.fastVariants.variantOf(entry.id);
457
- const id = fast ?? entry.id;
458
- return {
459
- provider: GROK_PROVIDER_ID,
460
- id,
461
- name: entry.name,
462
- ...entry.description === undefined ? {} : { description: entry.description },
463
- ...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
464
- };
465
- });
466
- return listed;
464
+ return resolveCatalog(imageless, [], hidden).entries.map((entry) => ({
465
+ provider: GROK_PROVIDER_ID,
466
+ id: entry.id,
467
+ name: entry.name,
468
+ ...entry.description === undefined ? {} : { description: entry.description },
469
+ ...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
470
+ }));
467
471
  }
468
472
  async hidden() {
469
473
  if (this.options.hiddenModels === undefined)
@@ -496,14 +500,13 @@ export class GrokAdapter extends LlmAdapter {
496
500
  ...reasoning === undefined ? {} : { reasoning },
497
501
  };
498
502
  }
499
- const reasoning = reasoningInfo(entry);
500
- // The fast selection names itself "Fast" so the picker trigger reads the mode, not
501
- // the base model it replaces; the id stays the fast wire id the request must send.
502
- const fast = pair !== undefined && pair.wireId === model;
503
+ // A row with a fast variant offers the `fast` rung; the picker shows the row under
504
+ // its own name and the mode as the effort, which is what the trigger already reads.
505
+ const reasoning = reasoningInfo(entry, this.fastVariants.variantOf(entry.id) !== undefined);
503
506
  return {
504
507
  provider: GROK_PROVIDER_ID,
505
508
  id: model,
506
- name: fast ? `${entry.name} Fast` : entry.name,
509
+ name: entry.name,
507
510
  ...entry.description === undefined ? {} : { description: entry.description },
508
511
  ...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
509
512
  context: { contextWindow: entry.contextWindow },
@@ -513,8 +516,17 @@ export class GrokAdapter extends LlmAdapter {
513
516
  }
514
517
  stream(options) {
515
518
  // Resolve @Nk context suffixes to the largest variant the endpoint offers.
516
- const model = this.resolveModelId(options.model);
517
- return streamProviderResponses({ ...options, model }, {
519
+ const base = this.resolveModelId(options.model);
520
+ // Fast mode rides the reasoning channel: `fast` is a rung of the row, not a model id
521
+ // of its own, so the row the picker selected stays dispatchable and the user can
522
+ // always select the standard model again. Only the wire id changes.
523
+ const fast = String(options.reasoningEffort ?? '') === 'fast';
524
+ const model = fast ? this.fastVariants.variantOf(base) ?? base : base;
525
+ const call = { ...options, model };
526
+ // xAI has no `fast` effort; the variant already carries the behaviour.
527
+ if (fast)
528
+ delete call.reasoningEffort;
529
+ return streamProviderResponses(call, {
518
530
  label: 'xAI API',
519
531
  tokens: this.options.tokens,
520
532
  request: (call, model, accessToken, signal) => this.request(call, model, accessToken, signal),
@@ -63,6 +63,10 @@ const EFFORT_LABELS = {
63
63
  high: { name: 'High', description: 'Deep chain of thought' },
64
64
  xhigh: { name: 'Max', description: 'Highest thinking budget Kimi accepts' },
65
65
  max: { name: 'Max', description: 'Highest thinking budget Kimi accepts' },
66
+ // Not a thinking budget: this rung is the model's fast variant, which the composer's
67
+ // quick-mode button selects. It rides the effort channel so the row keeps its own id —
68
+ // a swapped model id would leave the picker with no way back to the standard model.
69
+ fast: { name: 'Fast', description: 'Highspeed variant of this model' },
66
70
  };
67
71
  /**
68
72
  * Kimi Code's live coding catalog.
@@ -116,14 +120,20 @@ function effortInfo(effort) {
116
120
  const label = EFFORT_LABELS[effort] ?? { name: effort, description: '' };
117
121
  return { id: ReasoningEffortId(effort), name: label.name, description: label.description };
118
122
  }
119
- /** The reasoning block for a catalog entry, or undefined when it supports none. */
120
- function reasoningInfo(entry) {
123
+ /**
124
+ * The reasoning block for a catalog entry, or undefined when it supports none.
125
+ *
126
+ * @param entry - the catalog row.
127
+ * @param fast - add the `fast` rung when this row has a fast variant.
128
+ */
129
+ function reasoningInfo(entry, fast = false) {
121
130
  const efforts = entry.reasoningEfforts;
122
- if (efforts === undefined || efforts.length === 0)
131
+ const ids = fast ? [...efforts ?? [], 'fast'] : efforts;
132
+ if (ids === undefined || ids.length === 0)
123
133
  return undefined;
124
- const defaultEffort = entry.defaultEffort ?? efforts[efforts.length - 1];
134
+ const defaultEffort = entry.defaultEffort ?? ids[ids.length - 1];
125
135
  return {
126
- efforts: efforts.map(effortInfo),
136
+ efforts: ids.map(effortInfo),
127
137
  ...defaultEffort === undefined ? {} : { defaultEffort: ReasoningEffortId(defaultEffort) },
128
138
  };
129
139
  }
@@ -206,24 +216,18 @@ export class KimiAdapter extends LlmAdapter {
206
216
  return [];
207
217
  await this.syncUserModels();
208
218
  const hidden = await this.hidden();
209
- // The host validates a GUI selection against the exact ids `listModels` returns
210
- // and refuses an unknown one with `session/model-unavailable`, and its picker
211
- // lists every returned id as its own row. So a fast variant is published under
212
- // its base id: selecting it names the variant the request must send, and the
213
- // base's own id is withheld so the variant does not appear twice.
219
+ // One row per model, always under the model's own id: the host validates every GUI
220
+ // selection against this list, so publishing only the fast variant would leave the
221
+ // picker with no way back to the standard model. Fast mode is the row's `fast`
222
+ // reasoning rung instead (see `stream`).
214
223
  const imageless = this.catalog().filter((entry) => !isImageModel(entry.id));
215
- const listed = resolveCatalog(imageless, [], hidden).entries.map((entry) => {
216
- const fast = this.fastVariants.variantOf(entry.id);
217
- const id = fast ?? entry.id;
218
- return {
219
- provider: KIMI_PROVIDER_ID,
220
- id,
221
- name: entry.name,
222
- ...entry.description === undefined ? {} : { description: entry.description },
223
- ...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
224
- };
225
- });
226
- return listed;
224
+ return resolveCatalog(imageless, [], hidden).entries.map((entry) => ({
225
+ provider: KIMI_PROVIDER_ID,
226
+ id: entry.id,
227
+ name: entry.name,
228
+ ...entry.description === undefined ? {} : { description: entry.description },
229
+ ...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
230
+ }));
227
231
  }
228
232
  /** The image-generation model id, when discovery reported one. */
229
233
  imageModelId() {
@@ -264,17 +268,15 @@ export class KimiAdapter extends LlmAdapter {
264
268
  ...reasoning === undefined ? {} : { reasoning },
265
269
  };
266
270
  }
267
- const reasoning = reasoningInfo(entry);
268
- // A fast variant is a wire id of its own — the button switches to it and back, so the
269
- // selection must keep that id — while an ordinary alias is just another spelling of
270
- // the row and resolves onto it. The fast selection names itself "Fast" so the picker
271
- // trigger reads the mode, not the base model it replaces.
272
- const pair = this.fastVariants.pairOf(model);
273
- const fast = pair !== undefined && pair.wireId === model;
271
+ // A row with a fast variant offers the `fast` rung; the picker shows the row under
272
+ // its own name and the mode as the effort, which is what the trigger already reads.
273
+ const reasoning = reasoningInfo(entry, this.fastVariants.variantOf(entry.id) !== undefined);
274
+ // An alias is just another spelling of the row, so it resolves onto the row's own id:
275
+ // that is what keeps a selection dispatchable and the picker able to show it.
274
276
  return {
275
277
  provider: KIMI_PROVIDER_ID,
276
- id: fast ? model : entry.id,
277
- name: fast ? `${entry.name} Fast` : entry.name,
278
+ id: entry.id,
279
+ name: entry.name,
278
280
  ...entry.description === undefined ? {} : { description: entry.description },
279
281
  ...entry.inputModalities === undefined ? {} : { inputModalities: entry.inputModalities },
280
282
  context: { contextWindow: entry.contextWindow },
@@ -283,7 +285,16 @@ export class KimiAdapter extends LlmAdapter {
283
285
  };
284
286
  }
285
287
  stream(options) {
286
- return streamProviderResponses(options, {
288
+ // Fast mode rides the reasoning channel: `fast` is a rung of the row, not a model id
289
+ // of its own, so the row the picker selected stays dispatchable and the user can
290
+ // always select the standard model again. Only the wire id changes.
291
+ const fast = String(options.reasoningEffort ?? '') === 'fast';
292
+ const model = fast ? this.fastVariants.variantOf(options.model) ?? options.model : options.model;
293
+ const call = { ...options, model };
294
+ // Kimi has no `fast` effort; the variant already carries the behaviour.
295
+ if (fast)
296
+ delete call.reasoningEffort;
297
+ return streamProviderResponses(call, {
287
298
  label: 'Kimi API',
288
299
  tokens: this.options.tokens,
289
300
  request: (call, model, accessToken, signal) => this.request(call, model, accessToken, signal),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-subscription-oauth",
3
- "version": "0.8.16",
3
+ "version": "0.8.17",
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",