Skip to content

Relay API reference: TypeSpec→AsyncAPI 3.0 tooling + full Relay surface + Fern docs#423

Draft
Devon-White wants to merge 95 commits into
mainfrom
devon/relay-asyncapi-tooling
Draft

Relay API reference: TypeSpec→AsyncAPI 3.0 tooling + full Relay surface + Fern docs#423
Devon-White wants to merge 95 commits into
mainfrom
devon/relay-asyncapi-tooling

Conversation

@Devon-White

Copy link
Copy Markdown
Collaborator

Description

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Code cleanup / refactor

Related Issues

Testing

  • Added/updated unit tests
  • Tested manually
  • Tested with live SignalWire credentials (if applicable)

Checklist

  • I have read the CONTRIBUTING guidelines
  • My code follows the project's style guidelines
  • I have added tests for my changes (if applicable)
  • I have updated documentation (if applicable)
  • All existing tests pass

Additional Notes

Also fixes test harness: import the library and use the full
SignalWire.AsyncAPI namespace path so decorators resolve.
…uth security

Avoids depending on @typespec/http (whose lib tsp won't load in the
hoisted standalone tester); custom @bearerAuth keeps the emitter self-contained.
…dModel, inline-param docs

Addresses adversarial review: numeric enum/discriminator type inference (latent
invalid-schema bug), Array.isArray guard, isNamedModel helper, inline-parameter
description extraction, and a multi-method/multi-event collision-coverage test.
String-discriminator output is unchanged (golden snapshot + Relay artifact in sync).
@minValue/@maxValue/exclusive, @minLength/@maxlength, @minItems/@Maxitems,
@pattern, @Format, @secret→format:password, property defaults, and @example
now map to the corresponding JSON-Schema keywords (valid per AsyncAPI 3.0's
Draft-07 superset). Relay timeout now models its non-negative/default-30 semantics.
…odedname

Completes the standard property-decorator surface: @encode decays to its wire
type with a JSON-Schema format (e.g. utcDateTime+rfc3339 → string/date-time),
@Encodedname remaps the emitted JSON property key. No standard property decorator
is silently dropped now.
…r assertions, dup-method diagnostic

Addresses the remaining adversarial-review quality findings:
- Replace SchemaObject=Record<string,unknown> with a structured AsyncAPISchema
  interface (correct AsyncAPI/Draft-07 dialect: numeric exclusiveMin/Max, string
  discriminator, no nullable) — removes the as-Record casts. Not reusing
  @typespec/openapi3's OpenAPI3Schema, which models a different dialect.
- RefFn returns SchemaOrRef (= AsyncAPISchema | AsyncAPIRef); unionInline typed
  to Union (removes the as-any casts).
- emitRpcMethods/emitEvents take a typed EmitTarget context instead of drilling
  doc!.components! — removes non-null assertions.
- Add duplicate-@rpcMethod diagnostic + test.
…p invented /api/relay/wss path)

Verified against the TS + Python SDK clients: both connect to `wss://${host}` with
DEFAULT_RELAY_HOST = relay.signalwire.com and reject a host containing a path. The
service is selected by the JSON-RPC method in the payload, not a URL path.
With address null, Fern composes the channel URL as wss://<host>/<channelId>,
showing a misleading per-service path (e.g. wss://relay.signalwire.com/messaging).
Relay multiplexes every service over one root connection and routes by the JSON-RPC
method, so emit the root address "/" — Fern then renders wss://relay.signalwire.com/.
Verified live for the messaging and calling channels.
…pecs

The emitter's dist/ is gitignored and nothing built it in CI, so build:relay
failed with import-not-found on ../dist/src/index.js. build:relay now runs the
emitter's tsc build first (verified against a clean dist/).
The Relay API was rendering in the same flat sidebar as REST. Convert the apis
product nav to tabs (matching the compatibility-api pattern): a REST tab and a
Relay tab. URLs are preserved — Core stays at /docs/apis/<page>, REST at
/docs/apis/rest/..., Relay at /docs/apis/relay/... (tab carries the slug, the API
uses skip-slug). Verified live: both tabs render and all existing URLs 200.
…xample

Emitter now reads @opExample on RPC ops (parameters -> request frame,
returnType -> reply frame) and @example on event models (-> signalwire.event
carrier frame), emitting them as AsyncAPI message examples. Adds examples.test.ts.
…mples

Correctness fixes from the one-to-one spec audit (6 services / 71 methods / 26 events):
- pay: input enum speech->voice; add PayPrompt.attempt + require_matching_inputs;
  actions optional; numeric/bool params retyped to wire strings per pay_schema.md
- calling: join_conference recording_status_callback_event enum->string;
  hold/unhold result state literals; broaden TapCodec + detector-event enums
- signalwire: ConnectResult.ice_servers optional; strip internal jargon (BLADE/etc.)
- tasking: drop carrier fields (timestamp/space_id/project_id) the emitter synthesizes
- add missing customer-facing @doc across event/refer models
Examples: @opExample on every method + @example on every event; discriminator-union
variant models carry schema-level @example where an op frame can't narrow the base.
All 6 specs validate 0 errors via the official AsyncAPI CLI; fern check clean.
…_transcribe/translate

Verified the SWML models against the mod_openai/mod_infrastructure C engine
(96/96 AIParams fields parsed by the engine; SWAIG schema shared via one
process_swaig_function; live_transcribe/translate hit the same parse_transcribe_json).
Replicated the engine-confirmed shapes into the Relay specs (cross-import blocked by
@jsonSchema/SWMLVar), stripping ~72 markup arms:
- calling.ai/amazon_bedrock: params Record<unknown> -> typed AiBehaviorParams (91 fields)
- SWAIG: native_functions enum, web_hook_auth_* + meta_data on function/defaults/includes,
  mcp_servers; kept parameters/data_map/internal_fillers loose (@OneOf, validate-first)
- live_transcribe/translate: start/summarize/inject Record<unknown> -> typed action models
- added @opExample to all 7 AI ops
calling validates 0 errors (AsyncAPI CLI); fern check clean.
Replace the hand-replicated AiBehaviorParams (91 fields) with a direct spread of
the engine-verified SWML AIParams model, stripping its markup-only `| SWMLVar`
template-variable arms at emit time so they never reach the live JSON-RPC wire.

- typespec-emit-filter: standalone, generic @excludeFromEmit(...types) decorator
  package (TypeSpec's shared-decorator-library pattern).
- asyncapi emitter: honor @excludeFromEmit on models/unions/properties — drop the
  named arms and collapse the union (0 -> {}, 1 -> bare, all-string -> enum, else
  oneOf). Applied on both the component and inline-model paths (open models with a
  `...Record<unknown>` index signature always inline).
- asyncapi emitter: namespace-qualified component names via getTypeName so reused
  cross-namespace SWML types stay collision-free (service-local types stay bare);
  add a duplicate-type-name diagnostic backstop.
- relay calling: AiBehaviorParams now spreads SWML.Calling.AIParams, keeping the 2
  deprecated eleven_labs_* fields.

Verified: 32 emitter tests pass; AsyncAPI CLI 0 errors; fern check clean (only the
known FDR 403); parity diff vs 158d9c1 shows only additive/authoritative deltas
(added defaults/examples, SWML constraints, reused SWML.Calling.ConversationMessage,
+2 deprecated fields, int32->integer format drops); the other 5 relay specs are
byte-identical; SWML's own json-schema emit still includes SWMLVar.
…zon_bedrock

Extend the SWML reuse from `params` (AIParams) to the entire AI agent config object,
which mod_openai's create_app_from_json parses identically for the SWML `ai` verb and
Relay calling.ai (verified in C source). The Relay-local Ai* sub-models were incomplete
projections of one shared backend object; replace them with direct references to the
engine-verified SWML models.

- AiParams/AmazonBedrockParams: prompt -> AIPrompt, post_prompt -> AIPostPrompt,
  pronounce -> Pronounce, hints -> (string|Hint)[], languages -> Languages,
  SWAIG -> SWAIG (incl. the full function/parameters/data_map tree and the SWMLAction
  that returns a full SWML document), global_data -> GlobalData. Delete the 11 hand-rolled
  Ai* sub-models (-288 lines net).
- Exclude ONLY the markup-only `SWMLVar` template-variable arms via @excludeFromEmit on
  the entry models (resolved at SWML execution, never on the live JSON-RPC wire). Every
  other surface SWML accepts is emitted as-is, including the recursive SWML document a
  SWAIG data_map action can return (handled natively via $ref).
- Reused SWML as-is; SWML's current gaps vs Relay (missing web_hook_auth_* on SWAIG,
  Hint requiring pattern/replace, AIPrompt missing barge_confidence/model) are logged in
  SWML-REUSE-GAPS.md for a later SWML-truing pass.

Verified: 0 SWMLVar leak; valid AsyncAPI (fern check clean); fern docs dev renders the
calling AI reference incl. the recursive SWML `$ref`; other 5 relay specs byte-identical;
SWML's own emit unaffected.
Devon-White and others added 15 commits June 26, 2026 12:07
Remove the 'Relay (Single Channel)' tab and the 'Playground' page (which rendered
relay-single) from the Relay tab. Also fix the Webrtc section's stale
referenced-packages (webrtc/message/conferenceList -> webrtcVerto/webrtcMessage)
left over from the webrtc.verto rename + conference.list removal.
The relay-single (single-channel) spec is no longer used in the docs (tab +
Playground page removed). Drop its generation entirely: remove the
build:relay-single-spec step from build:relay, delete specs/relay/tspconfig.single.yaml
and the generated fern/apis/relay-single/ output. Only the one multi-channel Relay
AsyncAPI spec (relay.yaml) remains. The emitter's channel-mode:single capability and
its unit test are unchanged (still a supported feature, just unused by the build).
…nhance event models

- Introduced JsonRpcRequest and JsonRpcResponse models for standardized request/response handling across Relay services.
- Updated transfer and user-event operations to utilize new request/response models.
- Refactored messaging events (receive, state) to align with new event model structure.
- Enhanced connect and disconnect operations with new request/response models.
- Added new documentation pages for Relay authentication and error handling.
- Improved overall structure and clarity of Relay API specifications.
- emitter: a parameterless @channel op now emits a receive-only channel
  (channel + receive ops, no request frame, no send op); add the
  reply-without-request diagnostic; correct the stale channel-mode doc
- tasking: model queuing.relay.tasks as a receive-only channel and move
  TasksEvent off signalwire.receive (de-dup) with a pointer note on receive
- reorg every operation to models/{send,reply,events}.tsp (REST-aligned,
  AsyncAPI-named); split state.tsp into per-op events plus
  calling/events/shared.tsp; co-locate every per-op event with its op
- apis.yml: fix relay nav refs (messagingSend, provisioningConfigure,
  queuingRelayTasks; drop invalid tasking/webrtcMessage)
- rebuild all specs

The reorg is output-neutral (relay.yaml byte-identical).
- Removed redundant comments and documentation sections across various models in the Relay Calling API specifications to enhance clarity and reduce clutter.
- Streamlined model definitions by eliminating unnecessary comments related to shared structures and enums.
- Updated event and operation models to focus on essential documentation, improving readability and maintainability.
- Ensured consistency in documentation style across all models, enhancing the overall coherence of the API specifications.
…d new event models

- Added example values for Acknowledgement model in core.tsp.
- Introduced GroupSignalwireConnect and GroupSignalwireDisconnect constants for better organization in connect and disconnect operations.
- Enhanced ConnectRequest and ConnectResult models with additional example values for clarity.
- Updated Version model to reflect the current Relay protocol version and added examples.
- Improved DisconnectParams model with an example for the restart parameter.
- Refined receive and unreceive operations with new group constants and updated documentation.
- Added new event models for AI operations, including CallAiEvent, AiCompletionEvent, and others to support AI functionalities.
- Created new event models for room membership changes and user-defined events in the calling operations.
- Updated CallReceiveParams to make direction and context mandatory.
- Introduced RelayResultBase for base result handling, separating it from RelayResult.
- Updated various operation results (e.g., AiHoldResult, AiMessageResult) to use RelayResultWithCall for consistency.
- Added new events for live transcription and translation, including TranscribeUtteranceEvent and TranslateTranscriptDeltaEvent.
- Enhanced documentation across models and events for better understanding.
- Removed unused fields and clarified existing ones in various models (e.g., CallQueueStatus, DisconnectEvent).
- Adjusted response structures for connect and disconnect operations to reflect changes in event handling.
- Changed channel names from camelCase (e.g., `callingDial`) to dot notation (e.g., `calling.dial`) for consistency and clarity.
- Updated references in tests and serialization to reflect new channel naming convention.
- Modified serialization logic to inline repeated values instead of using YAML anchors/aliases, improving compatibility with OpenAPI/AsyncAPI tooling.
- Introduced new models for request parameters in channel operations, enhancing type safety and clarity in the API specification.
- Adjusted tests to validate the new structure and naming conventions across various scenarios, ensuring comprehensive coverage.
…rvices

- Added summaries for JoinRoomResult, LeaveRoomResult, SendDigitsResult, StreamResult, StreamStopResult, TranscribeResult, and others to improve clarity.
- Updated documentation for SendDigitsRequest and SendDigitsParams to specify DTMF tones more clearly.
- Clarified descriptions in Tap and UserEvent models, including detailed explanations for parameters and results.
- Improved the overall readability of JSON-RPC request and response models, including better descriptions for error handling and event frames.
- Enhanced the provisioning and WebRTC sections with more precise language regarding configuration and signaling.
Devon-White and others added 14 commits July 7, 2026 13:06
…e relay calling, messaging, provisioning, signalwire, tasking, and webrtc specifications. This cleanup enhances code clarity and reduces unnecessary dependencies.
- Added new call event operations for receiving inbound calls and call state changes.
- Updated the API navigation to include new call-related packages.
- Modified existing operations to remove unnecessary event types and streamline responses.
- Removed redundant imports and improved documentation for clarity on event subscriptions.
- Updated documentation for `calling.pass` to enhance clarity.
- Revised summaries and documentation for `calling.pay` operations to provide better context.
- Improved descriptions in `calling.play` operations for better understanding of control IDs.
- Clarified event documentation in `calling.queue` operations to specify event types.
- Enhanced descriptions in `calling.record` and `calling.refer` operations for better user guidance.
- Updated `calling.transcribe` documentation to clarify the flow of transcription results.
- Improved messaging operations documentation for better clarity on message IDs and outcomes.
- Refined `signalwire` operations documentation to enhance understanding of connection and disconnection processes.
- General improvements to documentation across various models to ensure consistency and clarity.
…lifecycle, members, settings, and volume control

- Implemented `call.raisehand` and `call.lowerhand` operations with corresponding parameters.
- Added layout management operations: `call.layout.list` and `call.layout.set`, including request and reply models.
- Introduced lifecycle operations: `call.end` and `call.hangup` with necessary parameters.
- Created member management operations: `call.member.list`, `call.member.remove`, and `call.member.position.set`.
- Developed settings operations for managing video-muted visibility, room locking, low-bitrate mode, denoise settings, and audio flags.
- Added volume control operations for microphone and speaker adjustments.
- Established subscriber online/offline operations for managing subscriber states.
- Implemented ping operations for connection keepalive and reauthentication processes.
- Updated configuration files for client and server to support new operations.
- Updated `MuteParams`, `UnmuteParams`, `DeafParams`, and `UndeafParams` to require `target` field for clarity.
- Enhanced documentation across various models to specify required fields and their usage.
- Added new events in `events/main.tsp` for audio playback, connection progress, recording states, and conversation messaging.
- Improved `send.tsp` models in messaging operations to clarify error handling and validation.
- Introduced separate client and server connection handling in `connect/client.tsp` and `connect/server.tsp`.
- Updated connection parameters to differentiate between client and server authentication methods.
- Enhanced documentation for `reauthenticate` models to clarify usage of project ID and JWT tokens.
- Removed `voice_id` from `RelayBedrockPromptText` and `RelayBedrockPromptPom` models due to backend constraints.
- Changed `result` in `CallCollectParams` from optional to required.
- Updated `digit_timeout` example in `CollectDigits` model to reflect default value.
- Made several fields in `ConferenceParams` required, including `name`, `region`, and `size`.
- Added new fields for call quality metrics in `ConferenceParams`.
- Added minimum value constraints for `max_duration` and `max_price_per_minute` in `ConnectParams`.
- Improved documentation for `DetectMachineParams` and related models.
- Updated `DialParams` to include `dest_swml` and clarified `tag` usage.
- Added `reason` field to `DisconnectParams` for opaque disconnect reasons.
- Enhanced `LiveTranscribeStart` and `LiveTranslateStart` models with additional parameters and constraints.
- Made `translate_data` in `TranslateConversationLogEventData` required.
- Clarified payment error documentation in `CallPayParams`.
- Updated `PayResult` to extend `RelayResult` instead of `RelayResultWithCall`.
- Added WhatsApp message types and parameters to `SendParams` for enhanced messaging capabilities.
- Removed unused `reply.tsp` in `disconnect` operation and cleaned up imports.
- Improved documentation across various models for clarity and completeness.
…operations in the Relay Fabric and WebRTC specifications

- Updated timestamps documentation to specify Unix timestamp format in milliseconds/seconds.
- Clarified descriptions for call leg operations, emphasizing the context of the call leg being operated from.
- Enhanced clarity in error handling and event descriptions, particularly for legacy methods and their compatibility with newer versions.
- Improved consistency in terminology, replacing "epoch" with "Unix timestamp" for better understanding.
- Adjusted examples to provide clearer context and usage scenarios for parameters in various models.
- Refined the descriptions of events and parameters in messaging and provisioning operations for better comprehension.
- Removed the overview page for Relay.
- Added new documentation for client-side authentication, connection lifecycle, errors, events, and an overview.
- Introduced server-side documentation for authentication, connection lifecycle, errors, events, and an overview.
- Updated content to clarify the differences between client and server implementations, including authentication methods and event handling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DOC] - Document Relay APIs

1 participant