Repository navigation
feat: automate TypeScript client contract handoff - #4234
Conversation
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
…pi-contract' into feat/oss-6124-typescript-client-release-handoff
enyst
left a comment
There was a problem hiding this comment.
Great, thank you! We need more of these ❤️
Python API breakage checks — ✅ PASSEDResult: ✅ PASSED |
REST API breakage checks (OpenAPI) — ✅ PASSEDResult: ✅ PASSED |
all-hands-bot
left a comment
There was a problem hiding this comment.
⚠️ QA Report: PASS WITH ISSUES
The OpenAPI artifact export and contract handoff work end-to-end, but the workflow currently depends on unmerged TypeScript-client automation.
Does this PR achieve its stated goal?
Yes, in the intended stacked setup: I generated the exact public openapi.json, validated it, ran the TypeScript client updater against the matching client automation branch, regenerated src/generated/agent-server-schema.ts, and produced a non-empty API summary. As a standalone release workflow against the current OpenHands/typescript-client default branch, it does not fully achieve the goal yet because npm run summarize:agent-server-api is missing there.
| Phase | Result |
|---|---|
| Environment Setup | ✅ make build completed; no tests, linters, type checks, or pre-commit hooks were run. |
| CI Status | Validate PR description is failing and qa-changes was in progress when checked. |
| Functional Verification |
Functional Verification
Test 1: Public OpenAPI release artifact generation
Step 1 — Establish baseline/problem:
The PR says the release handoff should use an exact versioned openapi.json artifact instead of leaving the client contract stale.
Step 2 — Apply the PR's changes:
Ran the new release-artifact path on commit e99e9f9446dca3f7be9bdc0469c6f988533c6c44:
OPENHANDS_SUPPRESS_BANNER=1 uv run python .github/scripts/export_agent_server_openapi.py --output /tmp/oh-pr4234-qa/release-assets/openapi.json
OPENHANDS_SUPPRESS_BANNER=1 uv run python .github/scripts/export_agent_server_openapi.py --output /tmp/oh-pr4234-qa/release-assets/openapi-second.json
cmp /tmp/oh-pr4234-qa/release-assets/openapi.json /tmp/oh-pr4234-qa/release-assets/openapi-second.json
uv run python .github/scripts/check_agent_server_openapi_quality.py --schema /tmp/oh-pr4234-qa/release-assets/openapi.json
npx --yes @apidevtools/swagger-cli@^4 validate /tmp/oh-pr4234-qa/release-assets/openapi.jsonObserved:
Agent Server OpenAPI type-quality check passed (98 allowlisted weak locations).
/tmp/oh-pr4234-qa/release-assets/openapi.json is valid
Artifact summary:
{
"openapi": "3.1.0",
"info": {"title": "OpenHands Agent Server", "version": "1.37.1"},
"path_count": 94,
"schema_count": 384,
"has_public_only": true,
"selected_paths": ["/api/mcp/test", "/api/settings"],
"selected_schemas": {
"AgentSettings": true,
"AgentSettingsPatch": true,
"MCPConfig": true,
"MCPConfigPatch": true,
"MCPTestResponse": true
}
}This shows the release artifact is deterministic, valid OpenAPI, public-API-filtered, versioned as 1.37.1, and includes the contract components the downstream client needs.
I also started the Agent Server with uvicorn and fetched /openapi.json over HTTP; the live app reported info.version: 1.37.1 and exposed /api/mcp/test plus /api/settings.
Test 2: Old image-only handoff reproduces the stale-contract problem
Step 1 — Reproduce / establish baseline without this PR's new handoff:
Cloned the real OpenHands/typescript-client default branch, which was pinned to ghcr.io/openhands/agent-server:1.37.0-python, then emulated the old workflow's version mirror replacement to 1.37.1.
Observed:
Baseline old workflow: 1.37.0 -> 1.37.1
schema_sha_before=af6c746f3fb6fb518aa7be1f1e69a21842af9437dbb2799468681b323a665fac
schema_sha_after=af6c746f3fb6fb518aa7be1f1e69a21842af9437dbb2799468681b323a665fac
changed_files:
AGENTS.md
README.md
package.json
package_image=ghcr.io/openhands/agent-server:1.37.1-python
This confirms the author’s stated problem: the old handoff updates the image pin but leaves src/generated/agent-server-schema.ts unchanged.
Test 3: New handoff updates mirrors, regenerates the client contract, and summarizes API changes
Step 2 — Apply the PR's changes:
Checked out the matching OpenHands/typescript-client PR branch (pull/303/head, commit 3ff8e35), installed dependencies with npm ci, and ran the same workflow commands this SDK PR adds:
python3 .github/scripts/prepare_typescript_client_agent_server_bump.py --client-root /tmp/oh-pr4234-qa/typescript-client --version 1.37.1 --openapi /tmp/oh-pr4234-qa/release-assets/openapi.json
AGENT_SERVER_OPENAPI_PATH=/tmp/oh-pr4234-qa/release-assets/openapi.json npm run generate:agent-server-api
npm run summarize:agent-server-api -- --before /tmp/oh-pr4234-qa/agent-server-schema-before-pr303.ts --after src/generated/agent-server-schema.ts --output /tmp/oh-pr4234-qa/agent-server-api-summary-pr303.mdObserved:
Prepared TypeScript client Agent Server bump 1.37.0 -> 1.37.1; changed files: package.json, AGENTS.md, README.md
Generated /tmp/oh-pr4234-qa/typescript-client/src/generated/agent-server-schema.ts from /tmp/oh-pr4234-qa/release-assets/openapi.json
schema_sha_before=b77dccad58b36925341bdc7d491776cf5dbafab429949443502cbc956cc3b8b2
schema_sha_after=160996871fb77b19af0855de300169b09f52aee058b1dd9ff8b4726e732be8a1
package_image_after=ghcr.io/openhands/agent-server:1.37.1-python
changed_files:
AGENTS.md
README.md
package.json
src/generated/agent-server-schema.ts
api_summary_lines=4
API summary preview:
- Generated TypeScript diff: **+7652 / -8599 lines**
- Added exported types: `AgentSettings`, `AgentSettingsPatch`, `AgentSettingsPatchWritable`, `McpAuthCredential`, `McpConfig`, `McpConfigPatch`, `McpConfigPatchWritable`, `McpNoneAuthCredential`, `McpServer`, `McpServerPatch`, `McpServerPatchWritable`, `McpTestResponse`, `RemoteMcpServer`, `RemoteMcpServerWritable`, `SettingsUpdateRequestWritable`, `StdioMcpServer`
- Removed exported types: `AliveAliveGetData`, `AliveAliveGetResponse`, `AliveAliveGetResponses`, `Annotation`, `AnnotationUrlCitation`, `BrowserActionWithRisk`, `BrowserClickActionWithRisk`, `BrowserCloseTabActionWithRisk`, `BrowserGetContentActionWithRisk`, `BrowserGetStateActionWithRisk`, `BrowserGetStorageActionWithRisk`, `BrowserGoBackActionWithRisk`, `BrowserListTabsActionWithRisk`, `BrowserNavigateActionWithRisk`, `BrowserScrollActionWithRisk`, `BrowserSetStorageActionWithRisk`, `BrowserStartRecordingActionWithRisk`, `BrowserStopRecordingActionWithRisk`, `BrowserSwitchTabActionWithRisk`, `BrowserTypeActionWithRisk`, `ChatCompletion`, `ChatCompletionAudio`, `ChatCompletionMessage`, `ChatCompletionMessageCustomToolCall`, `ChatCompletionMessageFunctionToolCall`, and 63 more
- Existing exported declarations may also contain field-level changes; review the generated diff.
This verifies the new flow changes the generated contract file and creates the API-change summary promised in the PR description.
Test 4: Exact-version artifact validation rejects mismatches
Ran the updater with an openapi.json whose info.version was changed to 9.9.9 while requesting release 1.37.1.
Observed:
exit_code=1
OpenAPI artifact version '9.9.9' does not match Agent Server release '1.37.1'
This confirms the updater rejects a non-exact OpenAPI artifact instead of silently using the wrong contract.
Unable to Verify / Dependency Caveat
The same new workflow commands do not currently complete against OpenHands/typescript-client default branch (ca939d7): after npm ci, prepare_typescript_client_agent_server_bump.py, and npm run generate:agent-server-api, the command npm run summarize:agent-server-api failed with:
npm error Missing script: "summarize:agent-server-api"
npm error
npm error Did you mean one of these?
npm error npm run generate:agent-server-api # run the "generate:agent-server-api" package script
npm error npm run check:agent-server-api # run the "check:agent-server-api" package script
I verified the full handoff on the matching client PR branch instead. Future QA would be simpler if AGENTS.md or the PR description named the exact downstream client branch/merge prerequisite for release-handoff verification.
Issues Found
- 🟠 Issue: The SDK release workflow currently requires
OpenHands/typescript-clientto already containsummarize:agent-server-api; the current default branch does not, so the handoff job fails unless the matching client PR lands first.
This QA review was created by an AI agent (OpenHands) on behalf of the user.
Final verdict: PASS WITH ISSUES.
| --openapi "$OPENAPI_PATH" | ||
| AGENT_SERVER_OPENAPI_PATH="$OPENAPI_PATH" \ | ||
| npm run generate:agent-server-api | ||
| npm run summarize:agent-server-api -- \ |
There was a problem hiding this comment.
🟠 Important: The workflow now calls npm run summarize:agent-server-api, but a real run against the current OpenHands/typescript-client default branch failed because that script is missing. I verified the full flow succeeds on the matching TypeScript-client PR branch (pull/303/head), so this is a release-order dependency: either ensure that downstream PR is merged before this SDK release handoff can run, or add a fallback/guard here so the job does not fail on the current client default branch.
HUMAN: I checked the code here.
AGENT:
Why
The existing SDK release job only changes the TypeScript client's Agent Server
image pin. That leaves the generated transport contract stale and makes the
release handoff depend on a reviewer noticing and regenerating it manually.
Fixes #4228
Linear: OSS-6124
Summary
artifact and updates every client-side Agent Server version mirror.
openapi.json, regenerate andcommit the client contract, and include a generated API-change summary in the
downstream PR.
required client PR checks so contract incompatibilities are visible without
preventing the update PR from being proposed.
Issue Number
#4228 / OSS-6124
How to Test
uv run pytest -q tests/cross/test_prepare_typescript_client_agent_server_bump.py— 7 passed.
pycodestyle, Pyright, import rules, and tool registration.
version-bump-prs.ymland asserted the exact-artifact step exists.an OpenAPI artifact exported by this stacked SDK code. It updated 1.37.0 to
the artifact's 1.37.1 version, regenerated the client, produced a non-empty
API summary, and verified the generated source metadata and image pin.
The matching client-side automation and fixtures are in
OpenHands/typescript-client#303 (OSS-6126). Agent Canvas typecheck and production
build also pass against that exact packed client in a disposable HOME/XDG/state/
settings environment;
~/.openhandswas never used.Video/Screenshots
Not applicable: release automation only.
Type
Notes
Stacked on #4229 and should be rebased to
mainafter that PR merges. This SDKworkflow intentionally opens the generated client update even if handwritten
aliases need adjustment; required checks on that PR expose the incompatibility
and must pass before merge.
Agent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdknikolaik/python-nodejs:python3.13-nodejs22-slimgolang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:07ee8d1-pythonRun
All tags pushed for this build
About Multi-Architecture Support
07ee8d1-python) is a multi-arch manifest supporting both amd64 and arm6407ee8d1-python-amd64) are also available if needed