From 771c357f5c94251413137a75c12b9c725edbc09c Mon Sep 17 00:00:00 2001 From: Jeongho Nam Date: Wed, 27 Nov 2024 19:27:25 +0900 Subject: [PATCH] Prepare break changes on dependencies --- README.md | 8 +- package.json | 15 +-- src/HttpOpenAi.ts | 138 +++++++++++++++++++++++ src/IHttpOpenAiApplication.ts | 38 ++++--- src/IHttpOpenAiFunction.ts | 90 +++++++++++++-- src/IOpenAiApplication.ts | 41 ------- src/IOpenAiFunction.ts | 39 ------- src/IOpenAiSchema.ts | 158 +++----------------------- src/ISwagger.ts | 4 +- src/ISwaggerComponents.ts | 4 +- src/ISwaggerMigrateApplication.ts | 28 +---- src/ISwaggerMigrateRoute.ts | 48 +------- src/ISwaggerOperation.ts | 84 ++++---------- src/ISwaggerPath.ts | 14 +-- src/ISwaggerSchema.ts | 148 ++---------------------- src/OpenAiTypeChecker.ts | 125 +-------------------- src/index.ts | 4 +- test/index.ts | 179 ------------------------------ test/tsconfig.json | 19 ---- 19 files changed, 314 insertions(+), 870 deletions(-) create mode 100644 src/HttpOpenAi.ts delete mode 100644 src/IOpenAiApplication.ts delete mode 100644 src/IOpenAiFunction.ts delete mode 100644 test/index.ts delete mode 100644 test/tsconfig.json diff --git a/README.md b/README.md index 8487baa..ef28b9f 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,9 @@ const application: IHttpOpenAiApplication = HttpLlm.application(document); Kind | `@wrtnio/schema` | `@samchon/openapi` -------------------------------------------------------------------------------------------|------------------------------|--------------------------- -[**HTTP LLM Application**](https://wrtn.ai/studio-pro/tech-specs/meta/schema/#application) | **`IHttpOpenAiApplication`** | **`IHttpLlmApplication`** -[HTTP LLM Function Schema](https://wrtn.ai/studio-pro/tech-specs/meta/schema/#function) | `IHttpOpenAiFunction` | `IHttpLlmFunction` -[LLM Type Schema](https://wrtn.ai/studio-pro/tech-specs/meta/schema/#schema) | `IOpenAiSchema` | `ILlmSchema` -[LLM Function Schema](https://typia.io/docs/llm/application/) | `IOpenAiFunction` | `ILlmFunction` -[LLM Application](https://typia.io/docs/llm/application/) | `IOpenAiApplication` | `ILlmApplication` +[**HTTP LLM Application**](https://wrtn.ai/studio-pro/tech-specs/meta/schema/#application) | **`IHttpOpenAiApplication`** | **`IHttpLlmApplication<"3.0">`** +[HTTP LLM Function Schema](https://wrtn.ai/studio-pro/tech-specs/meta/schema/#function) | `IHttpOpenAiFunction` | `IHttpLlmFunction<3.0">` +[LLM Type Schema](https://wrtn.ai/studio-pro/tech-specs/meta/schema/#schema) | `IOpenAiSchema` | `ILlmSchema<"3.0">` [**OpenAPI Document**](https://wrtn.ai/studio-pro/tech-specs/openapi/document/#document) | **`ISwagger`** | **`OpenApi.IDocument`** [Server URL Address](https://wrtn.ai/studio-pro/tech-specs/openapi/document/#server) | `ISwaggerServer` | `OpenApi.IServer` [API Operation](https://wrtn.ai/studio-pro/tech-specs/openapi/document/#operation) | `ISwaggerOperation` | `OpenApi.IOperation` diff --git a/package.json b/package.json index 5bb8ced..a534b53 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,15 @@ { "name": "@wrtnio/schema", - "version": "1.3.0", + "version": "2.0.0-dev.20241127", "description": "JSON and LLM function calling schemas extended for Wrtn Studio Pro", "main": "lib/index.js", "module": "./lib/index.mjs", "typings": "./lib/index.d.ts", "scripts": { "prepare": "ts-patch install", - "build": "npm run build:main && npm run build:test", + "build": "npm run build:main", "build:main": "rimraf lib && tsc && rollup -c", - "build:test": "rimraf bin && tsc -p test/tsconfig.json", - "dev": "npm run build:test -- --watch", - "test": "node bin/test" + "dev": "rimraf lib && tsc --watch" }, "repository": { "type": "git", @@ -31,10 +29,7 @@ }, "homepage": "https://github.com/wrtnio/schema#readme", "dependencies": { - "@samchon/openapi": "^1.2.2" - }, - "peerDependencies": { - "@samchon/openapi": ">=1.2.2" + "@samchon/openapi": "^2.0.0-dev.20241127-2" }, "devDependencies": { "@rollup/plugin-terser": "^0.4.4", @@ -46,7 +41,7 @@ "ts-patch": "^3.2.1", "typescript": "5.5.4", "typescript-transform-paths": "^3.5.1", - "typia": "^6.10.2" + "typia": "^7.0.0-dev.20241127-2" }, "files": [ "lib", diff --git a/src/HttpOpenAi.ts b/src/HttpOpenAi.ts new file mode 100644 index 0000000..64f07c3 --- /dev/null +++ b/src/HttpOpenAi.ts @@ -0,0 +1,138 @@ +import { + HttpLlm, + IHttpConnection, + IHttpLlmApplication, + IHttpLlmFunction, +} from "@samchon/openapi"; + +import { IHttpOpenAiApplication } from "./IHttpOpenAiApplication"; +import { IHttpOpenAiFunction } from "./IHttpOpenAiFunction"; +import { ISwagger } from "./ISwagger"; + +export namespace HttpOpenAi { + /* ----------------------------------------------------------- + APPLICATION + ----------------------------------------------------------- */ + export const application = (props: { + document: ISwagger; + options?: Partial; + }): IHttpOpenAiApplication => { + const app: IHttpLlmApplication<"3.0"> = HttpLlm.application({ + model: "3.0", + document: props.document, + options: props.options, + }); + return { + ...app, + functions: app.functions.map(functional), + }; + }; + + const functional = ( + keyword: IHttpLlmFunction<"3.0">, + ): IHttpOpenAiFunction => { + const properties = new Map( + Object.keys(keyword.parameters.properties).map((name, i) => [name, i]), + ); + return { + ...keyword, + keyword: keyword.parameters, + parameters: Object.values(keyword.parameters.properties), + separated: keyword.separated + ? { + llm: Object.entries(keyword.separated.llm?.properties ?? {}).map( + ([key, value]) => ({ + schema: value, + index: properties.get(key) ?? 0, + }), + ), + human: Object.entries( + keyword.separated.human?.properties ?? {}, + ).map(([key, value]) => ({ + schema: value, + index: properties.get(key) ?? 0, + })), + keyword: keyword.separated, + } + : undefined, + }; + }; + + /* ----------------------------------------------------------- + FETCHERS + ----------------------------------------------------------- */ + export interface IFetchProps { + connection: IHttpConnection; + application: IHttpOpenAiApplication; + function: IHttpOpenAiFunction; + arguments: unknown[]; + } + + export const execute = async (props: IFetchProps): Promise => + HttpLlm.execute(getProps(props)); + + export const propagate = async (props: IFetchProps): Promise => + HttpLlm.propagate(getProps(props)); + + const getProps = (props: IFetchProps): HttpLlm.IFetchProps<"3.0"> => { + const keys: string[] = Object.keys(props.function.keyword.properties); + const input: Record = Object.fromEntries( + props.arguments.map((arg, i) => [keys[i], arg]), + ); + return { + connection: props.connection, + application: { + ...props.application, + functions: [], + }, + function: { + ...props.function, + parameters: props.function.keyword, + separated: props.function.separated?.keyword, + }, + input, + }; + }; + + /* ----------------------------------------------------------- + MERGERS + ----------------------------------------------------------- */ + export interface IMergeProps { + function: IHttpOpenAiFunction; + llm: unknown[]; + human: unknown[]; + } + + export const mergeParameters = (props: IMergeProps): unknown[] => { + const separated: IHttpOpenAiFunction.ISeparated | undefined = + props.function.separated; + if (separated === undefined) + throw new Error( + "Error on OpenAiDataComposer.parameters(): the function parameters are not separated.", + ); + return new Array(props.function.parameters.length).fill(0).map((_, i) => { + const llm: number = separated.llm.findIndex((p) => p.index === i); + const human: number = separated.human.findIndex((p) => p.index === i); + if (llm === -1 && human === -1) + throw new Error( + "Error on OpenAiDataComposer.parameters(): failed to gather separated arguments, because both LLM and human sides are all empty.", + ); + return mergeValue(props.llm[llm], props.human[human]); + }); + }; + + export const mergeValue = (x: unknown, y: unknown): unknown => + typeof x === "object" && typeof y === "object" && x !== null && y !== null + ? combineObject(x, y) + : Array.isArray(x) && Array.isArray(y) + ? new Array(Math.max(x.length, y.length)) + .fill(0) + .map((_, i) => mergeValue(x[i], y[i])) + : (y ?? x); + + const combineObject = (x: any, y: any): any => { + const output: any = { ...x }; + for (const [k, v] of Object.entries(y)) output[k] = mergeValue(x[k], v); + return output; + }; +} diff --git a/src/IHttpOpenAiApplication.ts b/src/IHttpOpenAiApplication.ts index 17b865f..e8efbb7 100644 --- a/src/IHttpOpenAiApplication.ts +++ b/src/IHttpOpenAiApplication.ts @@ -1,29 +1,28 @@ import { IHttpLlmApplication } from "@samchon/openapi"; -import { IOpenAiSchema } from "./IOpenAiSchema"; -import { ISwaggerMigrateRoute } from "./ISwaggerMigrateRoute"; +import { IHttpOpenAiFunction } from "./IHttpOpenAiFunction"; import { ISwaggerOperation } from "./ISwaggerOperation"; /** * Application of OpenAI (LLM) function call from OpenAPI document. * * `IHttpOpenAiApplication` is a data structure representing a collection of - * {@link IOpenAiFunction LLM function calling schemas} composed from the + * {@link IHttpOpenAiFunction LLM function calling schemas} composed from the * {@link ISwagger OpenAPI document} and its {@link ISwaggerOperation operation} * metadata. It also contains {@link IHttpOpenAiApplication.errors failed operations}, and * adjusted {@link IHttpOpenAiApplication.options options} during the * `IHttpOpenAiApplication` construction. * * About the {@link ISwaggerOperation API operations}, they are converted to - * {@link IOpenAiFunction} type which represents LLM function calling schema. + * {@link IHttpOpenAiFunction} type which represents LLM function calling schema. * By the way, if tehre're some recursive types which can't escape the * {@link ISwaggerSchema.IReference} type, the operation would be failed and * pushed into the {@link IHttpOpenAiApplication.errors}. Otherwise not, the operation - * would be successfully converted to {@link IOpenAiFunction} and its type schemas + * would be successfully converted to {@link IHttpOpenAiFunction} and its type schemas * are downgraded to {@link OpenApiV3.IJsonSchema} and converted to {@link ILlmSchema}. * * About the options, if you've configured {@link IHttpOpenAiApplication.options.keyword} - * (as `true`), number of {@link IOpenAiFunction.parameters} are always 1 and the first + * (as `true`), number of {@link IHttpOpenAiFunction.parameters} are always 1 and the first * parameter type is always {@link ILlmSchema.IObject}. Otherwise, the parameters would * be multiple, and the sequence of the parameters are following below rules. * @@ -52,7 +51,7 @@ import { ISwaggerOperation } from "./ISwaggerOperation"; * like secrety key (password) are the examples. In that case, you can separate the * function parameters to both LLM and Human sides by configuring the * {@link IHttpOpenAiApplication.IOptions.separate} property. The separated parameters are - * assigned to the {@link IOpenAiFunction.separated} property. + * assigned to the {@link IHttpOpenAiFunction.separated} property. * * For reference, the actual function call execution is not by LLM, but by you. * When the LLM selects the proper function and fills the arguments, you just call @@ -66,24 +65,29 @@ import { ISwaggerOperation } from "./ISwaggerOperation"; * before the actual LLM function call execution. * * @reference https://platform.openai.com/docs/guides/function-calling + * @deprecated OpenAI's JSON schema specification has been changed * @author Samchon */ -export type IHttpOpenAiApplication = IHttpLlmApplication< - IOpenAiSchema, - ISwaggerOperation, - ISwaggerMigrateRoute ->; +export interface IHttpOpenAiApplication + extends Omit, "functions"> { + /** + * List of function metadata. + * + * List of function metadata that can be used for the LLM function call. + * + * When you want to execute the function with LLM constructed arguments, + * you can do it through {@link HttpOpenAi.execute} function. + */ + functions: IHttpOpenAiFunction[]; +} export namespace IHttpOpenAiApplication { /** * Error occurred in the composition. */ - export type IError = IHttpLlmApplication.IError< - ISwaggerOperation, - ISwaggerMigrateRoute - >; + export type IError = IHttpLlmApplication.IError; /** * Options for composing the LLM application. */ - export type IOptions = IHttpLlmApplication.IOptions; + export type IOptions = IHttpLlmApplication.IOptions<"3.0">; } diff --git a/src/IHttpOpenAiFunction.ts b/src/IHttpOpenAiFunction.ts index 325635b..004d1e8 100644 --- a/src/IHttpOpenAiFunction.ts +++ b/src/IHttpOpenAiFunction.ts @@ -1,7 +1,6 @@ import { IHttpLlmFunction } from "@samchon/openapi"; import { IOpenAiSchema } from "./IOpenAiSchema"; -import { ISwaggerMigrateRoute } from "./ISwaggerMigrateRoute"; import { ISwaggerOperation } from "./ISwaggerOperation"; /** @@ -54,22 +53,95 @@ import { ISwaggerOperation } from "./ISwaggerOperation"; * ``` * * @reference https://platform.openai.com/docs/guides/function-calling + * @deprecated OpenAI's JSON schema specification has been changed * @author Samchon */ -export type IHttpOpenAiFunction = IHttpLlmFunction< - IOpenAiSchema, - ISwaggerOperation, - ISwaggerMigrateRoute ->; +export interface IHttpOpenAiFunction + extends Omit, "parameters" | "separated"> { + /** + * List of parameter types. + * + * If you've configured {@link IHttpLlmApplication.IOptions.keyword} as `true`, + * number of {@link IHttpLlmFunction.parameters} are always 1 and the first + * parameter's type is always {@link ILlmSchema.IObject}. The + * properties' rule is: + * + * - `pathParameters`: Path parameters of {@link IHttpMigrateRoute.parameters} + * - `query`: Query parameter of {@link IHttpMigrateRoute.query} + * - `body`: Body parameter of {@link IHttpMigrateRoute.body} + * + * ```typescript + * { + * ...pathParameters, + * query, + * body, + * } + * ``` + * + * Otherwise, the parameters would be multiple, and the sequence of the + * parameters are following below rules: + * + * ```typescript + * [ + * ...pathParameters, + * ...(query ? [query] : []), + * ...(body ? [body] : []), + * ] + * ``` + */ + parameters: IOpenAiSchema[]; + + /** + * The keyworded parameters. + */ + keyword: IOpenAiSchema.IParameters; + + /** + * Collection of separated parameters. + * + * Filled only when {@link IHttpLlmApplication.IOptions.separate} is configured. + */ + separated?: IHttpOpenAiFunction.ISeparated; +} export namespace IHttpOpenAiFunction { + export interface IOptions extends IOpenAiSchema.IConfig { + separate: null | ((schema: IOpenAiSchema) => boolean); + } + /** * Collection of separated parameters. */ - export type ISeparated = IHttpLlmFunction.ISeparated; + export interface ISeparated { + /** + * Parameters that would be composed by the LLM. + */ + llm: ISeparatedParameter[]; + + /** + * Parameters that would be composed by the human. + */ + human: ISeparatedParameter[]; + + /** + * The keyworded parameters' separation. + */ + keyword: IHttpLlmFunction.ISeparated; + } /** * Separated parameter. */ - export type ISeparatedParameter = - IHttpLlmFunction.ISeparatedParameter; + export interface ISeparatedParameter { + /** + * Index of the parameter. + * + * @type uint + */ + index: number; + + /** + * Type schema info of the parameter. + */ + schema: IOpenAiSchema; + } } diff --git a/src/IOpenAiApplication.ts b/src/IOpenAiApplication.ts deleted file mode 100644 index 46b0462..0000000 --- a/src/IOpenAiApplication.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { ILlmApplication } from "@samchon/openapi"; - -import { IOpenAiSchema } from "./IOpenAiSchema"; - -/** - * Application of OpenAI (LLM) function calling. - * - * `IOpenAiApplication` is a data structure representing a collection of - * {@link IOpenAiFunction LLM function calling schemas}, composed from a native - * TypeScript class (or interface) type by the `typia.llm.application()` - * function. - * - * By the way, the LLM function calling application composition, converting - * `IOpenAiApplication` instance from TypeScript interface (or class) type is not always - * successful. As LLM provider like OpenAI cannot understand the recursive reference - * type that is embodied by {@link OpenApi.IJsonSchema.IReference}, if there're some - * recursive types in the TypeScript interface (or class) type, the conversion would - * be failed. - * - * Also, there can be some parameters (or their nested properties) which must be - * composed by Human, not by LLM. File uploading feature or some sensitive information - * like secrety key (password) are the examples. In that case, you can separate the - * function parameters to both LLM and human sides by configuring the - * {@link IOpenAiApplication.IOptions.separate} property. The separated parameters are - * assigned to the {@link IOpenAiFunction.separated} property. - * - * For reference, when both LLM and Human filled parameter values to call, you can - * merge them by calling the {@link HttpLlm.mergeParameters} function. In other words, - * if you've configured the {@link IOpenAiApplication.IOptions.separate} property, - * you have to merge the separated parameters before the funtion call execution. - * - * @reference https://platform.openai.com/docs/guides/function-calling - * @author Samchon - */ -export type IOpenAiApplication = ILlmApplication; -export namespace IOpenAiApplication { - /** - * Options for composing the LLM application. - */ - export type IOptions = ILlmApplication.IOptions; -} diff --git a/src/IOpenAiFunction.ts b/src/IOpenAiFunction.ts deleted file mode 100644 index 9647bdc..0000000 --- a/src/IOpenAiFunction.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { ILlmFunction } from "@samchon/openapi/lib/structures/ILlmFunction"; - -import { IOpenAiSchema } from "./IOpenAiSchema"; - -/** - * OpenAI (LLM) function metadata. - * - * `IOpenAiFunction` is an interface representing a function metadata, - * which has been used for the LLM (Language Large Model) function - * calling. Also, it's a function structure containing the function - * {@link name}, {@link parameters} and {@link output return type}. - * - * If you provide this `IOpenAiFunction` data to the LLM provider like "OpenAI", - * the "OpenAI" will compose a function arguments by analyzing conversations - * with the user. With the LLM composed arguments, you can execute the function - * and get the result. - * - * By the way, do not ensure that LLM will always provide the correct - * arguments. The LLM of present age is not perfect, so that you would - * better to validate the arguments before executing the function. - * I recommend you to validate the arguments before execution by using - * [`typia`](https://github.com/samchon/typia) library. - * - * @reference https://platform.openai.com/docs/guides/function-calling - * @author Samchon - */ -export type IOpenAiFunction = ILlmFunction; -export namespace IOpenAiFunction { - /** - * Collection of separated parameters. - */ - export type ISeparated = ILlmFunction.ISeparated; - - /** - * Separated parameter. - */ - export type ISeparatedParameter = - ILlmFunction.ISeparatedParameter; -} diff --git a/src/IOpenAiSchema.ts b/src/IOpenAiSchema.ts index fd22785..98eee67 100644 --- a/src/IOpenAiSchema.ts +++ b/src/IOpenAiSchema.ts @@ -1,152 +1,20 @@ -import { ILlmSchema } from "@samchon/openapi"; +import { ILlmSchemaV3 } from "@samchon/openapi"; import { ISwaggerSchemaCommonPlugin } from "./ISwaggerSchemaCommonPlugin"; import { ISwaggerSchemaPaymentPlugin } from "./ISwaggerSchemaPaymentPlugin"; import { ISwaggerSchemaSecurityPlugin } from "./ISwaggerSchemaSecurityPlugin"; -/** - * Type schema info of OpenAI (LLM) function call. - * - * `IOpenAiSchema` is a type schema info of OpenAI function call. - * - * `IOpenAiSchema` is basically follows the JSON schema definition of - * OpenAI v3.0: {@link OpenApiV3.IJsonSchema}. However, `IOpenAiSchema` does not - * have the reference type {@link OpenApiV3.IJsonSchema.IReference}. It's because - * the OpenAI cannot compose - * {@link OpenAiFetcher.IProps.arguments function call arguments} of - * the reference type. - * - * For reference, the OpenAPI v3.0 based JSON schema definition can't express - * the tuple array type. It has been supported since OpenAPI v3.1. Therefore, - * it would better to avoid using the tuple array type. - * - * @reference https://platform.openai.com/docs/guides/function-calling - * @author Samchon - */ -export type IOpenAiSchema = - | IOpenAiSchema.IBoolean - | IOpenAiSchema.IInteger - | IOpenAiSchema.INumber - | IOpenAiSchema.IString - | IOpenAiSchema.IArray - | IOpenAiSchema.IObject - | IOpenAiSchema.IUnknown - | IOpenAiSchema.INullOnly - | IOpenAiSchema.IOneOf; -export namespace IOpenAiSchema { - /** - * Boolean type schema info. - */ - export interface IBoolean - extends ILlmSchema.IBoolean, - ISwaggerSchemaCommonPlugin {} - - /** - * Integer type schema info. - */ - export interface IInteger - extends ILlmSchema.IInteger, - ISwaggerSchemaCommonPlugin, - ISwaggerSchemaPaymentPlugin.INumeric {} - - /** - * Number type schema info. - */ - export interface INumber - extends ILlmSchema.INumber, - ISwaggerSchemaCommonPlugin, - ISwaggerSchemaPaymentPlugin.INumeric {} - - /** - * String type schema info. - */ - export interface IString - extends ILlmSchema.IString, - ISwaggerSchemaCommonPlugin, - ISwaggerSchemaPaymentPlugin.IString, - ISwaggerSchemaSecurityPlugin {} - - /** - * Array type schema info. - */ - export interface IArray - extends Omit, - ISwaggerSchemaCommonPlugin { - /** - * Items type schema info. - * - * The `items` means the type of the array elements. In other words, it is - * the type schema info of the `T` in the TypeScript array type `Array`. - */ - items: IOpenAiSchema; - } - - /** - * Object type schema info. - */ - export interface IObject - extends Omit, - ISwaggerSchemaCommonPlugin { - /** - * Properties of the object. - * - * The `properties` means a list of key-value pairs of the object's - * regular properties. The key is the name of the regular property, - * and the value is the type schema info. - * - * If you need additional properties that is represented by dynamic key, - * you can use the {@link additionalProperties} instead. - */ - properties?: Record; - - /** - * Additional properties' info. - * - * The `additionalProperties` means the type schema info of the additional - * properties that are not listed in the {@link properties}. - * - * If the value is `true`, it means that the additional properties are not - * restricted. They can be any type. Otherwise, if the value is - * {@link ILlmSchema} type, it means that the additional properties must - * follow the type schema info. - * - * - `true`: `Record` - * - `ILlmSchema`: `Record` - */ - additionalProperties?: boolean | IOpenAiSchema; - } - - /** - * Unknown type schema info. - * - * It means the type of the value is `any`. - */ - export interface IUnknown - extends ILlmSchema.IUnknown, - ISwaggerSchemaCommonPlugin {} - - /** - * Null only type schema info. - */ - export interface INullOnly - extends ILlmSchema.INullOnly, - ISwaggerSchemaCommonPlugin {} - - /** - * One of type schema info. - * - * `IOneOf` represents an union type of the TypeScript (`A | B | C`). - * - * For reference, even though your Swagger (or OpenAPI) document has - * defined `anyOf` instead of the `oneOf`, {@link OpenAiComposer} forcibly - * converts it to `oneOf` type. - */ - export interface IOneOf - extends Omit, - ISwaggerSchemaCommonPlugin { - /** - * List of the union types. - */ - oneOf: Exclude[]; +export import IOpenAiSchema = ILlmSchemaV3; + +declare module "@samchon/openapi" { + export namespace ILlmSchemaV3 { + export namespace IJsonSchema { + export interface IInteger extends ISwaggerSchemaPaymentPlugin.INumeric {} + export interface INumber extends ISwaggerSchemaPaymentPlugin.INumeric {} + export interface IString + extends ISwaggerSchemaPaymentPlugin.IString, + ISwaggerSchemaSecurityPlugin {} + export interface __IAttribute extends ISwaggerSchemaCommonPlugin {} + } } } diff --git a/src/ISwagger.ts b/src/ISwagger.ts index 63a040c..7dbea53 100644 --- a/src/ISwagger.ts +++ b/src/ISwagger.ts @@ -1,7 +1,9 @@ import { OpenApi, OpenApiV3_1 } from "@samchon/openapi"; import { ISwaggerOperation } from "./ISwaggerOperation"; +import "./ISwaggerOperation"; import { ISwaggerSchema } from "./ISwaggerSchema"; +import "./ISwaggerSchema"; /** * Swagger Document. @@ -35,4 +37,4 @@ import { ISwaggerSchema } from "./ISwaggerSchema"; * * @author Samchon */ -export type ISwagger = OpenApi.IDocument; +export import ISwagger = OpenApi.IDocument; diff --git a/src/ISwaggerComponents.ts b/src/ISwaggerComponents.ts index 5db7097..382efe2 100644 --- a/src/ISwaggerComponents.ts +++ b/src/ISwaggerComponents.ts @@ -1,6 +1,6 @@ import { OpenApi } from "@samchon/openapi"; -import { ISwaggerSchema } from "./ISwaggerSchema"; +import "./ISwaggerSchema"; /** * Reusable components in Swagger. @@ -11,4 +11,4 @@ import { ISwaggerSchema } from "./ISwaggerSchema"; * * @author Samchon */ -export type ISwaggerComponents = OpenApi.IComponents; +export import ISwaggerComponents = OpenApi.IComponents; diff --git a/src/ISwaggerMigrateApplication.ts b/src/ISwaggerMigrateApplication.ts index c3e1443..2366b5b 100644 --- a/src/ISwaggerMigrateApplication.ts +++ b/src/ISwaggerMigrateApplication.ts @@ -1,28 +1,6 @@ import { IHttpMigrateApplication } from "@samchon/openapi"; -import { ISwaggerOperation } from "./ISwaggerOperation"; -import { ISwaggerSchema } from "./ISwaggerSchema"; +import "./ISwaggerOperation"; +import "./ISwaggerSchema"; -/** - * Document of migration. - * - * The `ISwaggerMigrateApplication` interface is an application migrated - * from {@link ISwagger OpenAPI document} to RPC (Remote Procedure Call) - * functions; {@link ISwaggerMigrateRoute}. - * - * As the `ISwaggerMigrate` and {@link ISwaggerMigrateRoute} have a lot of - * special stories, when you're developing OpenAPI generator library, please - * read their descriptions carefully including the description of properties. - * - * @author Samchon - */ -export type ISwaggerMigrateApplication = IHttpMigrateApplication< - ISwaggerSchema, - ISwaggerOperation ->; -export namespace ISwaggerMigrateApplication { - /** - * Error of migration in the operation level. - */ - export type IError = IHttpMigrateApplication.IError; -} +export import ISwaggerMigrateApplication = IHttpMigrateApplication; diff --git a/src/ISwaggerMigrateRoute.ts b/src/ISwaggerMigrateRoute.ts index 4847331..fd46751 100644 --- a/src/ISwaggerMigrateRoute.ts +++ b/src/ISwaggerMigrateRoute.ts @@ -1,48 +1,6 @@ import { IHttpMigrateRoute } from "@samchon/openapi"; -import { ISwaggerOperation } from "./ISwaggerOperation"; -import { ISwaggerSchema } from "./ISwaggerSchema"; +import "./ISwaggerOperation"; +import "./ISwaggerSchema"; -/** - * Route information for migration. - * - * The `ISwaggerMigrateRoute` is a structure representing a route information - * for OpenAPI generated RPC (Remote Procedure Call) function composed from the - * {@link ISwaggerOperation OpenAPI operation}. - * - * As the `ISwaggerMigrateRoute` has a lot of speical stories, when you're - * developing OpenAPI generator library, please read its description carefully - * including the description of its properties. - * - * @author Samchon - */ -export type ISwaggerMigrateRoute = IHttpMigrateRoute< - ISwaggerSchema, - ISwaggerOperation ->; -export namespace ISwaggerMigrateRoute { - /** - * Metadata of path parameter. - */ - export type IParameter = IHttpMigrateRoute.IParameter; - - /** - * Metadata of headers. - */ - export type IHeaders = IHttpMigrateRoute.IHeaders; - - /** - * Metadata of query values. - */ - export type IQuery = IHttpMigrateRoute.IQuery; - - /** - * Metadata of request/response body. - */ - export type IBody = IHttpMigrateRoute.IBody; - - /** - * Metadata of response body for exceptional status cases. - */ - export type IException = IHttpMigrateRoute.IException; -} +export import ISwaggerMigrateRoute = IHttpMigrateRoute; diff --git a/src/ISwaggerOperation.ts b/src/ISwaggerOperation.ts index 8de5a4b..6958741 100644 --- a/src/ISwaggerOperation.ts +++ b/src/ISwaggerOperation.ts @@ -1,65 +1,27 @@ import { OpenApi } from "@samchon/openapi"; import { tags } from "typia"; -import { ISwaggerSchema } from "./ISwaggerSchema"; - -/** - * Remote operation info. - * - * `ISwaggerOperation` represents an Restful API operation provided by the - * remote server. - * - * @author Samchon - */ -export interface ISwaggerOperation extends OpenApi.IOperation { - /** - * Icon URL. - * - * `x-wrtn-icon` is a property means an icon URL representing the target API. - */ - "x-wrtn-icon"?: string & tags.Format<"uri">; - - /** - * Whether standalone API or not. - * - * `x-wrtn-standalone` is a property means whether the target API is standalone - * so that it can be called without any other APIs or not. - */ - "x-wrtn-standalone"?: boolean; -} -export namespace ISwaggerOperation { - /** - * Method of the operation. - */ - export type Method = OpenApi.Method; - - /** - * Parameter of the operation. - */ - export type IParameter = OpenApi.IOperation.IParameter; - - /** - * Request body of the operation. - */ - export type IRequestBody = OpenApi.IOperation.IRequestBody; - - /** - * Response of the operation. - */ - export type IResponse = OpenApi.IOperation.IResponse; - - /** - * List of content types supported in request/response body. - */ - export type IContent = OpenApi.IOperation.IContent; - - /** - * Media type of a request/response body. - */ - export type IMediaType = OpenApi.IOperation.IMediaType; - - /** - * List of supported content media types. - */ - export type ContentType = OpenApi.IOperation.ContentType; +import "./ISwaggerSchema"; + +export import ISwaggerOperation = OpenApi.IOperation; + +declare module "@samchon/openapi" { + export namespace OpenApi { + export interface IOperation { + /** + * Icon URL. + * + * `x-wrtn-icon` is a property means an icon URL representing the target API. + */ + "x-wrtn-icon"?: string & tags.Format<"uri">; + + /** + * Whether standalone API or not. + * + * `x-wrtn-standalone` is a property means whether the target API is standalone + * so that it can be called without any other APIs or not. + */ + "x-wrtn-standalone"?: boolean; + } + } } diff --git a/src/ISwaggerPath.ts b/src/ISwaggerPath.ts index a6aba1f..834ccbc 100644 --- a/src/ISwaggerPath.ts +++ b/src/ISwaggerPath.ts @@ -1,14 +1,6 @@ import { OpenApi } from "@samchon/openapi"; -import { ISwaggerOperation } from "./ISwaggerOperation"; -import { ISwaggerSchema } from "./ISwaggerSchema"; +import "./ISwaggerOperation"; +import "./ISwaggerSchema"; -/** - * Path item. - * - * `ISwaggerPath` represents a path item of emended OpenAPI v3.1, - * collecting multiple method operations in a single path. - * - * @author Samchon - */ -export type ISwaggerPath = OpenApi.IPath; +export import ISwaggerPath = OpenApi.IPath; diff --git a/src/ISwaggerSchema.ts b/src/ISwaggerSchema.ts index ebc05e0..39a7a75 100644 --- a/src/ISwaggerSchema.ts +++ b/src/ISwaggerSchema.ts @@ -4,141 +4,17 @@ import { ISwaggerSchemaCommonPlugin } from "./ISwaggerSchemaCommonPlugin"; import { ISwaggerSchemaPaymentPlugin } from "./ISwaggerSchemaPaymentPlugin"; import { ISwaggerSchemaSecurityPlugin } from "./ISwaggerSchemaSecurityPlugin"; -/** - * Type schema info. - * - * `ISwaggerSchema` is a type schema info of the OpenAPI v3.1 specification, - * but a little shrinked and removed ambiguous and duplicated expressions of - * OpenAPI v3.1 fopr the convenience and clarity. - * - * - Decompose mixed type: {@link OpenApiV3_1.IJsonSchema.IMixed} - * - Resolve nullable property: {@link OpenApiV3_1.IJsonSchema.__ISignificant.nullable} - * - Array type utilizes only single {@link OpenAPI.IJsonSchema.IArray.items} - * - Tuple type utilizes only {@link OpenApi.IJsonSchema.ITuple.prefixItems} - * - Merge {@link OpenApiV3_1.IJsonSchema.IAnyOf} to {@link OpenApi.IJsonSchema.IOneOf} - * - Merge {@link OpenApiV3_1.IJsonSchema.IRecursiveReference} to {@link OpenApi.IJsonSchema.IReference} - * - Merge {@link OpenApiV3_1.IJsonSchema.IAllOf} to {@link OpenApi.IJsonSchema.IObject} - * - * Also, `ISwaggerSchema` extended some plugin properties for LLM - * (Large Language Model, OpenAI) function calling purpose. Below is the list of - * plugin properties newly added from {@link OpenApi.IJsonSchema} to `ISwaggerSchema`. - * - * - {@link ISwaggerSchema.IString.x-wrtn-secret-key} - * - {@link ISwaggerSchema.IString.x-wrtn-secret-scopes} - * - {@link ISwaggerSchemaCommonPlugin.x-wrtn-placeholder} - * - {@link ISwaggerSchemaCommonPlugin.x-wrtn-prerequisite} - * - * @author Samchon - */ -export type ISwaggerSchema = - | ISwaggerSchema.IConstant - | ISwaggerSchema.IBoolean - | ISwaggerSchema.IInteger - | ISwaggerSchema.INumber - | ISwaggerSchema.IString - | ISwaggerSchema.IArray - | ISwaggerSchema.ITuple - | ISwaggerSchema.IObject - | ISwaggerSchema.IReference - | ISwaggerSchema.IOneOf - | ISwaggerSchema.INull - | ISwaggerSchema.IUnknown; -export namespace ISwaggerSchema { - /** - * Constant value type. - */ - export interface IConstant - extends OpenApi.IJsonSchema.IConstant, - ISwaggerSchemaCommonPlugin {} - - /** - * Boolean type info. - */ - export interface IBoolean - extends OpenApi.IJsonSchema.IBoolean, - ISwaggerSchemaCommonPlugin {} - - /** - * Integer type info. - */ - export interface IInteger - extends OpenApi.IJsonSchema.IInteger, - ISwaggerSchemaCommonPlugin, - ISwaggerSchemaPaymentPlugin.INumeric {} - - /** - * Number (double) type info. - */ - export interface INumber - extends OpenApi.IJsonSchema.INumber, - ISwaggerSchemaPaymentPlugin.INumeric {} - - /** - * String type info. - */ - export interface IString - extends OpenApi.IJsonSchema.IString, - ISwaggerSchemaCommonPlugin, - ISwaggerSchemaPaymentPlugin.IString, - ISwaggerSchemaSecurityPlugin {} - - /** - * Array type info. - */ - export interface IArray - extends OpenApi.IJsonSchema.IArray, - ISwaggerSchemaCommonPlugin {} - - /** - * Tuple type info. - */ - export interface ITuple - extends OpenApi.IJsonSchema.ITuple, - ISwaggerSchemaCommonPlugin {} - - /** - * Object type info. - */ - export interface IObject - extends OpenApi.IJsonSchema.IObject, - ISwaggerSchemaCommonPlugin {} - - /** - * Reference type directing named schema. - */ - export interface IReference - extends OpenApi.IJsonSchema.IReference, - ISwaggerSchemaCommonPlugin {} - - /** - * Union type. - * - * IOneOf` represents an union type of the TypeScript (`A | B | C`). - * - * For reference, even though your Swagger (or OpenAPI) document has - * defined `anyOf` instead of the `oneOf`, {@link OpenApi} forcibly - * converts it to `oneOf` type. - */ - export interface IOneOf - extends Omit, - ISwaggerSchemaCommonPlugin { - /** - * List of the union types. - */ - oneOf: Exclude[]; +export import ISwaggerSchema = OpenApi.IJsonSchema; + +declare module "@samchon/openapi" { + export namespace OpenApi { + export namespace IJsonSchema { + export interface IInteger extends ISwaggerSchemaPaymentPlugin.INumeric {} + export interface INumber extends ISwaggerSchemaPaymentPlugin.INumeric {} + export interface IString + extends ISwaggerSchemaPaymentPlugin.IString, + ISwaggerSchemaSecurityPlugin {} + export interface __IAttribute extends ISwaggerSchemaCommonPlugin {} + } } - - /** - * Null type. - */ - export interface INull - extends OpenApi.IJsonSchema.INull, - ISwaggerSchemaCommonPlugin {} - - /** - * Unknown, `any` type. - */ - export interface IUnknown - extends OpenApi.IJsonSchema.IUnknown, - ISwaggerSchemaCommonPlugin {} } diff --git a/src/OpenAiTypeChecker.ts b/src/OpenAiTypeChecker.ts index b57db44..3b07543 100644 --- a/src/OpenAiTypeChecker.ts +++ b/src/OpenAiTypeChecker.ts @@ -1,124 +1,5 @@ -import { LlmTypeChecker } from "@samchon/openapi"; +import { LlmTypeCheckerV3 } from "@samchon/openapi"; -import { IOpenAiSchema } from "./IOpenAiSchema"; +import "./IOpenAiSchema"; -/** - * Type checker for OpenAI function call schema. - * - * `OpenAiTypeChecker` is a type checker of {@link IOpenAiSchema}. - * - * @author Samchon - */ -export namespace OpenAiTypeChecker { - /** - * Visit every nested schemas. - * - * Visit every nested schemas of the target, and apply the callback function - * to them. - * - * If the visitor meets an union type, it will visit every individual schemas - * in the union type. Otherwise meets an object type, it will visit every - * properties and additional properties. If the visitor meets an array type, - * it will visit the item type. - * - * @param schema Target schema to visit - * @param callback Callback function to apply - */ - export const visit = ( - schema: IOpenAiSchema, - callback: (schema: IOpenAiSchema) => void, - ): void => LlmTypeChecker.visit(schema, callback); - - /** - * Test whether the schema is an union type. - * - * @param schema Target schema - * @returns Whether union type or not - */ - export const isOneOf = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IOneOf => LlmTypeChecker.isOneOf(schema); - - /** - * Test whether the schema is an object type. - * - * @param schema Target schema - * @returns Whether object type or not - */ - export const isObject = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IObject => LlmTypeChecker.isObject(schema); - - /** - * Test whether the schema is an array type. - * - * @param schema Target schema - * @returns Whether array type or not - */ - export const isArray = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IArray => LlmTypeChecker.isArray(schema); - - /** - * Test whether the schema is a boolean type. - * - * @param schema Target schema - * @returns Whether boolean type or not - */ - export const isBoolean = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IBoolean => LlmTypeChecker.isBoolean(schema); - - /** - * Test whether the schema is a number type. - * - * @param schema Target schema - * @returns Whether number type or not - */ - export const isNumber = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.INumber => LlmTypeChecker.isNumber(schema); - - export const isInteger = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IInteger => LlmTypeChecker.isInteger(schema); - - /** - * Test whether the schema is a string type. - * - * @param schema Target schema - * @returns Whether string type or not - */ - export const isString = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IString => LlmTypeChecker.isString(schema); - - /** - * Test whether the schema is a null type. - * - * @param schema Target schema - * @returns Whether null type or not - */ - export const isNullOnly = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.INullOnly => LlmTypeChecker.isNullOnly(schema); - - /** - * Test whether the schema is a nullable type. - * - * @param schema Target schema - * @returns Whether nullable type or not - */ - export const isNullable = (schema: IOpenAiSchema): boolean => - LlmTypeChecker.isNullable(schema); - - /** - * Test whether the schema is an unknown type. - * - * @param schema Target schema - * @returns Whether unknown type or not - */ - export const isUnknown = ( - schema: IOpenAiSchema, - ): schema is IOpenAiSchema.IUnknown => LlmTypeChecker.isUnknown(schema); -} +export import OpenAiTypeChecker = LlmTypeCheckerV3; diff --git a/src/index.ts b/src/index.ts index 24b9479..315294c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,9 @@ // LLM TYPES export * from "./IHttpOpenAiApplication"; export * from "./IHttpOpenAiFunction"; -export * from "./IOpenAiApplication"; -export * from "./IOpenAiFunction"; - export * from "./IOpenAiSchema"; export * from "./OpenAiTypeChecker"; +export * from "./HttpOpenAi"; // OPENAPI TYPES export * from "./ISwagger"; diff --git a/test/index.ts b/test/index.ts deleted file mode 100644 index 8c5737c..0000000 --- a/test/index.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { - IHttpLlmApplication, - IHttpLlmFunction, - IHttpMigrateApplication, - IHttpMigrateRoute, - ILlmApplication, - ILlmSchema, - OpenApi, -} from "@samchon/openapi"; -import { ILlmFunction } from "@samchon/openapi/lib/structures/ILlmFunction"; -import { - IHttpOpenAiApplication, - IHttpOpenAiFunction, - IOpenAiApplication, - IOpenAiFunction, - IOpenAiSchema, - ISwagger, - ISwaggerComponents, - ISwaggerMigrateApplication, - ISwaggerMigrateRoute, - ISwaggerOperation, - ISwaggerPath, - ISwaggerSchema, -} from "@wrtnio/schema"; -import typia from "typia"; - -const validate = (props: { - createX: () => X; - createY: () => Y; - assertX: (input: unknown) => X; - assertY: (input: unknown) => Y; -}): void => - new Array(1_000).fill(0).forEach(() => { - const x = props.createX(); - const y = props.createY(); - props.assertX(x); - props.assertX(y); - props.assertY(x); - props.assertY(y); - }); - -// OPENAPI DOCUMENT -{ - let doc1: OpenApi.IDocument = null!; - let doc2: ISwagger = doc1; - doc1 = doc2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let comp1: OpenApi.IComponents = null!; - let comp2: ISwaggerComponents = comp1; - comp1 = comp2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let path1: OpenApi.IPath = null!; - let path2: ISwaggerPath = path1; - path1 = path2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let op1: OpenApi.IOperation = null!; - let op2: ISwaggerOperation = op1; - op1 = op2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let schema1: OpenApi.IJsonSchema = null!; - let schema2: ISwaggerSchema = schema1; - schema1 = schema2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); -} - -// MIGRATE APPLICATION -{ - let app1: IHttpMigrateApplication = null!; - let app2: ISwaggerMigrateApplication = app1; - app1 = app2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let route1: IHttpMigrateRoute = null!; - let route2: ISwaggerMigrateRoute = route1; - route1 = route2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); -} - -// LLM APPLICATION -{ - let httpApp1: IHttpLlmApplication = null!; - let httpApp2: IHttpOpenAiApplication = httpApp1; - httpApp1 = httpApp2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let httpFunc1: IHttpLlmFunction = null!; - let httpFunc2: IHttpOpenAiFunction = httpFunc1; - httpFunc1 = httpFunc2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let app1: ILlmApplication = null!; - let app2: IOpenAiApplication = app1; - app1 = app2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let func1: ILlmFunction = null!; - let func2: IOpenAiFunction = func1; - func1 = func2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let sep1: IHttpLlmFunction.ISeparated = null!; - let sep2: IHttpOpenAiFunction.ISeparated = sep1; - sep1 = sep2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); - - let schema1: ILlmSchema = null!; - let schema2: IOpenAiSchema = schema1; - schema1 = schema2; - validate({ - createX: typia.createRandom(), - createY: typia.createRandom(), - assertX: typia.createAssert(), - assertY: typia.createAssert(), - }); -} diff --git a/test/tsconfig.json b/test/tsconfig.json deleted file mode 100644 index 34f4780..0000000 --- a/test/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "outDir": "../bin", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "resolveJsonModule": true, - "paths": { - "@wrtnio/schema": ["../src/index.ts"], - "@wrtnio/schema/lib/*": ["../src/*"], - }, - "plugins": [ - { "transform": "typescript-transform-paths" }, - { "transform": "typia/lib/transform" }, - ] - }, - "include": ["../src", "../test"] -} \ No newline at end of file