190proof 1.0.117 → 1.0.119

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
@@ -290,7 +290,7 @@ Optional per-request knobs live on `payload` (`GenericPayload`):
290
290
  - `payload.streamTimeoutMs`: `number` - OpenRouter-only: total wall-clock budget per streaming attempt (default: 600000).
291
291
  - `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.
292
292
  - `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.
293
- - `payload.reasoningEffort`: `string` - OpenAI and OpenRouter: forwarded as `reasoning_effort` on the request. Valid values are model-dependent (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`). Direct OpenAI: 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`. Via OpenRouter the same models accept tools at any effort (OpenRouter fronts `/v1/responses`), so omitting this runs them at their native default. Ignored by all other adapters.
293
+ - `payload.reasoningEffort`: `string` - OpenAI and OpenRouter reasoning effort. Valid values are model-dependent (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`). OpenRouter: sent as the nested `reasoning: { effort }` object — the canonical form, and the only one that accepts `max` (the flat `reasoning_effort` field caps at `xhigh`). Direct OpenAI: sent flat as `reasoning_effort`; `max` is rejected there, and 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`. Via OpenRouter the same models accept tools at any effort (OpenRouter fronts `/v1/responses`), so omitting this runs them at their native default. Ignored by all other adapters.
294
294
 
295
295
  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.
296
296
 
package/dist/index.d.mts CHANGED
@@ -296,14 +296,17 @@ interface GenericPayload {
296
296
  */
297
297
  provider?: OpenRouterProviderPreferences;
298
298
  /**
299
- * OpenAI and OpenRouter: forwarded as `reasoning_effort` on the request.
300
- * Valid values are model-dependent
299
+ * OpenAI and OpenRouter reasoning effort. Valid values are model-dependent
301
300
  * (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`).
302
- * Direct OpenAI: reasoning-by-default models (gpt-5.6 family) 400 on
303
- * /chat/completions when function tools are present unless this is
304
- * explicitly `"none"` — their implicit default is `medium`. Via OpenRouter
305
- * the same models accept tools at any effort (OpenRouter fronts
306
- * /v1/responses), so omitting this runs them at their native default.
301
+ * OpenRouter: sent as the nested `reasoning: { effort }` object (the
302
+ * canonical form, and the only one where `max` is accepted — flat
303
+ * `reasoning_effort` caps at `xhigh`, and on gpt-5.6-luna nested `max`
304
+ * measurably out-reasons `xhigh` despite docs calling them aliases).
305
+ * Direct OpenAI: sent flat as `reasoning_effort`; `max` is rejected there,
306
+ * and reasoning-by-default models (gpt-5.6 family) 400 on /chat/completions
307
+ * when function tools are present unless this is explicitly `"none"` —
308
+ * their implicit default is `medium`. Via OpenRouter the same models accept
309
+ * tools at any effort (OpenRouter fronts /v1/responses).
307
310
  * Ignored by all other adapters.
308
311
  */
309
312
  reasoningEffort?: string;
package/dist/index.d.ts CHANGED
@@ -296,14 +296,17 @@ interface GenericPayload {
296
296
  */
297
297
  provider?: OpenRouterProviderPreferences;
298
298
  /**
299
- * OpenAI and OpenRouter: forwarded as `reasoning_effort` on the request.
300
- * Valid values are model-dependent
299
+ * OpenAI and OpenRouter reasoning effort. Valid values are model-dependent
301
300
  * (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`).
302
- * Direct OpenAI: reasoning-by-default models (gpt-5.6 family) 400 on
303
- * /chat/completions when function tools are present unless this is
304
- * explicitly `"none"` — their implicit default is `medium`. Via OpenRouter
305
- * the same models accept tools at any effort (OpenRouter fronts
306
- * /v1/responses), so omitting this runs them at their native default.
301
+ * OpenRouter: sent as the nested `reasoning: { effort }` object (the
302
+ * canonical form, and the only one where `max` is accepted — flat
303
+ * `reasoning_effort` caps at `xhigh`, and on gpt-5.6-luna nested `max`
304
+ * measurably out-reasons `xhigh` despite docs calling them aliases).
305
+ * Direct OpenAI: sent flat as `reasoning_effort`; `max` is rejected there,
306
+ * and reasoning-by-default models (gpt-5.6 family) 400 on /chat/completions
307
+ * when function tools are present unless this is explicitly `"none"` —
308
+ * their implicit default is `medium`. Via OpenRouter the same models accept
309
+ * tools at any effort (OpenRouter fronts /v1/responses).
307
310
  * Ignored by all other adapters.
308
311
  */
309
312
  reasoningEffort?: string;
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // index.ts
30
+ // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ClaudeModel: () => ClaudeModel,
@@ -44,7 +44,7 @@ __export(index_exports, {
44
44
  });
45
45
  module.exports = __toCommonJS(index_exports);
46
46
 
47
- // interfaces.ts
47
+ // src/interfaces.ts
48
48
  var ClaudeModel = /* @__PURE__ */ ((ClaudeModel2) => {
49
49
  ClaudeModel2["HAIKU_3"] = "claude-3-haiku-20240307";
50
50
  ClaudeModel2["SONNET_3"] = "claude-3-sonnet-20240229";
@@ -103,7 +103,7 @@ var GeminiModel = /* @__PURE__ */ ((GeminiModel2) => {
103
103
  return GeminiModel2;
104
104
  })(GeminiModel || {});
105
105
 
106
- // logger.ts
106
+ // src/logger.ts
107
107
  function formatIdentifier(identifier) {
108
108
  if (Array.isArray(identifier)) {
109
109
  return identifier.map((id) => `[${id}]`).join(" ");
@@ -128,11 +128,11 @@ var logger_default = {
128
128
  error
129
129
  };
130
130
 
131
- // index.ts
131
+ // src/index.ts
132
132
  var import_client_bedrock_runtime = require("@aws-sdk/client-bedrock-runtime");
133
133
  var import_axios = __toESM(require("axios"));
134
134
 
135
- // utils.ts
135
+ // src/utils.ts
136
136
  function timeout(ms) {
137
137
  return new Promise((resolve) => setTimeout(resolve, ms));
138
138
  }
@@ -142,7 +142,7 @@ function isHeicImage(name, mime) {
142
142
  return ["heic", "heif", "heics"].includes(extension) || !!(mime && ["image/heic", "image/heif", "image/heic-sequence"].includes(mime));
143
143
  }
144
144
 
145
- // index.ts
145
+ // src/index.ts
146
146
  var sharp = require("sharp");
147
147
  var decode = require("heic-decode");
148
148
  function anySignal(signals) {
@@ -1414,7 +1414,11 @@ function prepareOpenRouterPayload(payload) {
1414
1414
  tool_choice: payload.function_call ? typeof payload.function_call === "string" ? payload.function_call : { type: "function", function: payload.function_call } : void 0,
1415
1415
  temperature: payload.temperature,
1416
1416
  provider: payload.provider,
1417
- reasoning_effort: payload.reasoningEffort
1417
+ // Nested form is OpenRouter's canonical param and the only one that
1418
+ // accepts "max" (flat reasoning_effort rejects it — OpenAI enum tops out
1419
+ // at xhigh, and measured on gpt-5.6-luna nested max buys more reasoning
1420
+ // tokens than xhigh despite the docs calling them equivalent).
1421
+ reasoning: payload.reasoningEffort ? { effort: payload.reasoningEffort } : void 0
1418
1422
  };
1419
1423
  }
1420
1424
  var DSML_ENVELOPE_RE = /<|+DSML|+tool_calls>/;
@@ -1561,6 +1565,14 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1561
1565
  let finishReason = null;
1562
1566
  let sawDone = false;
1563
1567
  let dataChunks = 0;
1568
+ const RAW_HEAD_MAX = 3e3;
1569
+ const RAW_TAIL_MAX = 1500;
1570
+ let rawHead = "";
1571
+ let rawTail = "";
1572
+ let generationId;
1573
+ const unreadKeys = /* @__PURE__ */ new Set();
1574
+ const KNOWN_DELTA_KEYS = /* @__PURE__ */ new Set(["role", "content", "reasoning", "reasoning_details", "tool_calls"]);
1575
+ const KNOWN_CHOICE_KEYS = /* @__PURE__ */ new Set(["index", "delta", "finish_reason", "native_finish_reason", "logprobs"]);
1564
1576
  try {
1565
1577
  armStallTimer();
1566
1578
  const response = await fetch(openRouterEndpoint(), {
@@ -1612,6 +1624,11 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1612
1624
  sawDone = true;
1613
1625
  break outer;
1614
1626
  }
1627
+ if (rawHead.length < RAW_HEAD_MAX) {
1628
+ rawHead += dataStr.slice(0, RAW_HEAD_MAX - rawHead.length) + "\n";
1629
+ } else {
1630
+ rawTail = (rawTail + dataStr + "\n").slice(-RAW_TAIL_MAX);
1631
+ }
1615
1632
  let json;
1616
1633
  try {
1617
1634
  json = JSON.parse(dataStr);
@@ -1633,6 +1650,7 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1633
1650
  throw error2;
1634
1651
  }
1635
1652
  if (json.provider) provider = json.provider;
1653
+ if (json.id && !generationId) generationId = json.id;
1636
1654
  let useful = false;
1637
1655
  if (json.usage) {
1638
1656
  usage = json.usage;
@@ -1641,6 +1659,12 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1641
1659
  const choice = (_c = json.choices) == null ? void 0 : _c[0];
1642
1660
  if (choice) {
1643
1661
  const delta = (_d = choice.delta) != null ? _d : {};
1662
+ for (const k of Object.keys(choice)) {
1663
+ if (!KNOWN_CHOICE_KEYS.has(k) && choice[k] != null) unreadKeys.add(`choice.${k}`);
1664
+ }
1665
+ for (const k of Object.keys(delta)) {
1666
+ if (!KNOWN_DELTA_KEYS.has(k) && delta[k] != null && delta[k] !== "") unreadKeys.add(`delta.${k}`);
1667
+ }
1644
1668
  if (delta.content) {
1645
1669
  paragraph += delta.content;
1646
1670
  useful = true;
@@ -1697,7 +1721,12 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1697
1721
  usage,
1698
1722
  paragraph: paragraph.slice(0, 500),
1699
1723
  reasoningChars: reasoning.length,
1700
- toolCalls
1724
+ toolCalls,
1725
+ generationId,
1726
+ dataChunks,
1727
+ unreadKeys: [...unreadKeys],
1728
+ rawHead,
1729
+ rawTail: rawTail || void 0
1701
1730
  })
1702
1731
  });
1703
1732
  } catch (error2) {