feat(stream): headless claude -p transport behind a transport flag
The PTY transport stands in for a protocol that did not exist when it was written: it pastes bracketed text into claude's TUI, guesses when the Ink render loop has settled, re-presses Enter when the paste is swallowed, and tails the session JSONL at 100ms. `claude -p` with stream-json on both pipes is that protocol, so add it as a second transport and let callers pick with `BackendOptions.transport`. Measured on one host, same model and prompt, cold single-reply turn: pty burns 2.3s on TUI readiness before the prompt is even submitted (first event 2.5s, turn 5.2s); stream_json burns none (first event 0.3s, first token 1.9s, turn 2.7s). The gap is what `startup_delay`'s 60s cap exists to survive on slow hardware. Everything the old transport relies on carries over unchanged and was verified against a real CLI: multi-turn over one live process, MCP via --mcp-config, --resume, and `native_jsonl` history seeding. Two things are new rather than equal: `result` is native (so usage is the turn's aggregate and durations are real, not synthesized), and `include_partial_messages` yields token-level `StreamEvent`s — which the JSONL, holding only finished blocks, could never provide. Notably, assistant records carry `stop_reason: null` in this mode even at the end of a turn, so `result` is not just tidier than the PTY path's terminal-stop_reason heuristic, it is the only correct signal. Default stays `pty`; nothing changes for existing callers. Also: extract process-group bookkeeping into `procgroup` so both transports sweep claude's children on shutdown, and fix a stale assertion in test_backend that still expected the `is_error: None` that `_block_to_dict` deliberately stopped emitting.
This commit is contained in:
@@ -836,7 +836,9 @@ def test_synthesize_turn_messages_covers_whole_cycle() -> None:
|
||||
"type": "tool_result",
|
||||
"tool_use_id": "tu_1",
|
||||
"content": "result body",
|
||||
"is_error": None,
|
||||
# `is_error` is omitted rather than nulled — the
|
||||
# Anthropic API rejects a null with "Input should be
|
||||
# a valid boolean". See `_block_to_dict`.
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user