feat: add aggregate cloud and agent-server clients#267
Open
neubig wants to merge 4 commits into
Open
Conversation
6 tasks
Contributor
Endpoint audit❌ 40 off-contract call(s) — not on the agent-server · classifiers: cloud
❌ Not on agent-server (gated, 40)⛔ (no known backend) — served by no backend we can see (15)
|
ec3c082 to
11460fe
Compare
3 tasks
Co-authored-by: openhands <openhands@all-hands.dev>
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.
Live evidence
Run on 2026-07-13 UTC on Linux 6.8.0-134-generic x86_64, Node v24.15.0, and npm 11.14.0. The exact reusable harness is committed as
.pr/live_aggregate_clients.mjs.The live Agent Server was
ghcr.io/openhands/agent-server:1.35.0-pythonat digestsha256:8f2540d9025efb12e8958cfa5a565540e28f9b11c6df23c3ec7c9fb6c7bc878f, exposed only on127.0.0.1:8010. Cloud calls targetedhttps://app.all-hands.dev; the harness records only method, host, sanitized path, status, and timing, never credentials or response secrets.The identical committed harness was invoked against each checkout's built
dist/clients.js:Current
main: aggregate APIs are unavailableCommit:
941cc7e143c81961603107a9812e81d8c2bd077eThe built client exported none of
OpenHandsClient,AgentServerClient,CloudClient,startDeviceFlow, orpollForToken. The same process proved existing endpoint clients still work against the real server:{ "exports": { "OpenHandsClient": false, "AgentServerClient": false, "CloudClient": false, "startDeviceFlow": false, "pollForToken": false }, "legacy": { "health": "ok", "serverVersion": "1.35.0", "bashExitCode": 0, "bashStdout": "legacy-endpoint-ok" } }Sanitized trace:
GET /health -> 200,GET /server_info -> 200, andPOST /api/bash/execute_bash_command -> 200.PR head: aggregate and legacy clients work against live endpoints
Commit:
95495399f14a766e6364b2619be4a3d43f011342All five aggregate/device-flow exports were present. On Agent Server 1.35.0, both the legacy and aggregate namespaces returned
health=ok; direct aggregateGET /healthalso returnedok; and the legacy and aggregate bash clients each executed their distinctprintfcommand with exit code 0. Their sanitized request traces used the same/health,/server_info, and/api/bash/execute_bash_commandendpoints.The aggregate Cloud client then exercised real production read-only endpoints:
{ "kind": "cloud", "authTypePresent": true, "orgIdPresent": true, "organizationCount": 2, "currentOrgPresent": true, "agentSettingsDerived": true, "conversationSettingsDerived": true, "httpError": {"name": "HttpError", "status": 405} }Transport failures also propagated: an aggregate request to unused local port 9 raised an
Errorcontaining request-failure context, while an unsupported live CloudPOST /api/keys/currentproducedHttpErrorstatus 405.Complete live device flow and cleanup
The PR client started a real production device flow, authenticated the verification step using the already-authorized test account, polled through the PR's
CloudClient, validated the returned bearer token withGET /api/keys/current, deleted that temporary device key, and confirmed the deleted token then returned 401:{ "startSucceeded": true, "verificationHost": "app.all-hands.dev", "completeUriPresent": true, "expiresIn": 600, "interval": 5, "authenticatedVerificationStatus": 200, "pollReturnedBearer": true, "returnedKeyRecognized": true, "returnedKeyCleanedUp": true }The sanitized sequence was
POST /oauth/device/authorize -> 200,POST /oauth/device/verify-authenticated -> 200,POST /oauth/device/token -> 200,GET /api/keys/current -> 200,DELETE /api/keys/{id} -> 200, and a finalGET /api/keys/current -> 401. No token or raw key was printed or retained.npm run buildpassed locally. Fresh GitHub checks on the final head also passed for Node 22.12, Node 24.x, build, and the Docker-backed integration test.Why
agent-canvas currently owns OpenHands Cloud transport, proxy, and device-flow auth code while using this package for agent-server APIs. This adds shared client primitives so browser clients can use the TypeScript client for both local agent-server and cloud backends without breaking the current endpoint-client API.
Summary
OpenHandsClient,AgentServerClient, andCloudClientaggregate clients while preserving existing named endpoint clients and exports.mainso this PR is validated against the repository's currentagent-server:1.34.0-pythonbaseline.Issue Number
N/A
How to Test
npm cinpm run lintnpm run buildnpm run test:coveragenpm run format:checklocalhost:8010:npm run audit:endpointsandnpm run test:integration:deterministicCloudClientfrom./dist/clients.jsand call read-only Cloud endpoints withOPENHANDS_API_KEY, logging only sanitized metadata.Video/Screenshots
N/A - library/client API change.
Type
Notes
Stacked consumer PR: OpenHands/agent-canvas#1621 uses
CloudClientand the shared device-flow helpers from this branch. That downstream PR is currently separate and has its own merge conflict/PR-description blocker; this package PR no longer depends on an unmerged base branch and its diff remains scoped to the six intended files.Validation context: current
mainincludes ACP registry changes from #272. Its companion SDK PR is OpenHands/software-agent-sdk#4056; thevalidate-acp-providersworkflow uses that link when checking the merged PR context.Closes #274