Repository navigation
Add a Swift runtime for Prompty - #439
Merged
Merged
Conversation
Member
Author
|
Stale against current |
…0, no shim) The Typra Swift emitter at 0.9.0 emits a library that compiles cleanly without the source-defect shim that earlier versions (0.4.x) required, so the generated PromptyModel is committed as-emitted with no post-processing. This keeps Typra-emitted files unmodified, per project principle. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Bump schema dep to ^0.9.1 (published from Typra PR #231) which fixes the Swift-only BUG 1: absent required scalar/dict fields on discriminated-union subtypes now default silently (matching Rust unwrap_or_default) instead of throwing. Re-enable the Swift test-dir in tspconfig and regenerate. Regenerated PromptyModel now: - drops the absent-required-scalar throws across every Connection subtype - emits inherited Connection base fields (authenticationMode, usageDescription) on each subtype so they round-trip - emits @Coerce for bare-scalar Property shorthand - ships generated per-model + conformance tests (273 tests, 0 failures) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…contract Align the hand-written Prompty runtime's tests with the corrected generated model contract (closed Connection union, open Tool union, scalar/dict leniency, inherited base fields, @Coerce). No runtime code changed — all edits are test-side, and no generated code was touched. - GeneratedModelRoundTripTests: supply required connection to mcp/openapi/custom fixtures; assert Connection base fields round-trip; assert unknown Connection kind is rejected (closed union) rather than preserved - ContentPartDiscriminatorTests: empty/missing kind now surface as invalidField; give the shared CustomTool fixture its required connection - PropertyKindDispatchTests: assert bare-scalar @Coerce shorthand coerces to {kind, example} instead of throwing - ToolBindingTests: drop the canonicalizeParameters shim and its tripwire now that vectors.json declares canonical parameters; load tools verbatim - delete ConnectionRoundTripTests and WildcardPreservationTests: both encoded a now-invalid open-union Connection with a .unknown case that the closed union does not have; closed-union coverage lives in GeneratedModelRoundTripTests prompty-model: 273 tests, 0 failures. prompty runtime: 177 tests, 0 failures, 10 skipped (live-API + not-yet-landed vector guards). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add prompty-swift-check.yml mirroring the other per-runtime -check workflows: runs on PRs touching runtime/swift/** or schema/**, and is reusable via workflow_call. Builds and tests both the generated prompty-model package and the hand-written prompty runtime on ubuntu and macOS with Swift 6.0. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Seth Juarez (sethjuarez)
force-pushed
the
sejuare-microsoft/swift-runtime
branch
from
August 18, 2026 18:25
039ad07 to
2feec8f
Compare
The committed Swift model tree was generated with @typra/emitter 0.9.2 (the caret ^0.9.1 range resolved 0.9.2 in node_modules), but the lockfile pinned 0.9.1. CI's `npm ci` therefore regenerated Swift with 0.9.1, producing output that differed from the committed 0.9.2 tree (Package.swift, Contracts/Connectivity/*.swift, etc.) and failing the "regeneration produces no diff" check. Bump the pin to the latest published release (0.9.2) and refresh the lockfile so CI regenerates with the same emitter that produced the committed tree. A local regen on 0.9.2 yields no Swift diff, confirming the committed tree already matches 0.9.2 output. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The macOS job installed a standalone Swift 6.0.3 toolchain via swift-actions/setup-swift, but that compiler is then used against macos-latest's newer Xcode SDK (built with a later Swift), failing with "this SDK is not supported by the compiler. Please select a toolchain which matches the SDK." The Linux job is unaffected (no Xcode) and keeps passing. Split the toolchain setup by OS: Linux keeps the pinned standalone Swift 6.0 toolchain, while macOS selects Xcode via maxim-lobanov/setup-xcode and uses its bundled Swift, so the compiler and SDK are always matched. Aligns with issue #474 (toolchain pinning/reproducibility). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The Swift emit target's driver shells out to `swift-format` after emitting, but wraps the call in a catch that silently falls back to the emitter's own deterministic formatting when swift-format is absent (no warning is printed). The schema-repro-check regen runner has no Swift toolchain, so it regenerated the compact deterministic output while the committed tree had been formatted by swift-format on a machine that had it. The two never matched, so "regeneration produces no diff" failed across the whole Swift tree with no way for the gate's missing-formatter guard to attribute it (the driver emits no "Warning:" line). Set `format: false` on the Swift emit target (a sanctioned per-target emitter option) so the emitter's deterministic output is the single source of truth on every platform, with or without swift-format, and regenerate. The change is pure line-wrapping (long signatures inline instead of wrapped); the Swift is semantically identical and still compiles and passes both the ubuntu and macOS test jobs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Pin to the latest published emitter (0.9.3) to keep every runtime on the same version. 0.9.3 only changes relative Python cancellation-token import depth handling, so the Swift emit target is unaffected and regeneration produces no Swift diff (format is disabled for Swift, so its deterministic output is unchanged regardless). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Regenerate the Swift model tree against the canonical engine port and connection contracts introduced in #447. Adds the Swift EngineToolPort, EnginePermissionPort, EnginePostCommitPort, and EngineDurabilityPort protocols (native async throws cancellation) and propagates the Connection forward-compat `unknown` fallback into tool connection defaults. Deterministic emitter output (format: false); no hand edits. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ntract #447 redefined Connection as an open union: an unknown discriminator now survives as the wildcard `unknown` case instead of throwing (matching Rust's ConnectionKind::Unknown). Update the hand-written round-trip test to assert preservation rather than rejection, mirroring the Tool open-union test above. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Seth Juarez (sethjuarez)
added a commit
that referenced
this pull request
Aug 19, 2026
Swift runtime landed on main (#439) after this branch was authored, so regenerating #438's canonicalized StreamFailure contract against current main emits the Swift model files (FailureChunk case on StreamChunk, the StreamFailure struct, StreamFailureOutcome enum) plus the generated conformance test. Pure typra output; no hand edits. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Seth Juarez (sethjuarez)
added a commit
that referenced
this pull request
Aug 19, 2026
* feat(schema): classify stream failures Add a canonical StreamFailure contract and FailureChunk stream chunk kind so provider stream errors can be classified as determinate or indeterminate. Regenerated all runtime models, vscode schemas, and reference docs from the pinned emitter. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * feat(runtime): classify stream failures across rust and typescript Port the classified stream-failure behavior onto the regenerated FailureChunk/StreamFailure model. Rust (prompty pipeline + prompty-openai processor) and TypeScript (core pipeline, openai/anthropic processors) now surface determinate vs indeterminate stream failures with matching process vectors. Python, Go, and C# receive the feature via the regenerated model classes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * feat(swift): regenerate stream-failure contract for Swift runtime Swift runtime landed on main (#439) after this branch was authored, so regenerating #438's canonicalized StreamFailure contract against current main emits the Swift model files (FailureChunk case on StreamChunk, the StreamFailure struct, StreamFailureOutcome enum) plus the generated conformance test. Pure typra output; no hand edits. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Seth Juarez <sethjuarez@users.noreply.github.com>
Seth Juarez (sethjuarez)
added a commit
that referenced
this pull request
Aug 19, 2026
…-port + open-union contracts Brings the Java runtime up to parity with main after PRs #447 (engine ports, open-union Connection, stream-failure) and #439 (Swift) landed. - Resolve schema conflicts: union tspconfig.yaml (Java + Swift targets), pin @typra/emitter ^0.9.3, take main's package-lock + export-surfaces. - Regenerate: adds Engine{Durability,Permission,PostCommit,Tool}Port, FailureChunk, StreamFailure(Outcome), UnknownConnection (+ generated round-trip tests); Connection becomes an open union, StreamChunk gains the failure case. - Rewrite the hand-written unknown-connection-kind test to assert the new open-union round-trip (UnknownConnection preserves kind + extra keys) instead of expecting a throw. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a Swift implementation of the Prompty runtime. There was no Swift runtime in this repo before; nothing existing changes behaviour.
The Rust runtime is the behavioural reference throughout, and both are held to the same cross-runtime vectors emitted into
schema/tsp-output/.typra-generated/vectors.json.Note
Status: complete, green, and mergeable. No shim, no emitter pin gymnastics.
This PR was rebuilt from scratch on the published
@typra/emitter@0.9.1. The earlier version of this branch stood up a post-generation repair shim against an old emitter and was gated on an upstream release; that entire approach is gone. The one real Swift-only emitter defect it was working around (absent required scalar/dict fields on discriminated-union subtypes threw instead of defaulting, where Rust usesunwrap_or_default()) was fixed at source in Typra (sethjuarez/typra#231), released as@typra/emitter@0.9.1, and consumed here. The generated Swift now compiles and round-trips with no hand edits to generated code and no shim.What's here
Two SwiftPM packages, and the split is the point:
prompty-modelPromptyModelpromptyPromptypromptyPromptyOpenAIThe runtime defines no domain types of its own.
Prompty,Model,Message,ContentPart,Tooland the four pipeline protocols (Renderer,Parser,Executor,Processor) all come from the generated model, and the hand-written code conforms to them.Covered: loading (including
${env:}/${file:}), rendering, parsing, preparation, protocols and registries, provider execution and processing, tools and turns, structured output, streaming, and harness durability/replay.Model contract (verified against the generated Swift)
The rebuild pins down the cross-runtime contract exactly as Rust implements it:
Connectionis a closed union (reference,remote,key,anonymous,oauth,foundry). An unknownkindis rejected (unknownDiscriminator), matching the Rustpanic!. Inherited base fields (authenticationMode,usageDescription) are emitted on every subtype and round-trip.Toolis an open union. An unknownkindis preserved as aCustomToolcarrying its raw payload, and re-serialises losslessly.connectiononMcpTool/OpenApiTool/CustomTool) — the strictvalidate_input_atcontract shared by all runtimes.0.9.1fix, matching Rust'sunwrap_or_default().@coercenormalises a bare scalar shorthand into{kind, example}instead of throwing.ContentPartis closed; empty/missingkindsurfaces asinvalidField.Tests
prompty-model(generated tests): 273 tests, 0 failures.promptyruntime: 177 tests, 0 failures, 10 skipped (live-provider E2E that needOPENAI_API_KEY, plus self-guarding vector tests that auto-activate when theproperty_scalar_coercionvectors land from Define canonical engine port and connection contracts #447).Two hand-written test files (
ConnectionRoundTripTests,WildcardPreservationTests) were deleted: both encoded a now-invalid open-unionConnectionwith a.unknowncase the closed union does not have. Real Connection coverage lives inGeneratedModelRoundTripTests.CI:
.github/workflows/prompty-swift-check.ymlbuilds and tests both packages on ubuntu + macOS with Swift 6.0, on any PR touchingruntime/swift/**orschema/**.Commits
cd79a457f3e3a75d@typra/emitter0.9.1 and regenerate PromptyModel603ddf022feec8f6Emitter changes upstreamed
fix(swift): default absent required scalar/dict on union subtypes— sethjuarez/typra#231, merged and released as@typra/emitter@0.9.1. No generated code in this repo was hand-edited to compensate.