Files
firebase-ios-sdk/GeminiLanguageModel/Tests/GeminiLanguageModelTests/GeminiTranscriptTranslatorTests.swift
T
Andrew Heard c276eca72a refactor(ai): gate GLM Entry.data on Swift 6.4.2 (#16910)
Replace `#if canImport(FoundationModels, _version: 2.1)` with
`#if compiler(>=6.4.2)` around the `Transcript.Entry.data` case in
`GeminiTranscriptTranslator` and its test. Xcode 27.2 beta 3 bumped the
Swift compiler to 6.4.2, so the condition no longer depends on the
underscored `_version` parameter of `canImport`.

Earlier Xcode 27.2 betas report Swift 6.4 and skip the case, which is
acceptable since beta 3 supersedes them.
2026-10-14 22:34:59 -04:00

734 lines
26 KiB
Swift

// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(FoundationModels) && compiler(>=6.4)
import Foundation
import FoundationModels
import GeminiAPIDataModels
import GeminiTestUtilities
import Testing
import UniformTypeIdentifiers
@testable import GeminiLanguageModel
@Suite("GeminiTranscriptTranslator Tests", .requireFoundationModels)
struct GeminiTranscriptTranslatorTests {
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesInstructionsAndPrompt() throws {
let transcript = Transcript(
entries: [
.instructions(
Transcript.Instructions(
segments: [.text(Transcript.TextSegment(content: "You are a helpful assistant."))],
toolDefinitions: []
)
),
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Hello!"))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
let systemInstruction = try #require(result.systemInstruction)
#expect(
systemInstruction.parts?.first?.data == .text("You are a helpful assistant."))
#expect(result.contents.count == 1)
#expect(result.contents.first?.role == "user")
#expect(result.contents.first?.parts?.first?.data == .text("Hello!"))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func coalescesReasoningAndResponseIntoSingleModelTurn() throws {
let signatureData = Data("test-sig".utf8)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Explain 2+2."))]
)
),
.reasoning(
Transcript.Reasoning(
segments: [.text(Transcript.TextSegment(content: "Thinking about addition..."))],
signature: signatureData
)
),
.response(
Transcript.Response(
segments: [.text(Transcript.TextSegment(content: "2+2 is 4."))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 2)
#expect(result.contents[0].role == "user")
#expect(result.contents[1].role == "model")
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 2)
#expect(modelParts[0].thought == true)
#expect(modelParts[0].thoughtSignature == "test-sig")
#expect(modelParts[0].data == .text("Thinking about addition..."))
#expect(modelParts[1].data == .text("2+2 is 4."))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func attachesSignatureOnlyReasoningToFollowingResponsePart() throws {
let signatureData = Data("sig-only".utf8)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Hi."))]
)
),
.reasoning(
Transcript.Reasoning(
segments: [],
signature: signatureData
)
),
.response(
Transcript.Response(
segments: [.text(Transcript.TextSegment(content: "Hello!"))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 2)
#expect(result.contents[1].role == "model")
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 1)
#expect(modelParts[0].data == .text("Hello!"))
#expect(modelParts[0].thoughtSignature == "sig-only")
#expect(modelParts[0].thought == nil)
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func attachesTrailingSignatureOnlyReasoningToPrecedingResponsePart() throws {
let signatureData = Data("trailing-sig".utf8)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Weather in Seattle?"))]
)
),
.response(
Transcript.Response(
segments: [.text(Transcript.TextSegment(content: "It is 22°C and sunny."))]
)
),
.reasoning(
Transcript.Reasoning(
segments: [],
signature: signatureData
)
),
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "What about Miami?"))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 3)
#expect(result.contents[1].role == "model")
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 1)
#expect(modelParts[0].data == .text("It is 22°C and sunny."))
#expect(modelParts[0].thoughtSignature == "trailing-sig")
#expect(modelParts[0].thought == nil)
#expect(result.contents[2].role == "user")
#expect(result.contents[2].parts?.first?.data == .text("What about Miami?"))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func sequentialToolCallTurnsNeverEmitPartsWithoutData() throws {
let callSignature = Data("call-sig".utf8)
let responseSignature = Data("response-sig".utf8)
let args = try GeneratedContent(json: "{\"city\":\"Seattle\"}")
let toolCall = Transcript.ToolCall(id: "call-1", toolName: "getWeather", arguments: args)
let toolOutput = Transcript.ToolOutput(
id: "call-1",
toolName: "getWeather",
segments: [.text(Transcript.TextSegment(content: "22°C and sunny"))]
)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Weather in Seattle?"))]
)
),
.reasoning(Transcript.Reasoning(segments: [], signature: callSignature)),
.toolCalls(Transcript.ToolCalls(id: "calls-1", [toolCall])),
.toolOutput(toolOutput),
.response(
Transcript.Response(
segments: [.text(Transcript.TextSegment(content: "It is 22°C and sunny."))]
)
),
.reasoning(Transcript.Reasoning(segments: [], signature: responseSignature)),
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "What about Miami?"))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 5)
#expect(result.contents.map(\.role) == ["user", "model", "user", "model", "user"])
let allPartsHaveData = result.contents.allSatisfy { content in
content.parts?.allSatisfy { $0.data != nil } ?? true
}
#expect(allPartsHaveData)
let callParts = try #require(result.contents[1].parts)
#expect(callParts.count == 1)
guard case .functionCall(let functionCall) = callParts[0].data else {
Issue.record("Expected functionCall part data")
return
}
#expect(functionCall.name == "getWeather")
#expect(callParts[0].thoughtSignature == "call-sig")
let outputParts = try #require(result.contents[2].parts)
#expect(outputParts.count == 1)
guard case .functionResponse = outputParts[0].data else {
Issue.record("Expected functionResponse part data")
return
}
let responseParts = try #require(result.contents[3].parts)
#expect(responseParts.count == 1)
#expect(responseParts[0].data == .text("It is 22°C and sunny."))
#expect(responseParts[0].thoughtSignature == "response-sig")
#expect(responseParts[0].thought == nil)
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func trailingSignatureFallsBackToEmptyThoughtPartWhenLastPartIsSigned() throws {
let firstSignature = Data("sig-a".utf8)
let secondSignature = Data("sig-b".utf8)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Hi."))]
)
),
.reasoning(Transcript.Reasoning(segments: [], signature: firstSignature)),
.response(
Transcript.Response(
segments: [.text(Transcript.TextSegment(content: "Hello!"))]
)
),
.reasoning(Transcript.Reasoning(segments: [], signature: secondSignature)),
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Again?"))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 3)
#expect(result.contents[1].role == "model")
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 2)
#expect(modelParts[0].data == .text("Hello!"))
#expect(modelParts[0].thoughtSignature == "sig-a")
#expect(modelParts[1].data == .text(""))
#expect(modelParts[1].thought == true)
#expect(modelParts[1].thoughtSignature == "sig-b")
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func signatureOnlyReasoningWithoutModelPartEmitsEmptyThoughtPart() throws {
let signatureData = Data("orphan-sig".utf8)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Hi."))]
)
),
.reasoning(
Transcript.Reasoning(
segments: [],
signature: signatureData
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 2)
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 1)
#expect(modelParts[0].thought == true)
#expect(modelParts[0].thoughtSignature == "orphan-sig")
#expect(modelParts[0].data == .text(""))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesMultipleInstructionsEntriesIntoMultipleParts() throws {
let transcript = Transcript(
entries: [
.instructions(
Transcript.Instructions(
segments: [.text(Transcript.TextSegment(content: "First instruction."))],
toolDefinitions: []
)
),
.instructions(
Transcript.Instructions(
segments: [.text(Transcript.TextSegment(content: "Second instruction."))],
toolDefinitions: []
)
),
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Hello!"))]
)
),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
let systemInstruction = try #require(result.systemInstruction)
let parts = try #require(systemInstruction.parts)
#expect(parts.count == 2)
#expect(parts[0].data == .text("First instruction."))
#expect(parts[1].data == .text("Second instruction."))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolCallsIntoModelTurn() throws {
let args = try GeneratedContent(json: "{\"location\":\"Paris\"}")
let toolCall = Transcript.ToolCall(
id: "call-1",
toolName: "get_weather",
arguments: args
)
let transcript = Transcript(
entries: [
.prompt(
Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Weather?"))]
)
),
.toolCalls(Transcript.ToolCalls(id: "calls-1", [toolCall])),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 2)
#expect(result.contents[0].role == "user")
#expect(result.contents[1].role == "model")
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 1)
guard case .functionCall(let functionCall) = modelParts[0].data else {
Issue.record("Expected functionCall part data")
return
}
#expect(functionCall.id == "call-1")
#expect(functionCall.name == "get_weather")
#expect(functionCall.args?["location"] == .string("Paris"))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolOutputWithTextSegmentWrappingUnderResult() throws {
let toolOutput = Transcript.ToolOutput(
id: "call-1",
toolName: "get_weather",
segments: [.text(Transcript.TextSegment(content: "Sunny, 22°C"))]
)
let transcript = Transcript(entries: [.toolOutput(toolOutput)])
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 1)
#expect(result.contents[0].role == "user")
let userParts = try #require(result.contents[0].parts)
#expect(userParts.count == 1)
guard case .functionResponse(let functionResponse) = userParts[0].data else {
Issue.record("Expected functionResponse part data")
return
}
#expect(functionResponse.id == "call-1")
#expect(functionResponse.name == "get_weather")
#expect(functionResponse.response?["result"] == .string("Sunny, 22°C"))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolOutputWithJSONTextPreservingStringUnderResult() throws {
let jsonString = "{\"temperature\":22,\"condition\":\"sunny\"}"
let toolOutput = Transcript.ToolOutput(
id: "call-1",
toolName: "get_weather",
segments: [
.text(Transcript.TextSegment(content: jsonString))
]
)
let transcript = Transcript(entries: [.toolOutput(toolOutput)])
let result = try GeminiTranscriptTranslator.translate(transcript)
let userParts = try #require(result.contents.first?.parts)
guard case .functionResponse(let functionResponse) = userParts.first?.data else {
Issue.record("Expected functionResponse part data")
return
}
#expect(functionResponse.id == "call-1")
#expect(functionResponse.name == "get_weather")
#expect(functionResponse.response?["result"] == .string(jsonString))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolOutputWithStructuredSegmentUnpackingDirectly() throws {
let content = try GeneratedContent(json: "{\"temperature\":22}")
let structuredSegment = Transcript.StructuredSegment(
id: "seg-1",
schemaName: "Weather",
content: content
)
let toolOutput = Transcript.ToolOutput(
id: "call-1",
toolName: "get_weather",
segments: [.structure(structuredSegment)]
)
let transcript = Transcript(entries: [.toolOutput(toolOutput)])
let result = try GeminiTranscriptTranslator.translate(transcript)
let userParts = try #require(result.contents.first?.parts)
guard case .functionResponse(let functionResponse) = userParts.first?.data else {
Issue.record("Expected functionResponse part data")
return
}
#expect(functionResponse.id == "call-1")
#expect(functionResponse.name == "get_weather")
#expect(functionResponse.response?["temperature"] == .number(22))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func coalescesParallelToolCallsAndOutputs() throws {
let call1 = Transcript.ToolCall(
id: "call-1",
toolName: "get_weather",
arguments: try GeneratedContent(json: "{\"location\":\"Paris\"}")
)
let call2 = Transcript.ToolCall(
id: "call-2",
toolName: "get_time",
arguments: try GeneratedContent(json: "{\"location\":\"Tokyo\"}")
)
let output1 = Transcript.ToolOutput(
id: "call-1",
toolName: "get_weather",
segments: [.text(Transcript.TextSegment(content: "22°C"))]
)
let output2 = Transcript.ToolOutput(
id: "call-2",
toolName: "get_time",
segments: [.text(Transcript.TextSegment(content: "15:00"))]
)
let transcript = Transcript(
entries: [
.toolCalls(Transcript.ToolCalls(id: "calls-1", [call1, call2])),
.toolOutput(output1),
.toolOutput(output2),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 2)
#expect(result.contents[0].role == "model")
let modelParts = try #require(result.contents[0].parts)
#expect(modelParts.count == 2)
guard case .functionCall(let fc1) = modelParts[0].data,
case .functionCall(let fc2) = modelParts[1].data
else {
Issue.record("Expected two functionCall parts")
return
}
#expect(fc1.id == "call-1")
#expect(fc2.id == "call-2")
#expect(result.contents[1].role == "user")
let userParts = try #require(result.contents[1].parts)
#expect(userParts.count == 2)
guard case .functionResponse(let fr1) = userParts[0].data,
case .functionResponse(let fr2) = userParts[1].data
else {
Issue.record("Expected two functionResponse parts in single user turn")
return
}
#expect(fr1.id == "call-1")
#expect(fr2.id == "call-2")
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolCallsWithEmptyArguments() throws {
let call = Transcript.ToolCall(
id: "call-1",
toolName: "get_time",
arguments: try GeneratedContent(json: "{}")
)
let transcript = Transcript(
entries: [.toolCalls(Transcript.ToolCalls(id: "calls-1", [call]))]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
let modelParts = try #require(result.contents.first?.parts)
#expect(modelParts.count == 1)
guard case .functionCall(let functionCall) = modelParts[0].data else {
Issue.record("Expected functionCall part")
return
}
#expect(functionCall.id == "call-1")
#expect(functionCall.name == "get_time")
#expect(functionCall.args == nil)
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func coalescesReasoningAndToolCallsIntoSingleModelTurn() throws {
let signatureData = Data("test-sig".utf8)
let call = Transcript.ToolCall(
id: "call-1",
toolName: "get_weather",
arguments: try GeneratedContent(json: "{\"location\":\"Paris\"}")
)
let transcript = Transcript(
entries: [
.prompt(Transcript.Prompt(segments: [.text(Transcript.TextSegment(content: "Hi."))])),
.reasoning(
Transcript.Reasoning(
segments: [.text(Transcript.TextSegment(content: "Need to check weather."))],
signature: signatureData
)
),
.toolCalls(Transcript.ToolCalls(id: "calls-1", [call])),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
#expect(result.contents.count == 2)
#expect(result.contents[0].role == "user")
#expect(result.contents[1].role == "model")
let modelParts = try #require(result.contents[1].parts)
#expect(modelParts.count == 2)
#expect(modelParts[0].thought == true)
#expect(modelParts[0].thoughtSignature == nil)
#expect(modelParts[0].data == .text("Need to check weather."))
#expect(modelParts[1].thoughtSignature == "test-sig")
guard case .functionCall(let functionCall) = modelParts[1].data else {
Issue.record("Expected functionCall part")
return
}
#expect(functionCall.id == "call-1")
#expect(functionCall.name == "get_weather")
}
@Generable
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
@available(tvOS, unavailable)
struct City {
var name: String
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func instructionsWithToolDefinitionsTranslatesCleanly() throws {
let toolDefinition = Transcript.ToolDefinition(
name: "get_weather",
description: "Get weather",
parameters: City.generationSchema
)
let transcript = Transcript(
entries: [
.instructions(
Transcript.Instructions(
segments: [.text(Transcript.TextSegment(content: "Be concise."))],
toolDefinitions: [toolDefinition]
)
),
.prompt(Transcript.Prompt(segments: [.text(Transcript.TextSegment(content: "Hello"))])),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
let systemInstruction = try #require(result.systemInstruction)
#expect(systemInstruction.parts?.first?.data == Part.PartData.text("Be concise."))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolOutputWithMultipleSegmentsIntoMultipleParts() throws {
let toolOutput = Transcript.ToolOutput(
id: "call-1",
toolName: "get_weather",
segments: [
.text(Transcript.TextSegment(content: "Part 1")),
.text(Transcript.TextSegment(content: "Part 2")),
]
)
let transcript = Transcript(entries: [.toolOutput(toolOutput)])
let result = try GeminiTranscriptTranslator.translate(transcript)
let userParts = try #require(result.contents.first?.parts)
#expect(userParts.count == 2)
guard case .functionResponse(let fr1) = userParts[0].data,
case .functionResponse(let fr2) = userParts[1].data
else {
Issue.record("Expected functionResponse part data for both segments")
return
}
#expect(fr1.id == "call-1")
#expect(fr1.name == "get_weather")
#expect(fr1.response?["result"] == .string("Part 1"))
#expect(fr2.id == "call-1")
#expect(fr2.name == "get_weather")
#expect(fr2.response?["result"] == .string("Part 2"))
}
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func translatesToolOutputWithAttachmentThrowsUnsupportedTranscriptContent() throws {
let imageAttachment = Transcript.ImageAttachment(
imageURL: URL(fileURLWithPath: "/tmp/test.png")
)
let attachment = Transcript.Segment.attachment(
Transcript.AttachmentSegment(
id: "att-1",
content: .image(imageAttachment)
)
)
let toolOutput = Transcript.ToolOutput(
id: "call-1",
toolName: "get_weather",
segments: [
.text(Transcript.TextSegment(content: "Here is the image:")),
attachment,
]
)
let transcript = Transcript(entries: [.toolOutput(toolOutput)])
do {
_ = try GeminiTranscriptTranslator.translate(transcript)
Issue.record("Expected unsupportedTranscriptContent error")
} catch LanguageModelError.unsupportedTranscriptContent {
// Expected
} catch {
Issue.record("Unexpected error thrown: \(error)")
}
}
// `Transcript.Entry.data` was added in Xcode 27.2 (Swift 6.4.2+).
#if compiler(>=6.4.2)
@Test
@available(macOS 27.2, iOS 27.2, watchOS 27.2, visionOS 27.2, *)
@available(tvOS, unavailable)
func translatesDataEntryThrowsUnsupportedTranscriptContent() throws {
let dataEntry = Transcript.DataEntry(
id: "data-1",
contentType: .json,
content: Data(#"{"key":"value"}"#.utf8)
)
let transcript = Transcript(entries: [.data(dataEntry)])
do {
_ = try GeminiTranscriptTranslator.translate(transcript)
Issue.record("Expected unsupportedTranscriptContent error")
} catch LanguageModelError.unsupportedTranscriptContent(let context) {
#expect(context.unsupportedContent == [.data(dataEntry)])
} catch {
Issue.record("Unexpected error thrown: \(error)")
}
}
#endif // compiler(>=6.4.2)
@Test
@available(macOS 27.0, iOS 27.0, watchOS 27.0, visionOS 27.0, *)
func emptyToolCallsDoesNotDropPendingReasoningSignature() throws {
let signatureData = Data("test-sig".utf8)
let prompt = Transcript.Prompt(
segments: [.text(Transcript.TextSegment(content: "Hi"))]
)
let reasoning = Transcript.Reasoning(
segments: [.text(Transcript.TextSegment(content: "Thinking..."))],
signature: signatureData
)
let emptyToolCalls = Transcript.ToolCalls(id: "calls-empty", [])
let finalResponse = Transcript.Response(
segments: [.text(Transcript.TextSegment(content: "Hello!"))]
)
let transcript = Transcript(
entries: [
.prompt(prompt),
.reasoning(reasoning),
.toolCalls(emptyToolCalls),
.response(finalResponse),
]
)
let result = try GeminiTranscriptTranslator.translate(transcript)
let modelTurn = try #require(result.contents.last)
let modelParts = try #require(modelTurn.parts)
#expect(modelParts.first?.thoughtSignature == "test-sig")
}
}
#endif // canImport(FoundationModels) && compiler(>=6.4)