fix: restore model selection header + DSH/agent SSE stream termination & true tool streaming - #95
Open
kirigayakazima wants to merge 2 commits into
Open
Conversation
Google moved model routing from payload slot79 to the x-goog-ext-525001261-jspb request header (Issue Sophomoresty#82). Without it, every request is served by the account default model and model selection silently no-ops. Changes: - Add MODEL_IDS mapping (verified internal IDs from browser captures) - Add build_model_header() and send the header on both stream and non-stream paths with model_name threaded through call sites - Add fetch_xsrf_token() auto-discovery (FdrFJe, successor of SNlM0e) - load_cookie() now also accepts gemini-auth.json (exported by the bundled extension) and injects xsrf/gemini_bl/auth_user into CONFIG - Add gemini-3.8-flash model entry
… with tools, lean tool prompt Resolves turn never completing in strict OpenAI clients (DSH, Codex): - protocol_version=HTTP/1.0: SSE streams now end via connection close (EOF). HTTP/1.1 without chunked transfer encoding leaves strict clients waiting forever for a body terminator that BaseHTTPRequestHandler never sends, causing idle timeouts and endless 'thinking' states. - True streaming with tools: stream text chunks as they arrive (fast TTFT), emit parsed tool_calls + finish_reason=tool_calls at the end. Previously tool requests fell back to a blocking full-generate-then-single-chunk path. - Compact tool descriptions (trim to 150 chars, keep full parameters): DSH sends 43 tools (~32KB) which took Google Web minutes to process and hit clients' stream idle timeout (300s). Now ~12KB, responses in seconds. - Log to server.log in real time (stderr + file, unbuffered).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #82 — model selection is broken upstream: payload slot79 no longer routes models, every request is served by the account default.
Problem 1: Model routing is ignored
Google moved model routing from the payload
slot79field to thex-goog-ext-525001261-jspbrequest header (internal model ID selector). Without that header,slot79is ignored and every model name inMODELScomes back as the same account-default model. Issue #82 documents this in detail.Problem 2: Streams never terminate for strict OpenAI clients (DSH / Codex)
The SSE responses were sent over HTTP/1.1 without
Content-Lengthand withoutTransfer-Encoding: chunked. Python'sBaseHTTPRequestHandlerdoes not emit chunked encoding automatically, so strict clients (OpenAI SDK, used by coding agents like DeepSeek Harness) wait forever for a body terminator that never arrives — the connection stays open (keep-alive), the stream never ends, and the client shows an endless thinking state until its idle timeout (300s) fires.Fix:
protocol_version = HTTP/1.0→ the connection closes after the SSE body (EOF), which is the canonical SSE termination signal.Problem 3: Tool requests were not truly streaming
When
toolswere present, the handler fell back to a blocking full-generate-then-single-chunk path: it waited for Google to finish the entire response, parsed tool_calls, then returned one chunk. For agent clients sending 40+ tools, this produced multi-minute latencies and idle timeouts.Fix: true streaming with tools — stream text chunks as they arrive (fast time-to-first-token), then emit the parsed
tool_callsdelta +finish_reason: tool_callsat the end.Problem 4: Verbose tool descriptions blow up the prompt
Coding agents send 43 tools with long descriptions (~32KB JSON). Google Web takes minutes to process such a large prompt, again hitting client idle timeouts.
Fix: compact tool descriptions (trim each to ~150 chars, keep full parameter schemas) — ~32KB → ~12KB, responses in seconds while tools stay usable.
Changes
build_model_header()emittingx-goog-ext-525001261-jspb(threaded through both stream and non-stream paths)fetch_xsrf_token()auto-discovery (FdrFJe, successor of SNlM0e)load_cookie()acceptsgemini-auth.jsonand injects xsrf/gemini_bl/auth_usergemini-3.8-flashmodel entryserver.logoutput (stderr + file)Verification
Tested with a paid AI Pro account + DeepSeek Harness (DSH) as the OpenAI-compatible client:
slot39(56fdd199312815e2served, not thecf41b0e0dd7d53e5reject marker)finish_reason, then[DONE]— no more endless thinkingRelated
#88 (xsrf auto-refresh) and #91 (3.8-flash) are open PRs covering similar territory; happy to drop overlapping parts if those merge first.