Add JSON-RPC chat adapter (message/send + message/stream)#281
Merged
Conversation
Expose the canonical agents/chat ability over a JSON-RPC 2.0 wire keyed by agent id, so protocol chat clients can drive a registered runtime via `message/send` (request/response) and `message/stream` (Server-Sent Events). The adapter is a thin envelope over agents/chat: it reuses the existing handler, conversation store, run-control, and permission stack. agents/chat output maps almost 1:1 onto a JSON-RPC Task (run_id->id, session_id->sessionId, reply->status.message text, completed===false->input-required). Token streaming adds one seam: the `wp_agent_chat_stream_handler` filter (and a `register_chat_stream_handler()` helper), the token-by-token sibling of the synchronous `wp_agent_chat_handler`. It receives ($input, $emit) and emits canonical deltas (content / tool_call / tool_argument) which the route translates into `message/delta` SSE frames. When no streaming runtime is registered, `message/stream` degrades to the sync handler + a single terminal Task frame, so it works with any existing handler. The provider/turn-runner stays out of canonical (consumer territory, same boundary as agents/chat). End-to-end the endpoint composes with the opt-in default conversation store for durable WordPress-native sessions. - src/Channels/register-agents-chat-jsonrpc-route.php: the adapter - tests/agents-chat-jsonrpc-route-smoke.php: 36 assertions (mappers, delta wire shapes, frame builders, streaming-handler contract) - docs/external-clients.md: JSON-RPC Protocol Endpoint section - PHPStan max clean; full smoke suite green Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
What
A canonical JSON-RPC chat adapter that makes the existing
agents/chatability drivable by protocol chat clients (e.g. JSON-RPC/SSE chat UIs) — the third integration shape alongside Direct Channels and Remote Bridges.POST agents-api/v1/agent/{agent_id}, JSON-RPC 2.0:message/send{jsonrpc, id, method, params}{jsonrpc, id, result: Task}message/streamAccept: text/event-streamdata: {…}framesHow
It's a thin envelope over
agents/chat: it reuses the existing handler, conversation store, run-control, and permission stack. The canonical output maps almost 1:1 onto a JSON-RPCTask:Token streaming adds one new seam: the
wp_agent_chat_stream_handlerfilter (and aregister_chat_stream_handler()helper) — the token-by-token sibling of the synchronouswp_agent_chat_handler. It receives($input, $emit)and emits canonical deltas (content/tool_call/tool_argument), which the route translates intomessage/deltaSSE frames followed by a terminalresult: Taskframe.Graceful degradation: when no streaming runtime is registered,
message/streamruns the synchronous handler and emits a single terminal frame — so the endpoint works with any existing handler, just without token-level granularity.The provider/turn-runner stays out of canonical (consumer territory, the same boundary as
agents/chat). End-to-end, the endpoint composes with the opt-in default conversation store (#242) for durable WordPress-native sessions; the store is the persistence example, the endpoint is the transport, and the runtime is supplied by a consumer plugin.Files
src/Channels/register-agents-chat-jsonrpc-route.php— the adaptertests/agents-chat-jsonrpc-route-smoke.php— 36 assertions (request/response mappers, all three delta wire shapes, frame builders, streaming-handler contract via a mock handler +$emit)docs/external-clients.md— new JSON-RPC Protocol Endpoint sectionagents-api.php,composer.json— bootstrap require + smoke registrationVerification
[OK] No errors🤖 Generated with Claude Code