Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samchon/openapi",
"version": "4.6.0",
"version": "4.7.0-dev.20250805-3",
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.",
"main": "./lib/index.js",
"module": "./lib/index.mjs",
Expand Down
33 changes: 31 additions & 2 deletions src/structures/IHttpLlmApplication.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { OpenApi } from "../OpenApi";
import { IHttpLlmFunction } from "./IHttpLlmFunction";
import { IHttpMigrateRoute } from "./IHttpMigrateRoute";
import { ILlmApplication } from "./ILlmApplication";
import { ILlmSchema } from "./ILlmSchema";
import { ILlmSchemaV3 } from "./ILlmSchemaV3";

Expand Down Expand Up @@ -84,7 +83,37 @@ export interface IHttpLlmApplication<Model extends ILlmSchema.Model> {
export namespace IHttpLlmApplication {
/** Options for the HTTP LLM application schema composition. */
export type IOptions<Model extends ILlmSchema.Model> =
ILlmApplication.IOptions<Model> & {
ILlmSchema.ModelConfig[Model] & {
/**
* Separator function for the parameters.
*
* When composing parameter arguments through LLM function call, there can
* be a case that some parameters must be composed by human, or LLM cannot
* understand the parameter.
*
* For example, if the parameter type has configured
* {@link IGeminiSchema.IString.contentMediaType} which indicates file
* uploading, it must be composed by human, not by LLM (Large Language
* Model).
*
* In that case, if you configure this property with a function that
* predicating whether the schema value must be composed by human or not,
* the parameters would be separated into two parts.
*
* - {@link ILlmFunction.separated.llm}
* - {@link ILlmFunction.separated.human}
*
* When writing the function, note that returning value `true` means to be
* a human composing the value, and `false` means to LLM composing the
* value. Also, when predicating the schema, it would better to utilize
* the {@link GeminiTypeChecker} like features.
*
* @default null
* @param schema Schema to be separated.
* @returns Whether the schema value must be composed by human or not.
*/
separate?: null | ((schema: ILlmSchema.ModelSchema[Model]) => boolean);

/**
* Maximum length of function name.
*
Expand Down
67 changes: 63 additions & 4 deletions src/structures/ILlmApplication.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ILlmFunction } from "./ILlmFunction";
import { ILlmSchema } from "./ILlmSchema";
import { IValidation } from "./IValidation";

/**
* Application of LLM function calling.
Expand Down Expand Up @@ -41,7 +42,7 @@ export interface ILlmApplication<
functions: ILlmFunction<Model>[];

/** Configuration for the application. */
options: ILlmApplication.IOptions<Model>;
options: ILlmApplication.IOptions<Model, Class>;

/**
* Class type, the source of the LLM application.
Expand All @@ -53,7 +54,10 @@ export interface ILlmApplication<
}
export namespace ILlmApplication {
/** Options for application composition. */
export type IOptions<Model extends ILlmSchema.Model> = {
export type IOptions<
Model extends ILlmSchema.Model,
Class extends object = any,
> = ILlmSchema.ModelConfig[Model] & {
/**
* Separator function for the parameters.
*
Expand Down Expand Up @@ -82,6 +86,61 @@ export namespace ILlmApplication {
* @param schema Schema to be separated.
* @returns Whether the schema value must be composed by human or not.
*/
separate: null | ((schema: ILlmSchema.ModelSchema[Model]) => boolean);
} & ILlmSchema.ModelConfig[Model];
separate?: null | ((schema: ILlmSchema.ModelSchema[Model]) => boolean);

/**
* Custom validation functions for specific class methods.
*
* The `validate` property allows you to provide custom validation functions
* that will replace the default validation behavior for specific methods
* within the application class. When specified, these custom validators
* take precedence over the standard type validation generated by
* `typia.llm.application()`.
*
* This feature is particularly useful when you need to:
*
* - Implement business logic validation beyond type checking
* - Add custom constraints that cannot be expressed through type annotations
* - Provide more specific error messages for AI agents
* - Validate dynamic conditions based on runtime state
*
* Each validation function receives the same arguments as its corresponding
* method and must return an {@link IValidation} result. On validation
* success, it should return `{ success: true, data }`. On failure, it
* should return `{ success: false, data, errors }` with detailed error
* information that helps AI agents understand and correct their mistakes.
*
* @default null
*/
validate?: null | Partial<ILlmApplication.IValidationHook<Class>>;
};

/**
* Type for custom validation function hooks.
*
* `IValidationHook` defines the structure for custom validation functions
* that can be provided for each method in the application class. It creates a
* mapped type where each property corresponds to a method in the class, and
* the value is a validation function for that method's parameters.
*
* The validation hook functions:
*
* - Receive the same argument type as the original method
* - Must return an {@link IValidation} result indicating success or failure
* - Replace the default type validation when specified
* - Enable custom business logic and runtime validation
*
* Type constraints:
*
* - Only methods (functions) from the class can have validation hooks
* - Non-function properties are typed as `never` and cannot be validated
* - The validation function must match the method's parameter signature
*
* @template Class The application class type containing methods to validate
*/
export type IValidationHook<Class extends object> = {
[K in keyof Class]?: Class[K] extends (args: infer Argument) => unknown
? (input: Argument) => IValidation<unknown>
: never;
};
}