apache / apache/maka

bug(runtime): whitespace-only tool-argument deltas keep the stream watchdog alive for 15 minutes until the upstream cuts the stream

Open
#4,861 2 comments 0 reactions 1 assignee Claimed by @jsiu93 View on GitHub
Dominant language
TypeScript
Stars
5.4k
Forks
502
Avg merge
1d 2h
Merged PRs (30d)
715

Description

## Environment
- Maka `8c52a835` (`origin/main` 2026-09-05), CLI 0.2.0, TUI from `packages/cli/dist/dev-cli.js`, macOS arm64, Node 24.19.0.
- Connection: Custom relay (OpenAI Chat-compatible) → CLIProxyAPI 7.2.140 → Codex Responses API; models `gpt-6-astra` and `gpt-5.6-sol`. Permission mode Auto.

## Summary
In Auto mode the Bash tool advertises `boundary_intent` and `required_boundary` (`packages/runtime/src/builtin-tools.ts:669-670`). `required_boundary` is an optional nested object whose `required` lists do not cover every property, so it is not strict-compatible. `@ai-sdk/openai-compatible` never sends `strict`; a Chat-compatible relay that forwards to the Responses API therefore lets the upstream "attempt strict validation" on that schema, and the model degenerates into emitting whitespace-only argument deltas. Each delta is a stream chunk, `model-adapter.ts:390` reports it as activity, `ai-sdk-turn.ts:1555` resets the 120 s idle watchdog, and `tool-input-delta` is otherwise ignored (`model-adapter.ts:1100-1103`), so nothing bounds the stream. The turn dies only when the upstream closes at ~902 s with `stream closed before response.completed`, which is the output-free close already tracked in #4599 / #4600.

## Evidence (wire capture between the TUI and the relay)
- Auto session, two captured turns: first chunk 3.4 s; 29,914 and 29,921 chunks; 8,600,302 and 8,696,969 bytes; 29,885 and 29,887 deltas whitespace-only; max inter-chunk gap 1.6 s; SSE error at 901.9 s and 902.0 s. Aggregated arguments stop right after `"boundary_intent":"current"` and never close.
- Full access session (`/permissions bypass`, `sandbox_boundary_log` shows `{"kind":"bypass","revision":1}`): 10 of 87 requests looped the same way (B 2, A 4, C 4). Durations 201–902 s; the largest aggregated argument string was 3,280,178 characters, 3,279,819 of them trailing whitespace, 11.8 MB on the wire. Every one of the 87 requests still carried `boundary_intent` and `required_boundary` in the Bash schema.
- The usage ledger records `latencyMs=901907 / 902037`, `status=interrupted`, `providerCode=invalid_request_error`, `retryable=false`, `usageBasis=missing`.
- In an uninstrumented Auto session the same failure hit 4 of 4 tasks (each at 901.9–902.5 s).

## Isolation with curl (same request body, `tool_choice` forced to Bash, 60 s cap; relay 500s excluded)

| variant | gpt-5.6-sol | gpt-6-astra | total |
|---|---|---|---|
| request as Maka sends it (`strict` absent) | 5/10 loop | 4/12 loop | **9/22** |
| `"strict": false` on the function | 0/10 | 0/10 | **0/20** |
| `required_boundary` removed | 0/5 | 0/4 | **0/9** |
| `"strict": true` | 400 `Invalid schema for function 'Bash' … Missing 'filesystem'` | same | — |

Replaying the exact captured bodies with `tool_choice: "auto"` succeeded 4/4 (sol) and 1/1 (astra), so the trigger is probabilistic per generation, not a fixed property of one conversation.

## Why this is Maka's problem too
1. The Runtime has no bound on tool-input growth or on progress-free deltas: 8.6 MB of whitespace kept a turn alive for 15 minutes on a 120 s idle watchdog. A hostile or buggy provider can hold any turn open indefinitely the same way.
2. The Bash boundary schema is what the model trips on, and Maka ships it to `openai-compatible` connections without declaring `strict: false`.
3. Full access did not remove the fields either, so there was no way around the schema; that part is reported as #4859 with a fix in #4860. This issue is about the bound that Auto sessions still lack.

## Expected
- A tool-call argument stream that stops making JSON progress (or exceeds a size bound) is treated as a provider fault: abort the request, classify it as recoverable, and hand it to the bounded recovery in #4600 instead of waiting for the upstream cut.
- Sessions with a `bypass` boundary advertise the four-field Bash schema (#4860). Auto sessions still need the bound above.
- `openai-compatible` tool definitions carry `strict: false` explicitly (Chat Completions semantics), or the boundary schema is made strict-compatible.

## Relation to existing issues
- #4599 / #4600: what happens after the close. This issue is what fills the 902 s before it.
- #4859 / #4860: the Full access escape hatch. This issue is about Auto sessions, where the schema is legitimately advertised and the loop still has no bound.
- #4267 item 1 (sandboxed Bash toolchain): unrelated; the loop is upstream generation, not Seatbelt.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.