feat(cli-bridge): Use oneOf with discriminator for ServerMessage in OpenAPI spec
Summary
The iOS client (CodingBridge) uses OpenAPI code generation to stay in sync with cli-bridge types. With v0.4.1, WebSocket message schemas were added to the OpenAPI spec, which is great! However, ServerMessage uses anyOf instead of oneOf with a discriminator, which prevents proper Swift enum generation.
Current Behavior
ServerMessage in the OpenAPI spec uses anyOf:
{
"ServerMessage": {
"anyOf": [
{ "$ref": "#/components/schemas/ConnectedMessage" },
{ "$ref": "#/components/schemas/StreamServerMessage" },
{ "$ref": "#/components/schemas/PermissionRequestMessage" },
// ... more types
]
}
}
This generates a flat Swift struct with all properties from all message types:
// Generated (incorrect)
public struct ServerMessage: Codable {
public var type: ModelType
public var agentId: String // from ConnectedMessage
public var sessionId: UUID // from ConnectedMessage
public var tool: String // from PermissionRequestMessage
public var input: [String: JSONValue] // from PermissionRequestMessage
// ... 30+ properties merged together
}
Expected Behavior
ServerMessage should use oneOf with a discriminator (like StreamMessage and ClientMessage already do):
{
"ServerMessage": {
"oneOf": [
{ "$ref": "#/components/schemas/ConnectedMessage" },
{ "$ref": "#/components/schemas/StreamServerMessage" },
{ "$ref": "#/components/schemas/PermissionRequestMessage" },
// ... more types
],
"discriminator": {
"propertyName": "type",
"mapping": {
"connected": "#/components/schemas/ConnectedMessage",
"stream": "#/components/schemas/StreamServerMessage",
"permission": "#/components/schemas/PermissionRequestMessage"
// ... more mappings
}
}
}
}
This would generate a proper Swift enum with associated values:
// Generated (correct)
public enum ServerMessage: Codable {
case typeConnectedMessage(ConnectedMessage)
case typeStreamServerMessage(StreamServerMessage)
case typePermissionRequestMessage(PermissionRequestMessage)
// ...
}
Working Examples in Current Spec
These already use oneOf with discriminator and generate correctly:
ClientMessage✅StreamMessage✅ContentBlock✅
Impact
With this change, CodingBridge can be 100% generated from the OpenAPI spec, eliminating hand-written CLIServerMessage type and ensuring the iOS client stays perfectly in sync with the backend protocol.
Files to Update
src/hono/schemas/websocket.ts- ChangeServerMessagefromz.union()to use discriminated union pattern
Related
- cli-bridge v0.4.1 added WebSocket schemas to OpenAPI
- CodingBridge uses
openapi-generator swift6for code generation
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗