feat(agent): add AI Agent conversation APIs across all SDK bindings#557
Draft
sunli829 wants to merge 7 commits into
Draft
feat(agent): add AI Agent conversation APIs across all SDK bindings#557sunli829 wants to merge 7 commits into
sunli829 wants to merge 7 commits into
Conversation
Adds workspaces/agents/conversation/continue-conversation endpoints with both blocking and SSE-streaming response modes, matching each binding's own idiom: Stream in Rust core, blocking Iterator in Rust `blocking` and Python sync, async iterator in Python async, callback+Promise in Node.js and C/C++, and a real backpressured java.util.concurrent.Flow.Publisher in Java. httpclient gains its first SSE transport support to enable this.
Live testing against the real API surfaced several undocumented SSE event types (workflow_started, ping, chat_finished, chat_title_updated) that all correctly fall into the Other catch-all, but it previously discarded the discriminating `event` field, leaving callers with an unlabeled JSON blob. Other now carries both the event type name and the data, across all bindings.
…ping at WorkflowFinished Live testing showed the server can emit a few more housekeeping events (e.g. a chat_title_updated-shaped Other event, or a trailing ping) after workflow_finished and before actually closing the connection. Java's Flow.Publisher implementation treated WorkflowFinished as a hard stream terminator and silently dropped anything after it; every other binding already drained to the stream's natural end. Removed the early break so Java matches, and corrected the "WorkflowFinished is always the last event" doc claim across all bindings, which this behavior was based on and which real traffic disproves.
…meout The shared httpclient default (30s) wraps the whole request-response cycle, including waiting for the full body. In blocking mode the server holds the connection silent until the whole LLM turn is done, which can legitimately exceed 30s (observed twice live: a spurious RequestTimeout in both Rust and Python). Added a per-request timeout override to RequestBuilder and applied a 120s budget specifically to the agent domain's calls; every other domain keeps the 30s default.
…ated as typed events These four SSE event types aren't documented by the API but were consistently observed against the real service during live testing. Modeling them as proper ConversationStreamEvent variants (with typed payloads) instead of leaving them in the Other catch-all makes them discoverable and type-safe for callers. Payloads are marked as reverse-engineered/unverified against future API changes.
….js/Java
Extends the C, C++, Python, Node.js, and Java bindings with the
WorkflowStarted/Ping/ChatFinished/ChatTitleUpdated ConversationStreamEvent
variants added to the Rust core, keeping every binding's event handling in
sync. Also strips disclaimer-style ("not documented by the API",
"reverse-engineered from live traffic") doc comments across all bindings in
favor of plain factual descriptions.
5 tasks
…ents Extends the AI Agent conversation domain to match longbridge/developers#1176, which publishes complete SSE event documentation for the first time. Adds 14 new ConversationStreamEvent variants across Rust core and every binding (C/C++/Python/Node.js/Java): thinking phase (ThinkingStarted/Finished), tool calls (NodeToolUseStarted/Finished), subagent delegation (SubagentStarted/Progress/Finished), agent-as-tool delegation (AgentToolStarted/Progress/Finished), and auxiliary events (QueryMasked, PlanChanged, ContextCompressStarted/Finished). Also enriches MessagePayload with type/key/stage fields and WorkflowFinishedPayload with top-level error/error_code/error_message/error_args/process_data fields, per the docs. Fixes a real bug uncovered by the new docs: an interrupted run's SSE stream never emits WorkflowFinished at all (only human_interaction_required, then chat_finished) — previously every binding's "drive the stream to completion" helper would error out on any interrupted streaming conversation. Adds HumanInteractionRequired as a first-class terminal variant (carrying the same synthesized ConversationResponse WorkflowFinished carries) and fixes drive_conversation_stream to treat it as terminal alongside WorkflowFinished.
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.
Summary
Adds full SDK support for the new AI Agent conversation APIs (longbridge/developers#1129) across the Rust core and every language binding (C, C++, Python, Node.js, Java), in both blocking and SSE-streaming response modes.
Streamfor async Rust, a blockingIteratorfor Rustblocking/Python sync, anasync foriterator for Python async, callback + Promise for Node.js/C/C++, and a real-backpressurejava.util.concurrent.Flow.Publisherfor Java.rust/crates/httpclientgained generic SSE support (send_events, built oneventsource-stream) as new shared infrastructure, since no existing HTTP call in the SDK streamed a response before.Event types
The documented example only shows the success path (
chat_started→message→workflow_finished). Live testing against the production API surfaced four additional event types the docs don't mention:workflow_started,ping(heartbeat),chat_finished, andchat_title_updated(which can arrive before or afterworkflow_finished). All four are now modeled as first-classConversationStreamEventvariants (not just a genericOthercatch-all) across every binding.Bugs found via live testing (not reachable by code review alone)
ConversationStreamEvent::Otheroriginally discarded the SSE event-type name, leaving callers unable to tell what kind of unrecognized event they'd received — now carries{ event, data }.Flow.Publisherimplementation stopped as soon as it sawworkflow_finished, but that isn't always the last event in the stream (some runs emit trailing housekeeping events after it) — fixed to drain to the stream's actual end, matching every other binding.Test plan
cargo clippy --all --all-featuresandcargo +nightly fmt --allclean across the workspacecargo test -p longbridge agent)cargo build -p longbridge-c— header regenerates correctlymaturin develop— Python extension builds and imports correctly (sync + async)npm run build:debug— Node.js native binary +index.d.tsregenerate correctlymvn compile— Java sources compile against the JNI glue🤖 Generated with Claude Code