From 0507721049ea2bacdf7fbcb4e9e1b0b8e8672bee Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Fri, 13 Feb 2026 14:50:15 +0000 Subject: [PATCH] Fix the Swift translations in the AIT guides Translated using the translate-examples-to-swift skill in the as-yet-unmerged PR #3192. I've reviewed them. --- .../anthropic-message-per-response.mdx | 135 +++++++++++------- .../anthropic-message-per-token.mdx | 74 ++++++---- 2 files changed, 137 insertions(+), 72 deletions(-) diff --git a/src/pages/docs/guides/ai-transport/anthropic-message-per-response.mdx b/src/pages/docs/guides/ai-transport/anthropic-message-per-response.mdx index a02feb98b6..0455c365f3 100644 --- a/src/pages/docs/guides/ai-transport/anthropic-message-per-response.mdx +++ b/src/pages/docs/guides/ai-transport/anthropic-message-per-response.mdx @@ -628,6 +628,14 @@ await channel.subscribe((message) => { console.log('Subscriber ready, waiting for tokens...'); ``` +{/* Swift example test harness +ID: anthropic-message-per-response-1 +To verify: copy this comment into a Swift file, paste the example code into the function body, run `swift build` + +@MainActor +func example_anthropic_message_per_response_1() async throws { + // --- example code starts here --- +*/} ```client_swift import Ably @@ -640,37 +648,48 @@ let channel = realtime.channels.get("ai:{{RANDOM_CHANNEL_NAME}}") // Track responses by message serial var responses: [String: String] = [:] -// Subscribe to receive messages -channel.subscribe { message in - guard let serial = message.serial else { return } - - switch message.action { - case .create: - // New response started - print("\n[Response started] \(serial)") - responses[serial] = message.data as? String ?? "" - - case .messageAppend: - // Append token to existing response - let current = responses[serial] ?? "" - let token = message.data as? String ?? "" - responses[serial] = current + token - - // Display token as it arrives - print(token, terminator: "") - - case .update: - // Replace entire response content - responses[serial] = message.data as? String ?? "" - print("\n[Response updated with full content]") - - default: - break - } +// Subscribe to receive messages and wait for the channel to attach +try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + channel.subscribe(attachCallback: { error in + if let error { + continuation.resume(throwing: error) + } else { + continuation.resume() + } + }, callback: { message in + MainActor.assumeIsolated { + guard let serial = message.serial else { return } + guard let data = message.data as? String else { return } + + switch message.action { + case .create: + // New response started + print("\n[Response started] \(serial)") + responses[serial] = data + + case .append: + // Append token to existing response + let current = responses[serial] ?? "" + responses[serial] = current + data + + // Display token as it arrives + print(data, terminator: "") + + case .update: + // Replace entire response content + responses[serial] = data + print("\n[Response updated with full content]") + + default: + break + } + } + }) } print("Subscriber ready, waiting for tokens...") ``` +{/* --- end example code --- */} ```client_java import io.ably.lib.realtime.AblyRealtime; @@ -909,6 +928,14 @@ await channel.subscribe((message) => { }); ``` +{/* Swift example test harness +ID: anthropic-message-per-response-2 +To verify: copy this comment into a Swift file, paste the example code into the function body, run `swift build` + +@MainActor +func example_anthropic_message_per_response_2(realtime: ARTRealtime) async throws { + // --- example code starts here --- +*/} ```client_swift // Use rewind to receive recent historical messages let channelOptions = ARTRealtimeChannelOptions() @@ -918,29 +945,41 @@ let channel = realtime.channels.get("ai:{{RANDOM_CHANNEL_NAME}}", options: chann var responses: [String: String] = [:] -channel.subscribe { message in - guard let serial = message.serial else { return } - - switch message.action { - case .create: - responses[serial] = message.data as? String ?? "" - - case .messageAppend: - let current = responses[serial] ?? "" - let token = message.data as? String ?? "" - responses[serial] = current + token - print(token, terminator: "") - - case .update: - // Historical messages contain full concatenated response - responses[serial] = message.data as? String ?? "" - print("\n[Historical response]: \(responses[serial] ?? "")") - - default: - break - } +// Subscribe and wait for the channel to attach +try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + channel.subscribe(attachCallback: { error in + if let error { + continuation.resume(throwing: error) + } else { + continuation.resume() + } + }, callback: { message in + MainActor.assumeIsolated { + guard let serial = message.serial else { return } + guard let data = message.data as? String else { return } + + switch message.action { + case .create: + responses[serial] = data + + case .append: + let current = responses[serial] ?? "" + responses[serial] = current + data + print(data, terminator: "") + + case .update: + // Historical messages contain full concatenated response + responses[serial] = data + print("\n[Historical response]: \(responses[serial] ?? "")") + + default: + break + } + } + }) } ``` +{/* --- end example code --- */} ```client_java import io.ably.lib.realtime.AblyRealtime; diff --git a/src/pages/docs/guides/ai-transport/anthropic-message-per-token.mdx b/src/pages/docs/guides/ai-transport/anthropic-message-per-token.mdx index 73236cd591..0750cfccc5 100644 --- a/src/pages/docs/guides/ai-transport/anthropic-message-per-token.mdx +++ b/src/pages/docs/guides/ai-transport/anthropic-message-per-token.mdx @@ -613,6 +613,14 @@ await channel.subscribe('stop', (message) => { console.log('Subscriber ready, waiting for tokens...'); ``` +{/* Swift example test harness +ID: anthropic-message-per-token-1 +To verify: copy this comment into a Swift file, paste the example code into the function body, run `swift build` + +@MainActor +func example_anthropic_message_per_token_1() async throws { + // --- example code starts here --- +*/} ```client_swift import Ably @@ -625,34 +633,52 @@ let channel = realtime.channels.get("{{RANDOM_CHANNEL_NAME}}") // Track responses by ID var responses: [String: String] = [:] -// Handle response start -channel.subscribe("start") { message in - guard let responseId = message.extras?.headers?["responseId"] as? String else { return } - print("\n[Response started] \(responseId)") - responses[responseId] = "" -} - -// Handle tokens -channel.subscribe("token") { message in - guard let responseId = message.extras?.headers?["responseId"] as? String, - let token = message.data as? String else { return } - - // Append token to response - responses[responseId, default: ""] += token - - // Display token as it arrives - print(token, terminator: "") -} - -// Handle response stop -channel.subscribe("stop") { message in - guard let responseId = message.extras?.headers?["responseId"] as? String else { return } - let finalText = responses[responseId] ?? "" - print("\n[Response completed] \(responseId)") +// Subscribe to all events and handle by message name +try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + channel.subscribe(attachCallback: { error in + if let error { + continuation.resume(throwing: error) + } else { + continuation.resume() + } + }) { message in + MainActor.assumeIsolated { + guard let extras = (try? message.extras?.toJSON()) as? [String: Any], + let headers = extras["headers"] as? [String: Any], + let responseID = headers["responseId"] as? String else { return } + + switch message.name { + case "start": + // Handle response start + print("\n[Response started] \(responseID)") + responses[responseID] = "" + + case "token": + // Handle tokens + guard let token = message.data as? String else { return } + + // Append token to response + let currentText = responses[responseID] ?? "" + responses[responseID] = currentText + token + + // Display token as it arrives + print(token, terminator: "") + + case "stop": + // Handle response stop + let finalText = responses[responseID] + print("\n[Response completed] \(responseID)") + + default: + break + } + } + } } print("Subscriber ready, waiting for tokens...") ``` +{/* --- end example code --- */} ```client_java import io.ably.lib.realtime.AblyRealtime;