@typia/vercel 12.0.0-dev.20260311 → 12.0.0-dev.20260312
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +45 -5
- package/lib/index.js +46 -2
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +46 -3
- package/lib/index.mjs.map +1 -1
- package/lib/internal/VercelParameterConverter.d.ts +5 -0
- package/lib/internal/VercelParameterConverter.js +9 -0
- package/lib/internal/VercelParameterConverter.js.map +1 -0
- package/lib/internal/VercelParameterConverter.mjs +9 -0
- package/lib/internal/VercelParameterConverter.mjs.map +1 -0
- package/lib/internal/VercelToolsRegistrar.d.ts +1 -1
- package/lib/internal/VercelToolsRegistrar.js +36 -43
- package/lib/internal/VercelToolsRegistrar.js.map +1 -1
- package/lib/internal/VercelToolsRegistrar.mjs +36 -44
- package/lib/internal/VercelToolsRegistrar.mjs.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +155 -105
- package/src/internal/VercelParameterConverter.ts +8 -0
- package/src/internal/VercelToolsRegistrar.ts +166 -180
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IHttpLlmController, ILlmController } from "@typia/interface";
|
|
2
|
-
import type { Tool } from "ai";
|
|
1
|
+
import { IHttpLlmController, ILlmController, ILlmSchema } from "@typia/interface";
|
|
2
|
+
import type { Schema, Tool } from "ai";
|
|
3
3
|
/**
|
|
4
4
|
* Convert typia controllers to Vercel AI SDK tools.
|
|
5
5
|
*
|
|
@@ -21,8 +21,8 @@ import type { Tool } from "ai";
|
|
|
21
21
|
*
|
|
22
22
|
* class Calculator {
|
|
23
23
|
* /** Add two numbers together. */
|
|
24
|
-
* add(props: { a: number; b: number }): number {
|
|
25
|
-
* return props.a + props.b;
|
|
24
|
+
* add(props: { a: number; b: number }): { value: number } {
|
|
25
|
+
* return { value: props.a + props.b };
|
|
26
26
|
* }
|
|
27
27
|
* }
|
|
28
28
|
*
|
|
@@ -93,7 +93,47 @@ export declare function toVercelTools(props: {
|
|
|
93
93
|
* If `true`, tool names are formatted as `{controller}_{function}`. If
|
|
94
94
|
* `false`, only the function name is used (may cause conflicts).
|
|
95
95
|
*
|
|
96
|
-
* @default
|
|
96
|
+
* @default false
|
|
97
97
|
*/
|
|
98
98
|
prefix?: boolean | undefined;
|
|
99
99
|
}): Record<string, Tool>;
|
|
100
|
+
/**
|
|
101
|
+
* Convert LLM parameters schema to Vercel AI SDK schema format.
|
|
102
|
+
*
|
|
103
|
+
* Transforms {@link ILlmSchema.IParameters} into Vercel AI SDK's `Schema` type
|
|
104
|
+
* for use with `generateObject()`. Use with `typia.llm.structuredOutput<T>()`
|
|
105
|
+
* or `typia.llm.parameters<T>()`.
|
|
106
|
+
*
|
|
107
|
+
* ## Example
|
|
108
|
+
*
|
|
109
|
+
* ```typescript
|
|
110
|
+
* import { openai } from "@ai-sdk/openai";
|
|
111
|
+
* import { toVercelSchema } from "@typia/vercel";
|
|
112
|
+
* import { generateObject } from "ai";
|
|
113
|
+
* import typia from "typia";
|
|
114
|
+
*
|
|
115
|
+
* interface IMember {
|
|
116
|
+
* name: string;
|
|
117
|
+
* age: number;
|
|
118
|
+
* }
|
|
119
|
+
*
|
|
120
|
+
* const output = typia.llm.structuredOutput<IMember>();
|
|
121
|
+
* const schema = toVercelSchema(output.parameters);
|
|
122
|
+
*
|
|
123
|
+
* const { object } = await generateObject({
|
|
124
|
+
* model: openai("gpt-4o"),
|
|
125
|
+
* schema,
|
|
126
|
+
* prompt: "Generate a member named John who is 30 years old",
|
|
127
|
+
* });
|
|
128
|
+
*
|
|
129
|
+
* const coerced = output.coerce(object);
|
|
130
|
+
* const result = output.validate(coerced);
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
134
|
+
* @param parameters LLM parameters schema from
|
|
135
|
+
* `typia.llm.structuredOutput<T>().parameters` or
|
|
136
|
+
* `typia.llm.parameters<T>()`
|
|
137
|
+
* @returns Vercel AI SDK Schema for `generateObject()`
|
|
138
|
+
*/
|
|
139
|
+
export declare function toVercelSchema(parameters: ILlmSchema.IParameters): Schema<object>;
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toVercelTools = toVercelTools;
|
|
4
|
+
exports.toVercelSchema = toVercelSchema;
|
|
5
|
+
const VercelParameterConverter_1 = require("./internal/VercelParameterConverter");
|
|
4
6
|
const VercelToolsRegistrar_1 = require("./internal/VercelToolsRegistrar");
|
|
5
7
|
/**
|
|
6
8
|
* Convert typia controllers to Vercel AI SDK tools.
|
|
@@ -23,8 +25,8 @@ const VercelToolsRegistrar_1 = require("./internal/VercelToolsRegistrar");
|
|
|
23
25
|
*
|
|
24
26
|
* class Calculator {
|
|
25
27
|
* /** Add two numbers together. */
|
|
26
|
-
* add(props: { a: number; b: number }): number {
|
|
27
|
-
* return props.a + props.b;
|
|
28
|
+
* add(props: { a: number; b: number }): { value: number } {
|
|
29
|
+
* return { value: props.a + props.b };
|
|
28
30
|
* }
|
|
29
31
|
* }
|
|
30
32
|
*
|
|
@@ -82,4 +84,46 @@ const VercelToolsRegistrar_1 = require("./internal/VercelToolsRegistrar");
|
|
|
82
84
|
function toVercelTools(props) {
|
|
83
85
|
return VercelToolsRegistrar_1.VercelToolsRegistrar.convert(props);
|
|
84
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Convert LLM parameters schema to Vercel AI SDK schema format.
|
|
89
|
+
*
|
|
90
|
+
* Transforms {@link ILlmSchema.IParameters} into Vercel AI SDK's `Schema` type
|
|
91
|
+
* for use with `generateObject()`. Use with `typia.llm.structuredOutput<T>()`
|
|
92
|
+
* or `typia.llm.parameters<T>()`.
|
|
93
|
+
*
|
|
94
|
+
* ## Example
|
|
95
|
+
*
|
|
96
|
+
* ```typescript
|
|
97
|
+
* import { openai } from "@ai-sdk/openai";
|
|
98
|
+
* import { toVercelSchema } from "@typia/vercel";
|
|
99
|
+
* import { generateObject } from "ai";
|
|
100
|
+
* import typia from "typia";
|
|
101
|
+
*
|
|
102
|
+
* interface IMember {
|
|
103
|
+
* name: string;
|
|
104
|
+
* age: number;
|
|
105
|
+
* }
|
|
106
|
+
*
|
|
107
|
+
* const output = typia.llm.structuredOutput<IMember>();
|
|
108
|
+
* const schema = toVercelSchema(output.parameters);
|
|
109
|
+
*
|
|
110
|
+
* const { object } = await generateObject({
|
|
111
|
+
* model: openai("gpt-4o"),
|
|
112
|
+
* schema,
|
|
113
|
+
* prompt: "Generate a member named John who is 30 years old",
|
|
114
|
+
* });
|
|
115
|
+
*
|
|
116
|
+
* const coerced = output.coerce(object);
|
|
117
|
+
* const result = output.validate(coerced);
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
121
|
+
* @param parameters LLM parameters schema from
|
|
122
|
+
* `typia.llm.structuredOutput<T>().parameters` or
|
|
123
|
+
* `typia.llm.parameters<T>()`
|
|
124
|
+
* @returns Vercel AI SDK Schema for `generateObject()`
|
|
125
|
+
*/
|
|
126
|
+
function toVercelSchema(parameters) {
|
|
127
|
+
return VercelParameterConverter_1.VercelParameterConverter.convert(parameters);
|
|
128
|
+
}
|
|
85
129
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAuFA,sCAsBC;AAyCD,wCAIC;AAnJD,kFAA+E;AAC/E,0EAAuE;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AACH,SAAgB,aAAa,CAAC,KAoB7B;IACC,OAAO,2CAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,SAAgB,cAAc,CAC5B,UAAkC;IAElC,OAAO,mDAAwB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AACtD,CAAC"}
|
package/lib/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VercelParameterConverter } from './internal/VercelParameterConverter.mjs';
|
|
1
2
|
import { VercelToolsRegistrar } from './internal/VercelToolsRegistrar.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -21,8 +22,8 @@ import { VercelToolsRegistrar } from './internal/VercelToolsRegistrar.mjs';
|
|
|
21
22
|
*
|
|
22
23
|
* class Calculator {
|
|
23
24
|
* /** Add two numbers together. */
|
|
24
|
-
* add(props: { a: number; b: number }): number {
|
|
25
|
-
* return props.a + props.b;
|
|
25
|
+
* add(props: { a: number; b: number }): { value: number } {
|
|
26
|
+
* return { value: props.a + props.b };
|
|
26
27
|
* }
|
|
27
28
|
* }
|
|
28
29
|
*
|
|
@@ -80,6 +81,48 @@ import { VercelToolsRegistrar } from './internal/VercelToolsRegistrar.mjs';
|
|
|
80
81
|
function toVercelTools(props) {
|
|
81
82
|
return VercelToolsRegistrar.convert(props);
|
|
82
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Convert LLM parameters schema to Vercel AI SDK schema format.
|
|
86
|
+
*
|
|
87
|
+
* Transforms {@link ILlmSchema.IParameters} into Vercel AI SDK's `Schema` type
|
|
88
|
+
* for use with `generateObject()`. Use with `typia.llm.structuredOutput<T>()`
|
|
89
|
+
* or `typia.llm.parameters<T>()`.
|
|
90
|
+
*
|
|
91
|
+
* ## Example
|
|
92
|
+
*
|
|
93
|
+
* ```typescript
|
|
94
|
+
* import { openai } from "@ai-sdk/openai";
|
|
95
|
+
* import { toVercelSchema } from "@typia/vercel";
|
|
96
|
+
* import { generateObject } from "ai";
|
|
97
|
+
* import typia from "typia";
|
|
98
|
+
*
|
|
99
|
+
* interface IMember {
|
|
100
|
+
* name: string;
|
|
101
|
+
* age: number;
|
|
102
|
+
* }
|
|
103
|
+
*
|
|
104
|
+
* const output = typia.llm.structuredOutput<IMember>();
|
|
105
|
+
* const schema = toVercelSchema(output.parameters);
|
|
106
|
+
*
|
|
107
|
+
* const { object } = await generateObject({
|
|
108
|
+
* model: openai("gpt-4o"),
|
|
109
|
+
* schema,
|
|
110
|
+
* prompt: "Generate a member named John who is 30 years old",
|
|
111
|
+
* });
|
|
112
|
+
*
|
|
113
|
+
* const coerced = output.coerce(object);
|
|
114
|
+
* const result = output.validate(coerced);
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
118
|
+
* @param parameters LLM parameters schema from
|
|
119
|
+
* `typia.llm.structuredOutput<T>().parameters` or
|
|
120
|
+
* `typia.llm.parameters<T>()`
|
|
121
|
+
* @returns Vercel AI SDK Schema for `generateObject()`
|
|
122
|
+
*/
|
|
123
|
+
function toVercelSchema(parameters) {
|
|
124
|
+
return VercelParameterConverter.convert(parameters);
|
|
125
|
+
}
|
|
83
126
|
|
|
84
|
-
export { toVercelTools };
|
|
127
|
+
export { toVercelSchema, toVercelTools };
|
|
85
128
|
//# sourceMappingURL=index.mjs.map
|
package/lib/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4EG;AACG,SAAU,aAAa,CAAC,KAoB7B,EAAA;AACC,IAAA,OAAO,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC;AAC5C;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCG;AACG,SAAU,cAAc,CAC5B,UAAkC,EAAA;AAElC,IAAA,OAAO,wBAAwB,CAAC,OAAO,CAAC,UAAU,CAAC;AACrD;;;;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VercelParameterConverter = void 0;
|
|
4
|
+
const ai_1 = require("ai");
|
|
5
|
+
var VercelParameterConverter;
|
|
6
|
+
(function (VercelParameterConverter) {
|
|
7
|
+
VercelParameterConverter.convert = (parameters) => (0, ai_1.jsonSchema)(parameters);
|
|
8
|
+
})(VercelParameterConverter || (exports.VercelParameterConverter = VercelParameterConverter = {}));
|
|
9
|
+
//# sourceMappingURL=VercelParameterConverter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VercelParameterConverter.js","sourceRoot":"","sources":["../../src/internal/VercelParameterConverter.ts"],"names":[],"mappings":";;;AACA,2BAAwC;AAGxC,IAAiB,wBAAwB,CAGxC;AAHD,WAAiB,wBAAwB;IAC1B,gCAAO,GAAG,CAAC,UAAkC,EAAkB,EAAE,CAC5E,IAAA,eAAU,EAAS,UAAyB,CAAC,CAAC;AAClD,CAAC,EAHgB,wBAAwB,wCAAxB,wBAAwB,QAGxC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsonSchema } from 'ai';
|
|
2
|
+
|
|
3
|
+
var VercelParameterConverter;
|
|
4
|
+
(function (VercelParameterConverter) {
|
|
5
|
+
VercelParameterConverter.convert = (parameters) => jsonSchema(parameters);
|
|
6
|
+
})(VercelParameterConverter || (VercelParameterConverter = {}));
|
|
7
|
+
|
|
8
|
+
export { VercelParameterConverter };
|
|
9
|
+
//# sourceMappingURL=VercelParameterConverter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VercelParameterConverter.mjs","sources":["../../src/internal/VercelParameterConverter.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAIM,IAAW;AAAjB,CAAA,UAAiB,wBAAwB,EAAA;IAC1B,wBAAA,CAAA,OAAO,GAAG,CAAC,UAAkC,KACxD,UAAU,CAAS,UAAyB,CAAC;AACjD,CAAC,EAHgB,wBAAwB,KAAxB,wBAAwB,GAAA,EAAA,CAAA,CAAA;;;;"}
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.VercelToolsRegistrar = void 0;
|
|
13
13
|
const utils_1 = require("@typia/utils");
|
|
14
14
|
const ai_1 = require("ai");
|
|
15
|
+
const VercelParameterConverter_1 = require("./VercelParameterConverter");
|
|
15
16
|
var VercelToolsRegistrar;
|
|
16
17
|
(function (VercelToolsRegistrar) {
|
|
17
18
|
/**
|
|
@@ -22,22 +23,31 @@ var VercelToolsRegistrar;
|
|
|
22
23
|
*/
|
|
23
24
|
VercelToolsRegistrar.convert = (props) => {
|
|
24
25
|
var _a;
|
|
26
|
+
const prefix = (_a = props.prefix) !== null && _a !== void 0 ? _a : false;
|
|
25
27
|
const tools = {};
|
|
26
|
-
|
|
28
|
+
// check duplicate tool names
|
|
29
|
+
if (prefix === false && props.controllers.length >= 2) {
|
|
30
|
+
const names = new Map();
|
|
31
|
+
const duplicates = [];
|
|
32
|
+
for (const controller of props.controllers) {
|
|
33
|
+
for (const func of controller.application.functions) {
|
|
34
|
+
const existing = names.get(func.name);
|
|
35
|
+
if (existing !== undefined)
|
|
36
|
+
duplicates.push(`"${func.name}" in "${controller.name}" (conflicts with "${existing}")`);
|
|
37
|
+
else
|
|
38
|
+
names.set(func.name, controller.name);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (duplicates.length > 0)
|
|
42
|
+
throw new Error(`Duplicate tool names found:\n - ${duplicates.join("\n - ")}`);
|
|
43
|
+
}
|
|
44
|
+
// convert controllers to tools
|
|
27
45
|
for (const controller of props.controllers) {
|
|
28
46
|
if (controller.protocol === "class") {
|
|
29
|
-
registerClassController({
|
|
30
|
-
tools,
|
|
31
|
-
controller,
|
|
32
|
-
prefix,
|
|
33
|
-
});
|
|
47
|
+
registerClassController({ tools, controller, prefix });
|
|
34
48
|
}
|
|
35
49
|
else {
|
|
36
|
-
registerHttpController({
|
|
37
|
-
tools,
|
|
38
|
-
controller,
|
|
39
|
-
prefix,
|
|
40
|
-
});
|
|
50
|
+
registerHttpController({ tools, controller, prefix });
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
return tools;
|
|
@@ -49,14 +59,12 @@ var VercelToolsRegistrar;
|
|
|
49
59
|
const toolName = prefix
|
|
50
60
|
? `${controller.name}_${func.name}`
|
|
51
61
|
: func.name;
|
|
52
|
-
if (tools[toolName] !== undefined) {
|
|
53
|
-
throw new Error(`Duplicate tool name "${toolName}" from controller "${controller.name}"`);
|
|
54
|
-
}
|
|
55
62
|
const method = execute[func.name];
|
|
56
63
|
if (typeof method !== "function") {
|
|
57
64
|
throw new Error(`Method "${func.name}" not found on controller "${controller.name}"`);
|
|
58
65
|
}
|
|
59
66
|
tools[toolName] = createTool({
|
|
67
|
+
name: toolName,
|
|
60
68
|
func,
|
|
61
69
|
execute: (args) => __awaiter(this, void 0, void 0, function* () { return method.call(execute, args); }),
|
|
62
70
|
});
|
|
@@ -70,10 +78,8 @@ var VercelToolsRegistrar;
|
|
|
70
78
|
const toolName = prefix
|
|
71
79
|
? `${controller.name}_${func.name}`
|
|
72
80
|
: func.name;
|
|
73
|
-
if (tools[toolName] !== undefined) {
|
|
74
|
-
throw new Error(`Duplicate tool name "${toolName}" from controller "${controller.name}"`);
|
|
75
|
-
}
|
|
76
81
|
tools[toolName] = createTool({
|
|
82
|
+
name: toolName,
|
|
77
83
|
func,
|
|
78
84
|
execute: (args) => __awaiter(this, void 0, void 0, function* () {
|
|
79
85
|
if (controller.execute !== undefined) {
|
|
@@ -96,30 +102,30 @@ var VercelToolsRegistrar;
|
|
|
96
102
|
}
|
|
97
103
|
};
|
|
98
104
|
const createTool = (props) => {
|
|
99
|
-
|
|
105
|
+
var _a;
|
|
106
|
+
const { name, func, execute } = props;
|
|
100
107
|
return (0, ai_1.tool)({
|
|
101
|
-
description: func.description,
|
|
102
|
-
|
|
103
|
-
parameters: (0, ai_1.jsonSchema)(convertParameters(func.parameters)),
|
|
108
|
+
description: (_a = func.description) !== null && _a !== void 0 ? _a : "",
|
|
109
|
+
inputSchema: VercelParameterConverter_1.VercelParameterConverter.convert(func.parameters),
|
|
104
110
|
execute: (args) => __awaiter(this, void 0, void 0, function* () {
|
|
105
|
-
// Coerce and validate using typia's built-in functions
|
|
106
111
|
const coerced = utils_1.LlmJson.coerce(args, func.parameters);
|
|
107
112
|
const validation = func.validate(coerced);
|
|
108
|
-
if (!validation.success)
|
|
109
|
-
// Return validation error in LLM-friendly format
|
|
113
|
+
if (!validation.success)
|
|
110
114
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
success: false,
|
|
116
|
+
error: `Type errors in "${name}" arguments:\n\n` +
|
|
117
|
+
`\`\`\`json\n${utils_1.LlmJson.stringify(validation)}\n\`\`\``,
|
|
113
118
|
};
|
|
114
|
-
}
|
|
115
119
|
try {
|
|
116
120
|
const result = yield execute(validation.data);
|
|
117
|
-
return result === undefined
|
|
121
|
+
return result === undefined
|
|
122
|
+
? { success: true }
|
|
123
|
+
: { success: true, data: result };
|
|
118
124
|
}
|
|
119
125
|
catch (error) {
|
|
120
126
|
return {
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
success: false,
|
|
128
|
+
error: error instanceof Error
|
|
123
129
|
? `${error.name}: ${error.message}`
|
|
124
130
|
: String(error),
|
|
125
131
|
};
|
|
@@ -127,18 +133,5 @@ var VercelToolsRegistrar;
|
|
|
127
133
|
}),
|
|
128
134
|
});
|
|
129
135
|
};
|
|
130
|
-
const convertParameters = (params) => {
|
|
131
|
-
const schema = {
|
|
132
|
-
type: "object",
|
|
133
|
-
properties: params.properties,
|
|
134
|
-
required: params.required,
|
|
135
|
-
additionalProperties: params.additionalProperties,
|
|
136
|
-
};
|
|
137
|
-
// Add $defs if present
|
|
138
|
-
if (Object.keys(params.$defs).length > 0) {
|
|
139
|
-
schema.$defs = params.$defs;
|
|
140
|
-
}
|
|
141
|
-
return schema;
|
|
142
|
-
};
|
|
143
136
|
})(VercelToolsRegistrar || (exports.VercelToolsRegistrar = VercelToolsRegistrar = {}));
|
|
144
137
|
//# sourceMappingURL=VercelToolsRegistrar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VercelToolsRegistrar.js","sourceRoot":"","sources":["../../src/internal/VercelToolsRegistrar.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"VercelToolsRegistrar.js","sourceRoot":"","sources":["../../src/internal/VercelToolsRegistrar.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LlmJson, HttpLlm } from '@typia/utils';
|
|
2
|
-
import { tool
|
|
2
|
+
import { tool } from 'ai';
|
|
3
|
+
import { VercelParameterConverter } from './VercelParameterConverter.mjs';
|
|
3
4
|
|
|
4
5
|
var VercelToolsRegistrar;
|
|
5
6
|
(function (VercelToolsRegistrar) {
|
|
@@ -10,22 +11,31 @@ var VercelToolsRegistrar;
|
|
|
10
11
|
* @returns Record of Vercel AI SDK Tools
|
|
11
12
|
*/
|
|
12
13
|
VercelToolsRegistrar.convert = (props) => {
|
|
14
|
+
const prefix = props.prefix ?? false;
|
|
13
15
|
const tools = {};
|
|
14
|
-
|
|
16
|
+
// check duplicate tool names
|
|
17
|
+
if (prefix === false && props.controllers.length >= 2) {
|
|
18
|
+
const names = new Map();
|
|
19
|
+
const duplicates = [];
|
|
20
|
+
for (const controller of props.controllers) {
|
|
21
|
+
for (const func of controller.application.functions) {
|
|
22
|
+
const existing = names.get(func.name);
|
|
23
|
+
if (existing !== undefined)
|
|
24
|
+
duplicates.push(`"${func.name}" in "${controller.name}" (conflicts with "${existing}")`);
|
|
25
|
+
else
|
|
26
|
+
names.set(func.name, controller.name);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (duplicates.length > 0)
|
|
30
|
+
throw new Error(`Duplicate tool names found:\n - ${duplicates.join("\n - ")}`);
|
|
31
|
+
}
|
|
32
|
+
// convert controllers to tools
|
|
15
33
|
for (const controller of props.controllers) {
|
|
16
34
|
if (controller.protocol === "class") {
|
|
17
|
-
registerClassController({
|
|
18
|
-
tools,
|
|
19
|
-
controller,
|
|
20
|
-
prefix,
|
|
21
|
-
});
|
|
35
|
+
registerClassController({ tools, controller, prefix });
|
|
22
36
|
}
|
|
23
37
|
else {
|
|
24
|
-
registerHttpController({
|
|
25
|
-
tools,
|
|
26
|
-
controller,
|
|
27
|
-
prefix,
|
|
28
|
-
});
|
|
38
|
+
registerHttpController({ tools, controller, prefix });
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
return tools;
|
|
@@ -37,14 +47,12 @@ var VercelToolsRegistrar;
|
|
|
37
47
|
const toolName = prefix
|
|
38
48
|
? `${controller.name}_${func.name}`
|
|
39
49
|
: func.name;
|
|
40
|
-
if (tools[toolName] !== undefined) {
|
|
41
|
-
throw new Error(`Duplicate tool name "${toolName}" from controller "${controller.name}"`);
|
|
42
|
-
}
|
|
43
50
|
const method = execute[func.name];
|
|
44
51
|
if (typeof method !== "function") {
|
|
45
52
|
throw new Error(`Method "${func.name}" not found on controller "${controller.name}"`);
|
|
46
53
|
}
|
|
47
54
|
tools[toolName] = createTool({
|
|
55
|
+
name: toolName,
|
|
48
56
|
func,
|
|
49
57
|
execute: async (args) => method.call(execute, args),
|
|
50
58
|
});
|
|
@@ -58,10 +66,8 @@ var VercelToolsRegistrar;
|
|
|
58
66
|
const toolName = prefix
|
|
59
67
|
? `${controller.name}_${func.name}`
|
|
60
68
|
: func.name;
|
|
61
|
-
if (tools[toolName] !== undefined) {
|
|
62
|
-
throw new Error(`Duplicate tool name "${toolName}" from controller "${controller.name}"`);
|
|
63
|
-
}
|
|
64
69
|
tools[toolName] = createTool({
|
|
70
|
+
name: toolName,
|
|
65
71
|
func,
|
|
66
72
|
execute: async (args) => {
|
|
67
73
|
if (controller.execute !== undefined) {
|
|
@@ -84,30 +90,29 @@ var VercelToolsRegistrar;
|
|
|
84
90
|
}
|
|
85
91
|
};
|
|
86
92
|
const createTool = (props) => {
|
|
87
|
-
const { func, execute } = props;
|
|
93
|
+
const { name, func, execute } = props;
|
|
88
94
|
return tool({
|
|
89
|
-
description: func.description,
|
|
90
|
-
|
|
91
|
-
parameters: jsonSchema(convertParameters(func.parameters)),
|
|
95
|
+
description: func.description ?? "",
|
|
96
|
+
inputSchema: VercelParameterConverter.convert(func.parameters),
|
|
92
97
|
execute: async (args) => {
|
|
93
|
-
// Coerce and validate using typia's built-in functions
|
|
94
98
|
const coerced = LlmJson.coerce(args, func.parameters);
|
|
95
99
|
const validation = func.validate(coerced);
|
|
96
|
-
if (!validation.success)
|
|
97
|
-
// Return validation error in LLM-friendly format
|
|
100
|
+
if (!validation.success)
|
|
98
101
|
return {
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
success: false,
|
|
103
|
+
error: `Type errors in "${name}" arguments:\n\n` +
|
|
104
|
+
`\`\`\`json\n${LlmJson.stringify(validation)}\n\`\`\``,
|
|
101
105
|
};
|
|
102
|
-
}
|
|
103
106
|
try {
|
|
104
107
|
const result = await execute(validation.data);
|
|
105
|
-
return result === undefined
|
|
108
|
+
return result === undefined
|
|
109
|
+
? { success: true }
|
|
110
|
+
: { success: true, data: result };
|
|
106
111
|
}
|
|
107
112
|
catch (error) {
|
|
108
113
|
return {
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
success: false,
|
|
115
|
+
error: error instanceof Error
|
|
111
116
|
? `${error.name}: ${error.message}`
|
|
112
117
|
: String(error),
|
|
113
118
|
};
|
|
@@ -115,19 +120,6 @@ var VercelToolsRegistrar;
|
|
|
115
120
|
},
|
|
116
121
|
});
|
|
117
122
|
};
|
|
118
|
-
const convertParameters = (params) => {
|
|
119
|
-
const schema = {
|
|
120
|
-
type: "object",
|
|
121
|
-
properties: params.properties,
|
|
122
|
-
required: params.required,
|
|
123
|
-
additionalProperties: params.additionalProperties,
|
|
124
|
-
};
|
|
125
|
-
// Add $defs if present
|
|
126
|
-
if (Object.keys(params.$defs).length > 0) {
|
|
127
|
-
schema.$defs = params.$defs;
|
|
128
|
-
}
|
|
129
|
-
return schema;
|
|
130
|
-
};
|
|
131
123
|
})(VercelToolsRegistrar || (VercelToolsRegistrar = {}));
|
|
132
124
|
|
|
133
125
|
export { VercelToolsRegistrar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VercelToolsRegistrar.mjs","sources":["../../src/internal/VercelToolsRegistrar.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VercelToolsRegistrar.mjs","sources":["../../src/internal/VercelToolsRegistrar.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typia/vercel",
|
|
3
|
-
"version": "12.0.0-dev.
|
|
3
|
+
"version": "12.0.0-dev.20260312",
|
|
4
4
|
"description": "Vercel AI SDK integration for typia",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://typia.io",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@typia/
|
|
26
|
-
"@typia/
|
|
25
|
+
"@typia/interface": "^12.0.0-dev.20260312",
|
|
26
|
+
"@typia/utils": "^12.0.0-dev.20260312"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"ai": ">=
|
|
29
|
+
"ai": ">=6.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
33
33
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
34
34
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
35
35
|
"@types/json-schema": "^7.0.15",
|
|
36
|
-
"ai": "^
|
|
36
|
+
"ai": "^6.0.116",
|
|
37
37
|
"rimraf": "^6.1.2",
|
|
38
38
|
"rollup": "^4.56.0",
|
|
39
39
|
"rollup-plugin-auto-external": "^2.0.0",
|
package/src/index.ts
CHANGED
|
@@ -1,105 +1,155 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
1
|
+
import {
|
|
2
|
+
IHttpLlmController,
|
|
3
|
+
ILlmController,
|
|
4
|
+
ILlmSchema,
|
|
5
|
+
} from "@typia/interface";
|
|
6
|
+
import type { Schema, Tool } from "ai";
|
|
7
|
+
|
|
8
|
+
import { VercelParameterConverter } from "./internal/VercelParameterConverter";
|
|
9
|
+
import { VercelToolsRegistrar } from "./internal/VercelToolsRegistrar";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Convert typia controllers to Vercel AI SDK tools.
|
|
13
|
+
*
|
|
14
|
+
* Transforms TypeScript class methods via `typia.llm.controller<Class>()` or
|
|
15
|
+
* OpenAPI operations via `HttpLlm.controller()` into Vercel AI SDK tools that
|
|
16
|
+
* can be used with any LLM provider (OpenAI, Anthropic, Google, etc.).
|
|
17
|
+
*
|
|
18
|
+
* Every tool call is validated by typia. If the LLM provides invalid arguments,
|
|
19
|
+
* returns a validation error formatted by {@link LlmJson.stringify} so the LLM
|
|
20
|
+
* can auto-correct in the next turn.
|
|
21
|
+
*
|
|
22
|
+
* ## Example with OpenAI
|
|
23
|
+
*
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { generateText } from "ai";
|
|
26
|
+
* import { openai } from "@ai-sdk/openai";
|
|
27
|
+
* import typia from "typia";
|
|
28
|
+
* import { toVercelTools } from "@typia/vercel";
|
|
29
|
+
*
|
|
30
|
+
* class Calculator {
|
|
31
|
+
* /** Add two numbers together. */
|
|
32
|
+
* add(props: { a: number; b: number }): { value: number } {
|
|
33
|
+
* return { value: props.a + props.b };
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* const controller = typia.llm.controller<Calculator>("calc", new Calculator());
|
|
38
|
+
* const tools = toVercelTools({ controllers: [controller] });
|
|
39
|
+
*
|
|
40
|
+
* const result = await generateText({
|
|
41
|
+
* model: openai("gpt-4o"),
|
|
42
|
+
* tools,
|
|
43
|
+
* prompt: "What is 15 + 27?",
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* ## Example with Anthropic
|
|
48
|
+
*
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { anthropic } from "@ai-sdk/anthropic";
|
|
51
|
+
* import { toVercelTools } from "@typia/vercel";
|
|
52
|
+
* import { generateText } from "ai";
|
|
53
|
+
*
|
|
54
|
+
* const result = await generateText({
|
|
55
|
+
* model: anthropic("claude-sonnet-4-20250514"),
|
|
56
|
+
* tools: toVercelTools({ controllers: [controller] }),
|
|
57
|
+
* prompt: "Calculate 100 * 50",
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* ## Example with HTTP Controller (OpenAPI)
|
|
62
|
+
*
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { openai } from "@ai-sdk/openai";
|
|
65
|
+
* import { HttpLlm } from "@typia/utils";
|
|
66
|
+
* import { toVercelTools } from "@typia/vercel";
|
|
67
|
+
* import { generateText } from "ai";
|
|
68
|
+
*
|
|
69
|
+
* const controller = HttpLlm.controller({
|
|
70
|
+
* name: "shopping",
|
|
71
|
+
* document: await fetch("https://api.example.com/swagger.json").then(
|
|
72
|
+
* (r) => r.json(),
|
|
73
|
+
* ),
|
|
74
|
+
* connection: { host: "https://api.example.com" },
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* const result = await generateText({
|
|
78
|
+
* model: openai("gpt-4o"),
|
|
79
|
+
* tools: toVercelTools({ controllers: [controller] }),
|
|
80
|
+
* prompt: "Search for laptops under $1000",
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
85
|
+
* @param props Conversion properties
|
|
86
|
+
* @returns Record of Vercel AI SDK Tools keyed by tool name
|
|
87
|
+
*/
|
|
88
|
+
export function toVercelTools(props: {
|
|
89
|
+
/**
|
|
90
|
+
* List of controllers to convert to Vercel tools.
|
|
91
|
+
*
|
|
92
|
+
* - {@link ILlmController}: from `typia.llm.controller<Class>()`, converts all
|
|
93
|
+
* methods of the class to tools
|
|
94
|
+
* - {@link IHttpLlmController}: from `HttpLlm.controller()`, converts all
|
|
95
|
+
* operations from OpenAPI document to tools
|
|
96
|
+
*/
|
|
97
|
+
controllers: Array<ILlmController | IHttpLlmController>;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Whether to prefix tool names with controller name.
|
|
101
|
+
*
|
|
102
|
+
* If `true`, tool names are formatted as `{controller}_{function}`. If
|
|
103
|
+
* `false`, only the function name is used (may cause conflicts).
|
|
104
|
+
*
|
|
105
|
+
* @default false
|
|
106
|
+
*/
|
|
107
|
+
prefix?: boolean | undefined;
|
|
108
|
+
}): Record<string, Tool> {
|
|
109
|
+
return VercelToolsRegistrar.convert(props);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Convert LLM parameters schema to Vercel AI SDK schema format.
|
|
114
|
+
*
|
|
115
|
+
* Transforms {@link ILlmSchema.IParameters} into Vercel AI SDK's `Schema` type
|
|
116
|
+
* for use with `generateObject()`. Use with `typia.llm.structuredOutput<T>()`
|
|
117
|
+
* or `typia.llm.parameters<T>()`.
|
|
118
|
+
*
|
|
119
|
+
* ## Example
|
|
120
|
+
*
|
|
121
|
+
* ```typescript
|
|
122
|
+
* import { openai } from "@ai-sdk/openai";
|
|
123
|
+
* import { toVercelSchema } from "@typia/vercel";
|
|
124
|
+
* import { generateObject } from "ai";
|
|
125
|
+
* import typia from "typia";
|
|
126
|
+
*
|
|
127
|
+
* interface IMember {
|
|
128
|
+
* name: string;
|
|
129
|
+
* age: number;
|
|
130
|
+
* }
|
|
131
|
+
*
|
|
132
|
+
* const output = typia.llm.structuredOutput<IMember>();
|
|
133
|
+
* const schema = toVercelSchema(output.parameters);
|
|
134
|
+
*
|
|
135
|
+
* const { object } = await generateObject({
|
|
136
|
+
* model: openai("gpt-4o"),
|
|
137
|
+
* schema,
|
|
138
|
+
* prompt: "Generate a member named John who is 30 years old",
|
|
139
|
+
* });
|
|
140
|
+
*
|
|
141
|
+
* const coerced = output.coerce(object);
|
|
142
|
+
* const result = output.validate(coerced);
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
146
|
+
* @param parameters LLM parameters schema from
|
|
147
|
+
* `typia.llm.structuredOutput<T>().parameters` or
|
|
148
|
+
* `typia.llm.parameters<T>()`
|
|
149
|
+
* @returns Vercel AI SDK Schema for `generateObject()`
|
|
150
|
+
*/
|
|
151
|
+
export function toVercelSchema(
|
|
152
|
+
parameters: ILlmSchema.IParameters,
|
|
153
|
+
): Schema<object> {
|
|
154
|
+
return VercelParameterConverter.convert(parameters);
|
|
155
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ILlmSchema } from "@typia/interface";
|
|
2
|
+
import { Schema, jsonSchema } from "ai";
|
|
3
|
+
import { JSONSchema7 } from "json-schema";
|
|
4
|
+
|
|
5
|
+
export namespace VercelParameterConverter {
|
|
6
|
+
export const convert = (parameters: ILlmSchema.IParameters): Schema<object> =>
|
|
7
|
+
jsonSchema<object>(parameters as JSONSchema7);
|
|
8
|
+
}
|
|
@@ -1,180 +1,166 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IHttpLlmController,
|
|
3
|
-
IHttpLlmFunction,
|
|
4
|
-
ILlmController,
|
|
5
|
-
ILlmFunction,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "@typia/
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const tools: Record<string, Tool> = {};
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
controller
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
type: "object",
|
|
168
|
-
properties: params.properties as JSONSchema7["properties"],
|
|
169
|
-
required: params.required,
|
|
170
|
-
additionalProperties: params.additionalProperties,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// Add $defs if present
|
|
174
|
-
if (Object.keys(params.$defs).length > 0) {
|
|
175
|
-
schema.$defs = params.$defs as JSONSchema7["$defs"];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return schema;
|
|
179
|
-
};
|
|
180
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
IHttpLlmController,
|
|
3
|
+
IHttpLlmFunction,
|
|
4
|
+
ILlmController,
|
|
5
|
+
ILlmFunction,
|
|
6
|
+
IValidation,
|
|
7
|
+
} from "@typia/interface";
|
|
8
|
+
import { HttpLlm, LlmJson } from "@typia/utils";
|
|
9
|
+
import { Tool, tool } from "ai";
|
|
10
|
+
|
|
11
|
+
import { VercelParameterConverter } from "./VercelParameterConverter";
|
|
12
|
+
|
|
13
|
+
export namespace VercelToolsRegistrar {
|
|
14
|
+
/**
|
|
15
|
+
* Convert typia controllers to Vercel AI SDK tools.
|
|
16
|
+
*
|
|
17
|
+
* @param props Conversion properties
|
|
18
|
+
* @returns Record of Vercel AI SDK Tools
|
|
19
|
+
*/
|
|
20
|
+
export const convert = (props: {
|
|
21
|
+
controllers: Array<ILlmController | IHttpLlmController>;
|
|
22
|
+
prefix?: boolean | undefined;
|
|
23
|
+
}): Record<string, Tool> => {
|
|
24
|
+
const prefix: boolean = props.prefix ?? false;
|
|
25
|
+
const tools: Record<string, Tool> = {};
|
|
26
|
+
|
|
27
|
+
// check duplicate tool names
|
|
28
|
+
if (prefix === false && props.controllers.length >= 2) {
|
|
29
|
+
const names: Map<string, string> = new Map();
|
|
30
|
+
const duplicates: string[] = [];
|
|
31
|
+
for (const controller of props.controllers) {
|
|
32
|
+
for (const func of controller.application.functions) {
|
|
33
|
+
const existing: string | undefined = names.get(func.name);
|
|
34
|
+
if (existing !== undefined)
|
|
35
|
+
duplicates.push(
|
|
36
|
+
`"${func.name}" in "${controller.name}" (conflicts with "${existing}")`,
|
|
37
|
+
);
|
|
38
|
+
else names.set(func.name, controller.name);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (duplicates.length > 0)
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Duplicate tool names found:\n - ${duplicates.join("\n - ")}`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// convert controllers to tools
|
|
48
|
+
for (const controller of props.controllers) {
|
|
49
|
+
if (controller.protocol === "class") {
|
|
50
|
+
registerClassController({ tools, controller, prefix });
|
|
51
|
+
} else {
|
|
52
|
+
registerHttpController({ tools, controller, prefix });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return tools;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const registerClassController = (props: {
|
|
60
|
+
tools: Record<string, Tool>;
|
|
61
|
+
controller: ILlmController;
|
|
62
|
+
prefix: boolean;
|
|
63
|
+
}): void => {
|
|
64
|
+
const { tools, controller, prefix } = props;
|
|
65
|
+
const execute: Record<string, unknown> = controller.execute;
|
|
66
|
+
|
|
67
|
+
for (const func of controller.application.functions) {
|
|
68
|
+
const toolName: string = prefix
|
|
69
|
+
? `${controller.name}_${func.name}`
|
|
70
|
+
: func.name;
|
|
71
|
+
|
|
72
|
+
const method: unknown = execute[func.name];
|
|
73
|
+
if (typeof method !== "function") {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Method "${func.name}" not found on controller "${controller.name}"`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
tools[toolName] = createTool({
|
|
80
|
+
name: toolName,
|
|
81
|
+
func,
|
|
82
|
+
execute: async (args: unknown) => method.call(execute, args),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const registerHttpController = (props: {
|
|
88
|
+
tools: Record<string, Tool>;
|
|
89
|
+
controller: IHttpLlmController;
|
|
90
|
+
prefix: boolean;
|
|
91
|
+
}): void => {
|
|
92
|
+
const { tools, controller, prefix } = props;
|
|
93
|
+
const application = controller.application;
|
|
94
|
+
const connection = controller.connection;
|
|
95
|
+
|
|
96
|
+
for (const func of application.functions) {
|
|
97
|
+
const toolName: string = prefix
|
|
98
|
+
? `${controller.name}_${func.name}`
|
|
99
|
+
: func.name;
|
|
100
|
+
|
|
101
|
+
tools[toolName] = createTool({
|
|
102
|
+
name: toolName,
|
|
103
|
+
func,
|
|
104
|
+
execute: async (args: unknown) => {
|
|
105
|
+
if (controller.execute !== undefined) {
|
|
106
|
+
const response = await controller.execute({
|
|
107
|
+
connection,
|
|
108
|
+
application,
|
|
109
|
+
function: func,
|
|
110
|
+
arguments: args as object,
|
|
111
|
+
});
|
|
112
|
+
return response.body;
|
|
113
|
+
}
|
|
114
|
+
return HttpLlm.execute({
|
|
115
|
+
application,
|
|
116
|
+
function: func,
|
|
117
|
+
connection,
|
|
118
|
+
input: args as object,
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const createTool = (props: {
|
|
126
|
+
name: string;
|
|
127
|
+
func: ILlmFunction | IHttpLlmFunction;
|
|
128
|
+
execute: (args: unknown) => Promise<unknown>;
|
|
129
|
+
}): Tool => {
|
|
130
|
+
const { name, func, execute } = props;
|
|
131
|
+
|
|
132
|
+
return tool({
|
|
133
|
+
description: func.description ?? "",
|
|
134
|
+
inputSchema: VercelParameterConverter.convert(func.parameters),
|
|
135
|
+
execute: async (args: unknown): Promise<ITryResult> => {
|
|
136
|
+
const coerced: unknown = LlmJson.coerce(args, func.parameters);
|
|
137
|
+
const validation: IValidation<unknown> = func.validate(coerced);
|
|
138
|
+
if (!validation.success)
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
error:
|
|
142
|
+
`Type errors in "${name}" arguments:\n\n` +
|
|
143
|
+
`\`\`\`json\n${LlmJson.stringify(validation)}\n\`\`\``,
|
|
144
|
+
} satisfies ITryResult;
|
|
145
|
+
try {
|
|
146
|
+
const result: unknown = await execute(validation.data);
|
|
147
|
+
return result === undefined
|
|
148
|
+
? ({ success: true } satisfies ITryResult)
|
|
149
|
+
: ({ success: true, data: result } satisfies ITryResult);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
error:
|
|
154
|
+
error instanceof Error
|
|
155
|
+
? `${error.name}: ${error.message}`
|
|
156
|
+
: String(error),
|
|
157
|
+
} satisfies ITryResult;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
type ITryResult =
|
|
165
|
+
| { success: true; data?: unknown | undefined }
|
|
166
|
+
| { success: false; error: string };
|