feat(simulation): add endpoint handshake protocol (#37157)

This commit is contained in:
Kit Langton 2026-07-15 17:46:28 -04:00 committed by GitHub
commit 5e2e0d6965
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 350 additions and 2 deletions

View file

@ -17,6 +17,7 @@ Implementation checklist:
- [x] Add OpenTUI UI state extraction for screen, focus, elements, and generated actions.
- [x] Add OpenTUI UI action execution for typing, keys, enter, arrows, focus, and click.
- [x] Add reusable JSON-RPC WebSocket server at the manifest's UI endpoint.
- [x] Add `simulation.handshake` protocol, role, identity, version, and capability negotiation to both control endpoints.
- [x] Expose `ui.state`, `ui.action`, `ui.render`.
- [x] Expose `trace.list`, `trace.clear`, `trace.export`.
- [x] Wire visible V1/full-TUI renderer path through the same action protocol.

View file

@ -69,6 +69,7 @@ This is important because the frontend has direct access to the renderer, screen
Protocol:
- JSON-RPC 2.0 over WebSocket.
- Clients negotiate protocol version, endpoint role, and capabilities with `simulation.handshake` before using endpoint methods.
- Loopback only.
- `OPENCODE_DRIVE` names a manifest in the opencode-drive registry, or is `1` for the unnamed default endpoints.
- The manifest supplies exact loopback `ui` and `backend` WebSocket endpoints.
@ -77,6 +78,42 @@ Protocol:
The app should not send JSON-RPC requests back to the driver in the first milestone. The driver sends requests; the app responds and emits notifications/events as useful.
The canonical handshake request is:
```ts
{
jsonrpc: "2.0"
id: string | number | null
method: "simulation.handshake"
params: {
client: {
name: string
version: string
}
expectedRole: "ui" | "backend"
offeredVersions: Array<number>
requiredCapabilities: Array<string>
optionalCapabilities: Array<string>
}
}
```
The response result is:
```ts
{
protocolVersion: 1
role: "ui" | "backend"
server: {
name: string
version: string
}
capabilities: Array<string>
}
```
Capabilities are open strings. Each endpoint advertises only methods and notifications it actually implements. A role mismatch, no supported offered protocol version, or a missing required capability fails the request; unsupported optional capabilities do not.
Initial method groups:
- `ui.state`: return screen, elements, focus, and generated possible actions.