Skip to content

Commit a615793

Browse files
mattappersonclaude
andcommitted
feat: add anthropic-reasoning example with Claude-style messages
Demonstrates multi-turn conversations using: - ClaudeMessageParam type for Claude-style message format - fromClaudeMessages() to convert to OpenResponses input format - toClaudeMessage() to convert responses back to Claude format 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 01dd269 commit a615793

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3+
*/
4+
5+
import dotenv from "dotenv";
6+
7+
dotenv.config();
8+
9+
/**
10+
* Example demonstrating multi-turn conversations using Claude-style messages
11+
* with the anthropic-compat helper functions.
12+
*
13+
* This example shows how to:
14+
* 1. Use Claude-style message format (ClaudeMessageParam)
15+
* 2. Convert between Claude format and OpenResponses format
16+
* 3. Build a 3-turn conversation carrying message history forward
17+
*
18+
* To run this example from the examples directory with Bun:
19+
* bun run anthropic-reasoning.example.ts
20+
*/
21+
22+
import type { ClaudeMessageParam } from "../src/models/claude-message.js";
23+
import {
24+
OpenRouter,
25+
fromClaudeMessages,
26+
toClaudeMessage,
27+
} from "../src/index.js";
28+
29+
if (!process.env["OPENROUTER_API_KEY"]) {
30+
throw new Error("Missing OPENROUTER_API_KEY environment variable");
31+
}
32+
33+
const openRouter = new OpenRouter({
34+
apiKey: process.env["OPENROUTER_API_KEY"] ?? "",
35+
});
36+
37+
async function multiTurnClaudeConversation() {
38+
const model = "anthropic/claude-sonnet-4";
39+
40+
// Initialize message history with Claude-style message format
41+
const messages: ClaudeMessageParam[] = [
42+
{
43+
role: "user",
44+
content: "What are the key differences between functional and object-oriented programming?",
45+
},
46+
];
47+
48+
console.log("=== Turn 1 ===");
49+
console.log("User:", messages[0].content);
50+
console.log();
51+
52+
// First turn - convert Claude messages to OpenResponses format
53+
const result1 = await openRouter.callModel({
54+
model,
55+
input: fromClaudeMessages(messages),
56+
});
57+
58+
// Get the response and convert back to Claude format
59+
const response1 = await result1.getResponse();
60+
const claudeMessage1 = toClaudeMessage(response1);
61+
62+
// Extract text content from Claude message
63+
const content1 = extractTextContent(claudeMessage1.content);
64+
console.log("Assistant:", content1);
65+
console.log();
66+
67+
// Add assistant response to history (as Claude-style message)
68+
messages.push({
69+
role: "assistant",
70+
content: content1,
71+
});
72+
73+
// Add next user message
74+
messages.push({
75+
role: "user",
76+
content: "Can you show me an example of how the same problem would be solved differently in each paradigm?",
77+
});
78+
79+
console.log("=== Turn 2 ===");
80+
console.log("User:", messages[messages.length - 1].content);
81+
console.log();
82+
83+
// Second turn
84+
const result2 = await openRouter.callModel({
85+
model,
86+
input: fromClaudeMessages(messages),
87+
});
88+
89+
const response2 = await result2.getResponse();
90+
const claudeMessage2 = toClaudeMessage(response2);
91+
const content2 = extractTextContent(claudeMessage2.content);
92+
console.log("Assistant:", content2);
93+
console.log();
94+
95+
// Add to history
96+
messages.push({
97+
role: "assistant",
98+
content: content2,
99+
});
100+
101+
messages.push({
102+
role: "user",
103+
content: "Which paradigm would you recommend for building a large-scale web application and why?",
104+
});
105+
106+
console.log("=== Turn 3 ===");
107+
console.log("User:", messages[messages.length - 1].content);
108+
console.log();
109+
110+
// Third turn
111+
const result3 = await openRouter.callModel({
112+
model,
113+
input: fromClaudeMessages(messages),
114+
});
115+
116+
const response3 = await result3.getResponse();
117+
const claudeMessage3 = toClaudeMessage(response3);
118+
const content3 = extractTextContent(claudeMessage3.content);
119+
console.log("Assistant:", content3);
120+
console.log();
121+
122+
// Final message history
123+
messages.push({
124+
role: "assistant",
125+
content: content3,
126+
});
127+
128+
console.log("=== Conversation Complete ===");
129+
console.log(`Total messages in history: ${messages.length}`);
130+
131+
// Show the final Claude message structure
132+
console.log("\n=== Final Claude Message Structure ===");
133+
console.log("Stop reason:", claudeMessage3.stop_reason);
134+
console.log("Model:", claudeMessage3.model);
135+
console.log("Usage:", claudeMessage3.usage);
136+
}
137+
138+
/**
139+
* Helper to extract text content from Claude message content blocks
140+
*/
141+
function extractTextContent(
142+
content: Array<{ type: string; text?: string }>
143+
): string {
144+
return content
145+
.filter((block) => block.type === "text" && block.text)
146+
.map((block) => block.text)
147+
.join("");
148+
}
149+
150+
async function main() {
151+
try {
152+
await multiTurnClaudeConversation();
153+
} catch (error) {
154+
console.error("Error:", error);
155+
}
156+
}
157+
158+
main();

0 commit comments

Comments
 (0)