190proof 1.0.113 → 1.0.115

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/README.md CHANGED
@@ -279,6 +279,8 @@ Optional per-request knobs live on `payload` (`GenericPayload`):
279
279
  - `payload.streaming`: `boolean` - OpenRouter-only (default: true). Streams the completion over SSE. A streaming attempt is bounded by two independent timers instead of `requestTimeoutMs`: `streamTimeoutMs` (total wall clock, default 600000) and the per-useful-chunk stall timeout (`chunkTimeoutMs` argument, default 15000). A chunk is "useful" only if it advances content, reasoning, tool-call fragments, finish_reason, or usage — SSE comment keep-alives (`: OPENROUTER PROCESSING`) and role-only deltas don't reset the stall timer, so a hung provider dies within one stall window while a healthy long generation can run to the total budget. Set `streaming: false` for the old single-JSON-body transport.
280
280
  - `payload.streamTimeoutMs`: `number` - OpenRouter-only: total wall-clock budget per streaming attempt (default: 600000).
281
281
  - `payload.streamDeadlineAt`: `number` - OpenRouter-only: absolute deadline (epoch ms) for the whole call **including retries** — the caller's turn budget. Each attempt gets `min(streamTimeoutMs, deadline - now)`, and once under 10s remain the call fails fast instead of starting a generation that cannot be delivered. Use it whenever the caller has its own timeout: a per-attempt budget alone is re-granted on every retry and can outlive that timeout.
282
+ - `payload.thinkingConfig`: `Record<string, unknown>` - Google-only: forwarded verbatim as `generationConfig.thinkingConfig` on the Gemini request — e.g. `{ thinkingBudget: 0 }` to disable thinking, `{ thinkingLevel: "HIGH" }` on models that take a level. Ignored by all other adapters; shapes are model-specific and validated by Google, not the SDK.
283
+ - `payload.reasoningEffort`: `string` - OpenAI-only: forwarded as `reasoning_effort` on the request. Valid values are model-dependent (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`). Reasoning-by-default models (the gpt-5.6 family) reject function tools on `/chat/completions` with a 400 unless this is explicitly `"none"` — their implicit default is `medium`. Ignored by all other adapters.
282
284
 
283
285
  When a streaming attempt is cut at its **total deadline** and prose has already arrived, the partial answer is returned with `truncated: true` on the response rather than discarded — those tokens were generated and billed, so throwing them away costs money and gives the user nothing. Surface such a reply as incomplete. Salvage never applies to tool-call turns (half-streamed arguments are unparseable JSON), to stalls (the provider died mid-thought), or to caller aborts. When nothing is salvageable, the discard is logged with an approximate token count — aborted attempts never receive OpenRouter's `usage` chunk, so that log line is the only record of the wasted spend.
284
286
 
@@ -304,6 +306,9 @@ interface ParsedResponseMessage {
304
306
  prompt_tokens: number;
305
307
  completion_tokens: number;
306
308
  total_tokens: number;
309
+ // Reasoning/thinking tokens spent before the visible answer; currently
310
+ // populated from Google's usageMetadata.thoughtsTokenCount.
311
+ thoughts_tokens?: number;
307
312
  } | null; // null when streaming
308
313
  }
309
314
  ```
package/dist/index.d.mts CHANGED
@@ -199,6 +199,13 @@ interface ParsedResponseMessage {
199
199
  total_tokens: number;
200
200
  /** Prompt tokens served from the provider's cache (subset of prompt_tokens). */
201
201
  cached_tokens?: number;
202
+ /**
203
+ * Reasoning/thinking tokens spent before the visible answer (subset of
204
+ * completion_tokens on some providers, separate on others). Currently
205
+ * populated from Google's `usageMetadata.thoughtsTokenCount`; undefined
206
+ * when the provider reports none.
207
+ */
208
+ thoughts_tokens?: number;
202
209
  } | null;
203
210
  }
204
211
  interface FunctionCall {
@@ -275,11 +282,27 @@ interface GenericPayload {
275
282
  };
276
283
  temperature?: number;
277
284
  fallbackModel?: AnyModel;
285
+ /**
286
+ * Google-only: forwarded verbatim as `generationConfig.thinkingConfig` on
287
+ * the Gemini request — e.g. `{ thinkingBudget: 0 }` to disable thinking or
288
+ * `{ thinkingLevel: "HIGH" }` on models that take a level. Ignored by all
289
+ * other adapters. Shapes are model-specific and validated by Google, not
290
+ * the SDK.
291
+ */
292
+ thinkingConfig?: Record<string, unknown>;
278
293
  /**
279
294
  * OpenRouter-only: provider-routing preferences. Ignored by non-OpenRouter
280
295
  * adapters. Forwarded as the request body's `provider` field.
281
296
  */
282
297
  provider?: OpenRouterProviderPreferences;
298
+ /**
299
+ * OpenAI-only: forwarded as `reasoning_effort` on the request. Valid values
300
+ * are model-dependent (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`).
301
+ * Reasoning-by-default models (gpt-5.6 family) 400 on /chat/completions when
302
+ * function tools are present unless this is explicitly `"none"` — their
303
+ * implicit default is `medium`. Ignored by all other adapters.
304
+ */
305
+ reasoningEffort?: string;
283
306
  /**
284
307
  * Per-request HTTP timeout in ms for the underlying provider call (applied
285
308
  * per attempt, not across retries). Honored by all adapters (Anthropic,
package/dist/index.d.ts CHANGED
@@ -199,6 +199,13 @@ interface ParsedResponseMessage {
199
199
  total_tokens: number;
200
200
  /** Prompt tokens served from the provider's cache (subset of prompt_tokens). */
201
201
  cached_tokens?: number;
202
+ /**
203
+ * Reasoning/thinking tokens spent before the visible answer (subset of
204
+ * completion_tokens on some providers, separate on others). Currently
205
+ * populated from Google's `usageMetadata.thoughtsTokenCount`; undefined
206
+ * when the provider reports none.
207
+ */
208
+ thoughts_tokens?: number;
202
209
  } | null;
203
210
  }
204
211
  interface FunctionCall {
@@ -275,11 +282,27 @@ interface GenericPayload {
275
282
  };
276
283
  temperature?: number;
277
284
  fallbackModel?: AnyModel;
285
+ /**
286
+ * Google-only: forwarded verbatim as `generationConfig.thinkingConfig` on
287
+ * the Gemini request — e.g. `{ thinkingBudget: 0 }` to disable thinking or
288
+ * `{ thinkingLevel: "HIGH" }` on models that take a level. Ignored by all
289
+ * other adapters. Shapes are model-specific and validated by Google, not
290
+ * the SDK.
291
+ */
292
+ thinkingConfig?: Record<string, unknown>;
278
293
  /**
279
294
  * OpenRouter-only: provider-routing preferences. Ignored by non-OpenRouter
280
295
  * adapters. Forwarded as the request body's `provider` field.
281
296
  */
282
297
  provider?: OpenRouterProviderPreferences;
298
+ /**
299
+ * OpenAI-only: forwarded as `reasoning_effort` on the request. Valid values
300
+ * are model-dependent (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`).
301
+ * Reasoning-by-default models (gpt-5.6 family) 400 on /chat/completions when
302
+ * function tools are present unless this is explicitly `"none"` — their
303
+ * implicit default is `medium`. Ignored by all other adapters.
304
+ */
305
+ reasoningEffort?: string;
283
306
  /**
284
307
  * Per-request HTTP timeout in ms for the underlying provider call (applied
285
308
  * per attempt, not across retries). Honored by all adapters (Anthropic,
package/dist/index.js CHANGED
@@ -349,6 +349,7 @@ async function prepareOpenAIPayload(identifier, payload) {
349
349
  const preparedPayload = {
350
350
  model: payload.model,
351
351
  messages: [],
352
+ reasoning_effort: payload.reasoningEffort,
352
353
  tools: (_a = payload.functions) == null ? void 0 : _a.map((fn) => ({
353
354
  type: "function",
354
355
  function: fn
@@ -948,6 +949,7 @@ async function prepareGoogleAIPayload(_identifier, payload) {
948
949
  const preparedPayload = {
949
950
  model: payload.model,
950
951
  messages: [],
952
+ thinkingConfig: payload.thinkingConfig,
951
953
  tools: payload.functions ? {
952
954
  functionDeclarations: payload.functions.map((fn) => ({
953
955
  name: fn.name,
@@ -1044,7 +1046,10 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
1044
1046
  const contents = jigGoogleMessages(payload.messages);
1045
1047
  const requestBody = {
1046
1048
  contents,
1047
- generationConfig: { responseModalities: ["TEXT"] }
1049
+ generationConfig: {
1050
+ responseModalities: ["TEXT"],
1051
+ ...payload.thinkingConfig ? { thinkingConfig: payload.thinkingConfig } : {}
1052
+ }
1048
1053
  };
1049
1054
  if (payload.tools)
1050
1055
  requestBody.tools = [payload.tools];
@@ -1150,7 +1155,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
1150
1155
  prompt_tokens: (_o = response.usageMetadata.promptTokenCount) != null ? _o : 0,
1151
1156
  completion_tokens: (_p = response.usageMetadata.candidatesTokenCount) != null ? _p : 0,
1152
1157
  total_tokens: (_q = response.usageMetadata.totalTokenCount) != null ? _q : 0,
1153
- cached_tokens: (_r = response.usageMetadata.cachedContentTokenCount) != null ? _r : 0
1158
+ cached_tokens: (_r = response.usageMetadata.cachedContentTokenCount) != null ? _r : 0,
1159
+ thoughts_tokens: response.usageMetadata.thoughtsTokenCount
1154
1160
  } : null
1155
1161
  };
1156
1162
  }