@vedmalex/ai-connect 0.2.0 → 0.2.1

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
@@ -1248,6 +1248,8 @@ console.log(
1248
1248
 
1249
1249
  ## Publishing
1250
1250
 
1251
+ > Full release runbook (OIDC trusted publishing, cutting a release, caveats): [`docs/publishing.md`](./docs/publishing.md).
1252
+
1251
1253
  `@vedmalex/ai-connect` ships as a public scoped npm package. The package metadata enforces the publish boundary:
1252
1254
 
1253
1255
  - `publishConfig.access` is `public`, which is required for a scoped name to publish without an explicit `--access public` flag.
@@ -2172,6 +2172,7 @@ function normalizeResult(route, output, attempts) {
2172
2172
  attempts,
2173
2173
  ...output.toolCalls ? { toolCalls: output.toolCalls } : {},
2174
2174
  ...output.text !== void 0 ? { text: output.text } : {},
2175
+ ...output.reasoning !== void 0 ? { reasoning: output.reasoning } : {},
2175
2176
  ...output.data !== void 0 ? { data: output.data } : {},
2176
2177
  ...output.usage !== void 0 ? { usage: output.usage } : {}
2177
2178
  };
@@ -5548,6 +5549,9 @@ function extractText(value) {
5548
5549
  return [part];
5549
5550
  }
5550
5551
  if (part && typeof part === "object") {
5552
+ if (part.thought === true) {
5553
+ return [];
5554
+ }
5551
5555
  const candidate = part.text;
5552
5556
  if (typeof candidate === "string") {
5553
5557
  return [candidate];
@@ -5558,6 +5562,22 @@ function extractText(value) {
5558
5562
  }
5559
5563
  return "";
5560
5564
  }
5565
+ function extractThoughts(value) {
5566
+ if (!Array.isArray(value)) {
5567
+ return void 0;
5568
+ }
5569
+ const thoughts = value.flatMap((part) => {
5570
+ if (part && typeof part === "object" && part.thought === true) {
5571
+ const candidate = part.text;
5572
+ if (typeof candidate === "string") {
5573
+ return [candidate];
5574
+ }
5575
+ }
5576
+ return [];
5577
+ });
5578
+ const joined = thoughts.join("\n").trim();
5579
+ return joined.length > 0 ? joined : void 0;
5580
+ }
5561
5581
  function imageAttachmentsFromPayload(payload, ...sources) {
5562
5582
  return extractImagePayloads(payload, ...sources).map(
5563
5583
  (item) => preparePortableFile(item)
@@ -6100,8 +6120,11 @@ async function runGemini(fetchImpl, context) {
6100
6120
  throw classifyApiError(provider, response, payload);
6101
6121
  }
6102
6122
  const data = payload;
6123
+ const geminiThoughts = extractThoughts(data.candidates?.[0]?.content?.parts);
6103
6124
  return {
6104
6125
  text: extractText(data.candidates?.[0]?.content?.parts),
6126
+ // The model's `{ thought: true }` parts, separated from the answer (consumers route this to a thinking UI).
6127
+ ...geminiThoughts ? { reasoning: geminiThoughts } : {},
6105
6128
  data,
6106
6129
  ...geminiToolCallsFromPayload(data).length > 0 ? { toolCalls: geminiToolCallsFromPayload(data) } : {},
6107
6130
  ...(() => {