diff --git a/package.json b/package.json index 00f323c..f028f7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@wrtnio/openai-function-schema", - "version": "0.2.3", + "version": "0.2.4", "description": "OpenAI LLM function schema from OpenAPI (Swagger) document", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -37,16 +37,16 @@ "author": "", "license": "ISC", "dependencies": { - "@nestia/fetcher": "^3.8.0", - "@samchon/openapi": "^0.4.2", + "@nestia/fetcher": "^3.10.0", + "@samchon/openapi": "^0.4.3", "commander": "^10.0.0", "inquirer": "^8.2.5", - "typia": "^6.5.4" + "typia": "^6.7.2" }, "devDependencies": { - "@nestia/core": "^3.8.0", + "@nestia/core": "^3.10.0", "@nestia/e2e": "^0.7.0", - "@nestia/sdk": "^3.8.0", + "@nestia/sdk": "^3.10.0", "@nestjs/common": "^10.3.10", "@nestjs/core": "^10.3.10", "@nestjs/platform-express": "^10.3.10", diff --git a/src/OpenAiComposer.ts b/src/OpenAiComposer.ts index 756a2e1..ef86e19 100644 --- a/src/OpenAiComposer.ts +++ b/src/OpenAiComposer.ts @@ -165,7 +165,7 @@ export namespace OpenAiComposer { const downgraded: IOpenAiSchema = OpenApiV3Downgrader.downgradeSchema({ original: {}, downgraded: {}, - })(escaped); + })(escaped) as IOpenAiSchema; OpenAiTypeChecker.visit(downgraded, (schema) => { if ( OpenAiTypeChecker.isOneOf(schema) && @@ -240,6 +240,7 @@ export namespace OpenAiComposer { method: route.method as "get", path: route.path, name: route.accessor.join("_"), + strict: true, parameters, separated: options.separate ? OpenAiSchemaSeparator.parameters({ @@ -248,10 +249,10 @@ export namespace OpenAiComposer { }) : undefined, output: output - ? OpenApiV3Downgrader.downgradeSchema({ + ? (OpenApiV3Downgrader.downgradeSchema({ original: {}, downgraded: {}, - })(output) + })(output) as IOpenAiSchema) : undefined, description: (() => { if (operation.summary && operation.description) { diff --git a/src/structures/IOpenAiFunction.ts b/src/structures/IOpenAiFunction.ts index 3fc7c57..1dddce6 100644 --- a/src/structures/IOpenAiFunction.ts +++ b/src/structures/IOpenAiFunction.ts @@ -66,6 +66,15 @@ export interface IOpenAiFunction { */ name: string; + /** + * Whether the function schema types are strict or not. + * + * Newly added specification at 2024-08-07. + * + * @reference https://openai.com/index/introducing-structured-outputs-in-the-api/ + */ + strict: true; + /** * List of parameter schemas. */ diff --git a/test/keyword.json b/test/keyword.json index 7ef2f22..f87fa36 100644 --- a/test/keyword.json +++ b/test/keyword.json @@ -5,6 +5,7 @@ "method": "post", "path": "/bbs/articles", "name": "bbs_articles_post", + "strict": true, "parameters": [ { "type": "object", @@ -299,6 +300,7 @@ "method": "patch", "path": "/bbs/articles", "name": "bbs_articles_patch", + "strict": true, "parameters": [ { "type": "object", @@ -445,6 +447,7 @@ "method": "patch", "path": "/bbs/articles/abridges", "name": "bbs_articles_abridges_patch", + "strict": true, "parameters": [ { "type": "object", @@ -728,6 +731,7 @@ "method": "get", "path": "/bbs/articles/{id}", "name": "bbs_articles_getById", + "strict": true, "parameters": [ { "type": "object", @@ -878,6 +882,7 @@ "method": "put", "path": "/bbs/articles/{id}", "name": "bbs_articles_putById", + "strict": true, "parameters": [ { "type": "object", @@ -1137,6 +1142,7 @@ "method": "delete", "path": "/bbs/articles/{id}", "name": "bbs_articles_eraseById", + "strict": true, "parameters": [ { "type": "object", @@ -1195,6 +1201,7 @@ "method": "post", "path": "/membership/join", "name": "membership_join_post", + "strict": true, "parameters": [ { "type": "object", @@ -1361,6 +1368,7 @@ "method": "patch", "path": "/membership/login", "name": "membership_login_patch", + "strict": true, "parameters": [ { "type": "object", @@ -1480,6 +1488,7 @@ "method": "get", "path": "/membership/{secret}", "name": "membership_getBySecret", + "strict": true, "parameters": [ { "type": "object", @@ -1554,6 +1563,7 @@ "method": "patch", "path": "/membership/change", "name": "membership_change_patch", + "strict": true, "parameters": [ { "type": "object", @@ -1746,6 +1756,7 @@ "method": "patch", "path": "/membership/{secret}/change", "name": "membership_change_patchBySecret", + "strict": true, "parameters": [ { "type": "object", @@ -1922,6 +1933,7 @@ "method": "post", "path": "/multipart", "name": "multipart_post", + "strict": true, "parameters": [ { "type": "object", @@ -2090,6 +2102,7 @@ "method": "get", "path": "/query/typed", "name": "query_typed_get", + "strict": true, "parameters": [ { "type": "object", @@ -2199,6 +2212,7 @@ "method": "get", "path": "/query/nest", "name": "query_nest_get", + "strict": true, "parameters": [ { "type": "object", @@ -2316,6 +2330,7 @@ "method": "get", "path": "/query/individual", "name": "query_individual_get", + "strict": true, "parameters": [ { "type": "object", @@ -2368,6 +2383,7 @@ "method": "get", "path": "/query/composite/{id}", "name": "query_composite_getById", + "strict": true, "parameters": [ { "type": "object", @@ -2483,6 +2499,7 @@ "method": "post", "path": "/query/body", "name": "query_body_post", + "strict": true, "parameters": [ { "type": "object", diff --git a/test/plain.json b/test/plain.json index 4de3b76..63c2532 100644 --- a/test/plain.json +++ b/test/plain.json @@ -5,6 +5,7 @@ "method": "post", "path": "/bbs/articles", "name": "bbs_articles_post", + "strict": true, "parameters": [ { "type": "object", @@ -204,6 +205,7 @@ "method": "patch", "path": "/bbs/articles", "name": "bbs_articles_patch", + "strict": true, "parameters": [ { "type": "object", @@ -316,6 +318,7 @@ "method": "patch", "path": "/bbs/articles/abridges", "name": "bbs_articles_abridges_patch", + "strict": true, "parameters": [ { "type": "object", @@ -522,6 +525,7 @@ "method": "get", "path": "/bbs/articles/{id}", "name": "bbs_articles_getById", + "strict": true, "parameters": [ { "type": "string", @@ -649,6 +653,7 @@ "method": "put", "path": "/bbs/articles/{id}", "name": "bbs_articles_putById", + "strict": true, "parameters": [ { "type": "string", @@ -813,6 +818,7 @@ "method": "delete", "path": "/bbs/articles/{id}", "name": "bbs_articles_eraseById", + "strict": true, "parameters": [ { "type": "string", @@ -837,6 +843,7 @@ "method": "post", "path": "/membership/join", "name": "membership_join_post", + "strict": true, "parameters": [ { "type": "object", @@ -926,6 +933,7 @@ "method": "patch", "path": "/membership/login", "name": "membership_login_patch", + "strict": true, "parameters": [ { "type": "object", @@ -992,6 +1000,7 @@ "method": "get", "path": "/membership/{secret}", "name": "membership_getBySecret", + "strict": true, "parameters": [ { "type": "string", @@ -1043,6 +1052,7 @@ "method": "patch", "path": "/membership/change", "name": "membership_change_patch", + "strict": true, "parameters": [ { "type": "object", @@ -1145,6 +1155,7 @@ "method": "patch", "path": "/membership/{secret}/change", "name": "membership_change_patchBySecret", + "strict": true, "parameters": [ { "type": "string", @@ -1239,6 +1250,7 @@ "method": "post", "path": "/multipart", "name": "multipart_post", + "strict": true, "parameters": [ { "type": "object", @@ -1333,6 +1345,7 @@ "method": "get", "path": "/query/typed", "name": "query_typed_get", + "strict": true, "parameters": [ { "type": "object", @@ -1396,6 +1409,7 @@ "method": "get", "path": "/query/nest", "name": "query_nest_get", + "strict": true, "parameters": [ { "type": "object", @@ -1463,6 +1477,7 @@ "method": "get", "path": "/query/individual", "name": "query_individual_get", + "strict": true, "parameters": [ { "type": "object", @@ -1485,6 +1500,7 @@ "method": "get", "path": "/query/composite/{id}", "name": "query_composite_getById", + "strict": true, "parameters": [ { "type": "string", @@ -1551,6 +1567,7 @@ "method": "post", "path": "/query/body", "name": "query_body_post", + "strict": true, "parameters": [ { "type": "object", diff --git a/test/positional.json b/test/positional.json index 5ce2ba4..a697ac5 100644 --- a/test/positional.json +++ b/test/positional.json @@ -5,6 +5,7 @@ "method": "post", "path": "/bbs/articles", "name": "bbs_articles_post", + "strict": true, "parameters": [ { "type": "object", @@ -289,6 +290,7 @@ "method": "patch", "path": "/bbs/articles", "name": "bbs_articles_patch", + "strict": true, "parameters": [ { "type": "object", @@ -425,6 +427,7 @@ "method": "patch", "path": "/bbs/articles/abridges", "name": "bbs_articles_abridges_patch", + "strict": true, "parameters": [ { "type": "object", @@ -698,6 +701,7 @@ "method": "get", "path": "/bbs/articles/{id}", "name": "bbs_articles_getById", + "strict": true, "parameters": [ { "type": "string", @@ -838,6 +842,7 @@ "method": "put", "path": "/bbs/articles/{id}", "name": "bbs_articles_putById", + "strict": true, "parameters": [ { "type": "string", @@ -1090,6 +1095,7 @@ "method": "delete", "path": "/bbs/articles/{id}", "name": "bbs_articles_eraseById", + "strict": true, "parameters": [ { "type": "string", @@ -1141,6 +1147,7 @@ "method": "post", "path": "/membership/join", "name": "membership_join_post", + "strict": true, "parameters": [ { "type": "object", @@ -1292,6 +1299,7 @@ "method": "patch", "path": "/membership/login", "name": "membership_login_patch", + "strict": true, "parameters": [ { "type": "object", @@ -1396,6 +1404,7 @@ "method": "get", "path": "/membership/{secret}", "name": "membership_getBySecret", + "strict": true, "parameters": [ { "type": "string", @@ -1460,6 +1469,7 @@ "method": "patch", "path": "/membership/change", "name": "membership_change_patch", + "strict": true, "parameters": [ { "type": "object", @@ -1640,6 +1650,7 @@ "method": "patch", "path": "/membership/{secret}/change", "name": "membership_change_patchBySecret", + "strict": true, "parameters": [ { "type": "string", @@ -1804,6 +1815,7 @@ "method": "post", "path": "/multipart", "name": "multipart_post", + "strict": true, "parameters": [ { "type": "object", @@ -1962,6 +1974,7 @@ "method": "get", "path": "/query/typed", "name": "query_typed_get", + "strict": true, "parameters": [ { "type": "object", @@ -2061,6 +2074,7 @@ "method": "get", "path": "/query/nest", "name": "query_nest_get", + "strict": true, "parameters": [ { "type": "object", @@ -2168,6 +2182,7 @@ "method": "get", "path": "/query/individual", "name": "query_individual_get", + "strict": true, "parameters": [ { "type": "object", @@ -2210,6 +2225,7 @@ "method": "get", "path": "/query/composite/{id}", "name": "query_composite_getById", + "strict": true, "parameters": [ { "type": "string", @@ -2318,6 +2334,7 @@ "method": "post", "path": "/query/body", "name": "query_body_post", + "strict": true, "parameters": [ { "type": "object",