pi-antigravity-rotator 2.1.5 → 2.1.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.1.6] - 2026-06-12
6
+
7
+ ### Fixed
8
+ - **Streaming tool calls finish reason**: Fixed an issue where `streamCompatSse` emitted `finish_reason: "stop"` instead of `"tool_calls"` when function calls were streamed to the client via OpenAI compatibility layer. This resolves compatibility issues with clients like ZED editor that discard pending tool executions as canceled when receiving "stop".
9
+
5
10
  ## [2.1.5] - 2026-05-27
6
11
 
7
12
  ### Fixed
@@ -11,6 +16,8 @@
11
16
  - **Consecutive tool result merging**: Multiple `functionResponse` parts are now merged into a single `user` Gemini turn, ensuring all `tool_result` blocks appear in one message directly after the `tool_use` assistant message.
12
17
 
13
18
 
19
+ ## [2.1.4] - 2026-05-27
20
+
14
21
  ### Improved
15
22
  - **Less Lossy Schema Collapsing for Claude**: The `sanitizeClaudeViaGeminiSchema` function now handles complex `anyOf`/`oneOf`/`allOf` schemas with significantly less information loss:
16
23
  - **Nullable detection (lossless)**: `anyOf: [{type: X}, {type: "null"}]` patterns are now converted to `{type: X, nullable: true}` instead of losing the null variant.
package/README.md CHANGED
@@ -471,6 +471,7 @@ Current adapter scope:
471
471
 
472
472
  Thanks to these amazing people who have contributed to the project:
473
473
 
474
+ - **[@josenicomaia](https://github.com/josenicomaia)** (José Nicodemos Maia Neto) — Fixed streaming pass-through to emit correct `finish_reason` for tool calls, fixing tool execution on ZED editor. ([PR #8](https://github.com/tuxevil/pi-antigravity-rotator/pull/8))
474
475
  - **[@javargasm](https://github.com/javargasm)** (Jeisson Alexander Vargas Marroquin) — Anthropic tool-use compatibility layer (`tool_use`/`tool_result` content block conversion), JSON schema round-trip fixes, and compat test suite expansion. ([PR #3](https://github.com/tuxevil/pi-antigravity-rotator/pull/3), [PR #7](https://github.com/tuxevil/pi-antigravity-rotator/pull/7))
475
476
 
476
477
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-antigravity-rotator",
3
- "version": "2.1.5",
3
+ "version": "2.1.6",
4
4
  "description": "Multi-account rotation proxy for Google Antigravity with per-model routing, real-time quota tracking, and infringement detection",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/compat.ts CHANGED
@@ -1682,6 +1682,7 @@ async function streamCompatSse(
1682
1682
  const created = Math.floor(Date.now() / 1000);
1683
1683
  const id = format === "openai" ? `chatcmpl-${Date.now().toString(36)}` : `msg_${Date.now().toString(36)}`;
1684
1684
 
1685
+ const openaiToolCalls: OpenAIToolCall[] = [];
1685
1686
  let anthropicActiveBlockIndex = -1;
1686
1687
  let anthropicActiveBlockType: "thinking" | "text" | null = null;
1687
1688
  let anthropicHasToolUse = false;
@@ -1776,6 +1777,7 @@ async function streamCompatSse(
1776
1777
  cacheThoughtSignature(callId, part.thoughtSignature);
1777
1778
  }
1778
1779
  if (format === "openai") {
1780
+ openaiToolCalls.push({ id: callId, type: "function", function: { name, arguments: args } });
1779
1781
  res.write(`data: ${JSON.stringify({ id, object: "chat.completion.chunk", created, model, choices: [{ index: 0, delta: { tool_calls: [{ index: toolCallIndex - 1, id: callId, type: "function", function: { name, arguments: args } }] }, finish_reason: null }] })}\n\n`);
1780
1782
  } else {
1781
1783
  // Close any active text/thinking block before emitting tool_use
@@ -1813,7 +1815,8 @@ async function streamCompatSse(
1813
1815
 
1814
1816
  if (!reqClosed && !res.writableEnded) {
1815
1817
  if (format === "openai") {
1816
- res.write(`data: ${JSON.stringify({ id, object: "chat.completion.chunk", created, model, choices: [{ index: 0, delta: {}, finish_reason: "stop" }] })}\n\n`);
1818
+ const openaiFinishReason = toolCallIndex > 0 ? "tool_calls" : "stop";
1819
+ res.write(`data: ${JSON.stringify({ id, object: "chat.completion.chunk", created, model, choices: [{ index: 0, delta: {}, finish_reason: openaiFinishReason }] })}\n\n`);
1817
1820
  // Emit a usage chunk so agents (hermes, openwebui, etc.) can display token statistics
1818
1821
  if (inputTokens > 0 || outputTokens > 0) {
1819
1822
  res.write(`data: ${JSON.stringify({ id, object: "chat.completion.chunk", created, model, choices: [], usage: { prompt_tokens: inputTokens, completion_tokens: outputTokens, total_tokens: inputTokens + outputTokens } })}\n\n`);
@@ -1831,7 +1834,8 @@ async function streamCompatSse(
1831
1834
  res.end();
1832
1835
  }
1833
1836
 
1834
- return { text, inputTokens, outputTokens, responseId, toolCalls: anthropicToolCalls.length > 0 ? anthropicToolCalls : undefined };
1837
+ const collectedToolCalls = openaiToolCalls.length > 0 ? openaiToolCalls : anthropicToolCalls.length > 0 ? anthropicToolCalls : undefined;
1838
+ return { text, inputTokens, outputTokens, responseId, toolCalls: collectedToolCalls };
1835
1839
  }
1836
1840
 
1837
1841
  async function streamResponsesSse(