feat(sdks/kotlin): add interactive PTY session support#1052
Conversation
Expose execd's interactive pseudo-terminal sessions in the Kotlin SDK.
execd already serves the /pty endpoints and the /pty/{id}/ws WebSocket;
the SDK had no way to reach them.
- Add a Pty service (createSession / getSession / deleteSession) plus a
webSocketUrl(sessionId, mode, since, takeover) builder that derives the
ws/wss URL (PtyMode PTY|PIPE, since-offset replay, takeover) without a
network call.
- Add PtyAdapter as handwritten OkHttp transport, since the PTY routes are
not part of the OpenAPI specs (same pattern as the SSE command stream).
- Wire it through AdapterFactory and expose it as Sandbox.pty().
No spec, server, or generated-code changes. Driving the WebSocket itself
is left to the caller; this lands the session lifecycle and URL.
Co-authored-by: Atenea Agent <srv_atenea_gitlab@ofidona.net>
|
Changed directories: sdks. 📋 Recommended labels (based on changed files):
Other available labels:
💡 Tip: Use cc @ferponse |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 889b764cb5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…eaders - Replace Kotlin default arguments on the Pty interface with explicit overloads (createSession / webSocket) so Java callers get usable no-arg and partial overloads instead of having to pass every nullable argument. - Return the WebSocket target as PtyWebSocket(url, headers) instead of a bare URL, so the routing/auth headers resolved for the execd endpoint are sent on the WebSocket handshake too (header-mode ingress / secure access), matching what the REST calls already do. Co-authored-by: Atenea Agent <srv_atenea_gitlab@ofidona.net>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 15fb425238
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
- Document the /pty create/status/delete REST routes in specs/execd-api.yaml so the contract the SDK depends on is tracked and generatable (the interactive channel stays a WebSocket and is out of scope for codegen). - Preserve the Sandbox JVM constructor signature: wire the PTY service via an internal bindPtyService() after construction instead of adding a parameter, avoiding a source/ABI break for already-compiled consumers. - Map structured execd errors (e.g. 404 CONTEXT_NOT_FOUND, 501 NOT_SUPPORTED) to SandboxApiException with the parsed error code and X-Request-ID, like the other adapters, instead of a bare status code. - Honor https domains when building PTY REST/WebSocket URLs even if `protocol` is left at its default, mirroring lifecycle base-URL resolution. - Include the configured ConnectionConfig.headers in the WebSocket handshake headers (endpoint headers take precedence on conflicts). Co-authored-by: Atenea Agent <srv_atenea_gitlab@ofidona.net>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b7da8490ae
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…apters - Use ConnectionConfig.protocol for the resolved execd endpoint (REST + ws/wss), exactly like CommandsAdapter/HealthAdapter. Deriving https from the lifecycle domain broke direct-endpoint mode, where execd is reached on a raw pod IP / host-mapped port that serves plain HTTP. - Revert the /pty additions to specs/execd-api.yaml. Formalizing the PTY REST contract in the shared spec is a cross-SDK change (regenerating the committed JS/Python/Kotlin clients, aligning the server's real 200 delete status and the 501 NOT_SUPPORTED responses) and belongs in a dedicated spec PR with parity, not this Kotlin SDK feature. The adapter stays handwritten transport for the WebSocket-centric PTY protocol. Co-authored-by: Atenea Agent <srv_atenea_gitlab@ofidona.net>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bfdb7e0c91
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…spec - Resolve the PTY endpoint scheme by mode: server-proxy endpoints go back through the lifecycle server and inherit its scheme (honoring an https domain with the default protocol), while direct raw endpoints stay on config.protocol like CommandsAdapter. Fixes wrong http/ws for https server-proxy deployments without breaking direct deployments. - Re-add the /pty create/status/delete routes to specs/execd-api.yaml so the REST contract the SDK depends on is tracked and generatable, this time matching execd's real behavior: DELETE returns 200 (empty success body) and all three operations document the 501 NOT_SUPPORTED platform response. The interactive channel remains a WebSocket (out of scope for codegen). Co-authored-by: Atenea Agent <srv_atenea_gitlab@ofidona.net>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8fe18b3c1a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "500": | ||
| $ref: "#/components/responses/InternalServerError" | ||
|
|
||
| /pty: |
There was a problem hiding this comment.
Regenerate the execd clients for PTY
Fresh evidence since the earlier thread: this diff re-adds /pty to the source execd spec, but the committed generated clients are still stale (rg "createPtySession|CreatePtySessionRequest" sdks/sandbox/javascript/src/api/execd.ts sdks/sandbox/python/src/opensandbox/api/execd finds no PTY output). Because these generated API packages are published/used downstream, releases or generator checks can omit the new contract or produce uncommitted diffs; regenerate the affected execd clients alongside the spec addition.
Useful? React with 👍 / 👎.
Summary
execd already implements interactive PTY sessions — the
/ptyREST endpoints (create / status / delete) and the/pty/{sessionId}/wsWebSocket — but the Kotlin SDK had no way to reach them. This PR exposes the PTY session lifecycle in the SDK and builds the WebSocket URL clients connect to.Adds a
Ptyservice, accessible viasandbox.pty():createSession(cwd?, command?)→POST /pty(the shell starts on first WebSocket attach).getSession(sessionId)→GET /pty/{id}(running,outputOffsetfor replay).deleteSession(sessionId)→DELETE /pty/{id}.webSocketUrl(sessionId, mode = PTY, since?, takeover?)— derives thews/wssURL with thepty=0/since=/takeover=1query params, no network call.Notes / scope
PtyAdapteris handwritten OkHttp transport, mirroring the existing SSE command stream. No spec/server/generated-code changes.Testing
./gradlew spotlessCheck :sandbox:test— green (full:sandboxsuite: 184 tests, 0 failures).PtyAdapterTest(MockWebServer) covers create/get/delete request shape and parsing, error status mapping, endpoint-header forwarding, and thewebSocketUrlbuilder (params +wssfor https).SandboxTestcovers thepty()accessor.Breaking Changes
None for SDK consumers (additive API). Note: the internal
Sandboxconstructor gains aptyServiceparameter — it isinternal, not part of the public surface.Checklist
java.timeunaffected)/ptypaths tospecs/execd-api.yaml+ an E2E intests/java/if preferredCo-authored-by: Atenea Agent srv_atenea_gitlab@ofidona.net