-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathai.ts
More file actions
118 lines (104 loc) · 3.43 KB
/
ai.ts
File metadata and controls
118 lines (104 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import {
AnyTask,
isSchemaZodEsque,
Task,
type inferSchemaIn,
type TaskSchema,
type TaskWithSchema,
} from "@trigger.dev/core/v3";
import { dynamicTool, jsonSchema, JSONSchema7, Schema, Tool, ToolCallOptions, zodSchema } from "ai";
import { metadata } from "./metadata.js";
const METADATA_KEY = "tool.execute.options";
export type ToolCallExecutionOptions = Omit<ToolCallOptions, "abortSignal">;
type ToolResultContent = Array<
| {
type: "text";
text: string;
}
| {
type: "image";
data: string;
mimeType?: string;
}
>;
export type ToolOptions<TResult> = {
experimental_toToolResultContent?: (result: TResult) => ToolResultContent;
};
function toolFromTask<TIdentifier extends string, TInput = void, TOutput = unknown>(
task: Task<TIdentifier, TInput, TOutput>,
options?: ToolOptions<TOutput>
): Tool<TInput, TOutput>;
function toolFromTask<
TIdentifier extends string,
TTaskSchema extends TaskSchema | undefined = undefined,
TOutput = unknown,
>(
task: TaskWithSchema<TIdentifier, TTaskSchema, TOutput>,
options?: ToolOptions<TOutput>
): Tool<inferSchemaIn<TTaskSchema>, TOutput>;
function toolFromTask<
TIdentifier extends string,
TTaskSchema extends TaskSchema | undefined = undefined,
TInput = void,
TOutput = unknown,
>(
task: TaskWithSchema<TIdentifier, TTaskSchema, TOutput> | Task<TIdentifier, TInput, TOutput>,
options?: ToolOptions<TOutput>
): TTaskSchema extends TaskSchema
? Tool<inferSchemaIn<TTaskSchema>, TOutput>
: Tool<TInput, TOutput> {
if (("schema" in task && !task.schema) || ("jsonSchema" in task && !task.jsonSchema)) {
throw new Error(
"Cannot convert this task to to a tool because the task has no schema. Make sure to either use schemaTask or a task with an input jsonSchema."
);
}
const toolDefinition = dynamicTool({
description: task.description,
inputSchema: convertTaskSchemaToToolParameters(task),
execute: async (input, options) => {
const serializedOptions = options ? JSON.parse(JSON.stringify(options)) : undefined;
return await task
.triggerAndWait(input as inferSchemaIn<TTaskSchema>, {
metadata: {
[METADATA_KEY]: serializedOptions,
},
})
.unwrap();
},
...options,
});
return toolDefinition as TTaskSchema extends TaskSchema
? Tool<inferSchemaIn<TTaskSchema>, TOutput>
: Tool<TInput, TOutput>;
}
function getToolOptionsFromMetadata(): ToolCallExecutionOptions | undefined {
const tool = metadata.get(METADATA_KEY);
if (!tool) {
return undefined;
}
return tool as ToolCallExecutionOptions;
}
function convertTaskSchemaToToolParameters(
task: AnyTask | TaskWithSchema<any, any, any>
): Schema<unknown> {
if ("schema" in task) {
// If TaskSchema is ArkTypeEsque, use ai.jsonSchema to convert it to a Schema
if ("toJsonSchema" in task.schema && typeof task.schema.toJsonSchema === "function") {
return jsonSchema((task.schema as any).toJsonSchema());
}
// If TaskSchema is ZodEsque, use ai.zodSchema to convert it to a Schema
if (isSchemaZodEsque(task.schema)) {
return zodSchema(task.schema as any);
}
}
if ("jsonSchema" in task) {
return jsonSchema(task.jsonSchema as JSONSchema7);
}
throw new Error(
"Cannot convert task to a tool. Make sure to use a task with a schema or jsonSchema."
);
}
export const ai = {
tool: toolFromTask,
currentToolOptions: getToolOptionsFromMetadata,
};