@apinggithub/mydsh-auto-model-router 0.2.3 → 0.2.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/auto-adapter.mjs CHANGED
@@ -107,6 +107,49 @@ function reasoningEfforts(info) {
107
107
  return FALLBACK_EFFORTS.map((effort) => ({ ...effort }))
108
108
  }
109
109
 
110
+ /**
111
+ * Pick the reasoning effort to send to the routed model.
112
+ *
113
+ * The session's model selection keeps its own `reasoningEffort` and the host's
114
+ * selection listener re-applies it after every waterfall rewrite, so the value
115
+ * that reaches this adapter belongs to the *virtual* model, not to the model it
116
+ * forwards to. Passing it through unchanged sends a thinking parameter to a
117
+ * model with no thinking mode, which the provider rejects outright
118
+ * (`does not support reasoning effort "low"`).
119
+ *
120
+ * @param {object} llm - ctx.llm
121
+ * @param {object} route - the routed provider/model
122
+ * @param {unknown} requested - effort the caller asked for (usually the UI choice)
123
+ * @returns {Promise<string | undefined>} an effort the target advertises, or undefined
124
+ */
125
+ async function supportedEffort(llm, route, requested) {
126
+ const info = await underlyingInfo(llm, route)
127
+ const efforts = Array.isArray(info?.reasoning?.efforts) ? info.reasoning.efforts : []
128
+ if (efforts.length === 0) return undefined
129
+ const ids = new Set(efforts.map((effort) => effort.id))
130
+ if (typeof route.reasoningEffort === 'string' && ids.has(route.reasoningEffort)) return route.reasoningEffort
131
+ if (typeof requested === 'string' && ids.has(requested)) return requested
132
+ const fallback = info?.reasoning?.defaultEffort
133
+ return typeof fallback === 'string' && ids.has(fallback) ? fallback : undefined
134
+ }
135
+
136
+ /**
137
+ * Request options for the routed model: same call, different provider/model,
138
+ * and only the reasoning effort that model actually supports.
139
+ *
140
+ * @param {object} llm - ctx.llm
141
+ * @param {object} route - the routed provider/model
142
+ * @param {object} options - options the runtime handed to `stream()`
143
+ * @returns {Promise<object>}
144
+ */
145
+ async function forwardOptions(llm, route, options) {
146
+ const forwarded = { ...options, provider: route.provider, model: route.model }
147
+ delete forwarded.reasoningEffort
148
+ const effort = await supportedEffort(llm, route, options?.reasoningEffort)
149
+ if (effort !== undefined) forwarded.reasoningEffort = effort
150
+ return forwarded
151
+ }
152
+
110
153
  /**
111
154
  * Build the virtual adapter for one plugin mount.
112
155
  *
@@ -194,13 +237,9 @@ export function createAutoAdapter(resolve = {}) {
194
237
  // runtime; the adapter contract requires we stream chunks back.
195
238
  const llm = readLlm()
196
239
  if (typeof llm?.stream === 'function') {
240
+ const forwarded = await forwardOptions(llm, route, options)
197
241
  // ctx.llm.stream returns the AsyncIterable directly (not { stream }).
198
- const stream = llm.stream({
199
- ...options,
200
- provider: route.provider,
201
- model: route.model,
202
- ...route.reasoningEffort === undefined ? {} : { reasoningEffort: route.reasoningEffort },
203
- })
242
+ const stream = llm.stream(forwarded)
204
243
  for await (const chunk of stream) yield chunk
205
244
  return
206
245
  }
package/config.mjs CHANGED
@@ -22,7 +22,7 @@
22
22
  // fallbackChain: [route, ...] (model-level, appended with the default)
23
23
  // maxRetries: per-route retry budget on request-error
24
24
 
25
- export const PLUGIN_VERSION = '0.2.3'
25
+ export const PLUGIN_VERSION = '0.2.4'
26
26
 
27
27
  export const LEVEL_IDS = Object.freeze(['L0', 'L1', 'L2', 'L3'])
28
28
  export const COST_MODES = Object.freeze(['cost-first', 'quality-first', 'balanced'])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apinggithub/mydsh-auto-model-router",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Hybrid model router for DeepSeek Harness: declarative rules, user-configurable cost control (cost-first / quality-first / balanced), optional LLM task classifier, and failure fallback chains.",
5
5
  "type": "module",
6
6
  "main": "index.mjs",