Skip to content
Merged
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
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## 1.0.0

### Breaking Changes

- **Vercel AI SDK v5 support** - This version requires `@ai-sdk/provider` v2.0.0 and `@ai-sdk/provider-utils` v3.0.1
- Previous versions of Vercel AI SDK (v4) are no longer supported
- Updated `ai` dev dependency to v5.0.0

### Changes

- Refactored `langtail-language-model.ts` for AI SDK v5 compatibility
- Updated `convert-to-openai-chat-messages.ts` for new message format
- Updated `map-langtail-finish-reason.ts` for v5 finish reasons
- Updated `openai-prepare-tools.ts` for v5 tool format
- Removed deprecated `map-openai-chat-logprobs.ts`
- Added comprehensive test coverage for language model and message conversion

## 0.16.8

- Add GoogleGeminiV1 to ReasoningFormat and update related tests
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "langtail",
"version": "0.16.8",
"version": "1.0.0",
"description": "",
"main": "./Langtail.js",
"packageManager": "pnpm@8.15.6",
Expand Down Expand Up @@ -35,8 +35,9 @@
],
"license": "MIT",
"devDependencies": {
"@openrouter/ai-sdk-provider": "^1.2.7",
"@types/node": "^20.12.11",
"ai": "^4.3.3",
"ai": "^5.0.0",
"copyfiles": "^2.4.1",
"fs-extra": "^11.2.0",
"jsdom": "^24.1.0",
Expand Down Expand Up @@ -91,16 +92,16 @@
}
},
"dependencies": {
"@ai-sdk/provider": "^1.1.1",
"@ai-sdk/provider-utils": "^2.2.5",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.1",
"@langtail/handlebars-evalless": "^0.1.2",
"commander": "^12.1.0",
"date-fns": "^3.6.0",
"dotenv-flow": "^4.1.0",
"json-schema-to-zod": "^2.1.0",
"openai": "4.82.0",
"query-string": "^7.1.3",
"zod": "^3.23.8"
"zod": "^3.25.76"
},
"tsup": {
"dts": true,
Expand Down
41 changes: 41 additions & 0 deletions playground/openrouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import "dotenv-flow/config"
import { stepCountIs, streamText, tool } from "ai"
import { z } from "zod/v4"

import { openrouter } from "@openrouter/ai-sdk-provider"

async function main() {
const result = streamText({
model: openrouter("google/gemini-3-pro-preview"),
messages: [
{
role: "user",
content: "What is the weather in Tokyo?",
},
],
stopWhen: stepCountIs(5),
onStepFinish: (step) => {
console.log(step.content)
},
tools: {
weather: tool({
description: "Get the weather in a location",
inputSchema: z.object({
location: z.string().describe("The location to get the weather for"),
}),
execute: async ({ location }) => {
return {
location,
temperature: 12,
}
},
}),
},
})

for await (const chunk of result.fullStream) {
console.log("chunk", chunk)
}
}

main()
99 changes: 35 additions & 64 deletions playground/vercel.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,57 @@
import 'dotenv-flow/config'
import { generateText, tool, streamText } from 'ai';
import { langtail } from '../src/vercel-ai';
import fs from 'fs/promises';
import { z } from 'zod';

import "dotenv-flow/config"
import { stepCountIs, streamText, tool } from "ai"
import { langtail } from "../src/vercel-ai"
import { z } from "zod/v4"

async function main() {
const content = await fs.readFile('./playground/text.txt', 'utf-8');

const { text, reasoning } = await generateText({
model: langtail('vtip'),
const result = streamText({
model: langtail("vtip"),
messages: [
{
role: 'user',
role: "user",
content: "What is the weather in Tokyo?",
},
],
stopWhen: stepCountIs(5),
onStepFinish: (step) => {
console.log(step.content)
},
tools: {
weather: tool({
description: 'Get the weather in a location',
parameters: z.object({
location: z.string().describe('The location to get the weather for'),
description: "Get the weather in a location",
inputSchema: z.object({
location: z.string().describe("The location to get the weather for"),
}),
execute: async ({ location }) => {
async execute({ location }) {
return {
location,
temperature: 12,
type: "image",
data: "https://stickerapp.co.uk/cdn-assets/images/stickers/608t.png",
}
},
}),
},
});

const { text: text2, reasoning: reasoning2 } = await generateText({
model: langtail('vtip'),
providerOptions: {
anthropic: {
thinking: {
budgetTokens: 1025,
type: "enabled",
}
}
},
messages: [
{
role: 'user',
content: "What is the weather in Tokyo?",
},
{
role: 'assistant',
content: text,
},
{
role: 'user',
content: "What is the weather in Prague?",
},
],
tools: {
weather: tool({
description: 'Get the weather in a location',
parameters: z.object({
location: z.string().describe('The location to get the weather for'),
}),
execute: async ({ location }) => {
// map to tool result content for LLM consumption:
toModelOutput(result) {
return {
location,
temperature: 12,
type: "content",
value:
typeof result === "string"
? [{ type: "text", text: result }]
: [
{
type: "media",
data: result.data,
mediaType: "image/png",
},
],
}
},
}),
},
});

console.log(text);
console.log(reasoning);

console.log('--------------------------------');

console.log(text2);
console.log(reasoning2);
})

for await (const chunk of result.fullStream) {
console.log("chunk", chunk)
}
}

main();

main()
Loading
Loading