Add ai compatibility tests and preserve sdk behavior

Co-authored-by: Eric Allam <eric@trigger.dev>
This commit is contained in:
Cursor Agent
2026-02-14 23:23:57 +00:00
parent af510e668a
commit 092c2ba55c
5 changed files with 90 additions and 10 deletions
+3
View File
@@ -80,6 +80,9 @@ await myTask.trigger({ name: "Alice", age: 30, dob: "2020-01-01" }); // this is
The `ai.tool` function allows you to create an AI tool from an existing `schemaTask` to use with the Vercel [AI SDK](https://vercel.com/docs/ai-sdk):
> `@trigger.dev/ai` is the recommended import path. For backwards compatibility,
> `@trigger.dev/sdk/ai` continues to work.
```ts
import { ai } from "@trigger.dev/ai";
import { schemaTask } from "@trigger.dev/sdk";
+1 -1
View File
@@ -33,7 +33,7 @@
"build": "tshy && pnpm run update-version",
"dev": "tshy --watch",
"typecheck": "tsc --noEmit",
"test": "vitest",
"test": "vitest --exclude \"**/.tshy-build/**\"",
"update-version": "tsx ../../scripts/updateVersion.ts",
"check-exports": "attw --pack ."
},
+4 -2
View File
@@ -73,7 +73,9 @@ describe("ai helper", function () {
}).toThrowError("task has no schema");
});
it("returns undefined for current tool options outside task execution context", function () {
expect(ai.currentToolOptions()).toBeUndefined();
it("throws for current tool options outside task execution context", function () {
expect(function () {
ai.currentToolOptions();
}).toThrowError("Method not implemented.");
});
});
+1 -7
View File
@@ -89,13 +89,7 @@ function toolFromTask<
}
function getToolOptionsFromMetadata(): ToolCallExecutionOptions | undefined {
let tool: unknown;
try {
tool = runMetadata.getKey(METADATA_KEY);
} catch {
return undefined;
}
const tool = runMetadata.getKey(METADATA_KEY);
if (!tool) {
return undefined;
}
+81
View File
@@ -0,0 +1,81 @@
import { describe, expect, it } from "vitest";
import { z } from "zod";
import { ai } from "./ai.js";
import type { TaskWithSchema } from "@trigger.dev/core/v3";
describe("@trigger.dev/sdk/ai compatibility", function () {
it("creates a tool from a schema task and executes triggerAndWait", async function () {
let receivedInput: unknown = undefined;
const fakeTask = {
id: "fake-task",
description: "A fake task",
schema: z.object({
name: z.string(),
}),
triggerAndWait: function (payload: { name: string }) {
receivedInput = payload;
const resultPromise = Promise.resolve({
ok: true,
id: "run_123",
taskIdentifier: "fake-task",
output: {
greeting: `Hello ${payload.name}`,
},
});
return Object.assign(resultPromise, {
unwrap: async function () {
return {
greeting: `Hello ${payload.name}`,
};
},
});
},
} as unknown as TaskWithSchema<
"fake-task",
z.ZodObject<{ name: z.ZodString }>,
{ greeting: string }
>;
const tool = ai.tool(fakeTask);
const result = await tool.execute?.(
{
name: "Ada",
},
undefined as never
);
expect(receivedInput).toEqual({
name: "Ada",
});
expect(result).toEqual({
greeting: "Hello Ada",
});
});
it("throws when converting tasks without schema", function () {
const fakeTask = {
id: "no-schema",
description: "No schema task",
schema: undefined,
triggerAndWait: async function () {
return {
unwrap: async function () {
return {};
},
};
},
} as unknown as TaskWithSchema<"no-schema", undefined, unknown>;
expect(function () {
ai.tool(fakeTask);
}).toThrowError("task has no schema");
});
it("preserves currentToolOptions behavior outside task execution", function () {
expect(function () {
ai.currentToolOptions();
}).toThrowError("Method not implemented.");
});
});