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".
Formalizing the /pty REST routes in specs/execd-api.yaml forces a wholesale regeneration of the committed Python and JavaScript execd clients (and C#/Go parity), which is a cross-SDK contract change in its own right. To keep this PR focused on the Kotlin PTY feature, revert the spec addition and keep the adapter as handwritten transport (the interactive channel is a WebSocket and is out of scope for codegen regardless). The spec formalization + cross-SDK client regeneration will be a dedicated follow-up PR. 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: efad1ce520
ℹ️ 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".
|
Follow-up contract PR opened: #1054 adds the /pty routes to specs/execd-api.yaml and regenerates the Python and JS execd clients. Once it lands, the Kotlin adapter here can move onto the generated PTYApi. |
|
Closing in favour of a cleaner split: the auto-generatable part (the /pty REST lifecycle) now lives in #1054 — which adds /pty to the execd spec, regenerates the clients, and (incoming) wires the SDK PTY adapters onto the generated |
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