Skip to content

docs: native Swift SDK API design proposal - #165

Open
kitakkun wants to merge 2 commits into
mainfrom
docs/swift-sdk-design
Open

docs: native Swift SDK API design proposal#165
kitakkun wants to merge 2 commits into
mainfrom
docs/swift-sdk-design

Conversation

@kitakkun

Copy link
Copy Markdown
Owner

A design proposal (not implementation) for a native Swift SDK, following the Swift-Export feasibility study.

Core idea: do not export the Kotlin authoring surface (receiver-lambda DSLs, reified generics, @Serializable, sealed markers, abstract-class plugins all fail to bridge). Instead add a thin export-clean facade in commonMain and design an idiomatic Swift wrapper on top.

  • One rule: only strings/plain values cross the boundary. The messenger already exposes a monomorphic sendRaw/requestRaw pair (JetWhaleMessenger.kt:32,40); the Swift SDK builds on it and does its own Codable, so generics/serialization never bridge.
  • Swift API: JetWhale.start(host:port:) { config in … } value builder; Codable messages tagged by a stable messageType; a JetWhalePlugin protocol (Swift conforms, no subclassing); async request.
  • Kotlin facade: JetWhaleSwiftConfig, a SwiftPluginBridge interface (→ Obj-C protocol), a RawMessenger export; a SwiftBackedAgentPlugin adapts the bridge to a real JetWhaleAgentPlugin.
  • Distribution: XCFramework + SPM binaryTarget (KMMBridge), Obj-C interop today, Swift Export later without changing the Swift API.
  • Highlighted risk: wire-format/discriminator compatibility between Swift Codable and the host kotlinx.serialization — proposes a shared neutral schema + round-trip conformance test.
  • Network Inspector on Swift: a URLSession URLProtocol adapter feeding the existing transport-agnostic capture API (Phase 2).

Doc lives at docs/architecture/swift-sdk-design.md (not in the published VitePress nav).

Design for a pure-Swift SDK: an export-clean commonMain facade (config
builder, a SwiftPluginBridge interface, a raw string/JSON messenger) with an
idiomatic Swift wrapper (Codable messages tagged by a stable messageType, a
JetWhalePlugin protocol instead of subclassing, async request). Only strings
and plain values cross the boundary, so Kotlin generics and kotlinx.serialization
never need to bridge. Covers XCFramework + SPM binaryTarget distribution, the
wire-format compatibility risk, the URLSession network adapter, and phasing.
Copilot AI review requested due to automatic review settings July 19, 2026 10:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an architecture/design proposal document for a native Swift SDK wrapper around JetWhale’s agent runtime, focusing on an export-clean Kotlin façade and an idiomatic Swift Codable-first API that avoids exporting Kotlin-idiomatic surfaces.

Changes:

  • Introduces a Swift consumer-facing API sketch (JetWhale.start, JetWhalePlugin, JetWhaleMessenger, typed events/requests).
  • Proposes a Kotlin commonMain façade (JetWhaleSwiftConfig, SwiftPluginBridge, RawMessenger) suitable for Obj-C interop now and Swift Export later.
  • Documents key risks and rollout phases, especially wire-format/discriminator compatibility and a conformance-test gate.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to +36
This is already possible: `JetWhaleMessenger` exposes a monomorphic boundary today —
`sendRaw(messageType: String, payload: String): Boolean` and
`suspend requestRaw(messageType, payload, timeout): String`
(`jetwhale-protocol/core/.../JetWhaleMessenger.kt:32,40`). The typed `trySend`/`request` are just
reified extensions over these. The Swift SDK builds directly on the raw pair and does its own
`Codable` encode/decode, so generics and serialization never need to bridge.
Comment thread docs/architecture/swift-sdk-design.md Outdated
Comment on lines +177 to +179
The Network Inspector core is transport-agnostic — `JetWhaleNetworkAgentPlugin` exposes
`recordRequest`/`recordResponse`/`recordFailure`/`findMock`/`newTransactionId`
(`network/agent/.../JetWhaleNetworkAgentPlugin.kt:79-94`), and its docstring invites new adapters.
Comment thread docs/architecture/swift-sdk-design.md Outdated
Comment on lines +153 to +155
- **`messageType`** must equal the discriminator the Kotlin side registers for that message
(today derived from the `@Serializable` class). The Swift `static let messageType` is the explicit
contract; the shared-message module on the Kotlin side must register the same string.
Expand the shortened path references to full repo paths (JetWhaleMessenger.kt,
JetWhaleNetworkAgentPlugin.kt), and correct the wire-format note: the message
discriminator is the serializer descriptor serialName (FQ class name by
default, overridable with `@SerialName`), not simply "derived from the class".
@kitakkun kitakkun added the documentation Improvements or additions to documentation label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants