Compare commits
11 Commits
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,5 +1,63 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.11.12 (2026-05-26)
|
||||||
|
|
||||||
|
**New Antigravity v2 Handler (Mimicking anti-api)**
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
- **Complete rewrite of Antigravity handler** based on https://github.com/ink1ing/anti-api approach
|
||||||
|
- Safety settings (all OFF), stopSequences, sessionId, requestType: agent
|
||||||
|
- functionResponse uses `response: { result: string }` format matching anti-api
|
||||||
|
- Endpoint priority: `daily-cloudcode-pa.googleapis.com` first
|
||||||
|
- Simplified sanitizer: only deduplicates consecutive user text, never touches tool messages
|
||||||
|
|
||||||
|
## v3.11.11 (2026-05-26)
|
||||||
|
|
||||||
|
## v3.11.11 (2026-05-26)
|
||||||
|
|
||||||
|
**Antigravity Fix: Stricter function_call/output Pairing + Gemini Sanitizer Rewrite (PR #12)**
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
- **Stricter function_call/output pairing**: Only includes pairs where BOTH call and output exist — no orphan calls sent to Gemini
|
||||||
|
- **Gemini sanitizer rewritten**: Tool messages (`functionCall`/`functionResponse`) are always preserved as-is, never merged or skipped
|
||||||
|
- **Text merging more conservative**: Checks last message for tool content before merging consecutive text messages
|
||||||
|
- **Final trimming safe**: Only removes plain `message` items, never `function_call_output` (which would break tool pairs)
|
||||||
|
- **Merge PR #12**: Fix by qwen-chat coder
|
||||||
|
|
||||||
|
## v3.11.10 (2026-05-26)
|
||||||
|
|
||||||
|
## v3.11.10 (2026-05-26)
|
||||||
|
|
||||||
|
**Antigravity Fix: Interleave function_call/output Pairs, Gemini Turn Trimming (PR #11)**
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
- **Fix Antigravity function_call/output ordering**: Tool calls and their responses are now properly interleaved in sequence (`function_call` → `function_call_output` → `function_call` → ...) instead of being grouped separately
|
||||||
|
- **Gemini sanitizer trimming**: Leading/trailing non-user turns removed for Google API compliance (Google requires conversation to start and end with user turn)
|
||||||
|
- **Stricter role boundary enforcement**: `functionCall` (model) and `functionResponse` (user) never merged across role boundaries
|
||||||
|
- **Merge PR #11**: Fix by qwen-chat coder
|
||||||
|
|
||||||
|
## v3.11.9 (2026-05-26)
|
||||||
|
|
||||||
|
## v3.11.9 (2026-05-26)
|
||||||
|
|
||||||
|
**Antigravity Fix: Preserve functionCall/functionResponse in Gemini Sanitizer (PR #10)**
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **Fix Antigravity multi-turn tool use**: The Gemini message sanitizer was incorrectly merging/dropping `functionCall` and `functionResponse` turns, causing Antigravity to think forever without responding. These turns are now always preserved as separate messages.
|
||||||
|
- **Merge PR #10**: `fix: preserve functionCall/functionResponse in Gemini sanitizer` (qwen-chat coder)
|
||||||
|
|
||||||
|
## v3.11.8 (2026-05-26)
|
||||||
|
|
||||||
|
## v3.11.8 (2026-05-26)
|
||||||
|
|
||||||
|
**Vision Cache Persistence, PR #8 Merge**
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
- **Vision description cache persisted across requests**: Image descriptions from the vision fallback API are now cached in a file (`~/.cache/codex-proxy/vision-cache.json`) so the same image URL is never described twice — saves API calls and latency
|
||||||
|
- **Merge PR #8**: `fix: persist vision description cache across requests` (cobra91)
|
||||||
|
|
||||||
## v3.11.7 (2026-05-26)
|
## v3.11.7 (2026-05-26)
|
||||||
|
|
||||||
**Vision Auto-Detect, Proactive Non-Vision Model Detection, Unit Tests, Bug Fixes**
|
**Vision Auto-Detect, Proactive Non-Vision Model Detection, Unit Tests, Bug Fixes**
|
||||||
|
|||||||
BIN
codex-launcher_3.11.12_all.deb
Normal file
BIN
codex-launcher_3.11.12_all.deb
Normal file
Binary file not shown.
Binary file not shown.
@@ -27,6 +27,22 @@ model_catalog_json = ""
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
CHANGELOG = [
|
CHANGELOG = [
|
||||||
|
("3.11.12", "2026-05-26", [
|
||||||
|
"New Antigravity v2 handler mimicking anti-api",
|
||||||
|
"Safety settings, stopSequences, simplified sanitizer",
|
||||||
|
]),
|
||||||
|
("3.11.10", "2026-05-26", [
|
||||||
|
"Fix Antigravity: interleave function_call/output pairs (PR #11)",
|
||||||
|
"Gemini sanitizer: trim non-user turns for Google API compliance",
|
||||||
|
]),
|
||||||
|
("3.11.9", "2026-05-26", [
|
||||||
|
"Fix Antigravity: preserve functionCall/functionResponse (PR #10)",
|
||||||
|
"Prevents tool responses from being dropped in multi-turn sessions",
|
||||||
|
]),
|
||||||
|
("3.11.8", "2026-05-26", [
|
||||||
|
"Vision cache persisted across requests (PR #8 merge)",
|
||||||
|
"No redundant vision API calls for same image URL",
|
||||||
|
]),
|
||||||
("3.11.7", "2026-05-26", [
|
("3.11.7", "2026-05-26", [
|
||||||
"Vision auto-detect: uses provider's vision model for image description",
|
"Vision auto-detect: uses provider's vision model for image description",
|
||||||
"Vision preprocessing replaces image stripping",
|
"Vision preprocessing replaces image stripping",
|
||||||
|
|||||||
@@ -83,6 +83,29 @@ model_catalog_json = ""
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
CHANGELOG = [
|
CHANGELOG = [
|
||||||
|
("3.11.12", "2026-05-26", [
|
||||||
|
"New Antigravity v2 handler mimicking anti-api approach",
|
||||||
|
"Safety settings, stopSequences, sessionId, requestType: agent",
|
||||||
|
"Simplified sanitizer preserving functionCall/functionResponse",
|
||||||
|
"Endpoint priority: daily-cloudcode-pa first",
|
||||||
|
"functionResponse uses response.result (string) format",
|
||||||
|
]),
|
||||||
|
("3.11.11", "2026-05-26", [
|
||||||
|
"Final trimming only removes plain messages, never function_call_output",
|
||||||
|
]),
|
||||||
|
("3.11.10", "2026-05-26", [
|
||||||
|
"Fix Antigravity: interleave function_call/output pairs in correct sequence (PR #11)",
|
||||||
|
"Fix Gemini sanitizer: trim leading/trailing non-user turns for Google API compliance",
|
||||||
|
"Stricter function call/response isolation — no merging across role boundaries",
|
||||||
|
]),
|
||||||
|
("3.11.9", "2026-05-26", [
|
||||||
|
"Fix Antigravity: preserve functionCall/functionResponse in Gemini sanitizer (PR #10)",
|
||||||
|
"Prevents tool responses from being merged/dropped in multi-turn Antigravity sessions",
|
||||||
|
]),
|
||||||
|
("3.11.8", "2026-05-26", [
|
||||||
|
"Vision description cache persisted across requests (no redundant API calls for same image)",
|
||||||
|
"Merge PR #8: fix vision cache persistence across requests",
|
||||||
|
]),
|
||||||
("3.11.7", "2026-05-26", [
|
("3.11.7", "2026-05-26", [
|
||||||
"Vision auto-detect: uses provider's own vision model (e.g. 0G-Qwen-VL) as fallback for image description",
|
"Vision auto-detect: uses provider's own vision model (e.g. 0G-Qwen-VL) as fallback for image description",
|
||||||
"Vision preprocessing replaces image stripping: images described via API instead of just removed",
|
"Vision preprocessing replaces image stripping: images described via API instead of just removed",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@ Uses only stdlib unittest + unittest.mock (zero pip dependencies).
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
@@ -19,7 +20,7 @@ import importlib
|
|||||||
|
|
||||||
_spec = importlib.util.spec_from_file_location(
|
_spec = importlib.util.spec_from_file_location(
|
||||||
"translate_proxy",
|
"translate_proxy",
|
||||||
r"C:\dev\Codex-Launcher---Any-AI-Porovider\src\translate-proxy.py",
|
os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "src", "translate-proxy.py"),
|
||||||
)
|
)
|
||||||
tp = importlib.util.module_from_spec(_spec)
|
tp = importlib.util.module_from_spec(_spec)
|
||||||
_spec.loader.exec_module(tp)
|
_spec.loader.exec_module(tp)
|
||||||
@@ -121,36 +122,33 @@ class TestExtractXmlToolCalls(unittest.TestCase):
|
|||||||
self.assertEqual(tp._extract_xml_tool_calls("just plain text"), [])
|
self.assertEqual(tp._extract_xml_tool_calls("just plain text"), [])
|
||||||
|
|
||||||
def test_single_tool_call(self):
|
def test_single_tool_call(self):
|
||||||
# Regex: <tool_call>(\w+)(.*?)</tool_call>
|
text = '<invoke><exec_command>echo hi</exec_command></invoke>'
|
||||||
# Format: <tool_call>NAME>CONTENT</tool_call>
|
|
||||||
text = '<tool_call>bash>echo hi</tool_call>'
|
|
||||||
results = tp._extract_xml_tool_calls(text)
|
results = tp._extract_xml_tool_calls(text)
|
||||||
self.assertEqual(len(results), 1)
|
self.assertEqual(len(results), 1)
|
||||||
self.assertEqual(results[0]["name"], "bash")
|
self.assertEqual(results[0]["name"], "exec_command")
|
||||||
self.assertIn("call_id", results[0])
|
self.assertIn("call_id", results[0])
|
||||||
self.assertTrue(results[0]["call_id"].startswith("xml_"))
|
self.assertTrue(results[0]["call_id"].startswith("xml_"))
|
||||||
|
|
||||||
def test_multiple_tool_calls(self):
|
def test_multiple_tool_calls(self):
|
||||||
text = (
|
text = (
|
||||||
'<tool_call>bash>echo hi</tool_call>'
|
'<invoke><exec_command>echo hi</exec_command></invoke>'
|
||||||
'<tool_call>edit>test.py</tool_call>'
|
'<invoke><exec_command>test.py</exec_command></invoke>'
|
||||||
)
|
)
|
||||||
results = tp._extract_xml_tool_calls(text)
|
results = tp._extract_xml_tool_calls(text)
|
||||||
self.assertEqual(len(results), 2)
|
self.assertEqual(len(results), 2)
|
||||||
self.assertEqual(results[0]["name"], "bash")
|
self.assertEqual(results[0]["name"], "exec_command")
|
||||||
self.assertEqual(results[1]["name"], "edit")
|
self.assertEqual(results[1]["name"], "exec_command")
|
||||||
|
|
||||||
def test_json_args(self):
|
def test_json_args(self):
|
||||||
text = '<tool_call>tool>{"key": "value"}</tool_call>'
|
text = '<invoke><exec_command>{"key": "value"}</exec_command></invoke>'
|
||||||
results = tp._extract_xml_tool_calls(text)
|
results = tp._extract_xml_tool_calls(text)
|
||||||
self.assertEqual(len(results), 1)
|
self.assertEqual(len(results), 1)
|
||||||
self.assertEqual(results[0]["name"], "tool")
|
self.assertEqual(results[0]["name"], "exec_command")
|
||||||
args = json.loads(results[0]["args"])
|
args = json.loads(results[0]["args"])
|
||||||
# JSON parsing of XML content may vary - just check result exists
|
|
||||||
self.assertIn("args", results[0])
|
self.assertIn("args", results[0])
|
||||||
|
|
||||||
def test_code_fenced_args(self):
|
def test_code_fenced_args(self):
|
||||||
text = '<tool_call>tool>{"a": 1}</tool_call>'
|
text = '<invoke><exec_command>{"a": 1}</exec_command></invoke>'
|
||||||
results = tp._extract_xml_tool_calls(text)
|
results = tp._extract_xml_tool_calls(text)
|
||||||
self.assertEqual(len(results), 1)
|
self.assertEqual(len(results), 1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user