Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions bindings/typescript/tests/two-step-conversion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Two-step conversion test: Responses API format -> Lingua Messages -> Thread
*
* This test demonstrates the full conversion pipeline:
* 1. Import messages from spans (Responses API format -> Lingua Messages)
* 2. Thread preprocessor extracts and filters messages
*/

import { describe, test, expect } from "vitest";
import { importMessagesFromSpans } from "../src/index";

/* eslint-disable @typescript-eslint/no-explicit-any */

describe("Two-step conversion: Responses API to Thread", () => {
test("should extract messages from Responses API output format", () => {
// Your actual trace data - focusing on the output field
const outputFromTrace = [
{
id: "rs_0c7105cd8354f2660069824fe9039081938557c4fcb69a4d1a",
summary: [],
type: "reasoning",
},
{
content: [
{
annotations: [],
logprobs: [],
text: "I consulted the magic 8-ball for you (I will not reveal its exact words). Its guidance leans positively — so take this as a hopeful, mystical nudge toward yes.",
type: "output_text",
},
],
id: "msg_0c7105cd8354f2660069824fef675481938a1fde9d9e5917b9",
role: "assistant",
status: "completed",
type: "message",
},
];

// Step 1: Try importing from just the output field
console.log("\n=== Testing Output Field Conversion ===");
const messagesFromOutput = importMessagesFromSpans([
{ output: outputFromTrace },
]);
console.log(
"Messages from output:",
JSON.stringify(messagesFromOutput, null, 2)
);

// Check if assistant message was extracted
const assistantMessages = messagesFromOutput.filter(
(m: any) => m.role === "assistant"
);
console.log(`Found ${assistantMessages.length} assistant message(s)`);

if (assistantMessages.length > 0) {
// Find the message with actual text content (not reasoning)
const messageWithText = assistantMessages.find((m: any) => {
const content = JSON.stringify(m.content);
return content.includes("magic 8-ball");
});

if (messageWithText) {
console.log("✅ Found assistant message with magic 8-ball content");
expect(messageWithText).toBeDefined();
} else {
console.log("❌ No assistant message contains 'magic 8-ball'");
expect(messageWithText).toBeDefined();
}
} else {
console.log("❌ No assistant messages found from output field!");
expect(assistantMessages.length).toBeGreaterThan(0);

Check failure on line 71 in bindings/typescript/tests/two-step-conversion.test.ts

View workflow job for this annotation

GitHub Actions / test-typescript

tests/two-step-conversion.test.ts > Two-step conversion: Responses API to Thread > should extract messages from Responses API output format

AssertionError: expected 0 to be greater than 0 ❯ tests/two-step-conversion.test.ts:71:40
}
});
});
13 changes: 13 additions & 0 deletions crates/lingua/src/processing/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ fn try_converting_to_messages(data: &Value) -> Vec<Message> {
}
}

// Try Responses API output format
if let Ok(provider_messages) =
serde_json::from_value::<Vec<openai::OutputItem>>(data_to_parse.clone())
{
if let Ok(messages) =
<Vec<Message> as TryFromLLM<Vec<openai::OutputItem>>>::try_from(provider_messages)
{
if !messages.is_empty() {
return messages;
}
}
}

// Try Anthropic format
if let Ok(provider_messages) =
serde_json::from_value::<Vec<anthropic::InputMessage>>(data_to_parse.clone())
Expand Down
Loading