Compare commits
1 Commits
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## 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**
|
||||
|
||||
Binary file not shown.
BIN
codex-launcher_3.11.9_all.deb
Normal file
BIN
codex-launcher_3.11.9_all.deb
Normal file
Binary file not shown.
@@ -27,6 +27,10 @@ model_catalog_json = ""
|
||||
"""
|
||||
|
||||
CHANGELOG = [
|
||||
("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",
|
||||
|
||||
@@ -83,6 +83,10 @@ model_catalog_json = ""
|
||||
"""
|
||||
|
||||
CHANGELOG = [
|
||||
("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",
|
||||
|
||||
@@ -5562,10 +5562,16 @@ class Handler(http.server.BaseHTTPRequestHandler):
|
||||
parts = [p for p in content.get("parts", []) if isinstance(p, dict)]
|
||||
if not parts:
|
||||
continue
|
||||
# Check if this content has functionCall or functionResponse - these must be preserved
|
||||
has_function_call = any("functionCall" in p for p in parts)
|
||||
has_function_response = any("functionResponse" in p for p in parts)
|
||||
text_key = "\n".join([p.get("text", "") for p in parts if "text" in p]).strip()
|
||||
if role == "user" and text_key and text_key == last_user_text:
|
||||
# Skip duplicate user text messages, but NEVER skip function responses
|
||||
if role == "user" and text_key and text_key == last_user_text and not has_function_response:
|
||||
continue
|
||||
if role == last_role and role in ("user", "model") and sanitized:
|
||||
# Only merge same-role messages if they don't contain function calls/responses
|
||||
# Function calls and responses must remain as separate turns
|
||||
if role == last_role and role in ("user", "model") and sanitized and not has_function_call and not has_function_response:
|
||||
sanitized[-1].setdefault("parts", []).extend(parts)
|
||||
else:
|
||||
sanitized.append({"role": role, "parts": parts})
|
||||
|
||||
Reference in New Issue
Block a user