Repository navigation
feat(agent): add raw control sender - #789
GregHolmes wants to merge 2 commits into
Conversation
|
dg-coreylweathers
left a comment
There was a problem hiding this comment.
Verdict: approve with nits.
What this PR does
Adds public send_raw(message: Dict | str) on the sync and async Voice Agent socket clients so protocol-transparent bridges can forward any control frame without calling the private _send() (issue #785). Dicts are JSON-serialized; strings are sent byte-for-byte.
What I checked
- Does it send unchanged? Yes:
_senddoesjson.dumpsfor dicts and passes strings straight towebsocket.send; the four new tests capture exactly that, including that44100.0is not converted to an int. - Is the patch protected from regen? Yes:
agent/v1/socket_client.pywas already frozen; the PR adds the ledger bullet. - Gates in Docker: mypy clean, ruff clean on changed files, pytest 1038 passed.
Should-fix
send_rawappears only in the socket client, its tests,.fernignore, andAGENTS.md. Add asend_raw(message)line to the agent.v1 section ofreference.mdand a one-line mention in a voice-agent example or the skill file, otherwise bridge authors keep using_send().- State the number contract in the docstring: "Values are sent as given; whole-number floats are not converted to integers, so pass ints where the API expects them." That is what the tests pin and how it differs from the typed senders.
Nits: the Union[Dict, str] annotation is narrower than _send accepts (bytes also work), fine as the public contract. Needs a rebase: AGENTS.md/.fernignore conflict with main now, and after #797 lands agent/v1/socket_client.py is regenerated, so re-apply the two methods there.
589b545 to
fb06762
Compare
|
@dg-coreylweathers Rebased onto current |
fb06762 to
2b738dd
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dg-coreylweathers
left a comment
There was a problem hiding this comment.
Approving.
What this PR does
Adds a public send_raw() to the sync and async Voice Agent socket clients so relay apps can forward any JSON control message, including types the SDK does not model yet, without calling the private _send() (issue #785). A dict is converted to JSON; a string is sent exactly as given. No existing send_* method changes.
What I checked
- Were my earlier asks done? Yes:
send_rawis inreference.mdand the Voice Agent skill, both docstrings say whole-number floats are not converted to ints, and the branch is rebased on current main. - Does it send what it says? Yes: unit tests compare the exact text that reaches the socket, and a probe confirmed a string like
not json{goes out byte-for-byte while typed senders still convert1.0to1. - Does the live API accept it? Yes (request_id 01a1461b-33ab-7471-98ea-0325c23d0d34): Settings sent as a string got
SettingsApplied, a KeepAlive dict was accepted, an InjectAgentMessage dict made the agent speak; an unknown type gotError UNPARSABLE_CLIENT_MESSAGE. - Will the next Fern regen drop it? No: the file stays in
.fernignore, and a test merge with #803 (the open regen) keeps both methods with 46 socket tests passing and mypy clean.
Nits fixed in be28f5c: the reference.md entry now has an example line (agent.send_raw({"type": "KeepAlive"})) and says to prefer the typed method when one exists, and that the server answers an unknown type with Error UNPARSABLE_CLIENT_MESSAGE. The PR body now says this documents send_raw in the existing freeze entry.
Merge note: this conflicts with #788 in AGENTS.md (both edit the agent/v1/socket_client.py line). Keep this PR's line, then #788's StrictInt line below it.
Summary
send_raw()methods for protocol-transparent Agent control-frame bridges.send_rawin the existingagent/v1/socket_client.pyfreeze entry (.fernignore, AGENTS.md) and cover both input forms on both clients.Closes #785
Validation